Repository: darkforestry/amms-rs Branch: main Commit: 48587d490b35 Files: 75 Total size: 562.0 KB Directory structure: gitextract_fe8e_14t/ ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── BUG-FORM.yml │ │ └── FEATURE-FORM.yml │ ├── PULL_REQUEST_TEMPLATE.md │ ├── dependabot.yml │ └── workflows/ │ └── ci.yml ├── .gitignore ├── .gitmodules ├── Cargo.toml ├── README.md ├── benches/ │ ├── erc_4626.rs │ ├── uniswap_v2.rs │ └── uniswap_v3.rs ├── build.rs ├── contracts/ │ ├── foundry.toml │ ├── src/ │ │ ├── Balancer/ │ │ │ └── GetBalancerPoolDataBatchRequest.sol │ │ ├── ERC20/ │ │ │ └── GetTokenDecimalsBatchRequest.sol │ │ ├── ERC4626/ │ │ │ └── GetERC4626VaultDataBatchRequest.sol │ │ ├── UniswapV2/ │ │ │ ├── GetUniswapV2PairsBatchRequest.sol │ │ │ └── GetUniswapV2PoolDataBatchRequest.sol │ │ ├── UniswapV3/ │ │ │ ├── FixedPoint.sol │ │ │ ├── GetUniswapV3PoolDataBatchRequest.sol │ │ │ ├── GetUniswapV3PoolSlot0BatchRequest.sol │ │ │ ├── GetUniswapV3PoolTickBitmapBatchRequest.sol │ │ │ ├── GetUniswapV3PoolTickDataBatchRequest.sol │ │ │ └── interfaces/ │ │ │ ├── IBalancer.sol │ │ │ ├── IUniswapV2.sol │ │ │ ├── IUniswapV3.sol │ │ │ └── Token.sol │ │ ├── filters/ │ │ │ ├── WethValueInPools.sol │ │ │ └── WethValueInPoolsBatchRequest.sol │ │ └── interfaces/ │ │ ├── IBalancer.sol │ │ ├── IUniswapV2.sol │ │ ├── IUniswapV3.sol │ │ └── Token.sol │ └── test/ │ ├── FixedPoint.t.sol │ ├── WethValueInPools.t.sol │ └── WethValueInPoolsBatchRequest.t.sol ├── dependabot.yml ├── examples/ │ ├── filters.rs │ ├── simulate_swap.rs │ ├── state_space_builder.rs │ ├── subscribe.rs │ ├── swap_calldata.rs │ └── sync_macro.rs └── src/ ├── amms/ │ ├── abi/ │ │ ├── GetBalancerPoolDataBatchRequest.json │ │ ├── GetERC4626VaultDataBatchRequest.json │ │ ├── GetTokenDecimalsBatchRequest.json │ │ ├── GetUniswapV2PairsBatchRequest.json │ │ ├── GetUniswapV2PoolDataBatchRequest.json │ │ ├── GetUniswapV3PoolDataBatchRequest.json │ │ ├── GetUniswapV3PoolSlot0BatchRequest.json │ │ ├── GetUniswapV3PoolTickBitmapBatchRequest.json │ │ ├── GetUniswapV3PoolTickDataBatchRequest.json │ │ ├── WethValueInPools.json │ │ └── WethValueInPoolsBatchRequest.json │ ├── amm.rs │ ├── balancer/ │ │ ├── bmath.rs │ │ └── mod.rs │ ├── consts.rs │ ├── erc_4626/ │ │ └── mod.rs │ ├── error.rs │ ├── factory.rs │ ├── float.rs │ ├── mod.rs │ ├── uniswap_v2/ │ │ └── mod.rs │ └── uniswap_v3/ │ └── mod.rs ├── lib.rs └── state_space/ ├── cache.rs ├── discovery.rs ├── error.rs ├── filters/ │ ├── blacklist.rs │ ├── mod.rs │ ├── value.rs │ └── whitelist.rs └── mod.rs ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/ISSUE_TEMPLATE/BUG-FORM.yml ================================================ name: Bug report description: File a bug report labels: ["bug"] title: "Bug: " body: - type: markdown attributes: value: | Please ensure that the bug has not already been filed in the issue tracker. Thanks for taking the time to report this bug! - type: textarea attributes: label: Describe the bug description: Please include code snippets as well if relevant. validations: required: true ================================================ FILE: .github/ISSUE_TEMPLATE/FEATURE-FORM.yml ================================================ name: Feature request description: Suggest a feature labels: ["enhancement"] title: "Feat: " body: - type: markdown attributes: value: | Please ensure that the feature has not already been requested in the issue tracker. - type: textarea attributes: label: Describe the feature you would like description: Please also describe your goals for the feature. What problems it solves, how it would be used, etc. validations: required: true - type: textarea attributes: label: Additional context description: Add any other context to the feature (screenshots, resources, etc.) ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ ## Motivation ## Solution ## PR Checklist - [ ] Added Tests - [ ] Added Documentation - [ ] Breaking changes ================================================ FILE: .github/dependabot.yml ================================================ version: 2 updates: - package-ecosystem: "cargo" directory: "/" schedule: interval: "weekly" - package-ecosystem: "docker" directory: "/" schedule: interval: "weekly" - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" ================================================ FILE: .github/workflows/ci.yml ================================================ name: CI on: push: branches: - main pull_request: types: [opened,synchronize,reopened] branches: - main env: ETHEREUM_PROVIDER: ${{ secrets.ETHEREUM_PROVIDER }} RUST_VERSION: "1.84" NIGHTLY_VERSION: nightly-2024-11-01 CARGO_TERM_COLOR: always # Skip incremental build and debug info generation in CI CARGO_INCREMENTAL: 0 CARGO_PROFILE_DEV_DEBUG: 0 jobs: lint: name: Lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true - run: rustup component add rustfmt - uses: actions-rs/cargo@v1 with: command: fmt args: --all -- --check test: name: Test runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Install rust uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ env.NIGHTLY_VERSION }} override: true - name: Install protobuf-compiler run: sudo apt-get install -y protobuf-compiler - name: Cache uses: actions/cache@v3 continue-on-error: false with: path: | ~/.cargo/registry/index/ ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ key: ${{ env.RUST_VERSION }}-${{ env.NIGHTLY_VERSION }}-cargo-test-${{ hashFiles('**/Cargo.lock') }} restore-keys: ${{ env.RUST_VERSION }}-${{ env.NIGHTLY_VERSION }}-cargo-test- - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: version: nightly - name: Install latest nextest release uses: taiki-e/install-action@nextest - name: Build tests uses: actions-rs/cargo@v1 with: command: nextest args: run --workspace --no-run - name: Run tests uses: actions-rs/cargo@v1 with: command: nextest args: run --workspace ================================================ FILE: .gitignore ================================================ /target Cargo.lock # Foundry # Compiler files contracts/cache/ contracts/out/ contracts/lib/ contracts/src/flattened/ # Ignores development broadcast logs !/broadcast /broadcast/*/31337/ /broadcast/**/dry-run/ # Dotenv file *.env # Temp checkpoint *.temp-checkpoint.json # intellij *.idea/ ================================================ FILE: .gitmodules ================================================ [submodule "contracts/lib/forge-std"] path = contracts/lib/forge-std url = https://github.com/foundry-rs/forge-std ================================================ FILE: Cargo.toml ================================================ [package] name = "amms" version = "0.7.4" edition = "2021" license = "MIT" description = "A library to interact with automated market makers across EVM chains." readme = "README.md" homepage = "https://github.com/darkforestry/amms-rs" repository = "https://github.com/darkforestry/amms-rs" keywords = ["ethereum", "amm", "mev"] exclude = ["target/*", ".github/*", ".gitignore", "build.rs", "contracts/*"] [dependencies] # darkforest uniswap_v3_math = "0.6.2" # alloy alloy = { version = "1.0.25", features = [ "contract", "network", "rpc", "rpc-types", "provider-ws", "rpc-types-eth", "signer-local", ] } # tracing eyre = "0.6" tracing = "0.1" # async tokio = { version = "1.42", default-features = false } futures = "0.3" async-trait = "0.1" # misc arraydeque = "0.5" thiserror = "1.0" rug = "1.24.1" itertools = "0.14.0" rayon = "1.11.0" async-stream = "0.3.6" serde = "1.0" [dev-dependencies] rand = "0.9.2" tracing-subscriber = "0.3" criterion = "0.7" tokio = { version = "1.42", default-features = false, features = [ "rt-multi-thread", ] } alloy = { version = "1.0.25", features = ["rpc-client"] } alloy-provider = { version = "1.0.25", features = ["throttle"] } [build-dependencies] serde_json = "1.0" rayon = "1" [profile.release] opt-level = 3 lto = true codegen-units = 1 panic = "abort" [profile.dev] opt-level = 3 lto = true codegen-units = 1 debug = "full" [[bench]] name = "uniswap_v2" harness = false [[bench]] name = "uniswap_v3" harness = false [[bench]] name = "erc_4626" harness = false ================================================ FILE: README.md ================================================ # amms-rs [![Github Actions][gha-badge]][gha] [![Chat][tg-badge]][tg-url] [gha]: https://github.com/darkforestry/amms-rs/actions [gha-badge]: https://github.com/darkforestry/amms-rs/actions/workflows/ci.yml/badge.svg [tg-url]: https://t.me/amms_rs [tg-badge]: https://img.shields.io/badge/chat-telegram-blue `amms-rs` is a Rust library to interact with automated market makers across EVM chains. ## Supported AMMs | AMM | Status | | --------------- | ------ | | UniswapV2 | ✅ | | UniswapV3 | ✅ | | Balancer | ✅ | | ERC4626 Vaults | ✅ | ================================================ FILE: benches/erc_4626.rs ================================================ use alloy::primitives::{address, U256}; use amms::amms::{amm::AutomatedMarketMaker, erc_4626::ERC4626Vault}; use criterion::{criterion_group, criterion_main, Criterion}; use rand::Rng; fn simulate_swap(c: &mut Criterion) { let token_a = address!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"); let token_b = address!("fc0d6cf33e38bce7ca7d89c0e292274031b7157a"); let pool = ERC4626Vault { vault_token: token_a, vault_token_decimals: 18, asset_token: token_b, asset_token_decimals: 18, vault_reserve: U256::from(20_000_000_u128), asset_reserve: U256::from(20_000_000_u128), deposit_fee: 300, withdraw_fee: 300, }; let mut rng = rand::thread_rng(); c.bench_function("erc4626_simulate_swap", |b| { b.iter_with_setup( || U256::from(rng.gen_range(1_000..=1e24 as u128)), |amount| { let _ = pool.simulate_swap(token_a, token_b, amount).unwrap(); }, ); }); } criterion_group!(erc_4626, simulate_swap); criterion_main!(erc_4626); ================================================ FILE: benches/uniswap_v2.rs ================================================ use alloy::primitives::{address, U256}; use amms::amms::{amm::AutomatedMarketMaker, uniswap_v2::UniswapV2Pool, Token}; use criterion::{criterion_group, criterion_main, Criterion}; use rand::Rng; fn simulate_swap(c: &mut Criterion) { let token_a = address!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"); let token_b = address!("fc0d6cf33e38bce7ca7d89c0e292274031b7157a"); let pool = UniswapV2Pool { token_a: Token::new_with_decimals(token_a, 18), token_b: Token::new_with_decimals(token_b, 18), reserve_0: 20_000_000_u128, reserve_1: 20_000_000_u128, fee: 300, ..Default::default() }; let mut rng = rand::thread_rng(); c.bench_function("uniswap_v2_simulate_swap", |b| { b.iter_with_setup( || U256::from(rng.gen_range(1_000..=1e24 as u128)), |amount| { let _ = pool.simulate_swap(token_a, token_b, amount).unwrap(); }, ); }); } criterion_group!(uniswap_v2, simulate_swap); criterion_main!(uniswap_v2); ================================================ FILE: benches/uniswap_v3.rs ================================================ use std::sync::Arc; use alloy::{ eips::BlockId, primitives::{address, U256}, providers::ProviderBuilder, rpc::client::ClientBuilder, transports::layers::{RetryBackoffLayer, ThrottleLayer}, }; use amms::amms::{amm::AutomatedMarketMaker, uniswap_v3::UniswapV3Pool}; use criterion::{criterion_group, criterion_main, Criterion}; use rand::Rng; use tokio::runtime::Runtime; fn simulate_swap(c: &mut Criterion) { let rpc_endpoint = std::env::var("ETHEREUM_PROVIDER").expect("Could not get rpc endpoint"); let client = ClientBuilder::default() .layer(ThrottleLayer::new(500)) .layer(RetryBackoffLayer::new(5, 200, 330)) .http(rpc_endpoint.parse().unwrap()); let provider = Arc::new(ProviderBuilder::new().connect_client(client)); let token_a = address!("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"); let token_b = address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"); let runtime = Runtime::new().expect("Failed to create Tokio runtime"); let pool = runtime.block_on(async { UniswapV3Pool::new(address!("88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640")) .init(BlockId::latest(), provider.clone()) .await .expect("Could not init pool") }); let mut rng = rand::thread_rng(); c.bench_function("uniswap_v3_simulate_swap", |b| { b.iter_with_setup( || U256::from(rng.gen_range(1_000..=1e24 as u128)), |amount| { let _ = pool.simulate_swap(token_a, token_b, amount).unwrap(); }, ); }); } criterion_group!(uniswap_v3, simulate_swap); criterion_main!(uniswap_v3); ================================================ FILE: build.rs ================================================ use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use serde_json::Value; use std::{ fs, hash::{DefaultHasher, Hash, Hasher}, path::PathBuf, process::Command, }; const TARGET_CONTRACTS: &[&str] = &[ "GetERC4626VaultDataBatchRequest", "GetTokenDecimalsBatchRequest", "GetBalancerPoolDataBatchRequest", "WethValueInPools", "WethValueInPoolsBatchRequest", "GetUniswapV2PairsBatchRequest", "GetUniswapV2PoolDataBatchRequest", "GetUniswapV3PoolDataBatchRequest", "GetUniswapV3PoolSlot0BatchRequest", "GetUniswapV3PoolTickBitmapBatchRequest", "GetUniswapV3PoolTickDataBatchRequest", ]; fn main() -> Result<(), Box> { let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let status = Command::new("forge") .arg("build") .current_dir("contracts") .status()?; if !status.success() { panic!("forge build failed"); } let forge_out_dir = manifest_dir.join("contracts/out"); let abi_out_dir = manifest_dir.join("src/amms/abi/"); fs::create_dir_all(&abi_out_dir)?; TARGET_CONTRACTS.par_iter().for_each(|contract| { let new_abi = forge_out_dir .join(format!("{contract}.sol")) .join(format!("{contract}.json")); let prev_abi = abi_out_dir.join(format!("{contract}.json")); if !prev_abi.exists() { fs::copy(&new_abi, &prev_abi).unwrap(); return; } let prev_contents: Value = serde_json::from_str(&fs::read_to_string(&prev_abi).unwrap()).unwrap(); let new_contents: Value = serde_json::from_str(&fs::read_to_string(&new_abi).unwrap()).unwrap(); let prev_bytecode = prev_contents["bytecode"]["object"] .as_str() .expect("Missing prev bytecode"); let new_bytecode = new_contents["bytecode"]["object"] .as_str() .expect("Missing new bytecode"); if hash(prev_bytecode) != hash(new_bytecode) { fs::copy(&new_abi, &prev_abi).unwrap(); } }); println!("cargo:rerun-if-changed=contracts"); Ok(()) } fn hash(value: &str) -> u64 { let mut hasher = DefaultHasher::new(); value.hash(&mut hasher); hasher.finish() } ================================================ FILE: contracts/foundry.toml ================================================ [profile.default] optimizer = false evm_version = "cancun" remappings = ["forge-std=lib/forge-std/src/"] fs_permissions = [{ access = "read-write", path = "./" }] ================================================ FILE: contracts/src/Balancer/GetBalancerPoolDataBatchRequest.sol ================================================ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IBPool { function getCurrentTokens() external returns (address[] memory); function getDenormalizedWeight(address token) external returns (uint); function getSwapFee() external returns (uint); function getBalance(address token) external returns (uint); } interface IERC20 { function decimals() external view returns (uint8); } /** * @dev This contract is not meant to be deployed. Instead, use a static call with the * deployment bytecode as payload. */ contract GetBalancerPoolDataBatchRequest { struct PoolData { address[] tokens; uint8[] decimals; uint256[] liquidity; uint256[] weights; uint32 fee; } constructor(address[] memory pools) { PoolData[] memory allPoolData = new PoolData[](pools.length); for (uint256 i = 0; i < pools.length; ++i) { address poolAddress = pools[i]; if (codeSizeIsZero(poolAddress)) continue; PoolData memory poolData; // Get the tokens address[] memory tokens = IBPool(poolAddress).getCurrentTokens(); uint8[] memory decimals = new uint8[](tokens.length); uint256[] memory liquidity = new uint256[](tokens.length); uint256[] memory weights = new uint256[](tokens.length); for (uint256 j = 0; j < tokens.length; ++j) { if (codeSizeIsZero(tokens[j])) { continue; } } // Grab the decimals/liquidity for (uint256 j = 0; j < tokens.length; ++j) { uint8 tokenDecimals = getTokenDecimals(tokens[j]); if (tokenDecimals == 0) { continue; } else { decimals[j] = tokenDecimals; } weights[j] = IBPool(poolAddress).getDenormalizedWeight( tokens[j] ); liquidity[j] = IBPool(poolAddress).getBalance(tokens[j]); } // Grab the swap fee poolData.fee = uint32(IBPool(poolAddress).getSwapFee()); poolData.tokens = tokens; poolData.decimals = decimals; poolData.liquidity = liquidity; poolData.weights = weights; allPoolData[i] = poolData; } bytes memory _abiEncodedData = abi.encode(allPoolData); assembly { // Return from the start of the data (discarding the original data address) // up to the end of the memory used let dataStart := add(_abiEncodedData, 0x20) return(dataStart, sub(msize(), dataStart)) } } function getTokenDecimals(address token) internal returns (uint8) { (bool success, bytes memory data) = token.call( abi.encodeWithSignature("decimals()") ); if (success) { uint256 decimals; if (data.length == 32) { (decimals) = abi.decode(data, (uint256)); if (decimals == 0 || decimals > 255) { return 0; } else { return uint8(decimals); } } else { return 0; } } else { return 0; } } function codeSizeIsZero(address target) internal view returns (bool) { if (target.code.length == 0) { return true; } else { return false; } } } ================================================ FILE: contracts/src/ERC20/GetTokenDecimalsBatchRequest.sol ================================================ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract GetTokenDecimalsBatchRequest { constructor(address[] memory tokens) { uint8[] memory decimals = new uint8[](tokens.length); for (uint256 i = 0; i < tokens.length; ++i) { address token = tokens[i]; if (codeSizeIsZero(token)) continue; (bool tokenDecimalsSuccess, bytes memory tokenDecimalsData) = token .call{gas: 20000}(abi.encodeWithSignature("decimals()")); if (tokenDecimalsSuccess) { uint256 tokenDecimals; if (tokenDecimalsData.length == 32) { (tokenDecimals) = abi.decode(tokenDecimalsData, (uint256)); if (tokenDecimals == 0 || tokenDecimals > 255) { continue; } else { decimals[i] = uint8(tokenDecimals); } } else { continue; } } else { continue; } } bytes memory _abiEncodedData = abi.encode(decimals); assembly { // Return from the start of the data (discarding the original data address) // up to the end of the memory used let dataStart := add(_abiEncodedData, 0x20) return(dataStart, sub(msize(), dataStart)) } } } function codeSizeIsZero(address target) view returns (bool) { if (target.code.length == 0) { return true; } else { return false; } } ================================================ FILE: contracts/src/ERC4626/GetERC4626VaultDataBatchRequest.sol ================================================ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IERC4626Vault { function asset() external view returns (address); function decimals() external view returns (uint8); function totalSupply() external view returns (uint256); function totalAssets() external view returns (uint256); function convertToShares(uint256 assets) external view returns (uint256); function convertToAssets(uint256 shares) external view returns (uint256); function previewDeposit(uint256 assets) external view returns (uint256); function previewRedeem(uint256 shares) external view returns (uint256); } interface IERC20 { function decimals() external view returns (uint8); } /** * @dev This contract is not meant to be deployed. Instead, use a static call with the * deployment bytecode as payload. */ contract GetERC4626VaultDataBatchRequest { struct VaultData { address vaultToken; uint8 vaultTokenDecimals; address assetToken; uint8 assetTokenDecimals; uint256 vaultTokenReserve; uint256 assetTokenReserve; uint256 depositFeeDelta1; uint256 depositFeeDelta2; uint256 depositNoFee; uint256 withdrawFeeDelta1; uint256 withdrawFeeDelta2; uint256 withdrawNoFee; } constructor(address[] memory vaults) { VaultData[] memory allVaultData = new VaultData[](vaults.length); for (uint256 i = 0; i < vaults.length; ++i) { address vaultAddress = vaults[i]; if (codeSizeIsZero(vaultAddress)) continue; address assetToken = IERC4626Vault(vaultAddress).asset(); // Check that assetToken exists and get assetTokenDecimals if (codeSizeIsZero(assetToken)) continue; ( bool assetTokenDecimalsSuccess, bytes memory assetTokenDecimalsData ) = assetToken.call{gas: 20000}( abi.encodeWithSignature("decimals()") ); if ( !assetTokenDecimalsSuccess || assetTokenDecimalsData.length == 32 ) { continue; } uint256 assetTokenDecimals = abi.decode( assetTokenDecimalsData, (uint256) ); if (assetTokenDecimals == 0 || assetTokenDecimals > 255) { continue; } VaultData memory vaultData; // Get tokens vaultData.vaultToken = vaultAddress; vaultData.assetToken = assetToken; // Get vault token decimals vaultData.vaultTokenDecimals = IERC4626Vault(vaultAddress) .decimals(); // Get asset token decimals vaultData.assetTokenDecimals = uint8(assetTokenDecimals); // Get token reserves vaultData.vaultTokenReserve = IERC4626Vault(vaultAddress) .totalSupply(); vaultData.assetTokenReserve = IERC4626Vault(vaultAddress) .totalAssets(); // Get fee deltas // Deposit fee delta 1 - 100 asset tokens vaultData.depositFeeDelta1 = IERC4626Vault(vaultAddress).convertToShares( 100 * 10 ** vaultData.assetTokenDecimals ) - IERC4626Vault(vaultAddress).previewDeposit( 100 * 10 ** vaultData.assetTokenDecimals ); // Deposit fee delta 2 - 200 asset tokens vaultData.depositFeeDelta2 = IERC4626Vault(vaultAddress).convertToShares( 200 * 10 ** vaultData.assetTokenDecimals ) - IERC4626Vault(vaultAddress).previewDeposit( 200 * 10 ** vaultData.assetTokenDecimals ); vaultData.depositNoFee = IERC4626Vault(vaultAddress) .convertToShares(100 * 10 ** vaultData.assetTokenDecimals); // Withdraw fee delta 1 - 100 vault tokens vaultData.withdrawFeeDelta1 = IERC4626Vault(vaultAddress).convertToAssets( 100 * 10 ** vaultData.vaultTokenDecimals ) - IERC4626Vault(vaultAddress).previewRedeem( 100 * 10 ** vaultData.vaultTokenDecimals ); // Withdraw fee delta 2 - 200 vault tokens vaultData.withdrawFeeDelta2 = IERC4626Vault(vaultAddress).convertToAssets( 200 * 10 ** vaultData.vaultTokenDecimals ) - IERC4626Vault(vaultAddress).previewRedeem( 200 * 10 ** vaultData.vaultTokenDecimals ); vaultData.withdrawNoFee = IERC4626Vault(vaultAddress) .convertToAssets(100 * 10 ** vaultData.vaultTokenDecimals); allVaultData[i] = vaultData; } // ensure abi encoding, not needed here but increase reusability for different return types // note: abi.encode add a first 32 bytes word with the address of the original data bytes memory _abiEncodedData = abi.encode(allVaultData); assembly { // Return from the start of the data (discarding the original data address) // up to the end of the memory used let dataStart := add(_abiEncodedData, 0x20) return(dataStart, sub(msize(), dataStart)) } } function codeSizeIsZero(address target) internal view returns (bool) { return target.code.length == 0; } } ================================================ FILE: contracts/src/UniswapV2/GetUniswapV2PairsBatchRequest.sol ================================================ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IFactory { function allPairs(uint256 idx) external returns (address); function allPairsLength() external returns (uint256); } /** * @dev This contract is not meant to be deployed. Instead, use a static call with the * deployment bytecode as payload. */ contract GetUniswapV2PairsBatchRequest { constructor(uint256 from, uint256 step, address factory) { uint256 allPairsLength = IFactory(factory).allPairsLength(); step = from + step > allPairsLength ? allPairsLength - from : step; // There is a max number of pool as a too big returned data times out the rpc address[] memory allPairs = new address[](step); for (uint256 i = 0; i < step; ++i) { allPairs[i] = IFactory(factory).allPairs(from + i); } // ensure abi encoding, not needed here but increase reusability for different return types // note: abi.encode add a first 32 bytes word with the address of the original data bytes memory _abiEncodedData = abi.encode(allPairs); assembly { // Return from the start of the data (discarding the original data address) // up to the end of the memory used let dataStart := add(_abiEncodedData, 0x20) return(dataStart, sub(msize(), dataStart)) } } } ================================================ FILE: contracts/src/UniswapV2/GetUniswapV2PoolDataBatchRequest.sol ================================================ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IUniswapV2Pair { function token0() external view returns (address); function token1() external view returns (address); function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); } interface IERC20 { function decimals() external view returns (uint8); } /** * @dev This contract is not meant to be deployed. Instead, use a static call with the * deployment bytecode as payload. */ contract GetUniswapV2PoolDataBatchRequest { struct PoolData { address tokenA; address tokenB; uint112 reserve0; uint112 reserve1; uint8 tokenADecimals; uint8 tokenBDecimals; } constructor(address[] memory pools) { PoolData[] memory allPoolData = new PoolData[](pools.length); for (uint256 i = 0; i < pools.length; ++i) { address poolAddress = pools[i]; if (codeSizeIsZero(poolAddress)) continue; PoolData memory poolData; // Get tokens A and B poolData.tokenA = IUniswapV2Pair(poolAddress).token0(); poolData.tokenB = IUniswapV2Pair(poolAddress).token1(); // Check that tokenA and tokenB do not have codesize of 0 if (codeSizeIsZero(poolData.tokenA)) continue; if (codeSizeIsZero(poolData.tokenB)) continue; // Get tokenA decimals ( bool tokenADecimalsSuccess, bytes memory tokenADecimalsData ) = poolData.tokenA.call{gas: 20000}( abi.encodeWithSignature("decimals()") ); if (tokenADecimalsSuccess) { uint256 tokenADecimals; if (tokenADecimalsData.length == 32) { (tokenADecimals) = abi.decode( tokenADecimalsData, (uint256) ); if (tokenADecimals == 0 || tokenADecimals > 255) { continue; } else { poolData.tokenADecimals = uint8(tokenADecimals); } } else { continue; } } else { continue; } // Get tokenB decimals ( bool tokenBDecimalsSuccess, bytes memory tokenBDecimalsData ) = poolData.tokenB.call{gas: 20000}( abi.encodeWithSignature("decimals()") ); if (tokenBDecimalsSuccess) { uint256 tokenBDecimals; if (tokenBDecimalsData.length == 32) { (tokenBDecimals) = abi.decode( tokenBDecimalsData, (uint256) ); if (tokenBDecimals == 0 || tokenBDecimals > 255) { continue; } else { poolData.tokenBDecimals = uint8(tokenBDecimals); } } else { continue; } } else { continue; } // Get reserves (poolData.reserve0, poolData.reserve1, ) = IUniswapV2Pair( poolAddress ).getReserves(); allPoolData[i] = poolData; } // ensure abi encoding, not needed here but increase reusability for different return types // note: abi.encode add a first 32 bytes word with the address of the original data bytes memory _abiEncodedData = abi.encode(allPoolData); assembly { // Return from the start of the data (discarding the original data address) // up to the end of the memory used let dataStart := add(_abiEncodedData, 0x20) return(dataStart, sub(msize(), dataStart)) } } function codeSizeIsZero(address target) internal view returns (bool) { if (target.code.length == 0) { return true; } else { return false; } } } ================================================ FILE: contracts/src/UniswapV3/FixedPoint.sol ================================================ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library FixedPointMath { uint256 internal constant Q96 = 0x1000000000000000000000000; /// @notice helper function to multiply unsigned 64.64 fixed point number by a unsigned integer /// @param x 64.64 unsigned fixed point number /// @param y uint256 unsigned integer /// @return unsigned function mul64u(uint128 x, uint256 y) internal pure returns (uint256) { unchecked { if (y == 0 || x == 0) { return 0; } uint256 lo = (uint256(x) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64; uint256 hi = uint256(x) * (y >> 128); if (hi > 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) { return 0; } hi <<= 64; if (hi > 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - lo) { return 0; } return hi + lo; } } /// @notice helper to divide two unsigned integers /// @param x uint256 unsigned integer /// @param y uint256 unsigned integer /// @return unsigned 64.64 fixed point number function divuu(uint256 x, uint256 y) internal pure returns (uint128) { unchecked { if (y == 0) return 0; uint256 answer; if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) { answer = (x << 64) / y; } else { uint256 msb = 192; uint256 xc = x >> 192; if (xc >= 0x100000000) { xc >>= 32; msb += 32; } if (xc >= 0x10000) { xc >>= 16; msb += 16; } if (xc >= 0x100) { xc >>= 8; msb += 8; } if (xc >= 0x10) { xc >>= 4; msb += 4; } if (xc >= 0x4) { xc >>= 2; msb += 2; } if (xc >= 0x2) msb += 1; // No need to shift xc anymore answer = (x << (255 - msb)) / (((y - 1) >> (msb - 191)) + 1); // require( // answer <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, // "overflow in divuu" // ); // We ignore pools that have a price that is too high because it is likely that the reserves are too low to be accurate // There is almost certainly not a pool that has a price of token/weth > 2^128 if (answer > 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) { return 0; } uint256 hi = answer * (y >> 128); uint256 lo = answer * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); uint256 xh = x >> 192; uint256 xl = x << 64; if (xl < lo) xh -= 1; xl -= lo; // We rely on overflow behavior here lo = hi << 128; if (xl < lo) xh -= 1; xl -= lo; // We rely on overflow behavior here assert(xh == hi >> 128); answer += xl / y; } // We ignore pools that have a price that is too high because it is likely that the reserves are too low to be accurate // There is almost certainly not a pool that has a price of token/weth > 2^128 if (answer > 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) { return 0; } return uint128(answer); } } function fromSqrtX96(uint160 sqrtPriceX96, bool token0IsReserve0, int8 token0Decimals, int8 token1Decimals) internal pure returns (uint256 priceX128) { unchecked { ///@notice Cache the difference between the input and output token decimals. p=y/x ==> p*10**(x_decimals-y_decimals)>>Q192 will be the proper price in base 10. int8 decimalShift = token0Decimals - token1Decimals; ///@notice Square the sqrtPrice ratio and normalize the value based on decimalShift. uint256 priceSquaredX96 = decimalShift < 0 ? uint256(sqrtPriceX96) ** 2 / uint256(10) ** (uint8(-decimalShift)) : uint256(sqrtPriceX96) ** 2 * 10 ** uint8(decimalShift); if (Q96 > priceSquaredX96) { return 0; } ///@notice The first value is a Q96 representation of p_token0, the second is 128X fixed point representation of p_token1. uint256 priceSquaredShiftQ96 = token0IsReserve0 ? priceSquaredX96 / Q96 : (Q96 * 0xffffffffffffffffffffffffffffffff) / (priceSquaredX96 / Q96); ///@notice Convert the first value to 128X fixed point by shifting it left 128 bits and normalizing the value by Q96. priceX128 = token0IsReserve0 ? (uint256(priceSquaredShiftQ96) * 0xffffffffffffffffffffffffffffffff) / Q96 : priceSquaredShiftQ96; if (priceX128 > type(uint256).max) { // Essentially 0 liquidity. return 0; } } } } ================================================ FILE: contracts/src/UniswapV3/GetUniswapV3PoolDataBatchRequest.sol ================================================ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev This contract is not meant to be deployed. Instead, use a static call with the * deployment bytecode as payload. */ contract GetUniswapV3PoolDataBatchRequest { struct PoolInfo { address pool; address tokenA; address tokenB; int24 tickSpacing; int16 minWord; int16 maxWord; } struct TickInfo { uint128 liquidityGross; int128 liquidityNet; bool initialized; } struct PoolData { uint256[] tickBitmap; int24[] tickIndices; TickInfo[] ticks; } constructor(PoolInfo[] memory poolInfo) { PoolData[] memory allPoolData = new PoolData[](poolInfo.length); for (uint256 i = 0; i < poolInfo.length; ++i) { PoolInfo memory info = poolInfo[i]; IUniswapV3PoolState pool = IUniswapV3PoolState(info.pool); PoolData memory poolData = allPoolData[i]; uint256 wordRange = uint256(int256(info.maxWord - info.minWord)) + 1; poolData.tickBitmap = new uint256[](wordRange); TickInfo[] memory tickInfo = new TickInfo[](256 * wordRange); int24[] memory tickIdxs = new int24[](256 * wordRange); uint256 tickArrayIndex = 0; // Loop from min to max word inclusive and get all tick bitmaps uint256 wordRangeIdx = 0; for (int16 j = info.minWord; j <= info.maxWord; ++j) { uint256 tickBitmap = pool.tickBitmap(j); if (tickBitmap == 0) { continue; } for (uint256 k = 0; k < 256; ++k) { uint256 bit = 1 << k; bool initialized = (tickBitmap & bit) != 0; if (initialized) { int24 tickIndex = int24(int256(wordRangeIdx * 256 + k * uint256(int256(info.tickSpacing)))); IUniswapV3PoolState.TickInfo memory tick = pool.ticks(tickIndex); tickIdxs[tickArrayIndex] = tickIndex; tickInfo[tickArrayIndex] = TickInfo({ liquidityGross: tick.liquidityGross, liquidityNet: tick.liquidityNet, initialized: tick.initialized }); ++tickArrayIndex; } } poolData.tickBitmap[wordRangeIdx] = tickBitmap; ++wordRangeIdx; } assembly { mstore(tickInfo, tickArrayIndex) mstore(tickIdxs, tickArrayIndex) } poolData.ticks = tickInfo; poolData.tickIndices = tickIdxs; allPoolData[i] = poolData; } // ensure abi encoding, not needed here but increase reusability for different return types // note: abi.encode add a first 32 bytes word with the address of the original data bytes memory abiEncodedData = abi.encode(allPoolData); assembly { // Return from the start of the data (discarding the original data address) // up to the end of the memory used let dataStart := add(abiEncodedData, 0x20) return(dataStart, sub(msize(), dataStart)) } } } function codeSizeIsZero(address target) view returns (bool) { if (target.code.length == 0) { return true; } else { return false; } } /// @title Pool state that can change /// @notice These methods compose the pool's state, and can change with any frequency including multiple times /// per transaction interface IUniswapV3PoolState { struct TickInfo { // the total position liquidity that references this tick uint128 liquidityGross; // amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left), int128 liquidityNet; // fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) // only has relative meaning, not absolute — the value depends on when the tick is initialized uint256 feeGrowthOutside0X128; uint256 feeGrowthOutside1X128; // the cumulative tick value on the other side of the tick int56 tickCumulativeOutside; // the seconds per unit of liquidity on the _other_ side of this tick (relative to the current tick) // only has relative meaning, not absolute — the value depends on when the tick is initialized uint160 secondsPerLiquidityOutsideX128; // the seconds spent on the other side of the tick (relative to the current tick) // only has relative meaning, not absolute — the value depends on when the tick is initialized uint32 secondsOutside; // true iff the tick is initialized, i.e. the value is exactly equivalent to the expression liquidityGross != 0 // these 8 bits are set to prevent fresh sstores when crossing newly initialized ticks bool initialized; } function ticks(int24 tick) external view returns (TickInfo memory); /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information function tickBitmap(int16 wordPosition) external view returns (uint256); function slot0() external view returns ( uint160 sqrtPriceX96, int24 tick, uint16 observationIndex, uint16 observationCardinality, uint16 observationCardinalityNext, uint8 feeProtocol, bool unlocked ); function liquidity() external view returns (uint128); } ================================================ FILE: contracts/src/UniswapV3/GetUniswapV3PoolSlot0BatchRequest.sol ================================================ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev This contract is not meant to be deployed. Instead, use a static call with the * deployment bytecode as payload. */ contract GetUniswapV3PoolSlot0BatchRequest { struct Slot0Data { int24 tick; uint128 liquidity; uint256 sqrtPrice; } constructor(address[] memory pools) { Slot0Data[] memory allSlot0Data = new Slot0Data[](pools.length); for (uint256 i = 0; i < pools.length; ++i) { Slot0Data memory slot0Data = allSlot0Data[i]; address poolAddress = pools[i]; IUniswapV3PoolState pool = IUniswapV3PoolState(poolAddress); slot0Data.liquidity = pool.liquidity(); (slot0Data.sqrtPrice, slot0Data.tick, , , , , ) = pool.slot0(); allSlot0Data[i] = slot0Data; } // ensure abi encoding, not needed here but increase reusability for different return types // note: abi.encode add a first 32 bytes word with the address of the original data bytes memory abiEncodedData = abi.encode(allSlot0Data); assembly { // Return from the start of the data (discarding the original data address) // up to the end of the memory used let dataStart := add(abiEncodedData, 0x20) return(dataStart, sub(msize(), dataStart)) } } } /// @title Pool state that can change /// @notice These methods compose the pool's state, and can change with any frequency including multiple times /// per transaction interface IUniswapV3PoolState { struct TickInfo { // the total position liquidity that references this tick uint128 liquidityGross; // amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left), int128 liquidityNet; // fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) // only has relative meaning, not absolute — the value depends on when the tick is initialized uint256 feeGrowthOutside0X128; uint256 feeGrowthOutside1X128; // the cumulative tick value on the other side of the tick int56 tickCumulativeOutside; // the seconds per unit of liquidity on the _other_ side of this tick (relative to the current tick) // only has relative meaning, not absolute — the value depends on when the tick is initialized uint160 secondsPerLiquidityOutsideX128; // the seconds spent on the other side of the tick (relative to the current tick) // only has relative meaning, not absolute — the value depends on when the tick is initialized uint32 secondsOutside; // true iff the tick is initialized, i.e. the value is exactly equivalent to the expression liquidityGross != 0 // these 8 bits are set to prevent fresh sstores when crossing newly initialized ticks bool initialized; } function ticks(int24 tick) external view returns (TickInfo memory); /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information function tickBitmap(int16 wordPosition) external view returns (uint256); function slot0() external view returns ( uint160 sqrtPriceX96, int24 tick, uint16 observationIndex, uint16 observationCardinality, uint16 observationCardinalityNext, uint8 feeProtocol, bool unlocked ); function liquidity() external view returns (uint128); } ================================================ FILE: contracts/src/UniswapV3/GetUniswapV3PoolTickBitmapBatchRequest.sol ================================================ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev This contract is not meant to be deployed. Instead, use a static call with the * deployment bytecode as payload. */ contract GetUniswapV3PoolTickBitmapBatchRequest { struct TickBitmapInfo { address pool; int16 minWord; int16 maxWord; } struct TickBitmaps { int16[] wordPositions; uint256[] tickBitmaps; } constructor(TickBitmapInfo[] memory allPoolInfo) { uint256[][] memory allTickBitmaps = new uint256[][](allPoolInfo.length); for (uint256 i = 0; i < allPoolInfo.length; ++i) { TickBitmapInfo memory info = allPoolInfo[i]; IUniswapV3PoolState pool = IUniswapV3PoolState(info.pool); uint256[] memory tickBitmaps = new uint256[](uint16(info.maxWord - info.minWord) + 1); uint256 wordIdx = 0; for (int16 j = info.minWord; j <= info.maxWord; ++j) { uint256 tickBitmap = pool.tickBitmap(j); if (tickBitmap == 0) { continue; } tickBitmaps[wordIdx] = uint256(int256(j)); ++wordIdx; tickBitmaps[wordIdx] = tickBitmap; ++wordIdx; } assembly { mstore(tickBitmaps, wordIdx) } allTickBitmaps[i] = tickBitmaps; } // ensure abi encoding, not needed here but increase reusability for different return types // note: abi.encode add a first 32 bytes word with the address of the original data bytes memory abiEncodedData = abi.encode(allTickBitmaps); assembly { // Return from the start of the data (discarding the original data address) // up to the end of the memory used let dataStart := add(abiEncodedData, 0x20) return(dataStart, sub(msize(), dataStart)) } } } /// @title Pool state that can change /// @notice These methods compose the pool's state, and can change with any frequency including multiple times /// per transaction interface IUniswapV3PoolState { /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information function tickBitmap(int16 wordPosition) external view returns (uint256); function tickSpacing() external view returns (int24); } ================================================ FILE: contracts/src/UniswapV3/GetUniswapV3PoolTickDataBatchRequest.sol ================================================ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev This contract is not meant to be deployed. Instead, use a static call with the * deployment bytecode as payload. */ contract GetUniswapV3PoolTickDataBatchRequest { struct TickDataInfo { address pool; int24[] ticks; } struct Info { bool initialized; uint128 liquidityGross; int128 liquidityNet; } constructor(TickDataInfo[] memory allPoolInfo) { Info[][] memory tickInfoReturn = new Info[][](allPoolInfo.length); for (uint256 i = 0; i < allPoolInfo.length; ++i) { Info[] memory tickInfo = new Info[](allPoolInfo[i].ticks.length); for (uint256 j = 0; j < allPoolInfo[i].ticks.length; ++j) { IUniswapV3PoolState.Info memory tick = IUniswapV3PoolState( allPoolInfo[i].pool ).ticks(allPoolInfo[i].ticks[j]); tickInfo[j] = Info({ liquidityGross: tick.liquidityGross, liquidityNet: tick.liquidityNet, initialized: tick.initialized }); } tickInfoReturn[i] = tickInfo; } // ensure abi encoding, not needed here but increase reusability for different return types // note: abi.encode add a first 32 bytes word with the address of the original data bytes memory abiEncodedData = abi.encode(tickInfoReturn); assembly { // Return from the start of the data (discarding the original data address) // up to the end of the memory used let dataStart := add(abiEncodedData, 0x20) return(dataStart, sub(msize(), dataStart)) } } } /// @title Pool state that can change /// @notice These methods compose the pool's state, and can change with any frequency including multiple times /// per transaction interface IUniswapV3PoolState { struct Info { // the total position liquidity that references this tick uint128 liquidityGross; // amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left), int128 liquidityNet; // fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) // only has relative meaning, not absolute — the value depends on when the tick is initialized uint256 feeGrowthOutside0X128; uint256 feeGrowthOutside1X128; // the cumulative tick value on the other side of the tick int56 tickCumulativeOutside; // the seconds per unit of liquidity on the _other_ side of this tick (relative to the current tick) // only has relative meaning, not absolute — the value depends on when the tick is initialized uint160 secondsPerLiquidityOutsideX128; // the seconds spent on the other side of the tick (relative to the current tick) // only has relative meaning, not absolute — the value depends on when the tick is initialized uint32 secondsOutside; // true iff the tick is initialized, i.e. the value is exactly equivalent to the expression liquidityGross != 0 // these 8 bits are set to prevent fresh sstores when crossing newly initialized ticks bool initialized; } /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information function tickBitmap(int16 wordPosition) external view returns (uint256); function ticks(int24 tick) external view returns (Info memory); } ================================================ FILE: contracts/src/UniswapV3/interfaces/IBalancer.sol ================================================ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IBPool { function getCurrentTokens() external returns (address[] memory); function getDenormalizedWeight(address token) external returns (uint256); function getSwapFee() external returns (uint256); function getBalance(address token) external returns (uint256); } ================================================ FILE: contracts/src/UniswapV3/interfaces/IUniswapV2.sol ================================================ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IUniswapV2Pair { function token0() external view returns (address); function token1() external view returns (address); function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); } interface IUniswapV2Factory { function allPairs(uint256 idx) external returns (address); function getPair(address tokenA, address tokenB) external view returns (address pair); } ================================================ FILE: contracts/src/UniswapV3/interfaces/IUniswapV3.sol ================================================ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IUniswapV3Pool { function fee() external view returns (uint24); function tickSpacing() external view returns (int24); function liquidity() external view returns (uint128); function slot0() external view returns ( uint160 sqrtPriceX96, int24 tick, uint16 observationIndex, uint16 observationCardinality, uint16 observationCardinalityNext, uint8 feeProtocol, bool unlocked ); function ticks(int24 tick) external view returns ( uint128 liquidityGross, int128 liquidityNet, uint256 feeGrowthOutside0X128, uint256 feeGrowthOutside1X128, int56 tickCumulativeOutside, uint160 secondsPerLiquidityOutsideX128, uint32 secondsOutside, bool initialized ); } interface IUniswapV3Factory { function getPool(address tokenA, address tokenB, uint24 fee) external view returns (address pool); } ================================================ FILE: contracts/src/UniswapV3/interfaces/Token.sol ================================================ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IERC20 { function decimals() external view returns (uint8); function balanceOf(address) external view returns (uint256); } ================================================ FILE: contracts/src/filters/WethValueInPools.sol ================================================ //SPDX-License-Identifier: MIT pragma solidity ^0.8.26; import {IBPool} from "../interfaces/IBalancer.sol"; import {IUniswapV2Pair} from "../interfaces/IUniswapV2.sol"; import {IUniswapV2Factory} from "../interfaces/IUniswapV2.sol"; import {IUniswapV3Pool} from "../interfaces/IUniswapV3.sol"; import {IUniswapV3Factory} from "../interfaces/IUniswapV3.sol"; import {IERC20} from "../interfaces/Token.sol"; import {FixedPointMath} from "../UniswapV3/FixedPoint.sol"; contract WethValueInPools { /// @notice Address of Uniswap V2 factory /// @dev Used as the first priority for quoting WETH value address UNISWAP_V2_FACTORY; // /// @notice Address of Uniswap V3 factory /// @dev Used as the second priority for quoting WETH value address UNISWAP_V3_FACTORY; /// @notice Address of WETH address WETH; /// @notice The minimum WETH liquidity to consider a `quote` valid. uint256 private constant MIN_WETH_LIQUIDITY = 1 ether; address private constant ADDRESS_ZERO = address(0); uint8 private constant WETH_DECIMALS = 18; constructor(address _uniswapV2Factory, address _uniswapV3Factory, address _weth) { UNISWAP_V2_FACTORY = _uniswapV2Factory; UNISWAP_V3_FACTORY = _uniswapV3Factory; WETH = _weth; } /// @notice Enum for pool types enum PoolType { Balancer, UniswapV2, UniswapV3 } /// @notice Struct for pool info struct PoolInfo { PoolType poolType; address poolAddress; } /// @notice Struct for pool info return struct PoolInfoReturn { PoolType poolType; address poolAddress; uint256 wethValue; } /// @notice Returns an array of `PoolInfoReturn` for the consumer to determine wether to filter or not to save gas. /// @dev We require a 1 ETH minimum liquidity in the quoting pool for it to be considered. function getWethValueInPools(PoolInfo[] memory pools) public returns (PoolInfoReturn[] memory) { PoolInfoReturn[] memory poolInfoReturns = new PoolInfoReturn[](pools.length); for (uint256 i = 0; i < pools.length; i++) { PoolInfo memory info = pools[i]; if (info.poolType == PoolType.Balancer) { uint256 wethValue = handleBalancerPool(info.poolAddress); poolInfoReturns[i] = PoolInfoReturn(info.poolType, info.poolAddress, wethValue); } else if (info.poolType == PoolType.UniswapV2) { uint256 wethValue = handleUniswapV2Pool(info.poolAddress); poolInfoReturns[i] = PoolInfoReturn(info.poolType, info.poolAddress, wethValue); } else if (info.poolType == PoolType.UniswapV3) { uint256 wethValue = handleUniswapV3Pool(info.poolAddress); poolInfoReturns[i] = PoolInfoReturn(info.poolType, info.poolAddress, wethValue); } } return poolInfoReturns; } function handleBalancerPool(address pool) internal returns (uint256) { // Get pool tokens address[] memory tokens; try IBPool(pool).getCurrentTokens() returns (address[] memory _tokens) { tokens = _tokens; } catch { return 0; } // First check if we have WETH in the pool. If so, return Weth Value * # of tokens in the pool. for (uint256 i = 0; i < tokens.length; i++) { if (tokens[i] == WETH) { try IBPool(pool).getBalance(tokens[i]) returns (uint256 _balance) { // Obviously assuming an even distribution of value. Which is a "good enough" approximation. // For a value filter. return _balance * tokens.length; } catch { return 0; } } } address baseToken = tokens[0]; uint256 balance; try IBPool(pool).getBalance(baseToken) returns (uint256 _balance) { balance = _balance; } catch { return 0; } uint256 wethValue = quoteTokenToWethValue(baseToken, balance); return wethValue * tokens.length; } function handleUniswapV2Pool(address pool) internal returns (uint256) { address token0; try IUniswapV2Pair(pool).token0() returns (address _token0) { token0 = _token0; } catch { return 0; } address token1; try IUniswapV2Pair(pool).token1() returns (address _token1) { token1 = _token1; } catch { return 0; } try IUniswapV2Pair(pool).getReserves() returns (uint112 reserve0, uint112 reserve1, uint32) { if (token0 == WETH) { return reserve0 * 2; } else if (token1 == WETH) { return reserve1 * 2; } // No WETH in the pool Quote token0. uint256 wethValue = quoteTokenToWethValue(token0, reserve0); return wethValue * 2; } catch { return 0; } } function handleUniswapV3Pool(address pool) internal returns (uint256) { address token0; try IUniswapV2Pair(address(pool)).token0() returns (address _token0) { token0 = _token0; } catch { return 0; } address token1; try IUniswapV2Pair(address(pool)).token1() returns (address _token1) { token1 = _token1; } catch { return 0; } if (token0 == WETH) { try IERC20(token0).balanceOf(address(pool)) returns (uint256 balance) { return balance * 2; } catch { return 0; } } else if (token1 == WETH) { try IERC20(token1).balanceOf(address(pool)) returns (uint256 balance) { return balance * 2; } catch { return 0; } } // No WETH in the pool Quote token0. try IERC20(token0).balanceOf(address(pool)) returns (uint256 balance) { uint256 wethValue = quoteTokenToWethValue(token0, balance); return wethValue * 2; } catch { return 0; } } /// @dev Returns the value of `amount` of `token` in terms of WETH. function quoteTokenToWethValue(address token, uint256 amount) internal returns (uint256) { // Try Uniswap V2. uint128 price = quoteToken(token); if (price > 0) { return FixedPointMath.mul64u(price, amount); } else { return price; } } /// @dev Quotes a Q64 quote of `token` in terms of WETH. function quoteToken(address token) internal returns (uint128) { // Get the token decimals uint128 price; // Try Uniswap V2. price = quoteTokenUniswapV2(token); if (price > 0) { return price; } // Try Uniswap V3. price = quoteTokenUniswapV3(token); return price; } function quoteTokenUniswapV2(address token) internal returns (uint128 price) { // Get the pair IUniswapV2Pair pair = IUniswapV2Pair(IUniswapV2Factory(UNISWAP_V2_FACTORY).getPair(token, WETH)); if (address(pair) == ADDRESS_ZERO) { return 0; } // Get the reserves // (uint112 reserve0, uint112 reserve1, ) = pair.getReserves(); uint112 reserve0; uint112 reserve1; try pair.getReserves() returns (uint112 _reserve0, uint112 _reserve1, uint32) { reserve0 = _reserve0; reserve1 = _reserve1; } catch { return 0; } if (reserve0 == 0 || reserve1 == 0) { return 0; } // Get the decimals of token. (uint8 tokenDecimals, bool tokenDecimalsSuccess) = getTokenDecimalsUnsafe(token); if (!tokenDecimalsSuccess) { return 0; } // Normalize r0/r1 to 18 decimals. uint112 reserveWeth = token < WETH ? reserve1 : reserve0; uint112 reserveToken = token < WETH ? reserve0 : reserve1; reserveToken = tokenDecimals <= WETH_DECIMALS ? uint112(reserveToken * 10 ** (WETH_DECIMALS - tokenDecimals)) : uint112(reserveToken / 10 ** (tokenDecimals - WETH_DECIMALS)); price = FixedPointMath.divuu(reserveWeth, reserveToken); } function quoteTokenUniswapV3(address token) internal returns (uint128) { uint16[3] memory feeTiers = [500, 3000, 10000]; IUniswapV3Pool pool; for (uint256 i = 0; i < feeTiers.length; ++i) { // Get the pool IUniswapV3Pool pair = IUniswapV3Pool(IUniswapV3Factory(UNISWAP_V3_FACTORY).getPool(token, WETH, feeTiers[i])); if (address(pool) != ADDRESS_ZERO) { pool = pair; break; } } if (address(pool) == ADDRESS_ZERO) { return 0; } // Get slot 0 sqrtPriceX96 uint160 sqrtPriceX96; try pool.slot0() returns (uint160 _sqrtPriceX96, int24, uint16, uint16, uint16, uint8, bool) { sqrtPriceX96 = _sqrtPriceX96; } catch { return 0; } bool token0IsReserve0 = token < WETH; (uint8 tokenDecimals, bool token0DecimalsSuccess) = getTokenDecimalsUnsafe(token); if (!token0DecimalsSuccess) { return 0; } // Q128 -> Q64 return uint128( FixedPointMath.fromSqrtX96( sqrtPriceX96, token0IsReserve0, token0IsReserve0 ? int8(tokenDecimals) : int8(WETH_DECIMALS), token0IsReserve0 ? int8(WETH_DECIMALS) : int8(tokenDecimals) ) >> 64 ); } /// @notice returns true as the second return value if the token decimals can be successfully retrieved function getTokenDecimalsUnsafe(address token) internal returns (uint8, bool) { (bool tokenDecimalsSuccess, bytes memory tokenDecimalsData) = token.call{gas: 20000}(abi.encodeWithSignature("decimals()")); if (tokenDecimalsSuccess) { uint256 tokenDecimals; if (tokenDecimalsData.length == 32) { (tokenDecimals) = abi.decode(tokenDecimalsData, (uint256)); if (tokenDecimals == 0 || tokenDecimals > 255) { return (0, false); } else { return (uint8(tokenDecimals), true); } } else { return (0, false); } } else { return (0, false); } } } ================================================ FILE: contracts/src/filters/WethValueInPoolsBatchRequest.sol ================================================ //SPDX-License-Identifier: MIT pragma solidity ^0.8.26; import "./WethValueInPools.sol"; contract WethValueInPoolsBatchRequest is WethValueInPools { constructor( address _uniswapV2Factory, address _uniswapV3Factory, address _weth, WethValueInPools.PoolInfo[] memory pools ) WethValueInPools(_uniswapV2Factory, _uniswapV3Factory, _weth) { WethValueInPools.PoolInfoReturn[] memory poolInfoReturn = getWethValueInPools(pools); // insure abi encoding, not needed here but increase reusability for different return types // note: abi.encode add a first 32 bytes word with the address of the original data bytes memory abiEncodedData = abi.encode(poolInfoReturn); assembly { // Return from the start of the data (discarding the original data address) // up to the end of the memory used let dataStart := add(abiEncodedData, 0x20) return(dataStart, sub(msize(), dataStart)) } } } ================================================ FILE: contracts/src/interfaces/IBalancer.sol ================================================ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IBPool { function getCurrentTokens() external returns (address[] memory); function getDenormalizedWeight(address token) external returns (uint256); function getSwapFee() external returns (uint256); function getBalance(address token) external returns (uint256); } ================================================ FILE: contracts/src/interfaces/IUniswapV2.sol ================================================ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IUniswapV2Pair { function token0() external view returns (address); function token1() external view returns (address); function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); } interface IUniswapV2Factory { function allPairs(uint256 idx) external returns (address); function getPair(address tokenA, address tokenB) external view returns (address pair); } ================================================ FILE: contracts/src/interfaces/IUniswapV3.sol ================================================ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IUniswapV3Pool { function fee() external view returns (uint24); function tickSpacing() external view returns (int24); function liquidity() external view returns (uint128); function slot0() external view returns ( uint160 sqrtPriceX96, int24 tick, uint16 observationIndex, uint16 observationCardinality, uint16 observationCardinalityNext, uint8 feeProtocol, bool unlocked ); function ticks(int24 tick) external view returns ( uint128 liquidityGross, int128 liquidityNet, uint256 feeGrowthOutside0X128, uint256 feeGrowthOutside1X128, int56 tickCumulativeOutside, uint160 secondsPerLiquidityOutsideX128, uint32 secondsOutside, bool initialized ); } interface IUniswapV3Factory { function getPool(address tokenA, address tokenB, uint24 fee) external view returns (address pool); } ================================================ FILE: contracts/src/interfaces/Token.sol ================================================ //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IERC20 { function decimals() external view returns (uint8); function balanceOf(address) external view returns (uint256); } ================================================ FILE: contracts/test/FixedPoint.t.sol ================================================ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "forge-std/Test.sol"; import "../src/UniswapV3/FixedPoint.sol"; contract FixedPointTest is Test { /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK) uint160 internal constant MIN_SQRT_RATIO = 4295128739; /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK) uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342; function setUp() public {} function test_divuu_never_reverts(uint128 a, uint128 b) public pure { FixedPointMath.divuu(a, b); } function test_mul64u_never_reverts(uint128 a, uint256 b) public pure { FixedPointMath.mul64u(a, b); } function test_from_sqrt_x_96_never_reverts( uint160 x, bool token0IsReserve0, int8 token0Decimals, int8 token1Decimals ) public pure { // Bound x from min_sqrt_x_96 to max_sqrt_x_96 if (x >= MIN_SQRT_RATIO || x <= MAX_SQRT_RATIO) { FixedPointMath.fromSqrtX96(x, token0IsReserve0, token0Decimals, token1Decimals); } } } ================================================ FILE: contracts/test/WethValueInPools.t.sol ================================================ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "forge-std/Test.sol"; import "../src/filters/WethValueInPools.sol"; contract WethValueInPoolsTest is Test { WethValueInPools public wethValueInPools; address uniswapV2Factory = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f; address uniswapV3Factory = 0x1F98431c8aD98523631AE4a59f267346ea31F984; address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; address constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; function setUp() public { wethValueInPools = new WethValueInPools(uniswapV2Factory, uniswapV3Factory, WETH); } function test_getWethValueInPools_validWeth() public { WethValueInPools.PoolInfo[] memory testFixtureValidWeth = new WethValueInPools.PoolInfo[](3); testFixtureValidWeth[0] = WethValueInPools.PoolInfo({ poolType: WethValueInPools.PoolType.Balancer, poolAddress: 0x8a649274E4d777FFC6851F13d23A86BBFA2f2Fbf }); testFixtureValidWeth[1] = WethValueInPools.PoolInfo({ poolType: WethValueInPools.PoolType.UniswapV2, poolAddress: 0x397FF1542f962076d0BFE58eA045FfA2d347ACa0 }); testFixtureValidWeth[2] = WethValueInPools.PoolInfo({ poolType: WethValueInPools.PoolType.UniswapV3, poolAddress: 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640 }); WethValueInPools.PoolInfoReturn[] memory pools = wethValueInPools.getWethValueInPools(testFixtureValidWeth); assertEq(pools.length, 3); // Check weth value > 0 assertGt(pools[0].wethValue, 0); assertGt(pools[1].wethValue, 0); assertGt(pools[2].wethValue, 0); } function test_getWethValueInPools_validNoWeth() public { WethValueInPools.PoolInfo[] memory testFixtureValidNoWeth = new WethValueInPools.PoolInfo[](3); testFixtureValidNoWeth[0] = WethValueInPools.PoolInfo({ poolType: WethValueInPools.PoolType.Balancer, poolAddress: 0xE5D1fAB0C5596ef846DCC0958d6D0b20E1Ec4498 }); testFixtureValidNoWeth[1] = WethValueInPools.PoolInfo({ poolType: WethValueInPools.PoolType.UniswapV2, poolAddress: 0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5 }); testFixtureValidNoWeth[2] = WethValueInPools.PoolInfo({ poolType: WethValueInPools.PoolType.UniswapV3, poolAddress: 0x6c6Bc977E13Df9b0de53b251522280BB72383700 }); WethValueInPools.PoolInfoReturn[] memory pools = wethValueInPools.getWethValueInPools(testFixtureValidNoWeth); assertEq(pools.length, 3); // Check weth value > 0 assertGt(pools[0].wethValue, 0); assertGt(pools[1].wethValue, 0); assertGt(pools[2].wethValue, 0); } function test_getWethValueInPools_invalid_no_revert() public { WethValueInPools.PoolInfo[] memory testFixtureInvalid = new WethValueInPools.PoolInfo[](3); testFixtureInvalid[0] = WethValueInPools.PoolInfo({ poolType: WethValueInPools.PoolType.Balancer, poolAddress: 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f }); testFixtureInvalid[1] = WethValueInPools.PoolInfo({ poolType: WethValueInPools.PoolType.UniswapV2, poolAddress: 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f }); testFixtureInvalid[2] = WethValueInPools.PoolInfo({ poolType: WethValueInPools.PoolType.UniswapV3, poolAddress: 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f }); WethValueInPools.PoolInfoReturn[] memory pools = wethValueInPools.getWethValueInPools(testFixtureInvalid); assertEq(pools.length, 3); // Should all be zero assertEq(pools[0].wethValue, 0); assertEq(pools[1].wethValue, 0); assertEq(pools[2].wethValue, 0); } } ================================================ FILE: contracts/test/WethValueInPoolsBatchRequest.t.sol ================================================ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "forge-std/Test.sol"; import "../src/filters/WethValueInPoolsBatchRequest.sol"; contract WethValueInPoolsBatchRequestTest is Test { address uniswapV2Factory = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f; address uniswapV3Factory = 0x1F98431c8aD98523631AE4a59f267346ea31F984; address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; address constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; function setUp() public {} function test_WethValueInPoolsBatchRequest_validWeth() public { WethValueInPools.PoolInfo[] memory testFixtureValidWeth = new WethValueInPools.PoolInfo[](3); testFixtureValidWeth[0] = WethValueInPools.PoolInfo({ poolType: WethValueInPools.PoolType.Balancer, poolAddress: 0x8a649274E4d777FFC6851F13d23A86BBFA2f2Fbf }); testFixtureValidWeth[1] = WethValueInPools.PoolInfo({ poolType: WethValueInPools.PoolType.UniswapV2, poolAddress: 0x397FF1542f962076d0BFE58eA045FfA2d347ACa0 }); testFixtureValidWeth[2] = WethValueInPools.PoolInfo({ poolType: WethValueInPools.PoolType.UniswapV3, poolAddress: 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640 }); bytes memory returnData = address( new WethValueInPoolsBatchRequest(uniswapV2Factory, uniswapV3Factory, WETH, testFixtureValidWeth) ).code; WethValueInPools.PoolInfoReturn[] memory pools = abi.decode(returnData, (WethValueInPools.PoolInfoReturn[])); assertEq(pools.length, 3); // Check weth value > 0 and valid pool address and pool type for (uint256 i = 0; i < pools.length; i++) { assertGt(pools[i].wethValue, 0); assertEq(uint8(pools[i].poolType), uint8(testFixtureValidWeth[i].poolType)); assertEq(pools[i].poolAddress, testFixtureValidWeth[i].poolAddress); } } function test_WethValueInPoolsBatchRequest_validNoWeth() public { WethValueInPools.PoolInfo[] memory testFixtureValidNoWeth = new WethValueInPools.PoolInfo[](3); testFixtureValidNoWeth[0] = WethValueInPools.PoolInfo({ poolType: WethValueInPools.PoolType.Balancer, poolAddress: 0xE5D1fAB0C5596ef846DCC0958d6D0b20E1Ec4498 }); testFixtureValidNoWeth[1] = WethValueInPools.PoolInfo({ poolType: WethValueInPools.PoolType.UniswapV2, poolAddress: 0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5 }); testFixtureValidNoWeth[2] = WethValueInPools.PoolInfo({ poolType: WethValueInPools.PoolType.UniswapV3, poolAddress: 0x6c6Bc977E13Df9b0de53b251522280BB72383700 }); bytes memory returnData = address( new WethValueInPoolsBatchRequest(uniswapV2Factory, uniswapV3Factory, WETH, testFixtureValidNoWeth) ).code; WethValueInPools.PoolInfoReturn[] memory pools = abi.decode(returnData, (WethValueInPools.PoolInfoReturn[])); assertEq(pools.length, 3); // Check weth value > 0 and valid pool address and pool type for (uint256 i = 0; i < pools.length; i++) { assertGt(pools[i].wethValue, 0); assertEq(uint8(pools[i].poolType), uint8(testFixtureValidNoWeth[i].poolType)); assertEq(pools[i].poolAddress, testFixtureValidNoWeth[i].poolAddress); } } function test_WethValueInPoolsBatchRequest_invalid_no_revert() public { WethValueInPools.PoolInfo[] memory testFixtureInvalid = new WethValueInPools.PoolInfo[](3); testFixtureInvalid[0] = WethValueInPools.PoolInfo({ poolType: WethValueInPools.PoolType.Balancer, poolAddress: 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f }); testFixtureInvalid[1] = WethValueInPools.PoolInfo({ poolType: WethValueInPools.PoolType.UniswapV2, poolAddress: 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f }); testFixtureInvalid[2] = WethValueInPools.PoolInfo({ poolType: WethValueInPools.PoolType.UniswapV3, poolAddress: 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f }); bytes memory returnData = address(new WethValueInPoolsBatchRequest(uniswapV2Factory, uniswapV3Factory, WETH, testFixtureInvalid)).code; WethValueInPools.PoolInfoReturn[] memory pools = abi.decode(returnData, (WethValueInPools.PoolInfoReturn[])); assertEq(pools.length, 3); // All weth values should be zero for (uint256 i = 0; i < pools.length; i++) { assertEq(pools[i].wethValue, 0); assertEq(uint8(pools[i].poolType), uint8(testFixtureInvalid[i].poolType)); assertEq(pools[i].poolAddress, testFixtureInvalid[i].poolAddress); } } } ================================================ FILE: dependabot.yml ================================================ version: 2 updates: - package-ecosystem: "cargo" directory: "/" schedule: interval: "monthly" - package-ecosystem: "docker" directory: "/" schedule: interval: "monthly" - package-ecosystem: "github-actions" directory: "/" schedule: interval: "monthly" ================================================ FILE: examples/filters.rs ================================================ use alloy::{ primitives::address, providers::ProviderBuilder, rpc::client::ClientBuilder, transports::layers::{RetryBackoffLayer, ThrottleLayer}, }; use amms::{ amms::uniswap_v2::UniswapV2Factory, state_space::{ filters::whitelist::{PoolWhitelistFilter, TokenWhitelistFilter}, StateSpaceBuilder, }, }; use std::sync::Arc; #[tokio::main] async fn main() -> eyre::Result<()> { tracing_subscriber::fmt::init(); let rpc_endpoint = std::env::var("ETHEREUM_PROVIDER")?; let client = ClientBuilder::default() .layer(ThrottleLayer::new(500)) .layer(RetryBackoffLayer::new(5, 200, 330)) .http(rpc_endpoint.parse()?); let provider = Arc::new(ProviderBuilder::new().connect_client(client)); let factories = vec![ // UniswapV2 UniswapV2Factory::new( address!("5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f"), 300, 10000835, ) .into(), ]; /* PoolFilters are applied all AMMs when syncing the state space. Filters have two "stages", `FilterStage::Discovery` or `FilterStage::Sync`. Discovery filters are applied to AMMs after the `StateSpaceManager` has processed all pool created events. Sync filters are applied to AMMs after the `StateSpaceManager` has processed all pool sync events. This allows for efficient syncing of the state space by minimizing the amount of pools that need to sync state. In the following example, the `PoolWhitelistFilter` is applied to the `Discovery` stage and the `TokenWhitelistFilter` is applied to the `Sync` stage. Rather than syncing all pools from the factory, only the whitelisted pools are synced. The `TokenWhitelistFilter` is applied after syncing since pool creation logs do not always emit the tokens included in the pool, but this data will always be populated after syncing. */ let filters = vec![ PoolWhitelistFilter::new(vec![address!("88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640")]).into(), TokenWhitelistFilter::new(vec![address!("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48")]) .into(), ]; let _state_space_manager = StateSpaceBuilder::new(provider.clone()) .with_factories(factories) .with_filters(filters) .sync() .await; Ok(()) } ================================================ FILE: examples/simulate_swap.rs ================================================ use alloy::eips::BlockId; use alloy::primitives::{Address, U256}; use alloy::transports::layers::ThrottleLayer; use alloy::{ primitives::address, providers::ProviderBuilder, rpc::client::ClientBuilder, transports::layers::RetryBackoffLayer, }; use amms::amms::amm::AutomatedMarketMaker; use amms::amms::uniswap_v3::UniswapV3Pool; use std::sync::Arc; #[tokio::main] async fn main() -> eyre::Result<()> { let rpc_endpoint = std::env::var("ETHEREUM_PROVIDER")?; let client = ClientBuilder::default() .layer(ThrottleLayer::new(50)) .layer(RetryBackoffLayer::new(5, 200, 330)) .http(rpc_endpoint.parse()?); let provider = Arc::new(ProviderBuilder::new().connect_client(client)); let pool = UniswapV3Pool::new(address!("88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640")) .init(BlockId::latest(), provider) .await?; // Note that the token out does not need to be specified when // simulating a swap for pools with only two tokens. let amount_out = pool.simulate_swap( pool.token_a.address, Address::default(), U256::from(1000000), )?; println!("Amount out: {:?}", amount_out); Ok(()) } ================================================ FILE: examples/state_space_builder.rs ================================================ use std::sync::Arc; use alloy::{ primitives::address, providers::ProviderBuilder, rpc::client::ClientBuilder, transports::layers::{RetryBackoffLayer, ThrottleLayer}, }; use amms::{ amms::{ erc_4626::ERC4626Vault, uniswap_v2::{UniswapV2Factory, UniswapV2Pool}, uniswap_v3::{UniswapV3Factory, UniswapV3Pool}, }, state_space::StateSpaceBuilder, }; #[tokio::main] async fn main() -> eyre::Result<()> { tracing_subscriber::fmt::init(); let rpc_endpoint = std::env::var("ETHEREUM_PROVIDER")?; let client = ClientBuilder::default() .layer(ThrottleLayer::new(500)) .layer(RetryBackoffLayer::new(5, 200, 330)) .http(rpc_endpoint.parse()?); let provider = Arc::new(ProviderBuilder::new().connect_client(client)); /* The `StateSpaceBuilder` is used to sync a state space of AMMs. When specifying a set of factories to sync from, the `sync()` method fetches all pool creation logs from the factory contracts specified and syncs all pools to the latest block. This method returns a `StateSpaceManager` which can be used to subscribe to state changes and interact with AMMs the state space. */ let factories = vec![ // UniswapV2 UniswapV2Factory::new( address!("5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f"), 300, 10000835, ) .into(), // UniswapV3 UniswapV3Factory::new( address!("1F98431c8aD98523631AE4a59f267346ea31F984"), 12369621, ) .into(), ]; let _state_space_manager = StateSpaceBuilder::new(provider.clone()) .with_factories(factories.clone()) .sync() .await?; // ======================================================================================== // /* You can also sync pools directly without specifying factories. This is great for when you only need to track a handful of specific pools. */ let amms = vec![ UniswapV2Pool::new(address!("B4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc"), 300).into(), UniswapV3Pool::new(address!("88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640")).into(), ]; let _state_space_manager = StateSpaceBuilder::new(provider.clone()) .with_amms(amms) .sync() .await?; // ======================================================================================== // /* Additionally, you can specify specific factories to discover and sync pools from, as well as specify specific AMMs to sync. This can be helpful when there isnt a factory for a given AMM as is the case with ERC4626 vaults. */ let amms = vec![ERC4626Vault::new(address!("163538E22F4d38c1eb21B79939f3d2ee274198Ff")).into()]; let _state_space_manager = StateSpaceBuilder::new(provider.clone()) .with_factories(factories) .with_amms(amms) .sync() .await?; Ok(()) } ================================================ FILE: examples/subscribe.rs ================================================ use alloy::{ primitives::address, providers::ProviderBuilder, rpc::client::ClientBuilder, transports::layers::{RetryBackoffLayer, ThrottleLayer}, }; use amms::{amms::uniswap_v2::UniswapV2Factory, state_space::StateSpaceBuilder}; use futures::StreamExt; use std::sync::Arc; #[tokio::main] async fn main() -> eyre::Result<()> { tracing_subscriber::fmt::init(); let rpc_endpoint = std::env::var("ETHEREUM_PROVIDER")?; let client = ClientBuilder::default() .layer(ThrottleLayer::new(500)) .layer(RetryBackoffLayer::new(5, 200, 330)) .http(rpc_endpoint.parse()?); let sync_provider = Arc::new(ProviderBuilder::new().connect_client(client)); let factories = vec![UniswapV2Factory::new( address!("5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f"), 300, 10000835, ) .into()]; let state_space_manager = StateSpaceBuilder::new(sync_provider.clone()) .with_factories(factories) .sync() .await?; /* The subscribe method listens for new blocks and fetches all logs matching any `sync_events()` specified by the AMM variants in the state space. Under the hood, this method applies all state changes to any affected AMMs and returns a Vec of addresses, indicating which AMMs have been updated. */ let mut stream = state_space_manager.subscribe().await?.take(5); while let Some(updated_amms) = stream.next().await { if let Ok(amms) = updated_amms { println!("Updated AMMs: {:?}", amms); } } Ok(()) } ================================================ FILE: examples/swap_calldata.rs ================================================ use alloy::eips::BlockId; use alloy::primitives::U256; use alloy::transports::layers::ThrottleLayer; use alloy::{ primitives::address, providers::ProviderBuilder, rpc::client::ClientBuilder, transports::layers::RetryBackoffLayer, }; use amms::amms::{amm::AutomatedMarketMaker, uniswap_v2::UniswapV2Pool}; use std::sync::Arc; #[tokio::main] async fn main() -> eyre::Result<()> { let rpc_endpoint = std::env::var("ETHEREUM_PROVIDER")?; let client = ClientBuilder::default() .layer(ThrottleLayer::new(500)) .layer(RetryBackoffLayer::new(5, 200, 330)) .http(rpc_endpoint.parse()?); let provider = Arc::new(ProviderBuilder::new().connect_client(client)); let pool = UniswapV2Pool::new(address!("B4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc"), 300) .init(BlockId::latest(), provider) .await?; let to_address = address!("DecafC0ffee15BadDecafC0ffee15BadDecafC0f"); let swap_calldata = pool.swap_calldata(U256::from(10000), U256::ZERO, to_address, vec![]); println!("Swap calldata: {:?}", swap_calldata); Ok(()) } ================================================ FILE: examples/sync_macro.rs ================================================ use std::sync::Arc; use alloy::{ primitives::address, providers::ProviderBuilder, rpc::client::ClientBuilder, transports::layers::{RetryBackoffLayer, ThrottleLayer}, }; use amms::{ amms::{uniswap_v2::UniswapV2Factory, uniswap_v3::UniswapV3Factory}, state_space::{ filters::{ whitelist::{PoolWhitelistFilter, TokenWhitelistFilter}, PoolFilter, }, StateSpaceBuilder, }, sync, }; #[tokio::main] async fn main() -> eyre::Result<()> { tracing_subscriber::fmt::init(); let rpc_endpoint = std::env::var("ETHEREUM_PROVIDER")?; let client = ClientBuilder::default() .layer(ThrottleLayer::new(500)) .layer(RetryBackoffLayer::new(5, 200, 330)) .http(rpc_endpoint.parse()?); let provider = Arc::new(ProviderBuilder::new().connect_client(client)); let factories = vec![ // UniswapV2 UniswapV2Factory::new( address!("5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f"), 300, 10000835, ) .into(), // UniswapV3 UniswapV3Factory::new( address!("1F98431c8aD98523631AE4a59f267346ea31F984"), 12369621, ) .into(), ]; let filters: Vec = vec![ PoolWhitelistFilter::new(vec![address!("88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640")]).into(), TokenWhitelistFilter::new(vec![address!("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48")]) .into(), ]; let _state_space_manager = sync!(factories, filters, provider); Ok(()) } ================================================ FILE: src/amms/abi/GetBalancerPoolDataBatchRequest.json ================================================ {"abi":[{"type":"constructor","inputs":[{"name":"pools","type":"address[]","internalType":"address[]"}],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x608060405234801561000f575f5ffd5b50604051610de8380380610de8833981810160405281019061003191906108d3565b5f815167ffffffffffffffff81111561004d5761004c61073d565b5b60405190808252806020026020018201604052801561008657816020015b6100736106e4565b81526020019060019003908161006b5790505b5090505f5f90505b8251811015610533575f8382815181106100ab576100aa61091a565b5b602002602001015190506100c48161056160201b60201c565b156100cf5750610528565b6100d76106e4565b5f8273ffffffffffffffffffffffffffffffffffffffff1663cc77828d6040518163ffffffff1660e01b81526004015f604051808303815f875af1158015610121573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061014991906108d3565b90505f815167ffffffffffffffff8111156101675761016661073d565b5b6040519080825280602002602001820160405280156101955781602001602082028036833780820191505090505b5090505f825167ffffffffffffffff8111156101b4576101b361073d565b5b6040519080825280602002602001820160405280156101e25781602001602082028036833780820191505090505b5090505f835167ffffffffffffffff8111156102015761020061073d565b5b60405190808252806020026020018201604052801561022f5781602001602082028036833780820191505090505b5090505f5f90505b8451811015610275576102698582815181106102565761025561091a565b5b602002602001015161056160201b60201c565b50806001019050610237565b505f5f90505b8451811015610459575f6102ae86838151811061029b5761029a61091a565b5b602002602001015161059260201b60201c565b90505f8160ff16036102c0575061044e565b808583815181106102d4576102d361091a565b5b602002602001019060ff16908160ff16815250508773ffffffffffffffffffffffffffffffffffffffff1663948d8ce68784815181106103175761031661091a565b5b60200260200101516040518263ffffffff1660e01b815260040161033b9190610956565b6020604051808303815f875af1158015610357573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061037b91906109a2565b83838151811061038e5761038d61091a565b5b6020026020010181815250508773ffffffffffffffffffffffffffffffffffffffff1663f8b2cb4f8784815181106103c9576103c861091a565b5b60200260200101516040518263ffffffff1660e01b81526004016103ed9190610956565b6020604051808303815f875af1158015610409573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061042d91906109a2565b8483815181106104405761043f61091a565b5b602002602001018181525050505b80600101905061027b565b508573ffffffffffffffffffffffffffffffffffffffff1663d4cadf686040518163ffffffff1660e01b81526004016020604051808303815f875af11580156104a4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104c891906109a2565b856080019063ffffffff16908163ffffffff168152505083855f0181905250828560200181905250818560400181905250808560600181905250848888815181106105165761051561091a565b5b60200260200101819052505050505050505b80600101905061008e565b505f816040516020016105469190610d5f565b60405160208183030381529060405290506020810180590381f35b5f5f8273ffffffffffffffffffffffffffffffffffffffff163b03610589576001905061058d565b5f90505b919050565b5f5f5f8373ffffffffffffffffffffffffffffffffffffffff166040516024016040516020818303038152906040527f313ce567000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161063c9190610dd1565b5f604051808303815f865af19150503d805f8114610675576040519150601f19603f3d011682016040523d82523d5f602084013e61067a565b606091505b509150915081156106d9575f60208251036106ce57818060200190518101906106a391906109a2565b90505f8114806106b3575060ff81115b156106c3575f93505050506106df565b8093505050506106df565b5f93505050506106df565b5f925050505b919050565b6040518060a00160405280606081526020016060815260200160608152602001606081526020015f63ffffffff1681525090565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6107738261072d565b810181811067ffffffffffffffff821117156107925761079161073d565b5b80604052505050565b5f6107a4610718565b90506107b0828261076a565b919050565b5f67ffffffffffffffff8211156107cf576107ce61073d565b5b602082029050602081019050919050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61080d826107e4565b9050919050565b61081d81610803565b8114610827575f5ffd5b50565b5f8151905061083881610814565b92915050565b5f61085061084b846107b5565b61079b565b90508083825260208201905060208402830185811115610873576108726107e0565b5b835b8181101561089c5780610888888261082a565b845260208401935050602081019050610875565b5050509392505050565b5f82601f8301126108ba576108b9610729565b5b81516108ca84826020860161083e565b91505092915050565b5f602082840312156108e8576108e7610721565b5b5f82015167ffffffffffffffff81111561090557610904610725565b5b610911848285016108a6565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b61095081610803565b82525050565b5f6020820190506109695f830184610947565b92915050565b5f819050919050565b6109818161096f565b811461098b575f5ffd5b50565b5f8151905061099c81610978565b92915050565b5f602082840312156109b7576109b6610721565b5b5f6109c48482850161098e565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b610a2881610803565b82525050565b5f610a398383610a1f565b60208301905092915050565b5f602082019050919050565b5f610a5b826109f6565b610a658185610a00565b9350610a7083610a10565b805f5b83811015610aa0578151610a878882610a2e565b9750610a9283610a45565b925050600181019050610a73565b5085935050505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f60ff82169050919050565b610aeb81610ad6565b82525050565b5f610afc8383610ae2565b60208301905092915050565b5f602082019050919050565b5f610b1e82610aad565b610b288185610ab7565b9350610b3383610ac7565b805f5b83811015610b63578151610b4a8882610af1565b9750610b5583610b08565b925050600181019050610b36565b5085935050505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b610ba28161096f565b82525050565b5f610bb38383610b99565b60208301905092915050565b5f602082019050919050565b5f610bd582610b70565b610bdf8185610b7a565b9350610bea83610b8a565b805f5b83811015610c1a578151610c018882610ba8565b9750610c0c83610bbf565b925050600181019050610bed565b5085935050505092915050565b5f63ffffffff82169050919050565b610c3f81610c27565b82525050565b5f60a083015f8301518482035f860152610c5f8282610a51565b91505060208301518482036020860152610c798282610b14565b91505060408301518482036040860152610c938282610bcb565b91505060608301518482036060860152610cad8282610bcb565b9150506080830151610cc26080860182610c36565b508091505092915050565b5f610cd88383610c45565b905092915050565b5f602082019050919050565b5f610cf6826109cd565b610d0081856109d7565b935083602082028501610d12856109e7565b805f5b85811015610d4d5784840389528151610d2e8582610ccd565b9450610d3983610ce0565b925060208a01995050600181019050610d15565b50829750879550505050505092915050565b5f6020820190508181035f830152610d778184610cec565b905092915050565b5f81519050919050565b5f81905092915050565b8281835e5f83830152505050565b5f610dab82610d7f565b610db58185610d89565b9350610dc5818560208601610d93565b80840191505092915050565b5f610ddc8284610da1565b91508190509291505056fe","sourceMap":"550:3022:23:-:0;;;754:1990;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;800:29;847:5;:12;832:28;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;800:60;;876:9;888:1;876:13;;871:1526;895:5;:12;891:1;:16;871:1526;;;928:19;950:5;956:1;950:8;;;;;;;;:::i;:::-;;;;;;;;928:30;;977:27;992:11;977:14;;;:27;;:::i;:::-;973:41;;;1006:8;;;973:41;1029:24;;:::i;:::-;1098:23;1131:11;1124:36;;;:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1098:64;;1176:23;1214:6;:13;1202:26;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1176:52;;1242:26;1285:6;:13;1271:28;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1242:57;;1313:24;1354:6;:13;1340:28;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1313:55;;1388:9;1400:1;1388:13;;1383:156;1407:6;:13;1403:1;:17;1383:156;;;1449:25;1464:6;1471:1;1464:9;;;;;;;;:::i;:::-;;;;;;;;1449:14;;;:25;;:::i;:::-;1445:80;1422:3;;;;;1383:156;;;;1601:9;1613:1;1601:13;;1596:485;1620:6;:13;1616:1;:17;1596:485;;;1658:19;1680:27;1697:6;1704:1;1697:9;;;;;;;;:::i;:::-;;;;;;;;1680:16;;;:27;;:::i;:::-;1658:49;;1746:1;1729:13;:18;;;1725:147;;1771:8;;;1725:147;1840:13;1826:8;1835:1;1826:11;;;;;;;;:::i;:::-;;;;;;;:27;;;;;;;;;;;1909:11;1902:41;;;1965:6;1972:1;1965:9;;;;;;;;:::i;:::-;;;;;;;;1902:90;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1889:7;1897:1;1889:10;;;;;;;;:::i;:::-;;;;;;;:103;;;;;2032:11;2025:30;;;2056:6;2063:1;2056:9;;;;;;;;:::i;:::-;;;;;;;;2025:41;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2010:9;2020:1;2010:12;;;;;;;;:::i;:::-;;;;;;;:56;;;;;1640:441;1596:485;1635:3;;;;;1596:485;;;;2157:11;2150:30;;;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2128:8;:12;;:55;;;;;;;;;;;2215:6;2197:8;:15;;:24;;;;2255:8;2235;:17;;:28;;;;2298:9;2277:8;:18;;:30;;;;2340:7;2321:8;:16;;:26;;;;2378:8;2361:11;2373:1;2361:14;;;;;;;;:::i;:::-;;;;;;;:25;;;;914:1483;;;;;;871:1526;909:3;;;;;871:1526;;;;2407:28;2449:11;2438:23;;;;;;;;:::i;:::-;;;;;;;;;;;;;2407:54;;2668:4;2651:15;2647:26;2717:9;2708:7;2704:23;2693:9;2686:42;3377:193;3440:4;3482:1;3460:6;:18;;;:23;3456:108;;3506:4;3499:11;;;;3456:108;3548:5;3541:12;;3377:193;;;;:::o;2750:621::-;2809:5;2827:12;2841:17;2862:5;:10;;2886:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2862:71;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2826:107;;;;2948:7;2944:421;;;2971:16;3020:2;3005:4;:11;:17;3001:315;;3066:4;3055:27;;;;;;;;;;;;:::i;:::-;3042:40;;3116:1;3104:8;:13;:31;;;;3132:3;3121:8;:14;3104:31;3100:155;;;3166:1;3159:8;;;;;;;3100:155;3227:8;3214:22;;;;;;;3001:315;3300:1;3293:8;;;;;;;2944:421;3353:1;3346:8;;;;2750:621;;;;:::o;550:3022::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;7:75:41:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:117;443:1;440;433:12;457:102;498:6;549:2;545:7;540:2;533:5;529:14;525:28;515:38;;457:102;;;:::o;565:180::-;613:77;610:1;603:88;710:4;707:1;700:15;734:4;731:1;724:15;751:281;834:27;856:4;834:27;:::i;:::-;826:6;822:40;964:6;952:10;949:22;928:18;916:10;913:34;910:62;907:88;;;975:18;;:::i;:::-;907:88;1015:10;1011:2;1004:22;794:238;751:281;;:::o;1038:129::-;1072:6;1099:20;;:::i;:::-;1089:30;;1128:33;1156:4;1148:6;1128:33;:::i;:::-;1038:129;;;:::o;1173:311::-;1250:4;1340:18;1332:6;1329:30;1326:56;;;1362:18;;:::i;:::-;1326:56;1412:4;1404:6;1400:17;1392:25;;1472:4;1466;1462:15;1454:23;;1173:311;;;:::o;1490:117::-;1599:1;1596;1589:12;1613:126;1650:7;1690:42;1683:5;1679:54;1668:65;;1613:126;;;:::o;1745:96::-;1782:7;1811:24;1829:5;1811:24;:::i;:::-;1800:35;;1745:96;;;:::o;1847:122::-;1920:24;1938:5;1920:24;:::i;:::-;1913:5;1910:35;1900:63;;1959:1;1956;1949:12;1900:63;1847:122;:::o;1975:143::-;2032:5;2063:6;2057:13;2048:22;;2079:33;2106:5;2079:33;:::i;:::-;1975:143;;;;:::o;2141:732::-;2248:5;2273:81;2289:64;2346:6;2289:64;:::i;:::-;2273:81;:::i;:::-;2264:90;;2374:5;2403:6;2396:5;2389:21;2437:4;2430:5;2426:16;2419:23;;2490:4;2482:6;2478:17;2470:6;2466:30;2519:3;2511:6;2508:15;2505:122;;;2538:79;;:::i;:::-;2505:122;2653:6;2636:231;2670:6;2665:3;2662:15;2636:231;;;2745:3;2774:48;2818:3;2806:10;2774:48;:::i;:::-;2769:3;2762:61;2852:4;2847:3;2843:14;2836:21;;2712:155;2696:4;2691:3;2687:14;2680:21;;2636:231;;;2640:21;2254:619;;2141:732;;;;;:::o;2896:385::-;2978:5;3027:3;3020:4;3012:6;3008:17;3004:27;2994:122;;3035:79;;:::i;:::-;2994:122;3145:6;3139:13;3170:105;3271:3;3263:6;3256:4;3248:6;3244:17;3170:105;:::i;:::-;3161:114;;2984:297;2896:385;;;;:::o;3287:554::-;3382:6;3431:2;3419:9;3410:7;3406:23;3402:32;3399:119;;;3437:79;;:::i;:::-;3399:119;3578:1;3567:9;3563:17;3557:24;3608:18;3600:6;3597:30;3594:117;;;3630:79;;:::i;:::-;3594:117;3735:89;3816:7;3807:6;3796:9;3792:22;3735:89;:::i;:::-;3725:99;;3528:306;3287:554;;;;:::o;3847:180::-;3895:77;3892:1;3885:88;3992:4;3989:1;3982:15;4016:4;4013:1;4006:15;4033:118;4120:24;4138:5;4120:24;:::i;:::-;4115:3;4108:37;4033:118;;:::o;4157:222::-;4250:4;4288:2;4277:9;4273:18;4265:26;;4301:71;4369:1;4358:9;4354:17;4345:6;4301:71;:::i;:::-;4157:222;;;;:::o;4385:77::-;4422:7;4451:5;4440:16;;4385:77;;;:::o;4468:122::-;4541:24;4559:5;4541:24;:::i;:::-;4534:5;4531:35;4521:63;;4580:1;4577;4570:12;4521:63;4468:122;:::o;4596:143::-;4653:5;4684:6;4678:13;4669:22;;4700:33;4727:5;4700:33;:::i;:::-;4596:143;;;;:::o;4745:351::-;4815:6;4864:2;4852:9;4843:7;4839:23;4835:32;4832:119;;;4870:79;;:::i;:::-;4832:119;4990:1;5015:64;5071:7;5062:6;5051:9;5047:22;5015:64;:::i;:::-;5005:74;;4961:128;4745:351;;;;:::o;5102:141::-;5196:6;5230:5;5224:12;5214:22;;5102:141;;;:::o;5249:211::-;5375:11;5409:6;5404:3;5397:19;5449:4;5444:3;5440:14;5425:29;;5249:211;;;;:::o;5466:159::-;5560:4;5583:3;5575:11;;5613:4;5608:3;5604:14;5596:22;;5466:159;;;:::o;5631:114::-;5698:6;5732:5;5726:12;5716:22;;5631:114;;;:::o;5751:174::-;5840:11;5874:6;5869:3;5862:19;5914:4;5909:3;5905:14;5890:29;;5751:174;;;;:::o;5931:132::-;5998:4;6021:3;6013:11;;6051:4;6046:3;6042:14;6034:22;;5931:132;;;:::o;6069:108::-;6146:24;6164:5;6146:24;:::i;:::-;6141:3;6134:37;6069:108;;:::o;6183:179::-;6252:10;6273:46;6315:3;6307:6;6273:46;:::i;:::-;6351:4;6346:3;6342:14;6328:28;;6183:179;;;;:::o;6368:113::-;6438:4;6470;6465:3;6461:14;6453:22;;6368:113;;;:::o;6517:712::-;6626:3;6655:54;6703:5;6655:54;:::i;:::-;6725:76;6794:6;6789:3;6725:76;:::i;:::-;6718:83;;6825:56;6875:5;6825:56;:::i;:::-;6904:7;6935:1;6920:284;6945:6;6942:1;6939:13;6920:284;;;7021:6;7015:13;7048:63;7107:3;7092:13;7048:63;:::i;:::-;7041:70;;7134:60;7187:6;7134:60;:::i;:::-;7124:70;;6980:224;6967:1;6964;6960:9;6955:14;;6920:284;;;6924:14;7220:3;7213:10;;6631:598;;;6517:712;;;;:::o;7235:112::-;7300:6;7334:5;7328:12;7318:22;;7235:112;;;:::o;7353:172::-;7440:11;7474:6;7469:3;7462:19;7514:4;7509:3;7505:14;7490:29;;7353:172;;;;:::o;7531:130::-;7596:4;7619:3;7611:11;;7649:4;7644:3;7640:14;7632:22;;7531:130;;;:::o;7667:86::-;7702:7;7742:4;7735:5;7731:16;7720:27;;7667:86;;;:::o;7759:102::-;7832:22;7848:5;7832:22;:::i;:::-;7827:3;7820:35;7759:102;;:::o;7867:171::-;7932:10;7953:42;7991:3;7983:6;7953:42;:::i;:::-;8027:4;8022:3;8018:14;8004:28;;7867:171;;;;:::o;8044:111::-;8112:4;8144;8139:3;8135:14;8127:22;;8044:111;;;:::o;8187:696::-;8292:3;8321:52;8367:5;8321:52;:::i;:::-;8389:74;8456:6;8451:3;8389:74;:::i;:::-;8382:81;;8487:54;8535:5;8487:54;:::i;:::-;8564:7;8595:1;8580:278;8605:6;8602:1;8599:13;8580:278;;;8681:6;8675:13;8708:59;8763:3;8748:13;8708:59;:::i;:::-;8701:66;;8790:58;8841:6;8790:58;:::i;:::-;8780:68;;8640:218;8627:1;8624;8620:9;8615:14;;8580:278;;;8584:14;8874:3;8867:10;;8297:586;;;8187:696;;;;:::o;8889:114::-;8956:6;8990:5;8984:12;8974:22;;8889:114;;;:::o;9009:174::-;9098:11;9132:6;9127:3;9120:19;9172:4;9167:3;9163:14;9148:29;;9009:174;;;;:::o;9189:132::-;9256:4;9279:3;9271:11;;9309:4;9304:3;9300:14;9292:22;;9189:132;;;:::o;9327:108::-;9404:24;9422:5;9404:24;:::i;:::-;9399:3;9392:37;9327:108;;:::o;9441:179::-;9510:10;9531:46;9573:3;9565:6;9531:46;:::i;:::-;9609:4;9604:3;9600:14;9586:28;;9441:179;;;;:::o;9626:113::-;9696:4;9728;9723:3;9719:14;9711:22;;9626:113;;;:::o;9775:712::-;9884:3;9913:54;9961:5;9913:54;:::i;:::-;9983:76;10052:6;10047:3;9983:76;:::i;:::-;9976:83;;10083:56;10133:5;10083:56;:::i;:::-;10162:7;10193:1;10178:284;10203:6;10200:1;10197:13;10178:284;;;10279:6;10273:13;10306:63;10365:3;10350:13;10306:63;:::i;:::-;10299:70;;10392:60;10445:6;10392:60;:::i;:::-;10382:70;;10238:224;10225:1;10222;10218:9;10213:14;;10178:284;;;10182:14;10478:3;10471:10;;9889:598;;;9775:712;;;;:::o;10493:93::-;10529:7;10569:10;10562:5;10558:22;10547:33;;10493:93;;;:::o;10592:105::-;10667:23;10684:5;10667:23;:::i;:::-;10662:3;10655:36;10592:105;;:::o;10809:1462::-;10922:3;10958:4;10953:3;10949:14;11047:4;11040:5;11036:16;11030:23;11100:3;11094:4;11090:14;11083:4;11078:3;11074:14;11067:38;11126:103;11224:4;11210:12;11126:103;:::i;:::-;11118:111;;10973:267;11326:4;11319:5;11315:16;11309:23;11379:3;11373:4;11369:14;11362:4;11357:3;11353:14;11346:38;11405:99;11499:4;11485:12;11405:99;:::i;:::-;11397:107;;11250:265;11602:4;11595:5;11591:16;11585:23;11655:3;11649:4;11645:14;11638:4;11633:3;11629:14;11622:38;11681:103;11779:4;11765:12;11681:103;:::i;:::-;11673:111;;11525:270;11880:4;11873:5;11869:16;11863:23;11933:3;11927:4;11923:14;11916:4;11911:3;11907:14;11900:38;11959:103;12057:4;12043:12;11959:103;:::i;:::-;11951:111;;11805:268;12154:4;12147:5;12143:16;12137:23;12173:61;12228:4;12223:3;12219:14;12205:12;12173:61;:::i;:::-;12083:161;12261:4;12254:11;;10927:1344;10809:1462;;;;:::o;12277:264::-;12400:10;12435:100;12531:3;12523:6;12435:100;:::i;:::-;12421:114;;12277:264;;;;:::o;12547:140::-;12644:4;12676;12671:3;12667:14;12659:22;;12547:140;;;:::o;12803:1127::-;12976:3;13005:81;13080:5;13005:81;:::i;:::-;13102:113;13208:6;13203:3;13102:113;:::i;:::-;13095:120;;13241:3;13286:4;13278:6;13274:17;13269:3;13265:27;13316:83;13393:5;13316:83;:::i;:::-;13422:7;13453:1;13438:447;13463:6;13460:1;13457:13;13438:447;;;13534:9;13528:4;13524:20;13519:3;13512:33;13585:6;13579:13;13613:118;13726:4;13711:13;13613:118;:::i;:::-;13605:126;;13754:87;13834:6;13754:87;:::i;:::-;13744:97;;13870:4;13865:3;13861:14;13854:21;;13498:387;13485:1;13482;13478:9;13473:14;;13438:447;;;13442:14;13901:4;13894:11;;13921:3;13914:10;;12981:949;;;;;12803:1127;;;;:::o;13936:481::-;14133:4;14171:2;14160:9;14156:18;14148:26;;14220:9;14214:4;14210:20;14206:1;14195:9;14191:17;14184:47;14248:162;14405:4;14396:6;14248:162;:::i;:::-;14240:170;;13936:481;;;;:::o;14423:98::-;14474:6;14508:5;14502:12;14492:22;;14423:98;;;:::o;14527:147::-;14628:11;14665:3;14650:18;;14527:147;;;;:::o;14680:139::-;14769:6;14764:3;14759;14753:23;14810:1;14801:6;14796:3;14792:16;14785:27;14680:139;;;:::o;14825:386::-;14929:3;14957:38;14989:5;14957:38;:::i;:::-;15011:88;15092:6;15087:3;15011:88;:::i;:::-;15004:95;;15108:65;15166:6;15161:3;15154:4;15147:5;15143:16;15108:65;:::i;:::-;15198:6;15193:3;15189:16;15182:23;;14933:278;14825:386;;;;:::o;15217:271::-;15347:3;15369:93;15458:3;15449:6;15369:93;:::i;:::-;15362:100;;15479:3;15472:10;;15217:271;;;;:::o","linkReferences":{}},"deployedBytecode":{"object":"0x60806040525f5ffdfea164736f6c634300081c000a","sourceMap":"550:3022:23:-:0;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"pools\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}],\"devdoc\":{\"details\":\"This contract is not meant to be deployed. Instead, use a static call with the deployment bytecode as payload.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/Balancer/GetBalancerPoolDataBatchRequest.sol\":\"GetBalancerPoolDataBatchRequest\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":forge-std/=lib/forge-std/src/\"]},\"sources\":{\"src/Balancer/GetBalancerPoolDataBatchRequest.sol\":{\"keccak256\":\"0x3e1577d615b675bc39200e3dc32570558e53b8ea30312a81704e8dce264b98c2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ec97ff172e26f806289c07ec87d0a2416fc4d199b9dee267c65ed42c8a0a327d\",\"dweb:/ipfs/Qmf2VT6PM4HSfQ6vBhffX3DKrBnW7EtF9VWC8NE5SoQgwP\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address[]","name":"pools","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["forge-std/=lib/forge-std/src/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"src/Balancer/GetBalancerPoolDataBatchRequest.sol":"GetBalancerPoolDataBatchRequest"},"evmVersion":"cancun","libraries":{}},"sources":{"src/Balancer/GetBalancerPoolDataBatchRequest.sol":{"keccak256":"0x3e1577d615b675bc39200e3dc32570558e53b8ea30312a81704e8dce264b98c2","urls":["bzz-raw://ec97ff172e26f806289c07ec87d0a2416fc4d199b9dee267c65ed42c8a0a327d","dweb:/ipfs/Qmf2VT6PM4HSfQ6vBhffX3DKrBnW7EtF9VWC8NE5SoQgwP"],"license":"MIT"}},"version":1},"id":23} ================================================ FILE: src/amms/abi/GetERC4626VaultDataBatchRequest.json ================================================ {"abi":[{"type":"constructor","inputs":[{"name":"vaults","type":"address[]","internalType":"address[]"}],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x608060405234801561000f575f5ffd5b5060405161136d38038061136d83398181016040528101906100319190610d7a565b5f815167ffffffffffffffff81111561004d5761004c610be4565b5b60405190808252806020026020018201604052801561008657816020015b610073610b38565b81526020019060019003908161006b5790505b5090505f5f90505b8251811015610ae8575f8382815181106100ab576100aa610dc1565b5b602002602001015190506100c481610b1660201b60201c565b156100cf5750610add565b5f8173ffffffffffffffffffffffffffffffffffffffff166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610119573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061013d9190610dee565b905061014e81610b1660201b60201c565b1561015a575050610add565b5f5f8273ffffffffffffffffffffffffffffffffffffffff16614e206040516024016040516020818303038152906040527f313ce567000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516102069190610e6b565b5f604051808303815f8787f1925050503d805f8114610240576040519150601f19603f3d011682016040523d82523d5f602084013e610245565b606091505b5091509150811580610258575060208151145b156102665750505050610add565b5f8180602001905181019061027b9190610eb4565b90505f81148061028b575060ff81115b1561029a575050505050610add565b6102a2610b38565b85815f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505084816040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508573ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561035a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061037e9190610f15565b816020019060ff16908160ff168152505081816060019060ff16908160ff16815250508573ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103ea573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061040e9190610eb4565b8160800181815250508573ffffffffffffffffffffffffffffffffffffffff166301e1d1146040518163ffffffff1660e01b8152600401602060405180830381865afa158015610460573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104849190610eb4565b8160a00181815250508573ffffffffffffffffffffffffffffffffffffffff1663ef8b30f78260600151600a6104ba919061109c565b60646104c691906110e6565b6040518263ffffffff1660e01b81526004016104e29190611136565b602060405180830381865afa1580156104fd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105219190610eb4565b8673ffffffffffffffffffffffffffffffffffffffff1663c6e6f5928360600151600a61054e919061109c565b606461055a91906110e6565b6040518263ffffffff1660e01b81526004016105769190611136565b602060405180830381865afa158015610591573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105b59190610eb4565b6105bf919061114f565b8160c00181815250508573ffffffffffffffffffffffffffffffffffffffff1663ef8b30f78260600151600a6105f5919061109c565b60c861060191906110e6565b6040518263ffffffff1660e01b815260040161061d9190611136565b602060405180830381865afa158015610638573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061065c9190610eb4565b8673ffffffffffffffffffffffffffffffffffffffff1663c6e6f5928360600151600a610689919061109c565b60c861069591906110e6565b6040518263ffffffff1660e01b81526004016106b19190611136565b602060405180830381865afa1580156106cc573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f09190610eb4565b6106fa919061114f565b8160e00181815250508573ffffffffffffffffffffffffffffffffffffffff1663c6e6f5928260600151600a610730919061109c565b606461073c91906110e6565b6040518263ffffffff1660e01b81526004016107589190611136565b602060405180830381865afa158015610773573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107979190610eb4565b816101000181815250508573ffffffffffffffffffffffffffffffffffffffff16634cdad5068260200151600a6107ce919061109c565b60646107da91906110e6565b6040518263ffffffff1660e01b81526004016107f69190611136565b602060405180830381865afa158015610811573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108359190610eb4565b8673ffffffffffffffffffffffffffffffffffffffff166307a2d13a8360200151600a610862919061109c565b606461086e91906110e6565b6040518263ffffffff1660e01b815260040161088a9190611136565b602060405180830381865afa1580156108a5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108c99190610eb4565b6108d3919061114f565b816101200181815250508573ffffffffffffffffffffffffffffffffffffffff16634cdad5068260200151600a61090a919061109c565b60c861091691906110e6565b6040518263ffffffff1660e01b81526004016109329190611136565b602060405180830381865afa15801561094d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109719190610eb4565b8673ffffffffffffffffffffffffffffffffffffffff166307a2d13a8360200151600a61099e919061109c565b60c86109aa91906110e6565b6040518263ffffffff1660e01b81526004016109c69190611136565b602060405180830381865afa1580156109e1573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a059190610eb4565b610a0f919061114f565b816101400181815250508573ffffffffffffffffffffffffffffffffffffffff166307a2d13a8260200151600a610a46919061109c565b6064610a5291906110e6565b6040518263ffffffff1660e01b8152600401610a6e9190611136565b602060405180830381865afa158015610a89573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610aad9190610eb4565b8161016001818152505080888881518110610acb57610aca610dc1565b5b60200260200101819052505050505050505b80600101905061008e565b505f81604051602001610afb919061134c565b60405160208183030381529060405290506020810180590381f35b5f5f8273ffffffffffffffffffffffffffffffffffffffff163b149050919050565b6040518061018001604052805f73ffffffffffffffffffffffffffffffffffffffff1681526020015f60ff1681526020015f73ffffffffffffffffffffffffffffffffffffffff1681526020015f60ff1681526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b610c1a82610bd4565b810181811067ffffffffffffffff82111715610c3957610c38610be4565b5b80604052505050565b5f610c4b610bbf565b9050610c578282610c11565b919050565b5f67ffffffffffffffff821115610c7657610c75610be4565b5b602082029050602081019050919050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610cb482610c8b565b9050919050565b610cc481610caa565b8114610cce575f5ffd5b50565b5f81519050610cdf81610cbb565b92915050565b5f610cf7610cf284610c5c565b610c42565b90508083825260208201905060208402830185811115610d1a57610d19610c87565b5b835b81811015610d435780610d2f8882610cd1565b845260208401935050602081019050610d1c565b5050509392505050565b5f82601f830112610d6157610d60610bd0565b5b8151610d71848260208601610ce5565b91505092915050565b5f60208284031215610d8f57610d8e610bc8565b5b5f82015167ffffffffffffffff811115610dac57610dab610bcc565b5b610db884828501610d4d565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215610e0357610e02610bc8565b5b5f610e1084828501610cd1565b91505092915050565b5f81519050919050565b5f81905092915050565b8281835e5f83830152505050565b5f610e4582610e19565b610e4f8185610e23565b9350610e5f818560208601610e2d565b80840191505092915050565b5f610e768284610e3b565b915081905092915050565b5f819050919050565b610e9381610e81565b8114610e9d575f5ffd5b50565b5f81519050610eae81610e8a565b92915050565b5f60208284031215610ec957610ec8610bc8565b5b5f610ed684828501610ea0565b91505092915050565b5f60ff82169050919050565b610ef481610edf565b8114610efe575f5ffd5b50565b5f81519050610f0f81610eeb565b92915050565b5f60208284031215610f2a57610f29610bc8565b5b5f610f3784828501610f01565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f5f8291508390505b6001851115610fc257808604811115610f9e57610f9d610f40565b5b6001851615610fad5780820291505b8081029050610fbb85610f6d565b9450610f82565b94509492505050565b5f82610fda5760019050611095565b81610fe7575f9050611095565b8160018114610ffd576002811461100757611036565b6001915050611095565b60ff84111561101957611018610f40565b5b8360020a9150848211156110305761102f610f40565b5b50611095565b5060208310610133831016604e8410600b841016171561106b5782820a90508381111561106657611065610f40565b5b611095565b6110788484846001610f79565b9250905081840481111561108f5761108e610f40565b5b81810290505b9392505050565b5f6110a682610e81565b91506110b183610edf565b92506110de7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484610fcb565b905092915050565b5f6110f082610e81565b91506110fb83610e81565b925082820261110981610e81565b915082820484148315176111205761111f610f40565b5b5092915050565b61113081610e81565b82525050565b5f6020820190506111495f830184611127565b92915050565b5f61115982610e81565b915061116483610e81565b925082820390508181111561117c5761117b610f40565b5b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6111b481610caa565b82525050565b6111c381610edf565b82525050565b6111d281610e81565b82525050565b61018082015f8201516111ed5f8501826111ab565b50602082015161120060208501826111ba565b50604082015161121360408501826111ab565b50606082015161122660608501826111ba565b50608082015161123960808501826111c9565b5060a082015161124c60a08501826111c9565b5060c082015161125f60c08501826111c9565b5060e082015161127260e08501826111c9565b506101008201516112876101008501826111c9565b5061012082015161129c6101208501826111c9565b506101408201516112b16101408501826111c9565b506101608201516112c66101608501826111c9565b50505050565b5f6112d783836111d8565b6101808301905092915050565b5f602082019050919050565b5f6112fa82611182565b611304818561118c565b935061130f8361119c565b805f5b8381101561133f57815161132688826112cc565b9750611331836112e4565b925050600181019050611312565b5085935050505092915050565b5f6020820190508181035f83015261136481846112f0565b90509291505056fe","sourceMap":"843:4790:25:-:0;;;1313:4196;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1360:31;1410:6;:13;1394:30;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;1360:64;;1440:9;1452:1;1440:13;;1435:3533;1459:6;:13;1455:1;:17;1435:3533;;;1493:20;1516:6;1523:1;1516:9;;;;;;;;:::i;:::-;;;;;;;;1493:32;;1544:28;1559:12;1544:14;;;:28;;:::i;:::-;1540:42;;;1574:8;;;1540:42;1597:18;1632:12;1618:33;;;:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1597:56;;1742:26;1757:10;1742:14;;;:26;;:::i;:::-;1738:40;;;1770:8;;;;1738:40;1810:30;1858:35;1910:10;:15;;1931:5;1959:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1910:104;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1792:222;;;;2051:25;2050:26;:81;;;;2129:2;2096:22;:29;:35;2050:81;2029:158;;;2164:8;;;;;;2029:158;2201:26;2258:22;2230:91;;;;;;;;;;;;:::i;:::-;2201:120;;2361:1;2339:18;:23;:51;;;;2387:3;2366:18;:24;2339:51;2335:98;;;2410:8;;;;;;;2335:98;2447:26;;:::i;:::-;2537:12;2514:9;:20;;:35;;;;;;;;;;;2586:10;2563:9;:20;;:33;;;;;;;;;;;2696:12;2682:53;;;:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2651:9;:28;;:86;;;;;;;;;;;2828:18;2791:9;:28;;:56;;;;;;;;;;;2940:12;2926:56;;;:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2896:9;:27;;:88;;;;;3042:12;3028:56;;;:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2998:9;:27;;:88;;;;;3386:12;3372:42;;;3448:9;:28;;;3442:2;:34;;;;:::i;:::-;3436:3;:40;;;;:::i;:::-;3372:122;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3244:12;3230:43;;;3307:9;:28;;;3301:2;:34;;;;:::i;:::-;3295:3;:40;;;;:::i;:::-;3230:123;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:264;;;;:::i;:::-;3185:9;:26;;:309;;;;;3764:12;3750:42;;;3826:9;:28;;;3820:2;:34;;;;:::i;:::-;3814:3;:40;;;;:::i;:::-;3750:122;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3622:12;3608:43;;;3685:9;:28;;;3679:2;:34;;;;:::i;:::-;3673:3;:40;;;;:::i;:::-;3608:123;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:264;;;;:::i;:::-;3563:9;:26;;:309;;;;;3926:12;3912:60;;;3985:9;:28;;;3979:2;:34;;;;:::i;:::-;3973:3;:40;;;;:::i;:::-;3912:102;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3887:9;:22;;:127;;;;;4286:12;4272:41;;;4347:9;:28;;;4341:2;:34;;;;:::i;:::-;4335:3;:40;;;;:::i;:::-;4272:121;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4144:12;4130:43;;;4207:9;:28;;;4201:2;:34;;;;:::i;:::-;4195:3;:40;;;;:::i;:::-;4130:123;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:263;;;;:::i;:::-;4084:9;:27;;:309;;;;;4665:12;4651:41;;;4726:9;:28;;;4720:2;:34;;;;:::i;:::-;4714:3;:40;;;;:::i;:::-;4651:121;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4523:12;4509:43;;;4586:9;:28;;;4580:2;:34;;;;:::i;:::-;4574:3;:40;;;;:::i;:::-;4509:123;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:263;;;;:::i;:::-;4463:9;:27;;:309;;;;;4827:12;4813:60;;;4886:9;:28;;;4880:2;:34;;;;:::i;:::-;4874:3;:40;;;;:::i;:::-;4813:102;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4787:9;:23;;:128;;;;;4948:9;4930:12;4943:1;4930:15;;;;;;;;:::i;:::-;;;;;;;:27;;;;1479:3489;;;;;;1435:3533;1474:3;;;;;1435:3533;;;;5170:28;5212:12;5201:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;5170:55;;5433:4;5416:15;5412:26;5482:9;5473:7;5469:23;5458:9;5451:42;5515:116;5578:4;5623:1;5601:6;:18;;;:23;5594:30;;5515:116;;;:::o;843:4790::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;7:75:41:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:117;443:1;440;433:12;457:102;498:6;549:2;545:7;540:2;533:5;529:14;525:28;515:38;;457:102;;;:::o;565:180::-;613:77;610:1;603:88;710:4;707:1;700:15;734:4;731:1;724:15;751:281;834:27;856:4;834:27;:::i;:::-;826:6;822:40;964:6;952:10;949:22;928:18;916:10;913:34;910:62;907:88;;;975:18;;:::i;:::-;907:88;1015:10;1011:2;1004:22;794:238;751:281;;:::o;1038:129::-;1072:6;1099:20;;:::i;:::-;1089:30;;1128:33;1156:4;1148:6;1128:33;:::i;:::-;1038:129;;;:::o;1173:311::-;1250:4;1340:18;1332:6;1329:30;1326:56;;;1362:18;;:::i;:::-;1326:56;1412:4;1404:6;1400:17;1392:25;;1472:4;1466;1462:15;1454:23;;1173:311;;;:::o;1490:117::-;1599:1;1596;1589:12;1613:126;1650:7;1690:42;1683:5;1679:54;1668:65;;1613:126;;;:::o;1745:96::-;1782:7;1811:24;1829:5;1811:24;:::i;:::-;1800:35;;1745:96;;;:::o;1847:122::-;1920:24;1938:5;1920:24;:::i;:::-;1913:5;1910:35;1900:63;;1959:1;1956;1949:12;1900:63;1847:122;:::o;1975:143::-;2032:5;2063:6;2057:13;2048:22;;2079:33;2106:5;2079:33;:::i;:::-;1975:143;;;;:::o;2141:732::-;2248:5;2273:81;2289:64;2346:6;2289:64;:::i;:::-;2273:81;:::i;:::-;2264:90;;2374:5;2403:6;2396:5;2389:21;2437:4;2430:5;2426:16;2419:23;;2490:4;2482:6;2478:17;2470:6;2466:30;2519:3;2511:6;2508:15;2505:122;;;2538:79;;:::i;:::-;2505:122;2653:6;2636:231;2670:6;2665:3;2662:15;2636:231;;;2745:3;2774:48;2818:3;2806:10;2774:48;:::i;:::-;2769:3;2762:61;2852:4;2847:3;2843:14;2836:21;;2712:155;2696:4;2691:3;2687:14;2680:21;;2636:231;;;2640:21;2254:619;;2141:732;;;;;:::o;2896:385::-;2978:5;3027:3;3020:4;3012:6;3008:17;3004:27;2994:122;;3035:79;;:::i;:::-;2994:122;3145:6;3139:13;3170:105;3271:3;3263:6;3256:4;3248:6;3244:17;3170:105;:::i;:::-;3161:114;;2984:297;2896:385;;;;:::o;3287:554::-;3382:6;3431:2;3419:9;3410:7;3406:23;3402:32;3399:119;;;3437:79;;:::i;:::-;3399:119;3578:1;3567:9;3563:17;3557:24;3608:18;3600:6;3597:30;3594:117;;;3630:79;;:::i;:::-;3594:117;3735:89;3816:7;3807:6;3796:9;3792:22;3735:89;:::i;:::-;3725:99;;3528:306;3287:554;;;;:::o;3847:180::-;3895:77;3892:1;3885:88;3992:4;3989:1;3982:15;4016:4;4013:1;4006:15;4033:351;4103:6;4152:2;4140:9;4131:7;4127:23;4123:32;4120:119;;;4158:79;;:::i;:::-;4120:119;4278:1;4303:64;4359:7;4350:6;4339:9;4335:22;4303:64;:::i;:::-;4293:74;;4249:128;4033:351;;;;:::o;4390:98::-;4441:6;4475:5;4469:12;4459:22;;4390:98;;;:::o;4494:147::-;4595:11;4632:3;4617:18;;4494:147;;;;:::o;4647:139::-;4736:6;4731:3;4726;4720:23;4777:1;4768:6;4763:3;4759:16;4752:27;4647:139;;;:::o;4792:386::-;4896:3;4924:38;4956:5;4924:38;:::i;:::-;4978:88;5059:6;5054:3;4978:88;:::i;:::-;4971:95;;5075:65;5133:6;5128:3;5121:4;5114:5;5110:16;5075:65;:::i;:::-;5165:6;5160:3;5156:16;5149:23;;4900:278;4792:386;;;;:::o;5184:271::-;5314:3;5336:93;5425:3;5416:6;5336:93;:::i;:::-;5329:100;;5446:3;5439:10;;5184:271;;;;:::o;5461:77::-;5498:7;5527:5;5516:16;;5461:77;;;:::o;5544:122::-;5617:24;5635:5;5617:24;:::i;:::-;5610:5;5607:35;5597:63;;5656:1;5653;5646:12;5597:63;5544:122;:::o;5672:143::-;5729:5;5760:6;5754:13;5745:22;;5776:33;5803:5;5776:33;:::i;:::-;5672:143;;;;:::o;5821:351::-;5891:6;5940:2;5928:9;5919:7;5915:23;5911:32;5908:119;;;5946:79;;:::i;:::-;5908:119;6066:1;6091:64;6147:7;6138:6;6127:9;6123:22;6091:64;:::i;:::-;6081:74;;6037:128;5821:351;;;;:::o;6178:86::-;6213:7;6253:4;6246:5;6242:16;6231:27;;6178:86;;;:::o;6270:118::-;6341:22;6357:5;6341:22;:::i;:::-;6334:5;6331:33;6321:61;;6378:1;6375;6368:12;6321:61;6270:118;:::o;6394:139::-;6449:5;6480:6;6474:13;6465:22;;6496:31;6521:5;6496:31;:::i;:::-;6394:139;;;;:::o;6539:347::-;6607:6;6656:2;6644:9;6635:7;6631:23;6627:32;6624:119;;;6662:79;;:::i;:::-;6624:119;6782:1;6807:62;6861:7;6852:6;6841:9;6837:22;6807:62;:::i;:::-;6797:72;;6753:126;6539:347;;;;:::o;6892:180::-;6940:77;6937:1;6930:88;7037:4;7034:1;7027:15;7061:4;7058:1;7051:15;7078:102;7120:8;7167:5;7164:1;7160:13;7139:34;;7078:102;;;:::o;7186:848::-;7247:5;7254:4;7278:6;7269:15;;7302:5;7293:14;;7316:712;7337:1;7327:8;7324:15;7316:712;;;7432:4;7427:3;7423:14;7417:4;7414:24;7411:50;;;7441:18;;:::i;:::-;7411:50;7491:1;7481:8;7477:16;7474:451;;;7906:4;7899:5;7895:16;7886:25;;7474:451;7956:4;7950;7946:15;7938:23;;7986:32;8009:8;7986:32;:::i;:::-;7974:44;;7316:712;;;7186:848;;;;;;;:::o;8040:1073::-;8094:5;8285:8;8275:40;;8306:1;8297:10;;8308:5;;8275:40;8334:4;8324:36;;8351:1;8342:10;;8353:5;;8324:36;8420:4;8468:1;8463:27;;;;8504:1;8499:191;;;;8413:277;;8463:27;8481:1;8472:10;;8483:5;;;8499:191;8544:3;8534:8;8531:17;8528:43;;;8551:18;;:::i;:::-;8528:43;8600:8;8597:1;8593:16;8584:25;;8635:3;8628:5;8625:14;8622:40;;;8642:18;;:::i;:::-;8622:40;8675:5;;;8413:277;;8799:2;8789:8;8786:16;8780:3;8774:4;8771:13;8767:36;8749:2;8739:8;8736:16;8731:2;8725:4;8722:12;8718:35;8702:111;8699:246;;;8855:8;8849:4;8845:19;8836:28;;8890:3;8883:5;8880:14;8877:40;;;8897:18;;:::i;:::-;8877:40;8930:5;;8699:246;8970:42;9008:3;8998:8;8992:4;8989:1;8970:42;:::i;:::-;8955:57;;;;9044:4;9039:3;9035:14;9028:5;9025:25;9022:51;;;9053:18;;:::i;:::-;9022:51;9102:4;9095:5;9091:16;9082:25;;8040:1073;;;;;;:::o;9119:281::-;9177:5;9201:23;9219:4;9201:23;:::i;:::-;9193:31;;9245:25;9261:8;9245:25;:::i;:::-;9233:37;;9289:104;9326:66;9316:8;9310:4;9289:104;:::i;:::-;9280:113;;9119:281;;;;:::o;9406:410::-;9446:7;9469:20;9487:1;9469:20;:::i;:::-;9464:25;;9503:20;9521:1;9503:20;:::i;:::-;9498:25;;9558:1;9555;9551:9;9580:30;9598:11;9580:30;:::i;:::-;9569:41;;9759:1;9750:7;9746:15;9743:1;9740:22;9720:1;9713:9;9693:83;9670:139;;9789:18;;:::i;:::-;9670:139;9454:362;9406:410;;;;:::o;9822:118::-;9909:24;9927:5;9909:24;:::i;:::-;9904:3;9897:37;9822:118;;:::o;9946:222::-;10039:4;10077:2;10066:9;10062:18;10054:26;;10090:71;10158:1;10147:9;10143:17;10134:6;10090:71;:::i;:::-;9946:222;;;;:::o;10174:194::-;10214:4;10234:20;10252:1;10234:20;:::i;:::-;10229:25;;10268:20;10286:1;10268:20;:::i;:::-;10263:25;;10312:1;10309;10305:9;10297:17;;10336:1;10330:4;10327:11;10324:37;;;10341:18;;:::i;:::-;10324:37;10174:194;;;;:::o;10374:142::-;10469:6;10503:5;10497:12;10487:22;;10374:142;;;:::o;10522:212::-;10649:11;10683:6;10678:3;10671:19;10723:4;10718:3;10714:14;10699:29;;10522:212;;;;:::o;10740:160::-;10835:4;10858:3;10850:11;;10888:4;10883:3;10879:14;10871:22;;10740:160;;;:::o;10906:108::-;10983:24;11001:5;10983:24;:::i;:::-;10978:3;10971:37;10906:108;;:::o;11020:102::-;11093:22;11109:5;11093:22;:::i;:::-;11088:3;11081:35;11020:102;;:::o;11128:108::-;11205:24;11223:5;11205:24;:::i;:::-;11200:3;11193:37;11128:108;;:::o;11350:2386::-;11493:6;11488:3;11484:16;11588:4;11581:5;11577:16;11571:23;11607:63;11664:4;11659:3;11655:14;11641:12;11607:63;:::i;:::-;11510:170;11776:4;11769:5;11765:16;11759:23;11795:59;11848:4;11843:3;11839:14;11825:12;11795:59;:::i;:::-;11690:174;11952:4;11945:5;11941:16;11935:23;11971:63;12028:4;12023:3;12019:14;12005:12;11971:63;:::i;:::-;11874:170;12140:4;12133:5;12129:16;12123:23;12159:59;12212:4;12207:3;12203:14;12189:12;12159:59;:::i;:::-;12054:174;12323:4;12316:5;12312:16;12306:23;12342:63;12399:4;12394:3;12390:14;12376:12;12342:63;:::i;:::-;12238:177;12510:4;12503:5;12499:16;12493:23;12529:63;12586:4;12581:3;12577:14;12563:12;12529:63;:::i;:::-;12425:177;12696:4;12689:5;12685:16;12679:23;12715:63;12772:4;12767:3;12763:14;12749:12;12715:63;:::i;:::-;12612:176;12882:4;12875:5;12871:16;12865:23;12901:63;12958:4;12953:3;12949:14;12935:12;12901:63;:::i;:::-;12798:176;13064:6;13057:5;13053:18;13047:25;13085:65;13142:6;13137:3;13133:16;13119:12;13085:65;:::i;:::-;12984:176;13255:6;13248:5;13244:18;13238:25;13276:65;13333:6;13328:3;13324:16;13310:12;13276:65;:::i;:::-;13170:181;13446:6;13439:5;13435:18;13429:25;13467:65;13524:6;13519:3;13515:16;13501:12;13467:65;:::i;:::-;13361:181;13633:6;13626:5;13622:18;13616:25;13654:65;13711:6;13706:3;13702:16;13688:12;13654:65;:::i;:::-;13552:177;11462:2274;11350:2386;;:::o;13742:293::-;13867:10;13888:102;13986:3;13978:6;13888:102;:::i;:::-;14022:6;14017:3;14013:16;13999:30;;13742:293;;;;:::o;14041:141::-;14139:4;14171;14166:3;14162:14;14154:22;;14041:141;;;:::o;14300:956::-;14475:3;14504:82;14580:5;14504:82;:::i;:::-;14602:114;14709:6;14704:3;14602:114;:::i;:::-;14595:121;;14740:84;14818:5;14740:84;:::i;:::-;14847:7;14878:1;14863:368;14888:6;14885:1;14882:13;14863:368;;;14964:6;14958:13;14991:119;15106:3;15091:13;14991:119;:::i;:::-;14984:126;;15133:88;15214:6;15133:88;:::i;:::-;15123:98;;14923:308;14910:1;14907;14903:9;14898:14;;14863:368;;;14867:14;15247:3;15240:10;;14480:776;;;14300:956;;;;:::o;15262:485::-;15461:4;15499:2;15488:9;15484:18;15476:26;;15548:9;15542:4;15538:20;15534:1;15523:9;15519:17;15512:47;15576:164;15735:4;15726:6;15576:164;:::i;:::-;15568:172;;15262:485;;;;:::o","linkReferences":{}},"deployedBytecode":{"object":"0x60806040525f5ffdfea164736f6c634300081c000a","sourceMap":"843:4790:25:-:0;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"vaults\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}],\"devdoc\":{\"details\":\"This contract is not meant to be deployed. Instead, use a static call with the deployment bytecode as payload.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/ERC4626/GetERC4626VaultDataBatchRequest.sol\":\"GetERC4626VaultDataBatchRequest\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":forge-std/=lib/forge-std/src/\"]},\"sources\":{\"src/ERC4626/GetERC4626VaultDataBatchRequest.sol\":{\"keccak256\":\"0xb2fe86a5bf7fd8d2b4fc00233e05233fc326c1ff2cb3fa99ba835244d514abd7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f5b3b15b490d325b730f9d8b7dcbec77a7ee58430abfb7f8e830b7c53f3a6ed0\",\"dweb:/ipfs/QmaP3ZqjZymnv7tbVk5Q1Bgamfk9CGB3dboRTfGidV1Qck\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address[]","name":"vaults","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["forge-std/=lib/forge-std/src/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"src/ERC4626/GetERC4626VaultDataBatchRequest.sol":"GetERC4626VaultDataBatchRequest"},"evmVersion":"cancun","libraries":{}},"sources":{"src/ERC4626/GetERC4626VaultDataBatchRequest.sol":{"keccak256":"0xb2fe86a5bf7fd8d2b4fc00233e05233fc326c1ff2cb3fa99ba835244d514abd7","urls":["bzz-raw://f5b3b15b490d325b730f9d8b7dcbec77a7ee58430abfb7f8e830b7c53f3a6ed0","dweb:/ipfs/QmaP3ZqjZymnv7tbVk5Q1Bgamfk9CGB3dboRTfGidV1Qck"],"license":"MIT"}},"version":1},"id":25} ================================================ FILE: src/amms/abi/GetTokenDecimalsBatchRequest.json ================================================ {"abi":[{"type":"constructor","inputs":[{"name":"tokens","type":"address[]","internalType":"address[]"}],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x608060405234801561000f575f5ffd5b5060405161068138038061068183398181016040528101906100319190610463565b5f815167ffffffffffffffff81111561004d5761004c6102cd565b5b60405190808252806020026020018201604052801561007b5781602001602082028036833780820191505090505b5090505f5f90505b8251811015610249575f8382815181106100a05761009f6104aa565b5b602002602001015190506100b98161027760201b60201c565b156100c4575061023e565b5f5f8273ffffffffffffffffffffffffffffffffffffffff16614e206040516024016040516020818303038152906040527f313ce567000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516101709190610529565b5f604051808303815f8787f1925050503d805f81146101aa576040519150601f19603f3d011682016040523d82523d5f602084013e6101af565b606091505b50915091508115610232575f602082510361022357818060200190518101906101d89190610572565b90505f8114806101e8575060ff81115b156101f6575050505061023e565b8086868151811061020a576102096104aa565b5b602002602001019060ff16908160ff168152505061022c565b5050505061023e565b5061023a565b50505061023e565b5050505b806001019050610083565b505f8160405160200161025c9190610660565b60405160208183030381529060405290506020810180590381f35b5f5f8273ffffffffffffffffffffffffffffffffffffffff163b0361029f57600190506102a3565b5f90505b919050565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b610303826102bd565b810181811067ffffffffffffffff82111715610322576103216102cd565b5b80604052505050565b5f6103346102a8565b905061034082826102fa565b919050565b5f67ffffffffffffffff82111561035f5761035e6102cd565b5b602082029050602081019050919050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61039d82610374565b9050919050565b6103ad81610393565b81146103b7575f5ffd5b50565b5f815190506103c8816103a4565b92915050565b5f6103e06103db84610345565b61032b565b9050808382526020820190506020840283018581111561040357610402610370565b5b835b8181101561042c578061041888826103ba565b845260208401935050602081019050610405565b5050509392505050565b5f82601f83011261044a576104496102b9565b5b815161045a8482602086016103ce565b91505092915050565b5f60208284031215610478576104776102b1565b5b5f82015167ffffffffffffffff811115610495576104946102b5565b5b6104a184828501610436565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f81519050919050565b5f81905092915050565b8281835e5f83830152505050565b5f610503826104d7565b61050d81856104e1565b935061051d8185602086016104eb565b80840191505092915050565b5f61053482846104f9565b915081905092915050565b5f819050919050565b6105518161053f565b811461055b575f5ffd5b50565b5f8151905061056c81610548565b92915050565b5f60208284031215610587576105866102b1565b5b5f6105948482850161055e565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f60ff82169050919050565b6105db816105c6565b82525050565b5f6105ec83836105d2565b60208301905092915050565b5f602082019050919050565b5f61060e8261059d565b61061881856105a7565b9350610623836105b7565b805f5b8381101561065357815161063a88826105e1565b9750610645836105f8565b925050600181019050610626565b5085935050505092915050565b5f6020820190508181035f8301526106788184610604565b90509291505056fe","sourceMap":"56:1363:24:-:0;;;100:1317;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;147:23;185:6;:13;173:26;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;147:52;;215:9;227:1;215:13;;210:863;234:6;:13;230:1;:17;210:863;;;268:13;284:6;291:1;284:9;;;;;;;;:::i;:::-;;;;;;;;268:25;;312:21;327:5;312:14;;;:21;;:::i;:::-;308:35;;;335:8;;;308:35;359:25;386:30;420:5;:27;;453:5;460:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;420:78;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;358:140;;;;517:20;513:550;;;557:21;629:2;601:17;:24;:30;597:405;;684:17;673:40;;;;;;;;;;;;:::i;:::-;655:58;;757:1;740:13;:18;:41;;;;778:3;762:13;:19;740:41;736:193;;;809:8;;;;;;736:193;892:13;872:8;881:1;872:11;;;;;;;;:::i;:::-;;;;;;;:34;;;;;;;;;;;597:405;;;975:8;;;;;;597:405;539:477;513:550;;;1040:8;;;;;513:550;254:819;;;210:863;249:3;;;;;210:863;;;;1083:28;1125:8;1114:20;;;;;;;;:::i;:::-;;;;;;;;;;;;;1083:51;;1341:4;1324:15;1320:26;1390:9;1381:7;1377:23;1366:9;1359:42;1421:160;1475:4;1513:1;1491:6;:18;;;:23;1487:92;;1533:4;1526:11;;;;1487:92;1567:5;1560:12;;1421:160;;;;:::o;7:75:41:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:117;443:1;440;433:12;457:102;498:6;549:2;545:7;540:2;533:5;529:14;525:28;515:38;;457:102;;;:::o;565:180::-;613:77;610:1;603:88;710:4;707:1;700:15;734:4;731:1;724:15;751:281;834:27;856:4;834:27;:::i;:::-;826:6;822:40;964:6;952:10;949:22;928:18;916:10;913:34;910:62;907:88;;;975:18;;:::i;:::-;907:88;1015:10;1011:2;1004:22;794:238;751:281;;:::o;1038:129::-;1072:6;1099:20;;:::i;:::-;1089:30;;1128:33;1156:4;1148:6;1128:33;:::i;:::-;1038:129;;;:::o;1173:311::-;1250:4;1340:18;1332:6;1329:30;1326:56;;;1362:18;;:::i;:::-;1326:56;1412:4;1404:6;1400:17;1392:25;;1472:4;1466;1462:15;1454:23;;1173:311;;;:::o;1490:117::-;1599:1;1596;1589:12;1613:126;1650:7;1690:42;1683:5;1679:54;1668:65;;1613:126;;;:::o;1745:96::-;1782:7;1811:24;1829:5;1811:24;:::i;:::-;1800:35;;1745:96;;;:::o;1847:122::-;1920:24;1938:5;1920:24;:::i;:::-;1913:5;1910:35;1900:63;;1959:1;1956;1949:12;1900:63;1847:122;:::o;1975:143::-;2032:5;2063:6;2057:13;2048:22;;2079:33;2106:5;2079:33;:::i;:::-;1975:143;;;;:::o;2141:732::-;2248:5;2273:81;2289:64;2346:6;2289:64;:::i;:::-;2273:81;:::i;:::-;2264:90;;2374:5;2403:6;2396:5;2389:21;2437:4;2430:5;2426:16;2419:23;;2490:4;2482:6;2478:17;2470:6;2466:30;2519:3;2511:6;2508:15;2505:122;;;2538:79;;:::i;:::-;2505:122;2653:6;2636:231;2670:6;2665:3;2662:15;2636:231;;;2745:3;2774:48;2818:3;2806:10;2774:48;:::i;:::-;2769:3;2762:61;2852:4;2847:3;2843:14;2836:21;;2712:155;2696:4;2691:3;2687:14;2680:21;;2636:231;;;2640:21;2254:619;;2141:732;;;;;:::o;2896:385::-;2978:5;3027:3;3020:4;3012:6;3008:17;3004:27;2994:122;;3035:79;;:::i;:::-;2994:122;3145:6;3139:13;3170:105;3271:3;3263:6;3256:4;3248:6;3244:17;3170:105;:::i;:::-;3161:114;;2984:297;2896:385;;;;:::o;3287:554::-;3382:6;3431:2;3419:9;3410:7;3406:23;3402:32;3399:119;;;3437:79;;:::i;:::-;3399:119;3578:1;3567:9;3563:17;3557:24;3608:18;3600:6;3597:30;3594:117;;;3630:79;;:::i;:::-;3594:117;3735:89;3816:7;3807:6;3796:9;3792:22;3735:89;:::i;:::-;3725:99;;3528:306;3287:554;;;;:::o;3847:180::-;3895:77;3892:1;3885:88;3992:4;3989:1;3982:15;4016:4;4013:1;4006:15;4033:98;4084:6;4118:5;4112:12;4102:22;;4033:98;;;:::o;4137:147::-;4238:11;4275:3;4260:18;;4137:147;;;;:::o;4290:139::-;4379:6;4374:3;4369;4363:23;4420:1;4411:6;4406:3;4402:16;4395:27;4290:139;;;:::o;4435:386::-;4539:3;4567:38;4599:5;4567:38;:::i;:::-;4621:88;4702:6;4697:3;4621:88;:::i;:::-;4614:95;;4718:65;4776:6;4771:3;4764:4;4757:5;4753:16;4718:65;:::i;:::-;4808:6;4803:3;4799:16;4792:23;;4543:278;4435:386;;;;:::o;4827:271::-;4957:3;4979:93;5068:3;5059:6;4979:93;:::i;:::-;4972:100;;5089:3;5082:10;;4827:271;;;;:::o;5104:77::-;5141:7;5170:5;5159:16;;5104:77;;;:::o;5187:122::-;5260:24;5278:5;5260:24;:::i;:::-;5253:5;5250:35;5240:63;;5299:1;5296;5289:12;5240:63;5187:122;:::o;5315:143::-;5372:5;5403:6;5397:13;5388:22;;5419:33;5446:5;5419:33;:::i;:::-;5315:143;;;;:::o;5464:351::-;5534:6;5583:2;5571:9;5562:7;5558:23;5554:32;5551:119;;;5589:79;;:::i;:::-;5551:119;5709:1;5734:64;5790:7;5781:6;5770:9;5766:22;5734:64;:::i;:::-;5724:74;;5680:128;5464:351;;;;:::o;5821:112::-;5886:6;5920:5;5914:12;5904:22;;5821:112;;;:::o;5939:182::-;6036:11;6070:6;6065:3;6058:19;6110:4;6105:3;6101:14;6086:29;;5939:182;;;;:::o;6127:130::-;6192:4;6215:3;6207:11;;6245:4;6240:3;6236:14;6228:22;;6127:130;;;:::o;6263:86::-;6298:7;6338:4;6331:5;6327:16;6316:27;;6263:86;;;:::o;6355:102::-;6428:22;6444:5;6428:22;:::i;:::-;6423:3;6416:35;6355:102;;:::o;6463:171::-;6528:10;6549:42;6587:3;6579:6;6549:42;:::i;:::-;6623:4;6618:3;6614:14;6600:28;;6463:171;;;;:::o;6640:111::-;6708:4;6740;6735:3;6731:14;6723:22;;6640:111;;;:::o;6783:716::-;6898:3;6927:52;6973:5;6927:52;:::i;:::-;6995:84;7072:6;7067:3;6995:84;:::i;:::-;6988:91;;7103:54;7151:5;7103:54;:::i;:::-;7180:7;7211:1;7196:278;7221:6;7218:1;7215:13;7196:278;;;7297:6;7291:13;7324:59;7379:3;7364:13;7324:59;:::i;:::-;7317:66;;7406:58;7457:6;7406:58;:::i;:::-;7396:68;;7256:218;7243:1;7240;7236:9;7231:14;;7196:278;;;7200:14;7490:3;7483:10;;6903:596;;;6783:716;;;;:::o;7505:365::-;7644:4;7682:2;7671:9;7667:18;7659:26;;7731:9;7725:4;7721:20;7717:1;7706:9;7702:17;7695:47;7759:104;7858:4;7849:6;7759:104;:::i;:::-;7751:112;;7505:365;;;;:::o","linkReferences":{}},"deployedBytecode":{"object":"0x60806040525f5ffdfea164736f6c634300081c000a","sourceMap":"56:1363:24:-:0;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/ERC20/GetTokenDecimalsBatchRequest.sol\":\"GetTokenDecimalsBatchRequest\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":forge-std/=lib/forge-std/src/\"]},\"sources\":{\"src/ERC20/GetTokenDecimalsBatchRequest.sol\":{\"keccak256\":\"0xc7540761024525cf0d1371c70d9890b2beb0d8e5c996a238139e61541fc36ec5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fa59b893b03692814beb0d442247b028099e8a8582e5b3757bf3e5dd8231ae98\",\"dweb:/ipfs/QmUXeRAb4EAsaLRXCx7rHaJmyDA9dPnKoJbPoBoTWZfTZr\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["forge-std/=lib/forge-std/src/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"src/ERC20/GetTokenDecimalsBatchRequest.sol":"GetTokenDecimalsBatchRequest"},"evmVersion":"cancun","libraries":{}},"sources":{"src/ERC20/GetTokenDecimalsBatchRequest.sol":{"keccak256":"0xc7540761024525cf0d1371c70d9890b2beb0d8e5c996a238139e61541fc36ec5","urls":["bzz-raw://fa59b893b03692814beb0d442247b028099e8a8582e5b3757bf3e5dd8231ae98","dweb:/ipfs/QmUXeRAb4EAsaLRXCx7rHaJmyDA9dPnKoJbPoBoTWZfTZr"],"license":"MIT"}},"version":1},"id":24} ================================================ FILE: src/amms/abi/GetUniswapV2PairsBatchRequest.json ================================================ {"abi":[{"type":"constructor","inputs":[{"name":"from","type":"uint256","internalType":"uint256"},{"name":"step","type":"uint256","internalType":"uint256"},{"name":"factory","type":"address","internalType":"address"}],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x608060405234801561000f575f5ffd5b50604051610550380380610550833981810160405281019061003191906102bd565b5f8173ffffffffffffffffffffffffffffffffffffffff1663574f2ba36040518163ffffffff1660e01b81526004016020604051808303815f875af115801561007c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100a0919061030d565b90508083856100af9190610365565b116100ba57826100c7565b83816100c69190610398565b5b92505f8367ffffffffffffffff8111156100e4576100e36103cb565b5b6040519080825280602002602001820160405280156101125781602001602082028036833780820191505090505b5090505f5f90505b848110156101fe578373ffffffffffffffffffffffffffffffffffffffff16631e3dd18b828861014a9190610365565b6040518263ffffffff1660e01b81526004016101669190610407565b6020604051808303815f875af1158015610182573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101a69190610420565b8282815181106101b9576101b861044b565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505080600101905061011a565b505f81604051602001610211919061052f565b60405160208183030381529060405290506020810180590381f35b5f5ffd5b5f819050919050565b61024281610230565b811461024c575f5ffd5b50565b5f8151905061025d81610239565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61028c82610263565b9050919050565b61029c81610282565b81146102a6575f5ffd5b50565b5f815190506102b781610293565b92915050565b5f5f5f606084860312156102d4576102d361022c565b5b5f6102e18682870161024f565b93505060206102f28682870161024f565b9250506040610303868287016102a9565b9150509250925092565b5f602082840312156103225761032161022c565b5b5f61032f8482850161024f565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61036f82610230565b915061037a83610230565b925082820190508082111561039257610391610338565b5b92915050565b5f6103a282610230565b91506103ad83610230565b92508282039050818111156103c5576103c4610338565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61040181610230565b82525050565b5f60208201905061041a5f8301846103f8565b92915050565b5f602082840312156104355761043461022c565b5b5f610442848285016102a9565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6104aa81610282565b82525050565b5f6104bb83836104a1565b60208301905092915050565b5f602082019050919050565b5f6104dd82610478565b6104e78185610482565b93506104f283610492565b805f5b8381101561052257815161050988826104b0565b9750610514836104c7565b9250506001810190506104f5565b5085935050505092915050565b5f6020820190508181035f83015261054781846104d3565b90509291505056fe","sourceMap":"337:1052:26:-:0;;;382:1005;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;449:22;483:7;474:32;;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;449:59;;540:14;533:4;526;:11;;;;:::i;:::-;:28;:59;;581:4;526:59;;;574:4;557:14;:21;;;;:::i;:::-;526:59;519:66;;682:25;724:4;710:19;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;682:47;;745:9;757:1;745:13;;740:110;764:4;760:1;:8;740:110;;;812:7;803:26;;;837:1;830:4;:8;;;;:::i;:::-;803:36;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;789:8;798:1;789:11;;;;;;;;:::i;:::-;;;;;;;:50;;;;;;;;;;;770:3;;;;;740:110;;;;1052:28;1094:8;1083:20;;;;;;;;:::i;:::-;;;;;;;;;;;;;1052:51;;1311:4;1294:15;1290:26;1360:9;1351:7;1347:23;1336:9;1329:42;88:117:41;197:1;194;187:12;334:77;371:7;400:5;389:16;;334:77;;;:::o;417:122::-;490:24;508:5;490:24;:::i;:::-;483:5;480:35;470:63;;529:1;526;519:12;470:63;417:122;:::o;545:143::-;602:5;633:6;627:13;618:22;;649:33;676:5;649:33;:::i;:::-;545:143;;;;:::o;694:126::-;731:7;771:42;764:5;760:54;749:65;;694:126;;;:::o;826:96::-;863:7;892:24;910:5;892:24;:::i;:::-;881:35;;826:96;;;:::o;928:122::-;1001:24;1019:5;1001:24;:::i;:::-;994:5;991:35;981:63;;1040:1;1037;1030:12;981:63;928:122;:::o;1056:143::-;1113:5;1144:6;1138:13;1129:22;;1160:33;1187:5;1160:33;:::i;:::-;1056:143;;;;:::o;1205:663::-;1293:6;1301;1309;1358:2;1346:9;1337:7;1333:23;1329:32;1326:119;;;1364:79;;:::i;:::-;1326:119;1484:1;1509:64;1565:7;1556:6;1545:9;1541:22;1509:64;:::i;:::-;1499:74;;1455:128;1622:2;1648:64;1704:7;1695:6;1684:9;1680:22;1648:64;:::i;:::-;1638:74;;1593:129;1761:2;1787:64;1843:7;1834:6;1823:9;1819:22;1787:64;:::i;:::-;1777:74;;1732:129;1205:663;;;;;:::o;1874:351::-;1944:6;1993:2;1981:9;1972:7;1968:23;1964:32;1961:119;;;1999:79;;:::i;:::-;1961:119;2119:1;2144:64;2200:7;2191:6;2180:9;2176:22;2144:64;:::i;:::-;2134:74;;2090:128;1874:351;;;;:::o;2231:180::-;2279:77;2276:1;2269:88;2376:4;2373:1;2366:15;2400:4;2397:1;2390:15;2417:191;2457:3;2476:20;2494:1;2476:20;:::i;:::-;2471:25;;2510:20;2528:1;2510:20;:::i;:::-;2505:25;;2553:1;2550;2546:9;2539:16;;2574:3;2571:1;2568:10;2565:36;;;2581:18;;:::i;:::-;2565:36;2417:191;;;;:::o;2614:194::-;2654:4;2674:20;2692:1;2674:20;:::i;:::-;2669:25;;2708:20;2726:1;2708:20;:::i;:::-;2703:25;;2752:1;2749;2745:9;2737:17;;2776:1;2770:4;2767:11;2764:37;;;2781:18;;:::i;:::-;2764:37;2614:194;;;;:::o;2814:180::-;2862:77;2859:1;2852:88;2959:4;2956:1;2949:15;2983:4;2980:1;2973:15;3000:118;3087:24;3105:5;3087:24;:::i;:::-;3082:3;3075:37;3000:118;;:::o;3124:222::-;3217:4;3255:2;3244:9;3240:18;3232:26;;3268:71;3336:1;3325:9;3321:17;3312:6;3268:71;:::i;:::-;3124:222;;;;:::o;3352:351::-;3422:6;3471:2;3459:9;3450:7;3446:23;3442:32;3439:119;;;3477:79;;:::i;:::-;3439:119;3597:1;3622:64;3678:7;3669:6;3658:9;3654:22;3622:64;:::i;:::-;3612:74;;3568:128;3352:351;;;;:::o;3709:180::-;3757:77;3754:1;3747:88;3854:4;3851:1;3844:15;3878:4;3875:1;3868:15;3895:114;3962:6;3996:5;3990:12;3980:22;;3895:114;;;:::o;4015:184::-;4114:11;4148:6;4143:3;4136:19;4188:4;4183:3;4179:14;4164:29;;4015:184;;;;:::o;4205:132::-;4272:4;4295:3;4287:11;;4325:4;4320:3;4316:14;4308:22;;4205:132;;;:::o;4343:108::-;4420:24;4438:5;4420:24;:::i;:::-;4415:3;4408:37;4343:108;;:::o;4457:179::-;4526:10;4547:46;4589:3;4581:6;4547:46;:::i;:::-;4625:4;4620:3;4616:14;4602:28;;4457:179;;;;:::o;4642:113::-;4712:4;4744;4739:3;4735:14;4727:22;;4642:113;;;:::o;4791:732::-;4910:3;4939:54;4987:5;4939:54;:::i;:::-;5009:86;5088:6;5083:3;5009:86;:::i;:::-;5002:93;;5119:56;5169:5;5119:56;:::i;:::-;5198:7;5229:1;5214:284;5239:6;5236:1;5233:13;5214:284;;;5315:6;5309:13;5342:63;5401:3;5386:13;5342:63;:::i;:::-;5335:70;;5428:60;5481:6;5428:60;:::i;:::-;5418:70;;5274:224;5261:1;5258;5254:9;5249:14;;5214:284;;;5218:14;5514:3;5507:10;;4915:608;;;4791:732;;;;:::o;5529:373::-;5672:4;5710:2;5699:9;5695:18;5687:26;;5759:9;5753:4;5749:20;5745:1;5734:9;5730:17;5723:47;5787:108;5890:4;5881:6;5787:108;:::i;:::-;5779:116;;5529:373;;;;:::o","linkReferences":{}},"deployedBytecode":{"object":"0x60806040525f5ffdfea164736f6c634300081c000a","sourceMap":"337:1052:26:-:0;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"from\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"step\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}],\"devdoc\":{\"details\":\"This contract is not meant to be deployed. Instead, use a static call with the deployment bytecode as payload.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/UniswapV2/GetUniswapV2PairsBatchRequest.sol\":\"GetUniswapV2PairsBatchRequest\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":forge-std/=lib/forge-std/src/\"]},\"sources\":{\"src/UniswapV2/GetUniswapV2PairsBatchRequest.sol\":{\"keccak256\":\"0x44d0d290e07e6cc3f6a365f4c907b81419593172a9b47dd1a64e3d2942d20229\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9f90e9388ee75d7b9c82f144e7f440de704bbe058c0287db83db0677f3819707\",\"dweb:/ipfs/QmfP1KFxDHdAFZSNYK9oP2prKypbw5FbqufxFGp3BVPMGB\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"uint256","name":"from","type":"uint256"},{"internalType":"uint256","name":"step","type":"uint256"},{"internalType":"address","name":"factory","type":"address"}],"stateMutability":"nonpayable","type":"constructor"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["forge-std/=lib/forge-std/src/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"src/UniswapV2/GetUniswapV2PairsBatchRequest.sol":"GetUniswapV2PairsBatchRequest"},"evmVersion":"cancun","libraries":{}},"sources":{"src/UniswapV2/GetUniswapV2PairsBatchRequest.sol":{"keccak256":"0x44d0d290e07e6cc3f6a365f4c907b81419593172a9b47dd1a64e3d2942d20229","urls":["bzz-raw://9f90e9388ee75d7b9c82f144e7f440de704bbe058c0287db83db0677f3819707","dweb:/ipfs/QmfP1KFxDHdAFZSNYK9oP2prKypbw5FbqufxFGp3BVPMGB"],"license":"MIT"}},"version":1},"id":26} ================================================ FILE: src/amms/abi/GetUniswapV2PoolDataBatchRequest.json ================================================ { "abi": [ { "type": "constructor", "inputs": [ { "name": "pools", "type": "address[]", "internalType": "address[]" } ], "stateMutability": "nonpayable" } ], "bytecode": { "object": "0x608060405234801561000f575f5ffd5b50604051610c67380380610c67833981810160405281019061003191906108bb565b5f815167ffffffffffffffff81111561004d5761004c610725565b5b60405190808252806020026020018201604052801561008657816020015b61007361067e565b81526020019060019003908161006b5790505b5090505f5f90505b825181101561061f575f8382815181106100ab576100aa610902565b5b602002602001015190506100c48161064d60201b60201c565b156100cf5750610614565b6100d761067e565b8173ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610120573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610144919061092f565b815f019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff1663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101c3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101e7919061092f565b816020019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050610230815f015161064d60201b60201c565b1561023c575050610614565b61024f816020015161064d60201b60201c565b1561025b575050610614565b5f5f825f015173ffffffffffffffffffffffffffffffffffffffff16614e206040516024016040516020818303038152906040527f313ce567000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161030a91906109ac565b5f604051808303815f8787f1925050503d805f8114610344576040519150601f19603f3d011682016040523d82523d5f602084013e610349565b606091505b509150915081156103b8575f60208251036103a8578180602001905181019061037291906109f5565b90505f811480610382575060ff81115b15610391575050505050610614565b80846080019060ff16908160ff16815250506103b2565b5050505050610614565b506103c1565b50505050610614565b5f5f846020015173ffffffffffffffffffffffffffffffffffffffff16614e206040516024016040516020818303038152906040527f313ce567000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161047191906109ac565b5f604051808303815f8787f1925050503d805f81146104ab576040519150601f19603f3d011682016040523d82523d5f602084013e6104b0565b606091505b50915091508115610523575f602082510361051157818060200190518101906104d991906109f5565b90505f8114806104e9575060ff81115b156104fa5750505050505050610614565b808660a0019060ff16908160ff168152505061051d565b50505050505050610614565b5061052e565b505050505050610614565b8573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015610577573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061059b9190610a9c565b508660400187606001826dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff16815250826dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff1681525050508488888151811061060257610601610902565b5b60200260200101819052505050505050505b80600101905061008e565b505f816040516020016106329190610c46565b60405160208183030381529060405290506020810180590381f35b5f5f8273ffffffffffffffffffffffffffffffffffffffff163b036106755760019050610679565b5f90505b919050565b6040518060c001604052805f73ffffffffffffffffffffffffffffffffffffffff1681526020015f73ffffffffffffffffffffffffffffffffffffffff1681526020015f6dffffffffffffffffffffffffffff1681526020015f6dffffffffffffffffffffffffffff1681526020015f60ff1681526020015f60ff1681525090565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61075b82610715565b810181811067ffffffffffffffff8211171561077a57610779610725565b5b80604052505050565b5f61078c610700565b90506107988282610752565b919050565b5f67ffffffffffffffff8211156107b7576107b6610725565b5b602082029050602081019050919050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6107f5826107cc565b9050919050565b610805816107eb565b811461080f575f5ffd5b50565b5f81519050610820816107fc565b92915050565b5f6108386108338461079d565b610783565b9050808382526020820190506020840283018581111561085b5761085a6107c8565b5b835b8181101561088457806108708882610812565b84526020840193505060208101905061085d565b5050509392505050565b5f82601f8301126108a2576108a1610711565b5b81516108b2848260208601610826565b91505092915050565b5f602082840312156108d0576108cf610709565b5b5f82015167ffffffffffffffff8111156108ed576108ec61070d565b5b6108f98482850161088e565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6020828403121561094457610943610709565b5b5f61095184828501610812565b91505092915050565b5f81519050919050565b5f81905092915050565b8281835e5f83830152505050565b5f6109868261095a565b6109908185610964565b93506109a081856020860161096e565b80840191505092915050565b5f6109b7828461097c565b915081905092915050565b5f819050919050565b6109d4816109c2565b81146109de575f5ffd5b50565b5f815190506109ef816109cb565b92915050565b5f60208284031215610a0a57610a09610709565b5b5f610a17848285016109e1565b91505092915050565b5f6dffffffffffffffffffffffffffff82169050919050565b610a4281610a20565b8114610a4c575f5ffd5b50565b5f81519050610a5d81610a39565b92915050565b5f63ffffffff82169050919050565b610a7b81610a63565b8114610a85575f5ffd5b50565b5f81519050610a9681610a72565b92915050565b5f5f5f60608486031215610ab357610ab2610709565b5b5f610ac086828701610a4f565b9350506020610ad186828701610a4f565b9250506040610ae286828701610a88565b9150509250925092565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b610b1e816107eb565b82525050565b610b2d81610a20565b82525050565b5f60ff82169050919050565b610b4881610b33565b82525050565b60c082015f820151610b625f850182610b15565b506020820151610b756020850182610b15565b506040820151610b886040850182610b24565b506060820151610b9b6060850182610b24565b506080820151610bae6080850182610b3f565b5060a0820151610bc160a0850182610b3f565b50505050565b5f610bd28383610b4e565b60c08301905092915050565b5f602082019050919050565b5f610bf482610aec565b610bfe8185610af6565b9350610c0983610b06565b805f5b83811015610c39578151610c208882610bc7565b9750610c2b83610bde565b925050600181019050610c0c565b5085935050505092915050565b5f6020820190508181035f830152610c5e8184610bea565b90509291505056fe", "sourceMap": "549:3691:27:-:0;;;786:3253;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;832:29;879:5;:12;864:28;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;832:60;;908:9;920:1;908:13;;903:2596;927:5;:12;923:1;:16;903:2596;;;960:19;982:5;988:1;982:8;;;;;;;;:::i;:::-;;;;;;;;960:30;;1009:27;1024:11;1009:14;;;:27;;:::i;:::-;1005:41;;;1038:8;;;1005:41;1061:24;;:::i;:::-;1167:11;1152:34;;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1134:8;:15;;:54;;;;;;;;;;;1235:11;1220:34;;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1202:8;:15;;:54;;;;;;;;;;;1345:31;1360:8;:15;;;1345:14;;;:31;;:::i;:::-;1341:45;;;1378:8;;;;1341:45;1404:31;1419:8;:15;;;1404:14;;;:31;;:::i;:::-;1400:45;;;1437:8;;;;1400:45;1513:26;1557:31;1605:8;:15;;;:20;;1631:5;1659:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1605:109;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1495:219;;;;1733:21;1729:640;;;1774:22;1848:2;1819:18;:25;:31;1815:493;;1929:18;1893:111;;;;;;;;;;;;:::i;:::-;1874:130;;2049:1;2031:14;:19;:43;;;;2071:3;2054:14;:20;2031:43;2027:208;;;2102:8;;;;;;;2027:208;2197:14;2165:8;:23;;:47;;;;;;;;;;;1815:493;;;2281:8;;;;;;;1815:493;1756:566;1729:640;;;2346:8;;;;;;1729:640;2436:26;2480:31;2528:8;:15;;;:20;;2554:5;2582:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2528:109;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2418:219;;;;2656:21;2652:640;;;2697:22;2771:2;2742:18;:25;:31;2738:493;;2852:18;2816:111;;;;;;;;;;;;:::i;:::-;2797:130;;2972:1;2954:14;:19;:43;;;;2994:3;2977:14;:20;2954:43;2950:208;;;3025:8;;;;;;;;;2950:208;3120:14;3088:8;:23;;:47;;;;;;;;;;;2738:493;;;3204:8;;;;;;;;;2738:493;2679:566;2652:640;;;3269:8;;;;;;;;2652:640;3409:11;3377:69;;;:71;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3334:114;3335:8;:17;;3354:8;:17;;3334:114;;;;;;;;;;;;;;;;;;3480:8;3463:11;3475:1;3463:14;;;;;;;;:::i;:::-;;;;;;;:25;;;;946:2553;;;;;;903:2596;941:3;;;;;903:2596;;;;3701:28;3743:11;3732:23;;;;;;;;:::i;:::-;;;;;;;;;;;;;3701:54;;3963:4;3946:15;3942:26;4012:9;4003:7;3999:23;3988:9;3981:42;4045:193;4108:4;4150:1;4128:6;:18;;;:23;4124:108;;4174:4;4167:11;;;;4124:108;4216:5;4209:12;;4045:193;;;;:::o;549:3691::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;7:75:41:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:117;443:1;440;433:12;457:102;498:6;549:2;545:7;540:2;533:5;529:14;525:28;515:38;;457:102;;;:::o;565:180::-;613:77;610:1;603:88;710:4;707:1;700:15;734:4;731:1;724:15;751:281;834:27;856:4;834:27;:::i;:::-;826:6;822:40;964:6;952:10;949:22;928:18;916:10;913:34;910:62;907:88;;;975:18;;:::i;:::-;907:88;1015:10;1011:2;1004:22;794:238;751:281;;:::o;1038:129::-;1072:6;1099:20;;:::i;:::-;1089:30;;1128:33;1156:4;1148:6;1128:33;:::i;:::-;1038:129;;;:::o;1173:311::-;1250:4;1340:18;1332:6;1329:30;1326:56;;;1362:18;;:::i;:::-;1326:56;1412:4;1404:6;1400:17;1392:25;;1472:4;1466;1462:15;1454:23;;1173:311;;;:::o;1490:117::-;1599:1;1596;1589:12;1613:126;1650:7;1690:42;1683:5;1679:54;1668:65;;1613:126;;;:::o;1745:96::-;1782:7;1811:24;1829:5;1811:24;:::i;:::-;1800:35;;1745:96;;;:::o;1847:122::-;1920:24;1938:5;1920:24;:::i;:::-;1913:5;1910:35;1900:63;;1959:1;1956;1949:12;1900:63;1847:122;:::o;1975:143::-;2032:5;2063:6;2057:13;2048:22;;2079:33;2106:5;2079:33;:::i;:::-;1975:143;;;;:::o;2141:732::-;2248:5;2273:81;2289:64;2346:6;2289:64;:::i;:::-;2273:81;:::i;:::-;2264:90;;2374:5;2403:6;2396:5;2389:21;2437:4;2430:5;2426:16;2419:23;;2490:4;2482:6;2478:17;2470:6;2466:30;2519:3;2511:6;2508:15;2505:122;;;2538:79;;:::i;:::-;2505:122;2653:6;2636:231;2670:6;2665:3;2662:15;2636:231;;;2745:3;2774:48;2818:3;2806:10;2774:48;:::i;:::-;2769:3;2762:61;2852:4;2847:3;2843:14;2836:21;;2712:155;2696:4;2691:3;2687:14;2680:21;;2636:231;;;2640:21;2254:619;;2141:732;;;;;:::o;2896:385::-;2978:5;3027:3;3020:4;3012:6;3008:17;3004:27;2994:122;;3035:79;;:::i;:::-;2994:122;3145:6;3139:13;3170:105;3271:3;3263:6;3256:4;3248:6;3244:17;3170:105;:::i;:::-;3161:114;;2984:297;2896:385;;;;:::o;3287:554::-;3382:6;3431:2;3419:9;3410:7;3406:23;3402:32;3399:119;;;3437:79;;:::i;:::-;3399:119;3578:1;3567:9;3563:17;3557:24;3608:18;3600:6;3597:30;3594:117;;;3630:79;;:::i;:::-;3594:117;3735:89;3816:7;3807:6;3796:9;3792:22;3735:89;:::i;:::-;3725:99;;3528:306;3287:554;;;;:::o;3847:180::-;3895:77;3892:1;3885:88;3992:4;3989:1;3982:15;4016:4;4013:1;4006:15;4033:351;4103:6;4152:2;4140:9;4131:7;4127:23;4123:32;4120:119;;;4158:79;;:::i;:::-;4120:119;4278:1;4303:64;4359:7;4350:6;4339:9;4335:22;4303:64;:::i;:::-;4293:74;;4249:128;4033:351;;;;:::o;4390:98::-;4441:6;4475:5;4469:12;4459:22;;4390:98;;;:::o;4494:147::-;4595:11;4632:3;4617:18;;4494:147;;;;:::o;4647:139::-;4736:6;4731:3;4726;4720:23;4777:1;4768:6;4763:3;4759:16;4752:27;4647:139;;;:::o;4792:386::-;4896:3;4924:38;4956:5;4924:38;:::i;:::-;4978:88;5059:6;5054:3;4978:88;:::i;:::-;4971:95;;5075:65;5133:6;5128:3;5121:4;5114:5;5110:16;5075:65;:::i;:::-;5165:6;5160:3;5156:16;5149:23;;4900:278;4792:386;;;;:::o;5184:271::-;5314:3;5336:93;5425:3;5416:6;5336:93;:::i;:::-;5329:100;;5446:3;5439:10;;5184:271;;;;:::o;5461:77::-;5498:7;5527:5;5516:16;;5461:77;;;:::o;5544:122::-;5617:24;5635:5;5617:24;:::i;:::-;5610:5;5607:35;5597:63;;5656:1;5653;5646:12;5597:63;5544:122;:::o;5672:143::-;5729:5;5760:6;5754:13;5745:22;;5776:33;5803:5;5776:33;:::i;:::-;5672:143;;;;:::o;5821:351::-;5891:6;5940:2;5928:9;5919:7;5915:23;5911:32;5908:119;;;5946:79;;:::i;:::-;5908:119;6066:1;6091:64;6147:7;6138:6;6127:9;6123:22;6091:64;:::i;:::-;6081:74;;6037:128;5821:351;;;;:::o;6178:114::-;6215:7;6255:30;6248:5;6244:42;6233:53;;6178:114;;;:::o;6298:122::-;6371:24;6389:5;6371:24;:::i;:::-;6364:5;6361:35;6351:63;;6410:1;6407;6400:12;6351:63;6298:122;:::o;6426:143::-;6483:5;6514:6;6508:13;6499:22;;6530:33;6557:5;6530:33;:::i;:::-;6426:143;;;;:::o;6575:93::-;6611:7;6651:10;6644:5;6640:22;6629:33;;6575:93;;;:::o;6674:120::-;6746:23;6763:5;6746:23;:::i;:::-;6739:5;6736:34;6726:62;;6784:1;6781;6774:12;6726:62;6674:120;:::o;6800:141::-;6856:5;6887:6;6881:13;6872:22;;6903:32;6929:5;6903:32;:::i;:::-;6800:141;;;;:::o;6947:661::-;7034:6;7042;7050;7099:2;7087:9;7078:7;7074:23;7070:32;7067:119;;;7105:79;;:::i;:::-;7067:119;7225:1;7250:64;7306:7;7297:6;7286:9;7282:22;7250:64;:::i;:::-;7240:74;;7196:128;7363:2;7389:64;7445:7;7436:6;7425:9;7421:22;7389:64;:::i;:::-;7379:74;;7334:129;7502:2;7528:63;7583:7;7574:6;7563:9;7559:22;7528:63;:::i;:::-;7518:73;;7473:128;6947:661;;;;;:::o;7614:141::-;7708:6;7742:5;7736:12;7726:22;;7614:141;;;:::o;7761:211::-;7887:11;7921:6;7916:3;7909:19;7961:4;7956:3;7952:14;7937:29;;7761:211;;;;:::o;7978:159::-;8072:4;8095:3;8087:11;;8125:4;8120:3;8116:14;8108:22;;7978:159;;;:::o;8143:108::-;8220:24;8238:5;8220:24;:::i;:::-;8215:3;8208:37;8143:108;;:::o;8257:::-;8334:24;8352:5;8334:24;:::i;:::-;8329:3;8322:37;8257:108;;:::o;8371:86::-;8406:7;8446:4;8439:5;8435:16;8424:27;;8371:86;;;:::o;8463:102::-;8536:22;8552:5;8536:22;:::i;:::-;8531:3;8524:35;8463:102;;:::o;8679:1221::-;8820:4;8815:3;8811:14;8909:4;8902:5;8898:16;8892:23;8928:63;8985:4;8980:3;8976:14;8962:12;8928:63;:::i;:::-;8835:166;9085:4;9078:5;9074:16;9068:23;9104:63;9161:4;9156:3;9152:14;9138:12;9104:63;:::i;:::-;9011:166;9263:4;9256:5;9252:16;9246:23;9282:63;9339:4;9334:3;9330:14;9316:12;9282:63;:::i;:::-;9187:168;9441:4;9434:5;9430:16;9424:23;9460:63;9517:4;9512:3;9508:14;9494:12;9460:63;:::i;:::-;9365:168;9625:4;9618:5;9614:16;9608:23;9644:59;9697:4;9692:3;9688:14;9674:12;9644:59;:::i;:::-;9543:170;9805:4;9798:5;9794:16;9788:23;9824:59;9877:4;9872:3;9868:14;9854:12;9824:59;:::i;:::-;9723:170;8789:1111;8679:1221;;:::o;9906:287::-;10029:10;10050:100;10146:3;10138:6;10050:100;:::i;:::-;10182:4;10177:3;10173:14;10159:28;;9906:287;;;;:::o;10199:140::-;10296:4;10328;10323:3;10319:14;10311:22;;10199:140;;;:::o;10457:948::-;10630:3;10659:81;10734:5;10659:81;:::i;:::-;10756:113;10862:6;10857:3;10756:113;:::i;:::-;10749:120;;10893:83;10970:5;10893:83;:::i;:::-;10999:7;11030:1;11015:365;11040:6;11037:1;11034:13;11015:365;;;11116:6;11110:13;11143:117;11256:3;11241:13;11143:117;:::i;:::-;11136:124;;11283:87;11363:6;11283:87;:::i;:::-;11273:97;;11075:305;11062:1;11059;11055:9;11050:14;;11015:365;;;11019:14;11396:3;11389:10;;10635:770;;;10457:948;;;;:::o;11411:481::-;11608:4;11646:2;11635:9;11631:18;11623:26;;11695:9;11689:4;11685:20;11681:1;11670:9;11666:17;11659:47;11723:162;11880:4;11871:6;11723:162;:::i;:::-;11715:170;;11411:481;;;;:::o", "linkReferences": {} }, "deployedBytecode": { "object": "0x60806040525f5ffdfea164736f6c634300081c000a", "sourceMap": "549:3691:27:-:0;;;;;", "linkReferences": {} }, "methodIdentifiers": {}, "rawMetadata": "{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"pools\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}],\"devdoc\":{\"details\":\"This contract is not meant to be deployed. Instead, use a static call with the deployment bytecode as payload.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/UniswapV2/GetUniswapV2PoolDataBatchRequest.sol\":\"GetUniswapV2PoolDataBatchRequest\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":forge-std/=lib/forge-std/src/\"]},\"sources\":{\"src/UniswapV2/GetUniswapV2PoolDataBatchRequest.sol\":{\"keccak256\":\"0x1064713fd23fc7576c8aa10c7de0032af68c8c1ce6e4a2a645403e99e73ee0a9\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8c9ba9f29f761a7fad1def642d9b248d5114e2ab7595d1a2f98d567b28175222\",\"dweb:/ipfs/QmZBgGhkWxFoPho5Jt34B9xaAFrYAAwgukLPqc4mV3LCHy\"]}},\"version\":1}", "metadata": { "compiler": { "version": "0.8.28+commit.7893614a" }, "language": "Solidity", "output": { "abi": [ { "inputs": [ { "internalType": "address[]", "name": "pools", "type": "address[]" } ], "stateMutability": "nonpayable", "type": "constructor" } ], "devdoc": { "kind": "dev", "methods": {}, "version": 1 }, "userdoc": { "kind": "user", "methods": {}, "version": 1 } }, "settings": { "remappings": [ "forge-std/=lib/forge-std/src/" ], "optimizer": { "enabled": false, "runs": 200 }, "metadata": { "bytecodeHash": "none" }, "compilationTarget": { "src/UniswapV2/GetUniswapV2PoolDataBatchRequest.sol": "GetUniswapV2PoolDataBatchRequest" }, "evmVersion": "cancun", "libraries": {} }, "sources": { "src/UniswapV2/GetUniswapV2PoolDataBatchRequest.sol": { "keccak256": "0x1064713fd23fc7576c8aa10c7de0032af68c8c1ce6e4a2a645403e99e73ee0a9", "urls": [ "bzz-raw://8c9ba9f29f761a7fad1def642d9b248d5114e2ab7595d1a2f98d567b28175222", "dweb:/ipfs/QmZBgGhkWxFoPho5Jt34B9xaAFrYAAwgukLPqc4mV3LCHy" ], "license": "MIT" } }, "version": 1 }, "id": 27 } ================================================ FILE: src/amms/abi/GetUniswapV3PoolDataBatchRequest.json ================================================ {"abi":[{"type":"constructor","inputs":[{"name":"poolInfo","type":"tuple[]","internalType":"struct GetUniswapV3PoolDataBatchRequest.PoolInfo[]","components":[{"name":"pool","type":"address","internalType":"address"},{"name":"tokenA","type":"address","internalType":"address"},{"name":"tokenB","type":"address","internalType":"address"},{"name":"tickSpacing","type":"int24","internalType":"int24"},{"name":"minWord","type":"int16","internalType":"int16"},{"name":"maxWord","type":"int16","internalType":"int16"}]}],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x608060405234801561000f575f5ffd5b5060405161108238038061108283398181016040528101906100319190610800565b5f815167ffffffffffffffff81111561004d5761004c61055d565b5b60405190808252806020026020018201604052801561008657816020015b6100736104e2565b81526020019060019003908161006b5790505b5090505f5f90505b82518110156104b4575f8382815181106100ab576100aa610847565b5b602002602001015190505f815f015190505f8484815181106100d0576100cf610847565b5b602002602001015190505f600184608001518560a001516100f191906108a1565b60010b6100fe9190610903565b90508067ffffffffffffffff81111561011a5761011961055d565b5b6040519080825280602002602001820160405280156101485781602001602082028036833780820191505090505b50825f01819052505f8161010061015f9190610936565b67ffffffffffffffff8111156101785761017761055d565b5b6040519080825280602002602001820160405280156101b157816020015b61019e610503565b8152602001906001900390816101965790505b5090505f826101006101c39190610936565b67ffffffffffffffff8111156101dc576101db61055d565b5b60405190808252806020026020018201604052801561020a5781602001602082028036833780820191505090505b5090505f5f90505f5f90505f886080015190505b8860a0015160010b8160010b13610469575f8873ffffffffffffffffffffffffffffffffffffffff16635339c296836040518263ffffffff1660e01b81526004016102699190610986565b602060405180830381865afa158015610284573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102a891906109c9565b90505f81036102b75750610458565b5f5f90505b610100811015610426575f816001901b90505f5f828516141590508015610419575f8d6060015160020b846102f19190610936565b610100886102ff9190610936565b6103099190610903565b90505f8d73ffffffffffffffffffffffffffffffffffffffff1663f30dba93836040518263ffffffff1660e01b81526004016103459190610a03565b61010060405180830381865afa158015610361573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103859190610c2c565b9050818a8a8151811061039b5761039a610847565b5b602002602001019060020b908160020b815250506040518060600160405280825f01516fffffffffffffffffffffffffffffffff1681526020018260200151600f0b81526020018260e0015115158152508b8a815181106103ff576103fe610847565b5b60200260200101819052508861041490610c58565b985050505b50508060010190506102bc565b5080885f0151848151811061043e5761043d610847565b5b6020026020010181815250508261045490610c58565b9250505b8061046290610c9f565b905061021e565b50818452818352838660400181905250828660200181905250858a8a8151811061049657610495610847565b5b6020026020010181905250505050505050505080600101905061008e565b505f816040516020016104c79190611061565b60405160208183030381529060405290506020810180590381f35b60405180606001604052806060815260200160608152602001606081525090565b60405180606001604052805f6fffffffffffffffffffffffffffffffff1681526020015f600f0b81526020015f151581525090565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6105938261054d565b810181811067ffffffffffffffff821117156105b2576105b161055d565b5b80604052505050565b5f6105c4610538565b90506105d0828261058a565b919050565b5f67ffffffffffffffff8211156105ef576105ee61055d565b5b602082029050602081019050919050565b5f5ffd5b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61063182610608565b9050919050565b61064181610627565b811461064b575f5ffd5b50565b5f8151905061065c81610638565b92915050565b5f8160020b9050919050565b61067781610662565b8114610681575f5ffd5b50565b5f815190506106928161066e565b92915050565b5f8160010b9050919050565b6106ad81610698565b81146106b7575f5ffd5b50565b5f815190506106c8816106a4565b92915050565b5f60c082840312156106e3576106e2610604565b5b6106ed60c06105bb565b90505f6106fc8482850161064e565b5f83015250602061070f8482850161064e565b60208301525060406107238482850161064e565b604083015250606061073784828501610684565b606083015250608061074b848285016106ba565b60808301525060a061075f848285016106ba565b60a08301525092915050565b5f61077d610778846105d5565b6105bb565b90508083825260208201905060c084028301858111156107a05761079f610600565b5b835b818110156107c957806107b588826106ce565b84526020840193505060c0810190506107a2565b5050509392505050565b5f82601f8301126107e7576107e6610549565b5b81516107f784826020860161076b565b91505092915050565b5f6020828403121561081557610814610541565b5b5f82015167ffffffffffffffff81111561083257610831610545565b5b61083e848285016107d3565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6108ab82610698565b91506108b683610698565b92508282039050617fff81137fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000821217156108f4576108f3610874565b5b92915050565b5f819050919050565b5f61090d826108fa565b9150610918836108fa565b92508282019050808211156109305761092f610874565b5b92915050565b5f610940826108fa565b915061094b836108fa565b9250828202610959816108fa565b915082820484148315176109705761096f610874565b5b5092915050565b61098081610698565b82525050565b5f6020820190506109995f830184610977565b92915050565b6109a8816108fa565b81146109b2575f5ffd5b50565b5f815190506109c38161099f565b92915050565b5f602082840312156109de576109dd610541565b5b5f6109eb848285016109b5565b91505092915050565b6109fd81610662565b82525050565b5f602082019050610a165f8301846109f4565b92915050565b5f6fffffffffffffffffffffffffffffffff82169050919050565b610a4081610a1c565b8114610a4a575f5ffd5b50565b5f81519050610a5b81610a37565b92915050565b5f81600f0b9050919050565b610a7681610a61565b8114610a80575f5ffd5b50565b5f81519050610a9181610a6d565b92915050565b5f8160060b9050919050565b610aac81610a97565b8114610ab6575f5ffd5b50565b5f81519050610ac781610aa3565b92915050565b610ad681610608565b8114610ae0575f5ffd5b50565b5f81519050610af181610acd565b92915050565b5f63ffffffff82169050919050565b610b0f81610af7565b8114610b19575f5ffd5b50565b5f81519050610b2a81610b06565b92915050565b5f8115159050919050565b610b4481610b30565b8114610b4e575f5ffd5b50565b5f81519050610b5f81610b3b565b92915050565b5f6101008284031215610b7b57610b7a610604565b5b610b866101006105bb565b90505f610b9584828501610a4d565b5f830152506020610ba884828501610a83565b6020830152506040610bbc848285016109b5565b6040830152506060610bd0848285016109b5565b6060830152506080610be484828501610ab9565b60808301525060a0610bf884828501610ae3565b60a08301525060c0610c0c84828501610b1c565b60c08301525060e0610c2084828501610b51565b60e08301525092915050565b5f6101008284031215610c4257610c41610541565b5b5f610c4f84828501610b65565b91505092915050565b5f610c62826108fa565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610c9457610c93610874565b5b600182019050919050565b5f610ca982610698565b9150617fff8203610cbd57610cbc610874565b5b600182019050919050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b610d23816108fa565b82525050565b5f610d348383610d1a565b60208301905092915050565b5f602082019050919050565b5f610d5682610cf1565b610d608185610cfb565b9350610d6b83610d0b565b805f5b83811015610d9b578151610d828882610d29565b9750610d8d83610d40565b925050600181019050610d6e565b5085935050505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b610dda81610662565b82525050565b5f610deb8383610dd1565b60208301905092915050565b5f602082019050919050565b5f610e0d82610da8565b610e178185610db2565b9350610e2283610dc2565b805f5b83811015610e52578151610e398882610de0565b9750610e4483610df7565b925050600181019050610e25565b5085935050505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b610e9181610a1c565b82525050565b610ea081610a61565b82525050565b610eaf81610b30565b82525050565b606082015f820151610ec95f850182610e88565b506020820151610edc6020850182610e97565b506040820151610eef6040850182610ea6565b50505050565b5f610f008383610eb5565b60608301905092915050565b5f602082019050919050565b5f610f2282610e5f565b610f2c8185610e69565b9350610f3783610e79565b805f5b83811015610f67578151610f4e8882610ef5565b9750610f5983610f0c565b925050600181019050610f3a565b5085935050505092915050565b5f606083015f8301518482035f860152610f8e8282610d4c565b91505060208301518482036020860152610fa88282610e03565b91505060408301518482036040860152610fc28282610f18565b9150508091505092915050565b5f610fda8383610f74565b905092915050565b5f602082019050919050565b5f610ff882610cc8565b6110028185610cd2565b93508360208202850161101485610ce2565b805f5b8581101561104f57848403895281516110308582610fcf565b945061103b83610fe2565b925060208a01995050600181019050611017565b50829750879550505050505092915050565b5f6020820190508181035f8301526110798184610fee565b90509291505056fe","sourceMap":"192:3422:29:-:0;;;728:2884;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;778:29;825:8;:15;810:31;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;778:63;;857:9;869:1;857:13;;852:2222;876:8;:15;872:1;:19;852:2222;;;912:20;935:8;944:1;935:11;;;;;;;;:::i;:::-;;;;;;;;912:34;;960:24;1007:4;:9;;;960:57;;1032:24;1059:11;1071:1;1059:14;;;;;;;;:::i;:::-;;;;;;;;1032:41;;1087:17;1154:1;1137:4;:12;;;1122:4;:12;;;:27;;;;:::i;:::-;1115:35;;1107:48;;;;:::i;:::-;1087:68;;1206:9;1192:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1170:8;:19;;:46;;;;1231:26;1281:9;1275:3;:15;;;;:::i;:::-;1260:31;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;1231:60;;1305:23;1349:9;1343:3;:15;;;;:::i;:::-;1331:28;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1305:54;;1374:22;1399:1;1374:26;;1629:20;1652:1;1629:24;;1672:7;1682:4;:12;;;1672:22;;1667:1137;1701:4;:12;;;1696:17;;:1;:17;;;1667:1137;;1738:18;1759:4;:15;;;1775:1;1759:18;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1738:39;;1814:1;1800:10;:15;1796:70;;1839:8;;;1796:70;1889:9;1901:1;1889:13;;1884:809;1908:3;1904:1;:7;1884:809;;;1940:11;1959:1;1954;:6;;1940:20;;1983:16;2024:1;2016:3;2003:10;:16;2002:23;;1983:42;;2051:11;2047:628;;;2090:15;2161:4;:16;;;2154:24;;2142:1;:37;;;;:::i;:::-;2136:3;2121:12;:18;;;;:::i;:::-;:58;;;;:::i;:::-;2090:91;;2208:40;2251:4;:10;;;2262:9;2251:21;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2208:64;;2326:9;2299:8;2308:14;2299:24;;;;;;;;:::i;:::-;;;;;;;:36;;;;;;;;;;;2388:221;;;;;;;;2443:4;:19;;;2388:221;;;;;;2506:4;:17;;;2388:221;;;;;;2566:4;:16;;;2388:221;;;;;2361:8;2370:14;2361:24;;;;;;;;:::i;:::-;;;;;;;:248;;;;2636:16;;;;:::i;:::-;;;2064:611;;2047:628;1918:775;;1913:3;;;;;1884:809;;;;2747:10;2711:8;:19;;;2731:12;2711:33;;;;;;;;:::i;:::-;;;;;;;:46;;;;;2775:14;;;;:::i;:::-;;;1720:1084;1667:1137;1715:3;;;;:::i;:::-;;;1667:1137;;;;2862:14;2852:8;2845:32;2911:14;2901:8;2894:32;2971:8;2954;:14;;:25;;;;3016:8;2993;:20;;:31;;;;3055:8;3038:11;3050:1;3038:14;;;;;;;;:::i;:::-;;;;;;;:25;;;;898:2176;;;;;;;;893:3;;;;;852:2222;;;;3276:27;3317:11;3306:23;;;;;;;;:::i;:::-;;;;;;;;;;;;;3276:53;;3536:4;3520:14;3516:25;3585:9;3576:7;3572:23;3561:9;3554:42;192:3422;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;7:75:41:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:117;443:1;440;433:12;457:102;498:6;549:2;545:7;540:2;533:5;529:14;525:28;515:38;;457:102;;;:::o;565:180::-;613:77;610:1;603:88;710:4;707:1;700:15;734:4;731:1;724:15;751:281;834:27;856:4;834:27;:::i;:::-;826:6;822:40;964:6;952:10;949:22;928:18;916:10;913:34;910:62;907:88;;;975:18;;:::i;:::-;907:88;1015:10;1011:2;1004:22;794:238;751:281;;:::o;1038:129::-;1072:6;1099:20;;:::i;:::-;1089:30;;1128:33;1156:4;1148:6;1128:33;:::i;:::-;1038:129;;;:::o;1173:338::-;1277:4;1367:18;1359:6;1356:30;1353:56;;;1389:18;;:::i;:::-;1353:56;1439:4;1431:6;1427:17;1419:25;;1499:4;1493;1489:15;1481:23;;1173:338;;;:::o;1517:117::-;1626:1;1623;1616:12;1640:117;1749:1;1746;1739:12;1886:126;1923:7;1963:42;1956:5;1952:54;1941:65;;1886:126;;;:::o;2018:96::-;2055:7;2084:24;2102:5;2084:24;:::i;:::-;2073:35;;2018:96;;;:::o;2120:122::-;2193:24;2211:5;2193:24;:::i;:::-;2186:5;2183:35;2173:63;;2232:1;2229;2222:12;2173:63;2120:122;:::o;2248:143::-;2305:5;2336:6;2330:13;2321:22;;2352:33;2379:5;2352:33;:::i;:::-;2248:143;;;;:::o;2397:90::-;2432:7;2475:5;2472:1;2461:20;2450:31;;2397:90;;;:::o;2493:118::-;2564:22;2580:5;2564:22;:::i;:::-;2557:5;2554:33;2544:61;;2601:1;2598;2591:12;2544:61;2493:118;:::o;2617:139::-;2672:5;2703:6;2697:13;2688:22;;2719:31;2744:5;2719:31;:::i;:::-;2617:139;;;;:::o;2762:90::-;2797:7;2840:5;2837:1;2826:20;2815:31;;2762:90;;;:::o;2858:118::-;2929:22;2945:5;2929:22;:::i;:::-;2922:5;2919:33;2909:61;;2966:1;2963;2956:12;2909:61;2858:118;:::o;2982:139::-;3037:5;3068:6;3062:13;3053:22;;3084:31;3109:5;3084:31;:::i;:::-;2982:139;;;;:::o;3183:1310::-;3270:5;3314:4;3302:9;3297:3;3293:19;3289:30;3286:117;;;3322:79;;:::i;:::-;3286:117;3421:21;3437:4;3421:21;:::i;:::-;3412:30;;3501:1;3541:60;3597:3;3588:6;3577:9;3573:22;3541:60;:::i;:::-;3534:4;3527:5;3523:16;3516:86;3452:161;3674:2;3715:60;3771:3;3762:6;3751:9;3747:22;3715:60;:::i;:::-;3708:4;3701:5;3697:16;3690:86;3623:164;3848:2;3889:60;3945:3;3936:6;3925:9;3921:22;3889:60;:::i;:::-;3882:4;3875:5;3871:16;3864:86;3797:164;4027:2;4068:58;4122:3;4113:6;4102:9;4098:22;4068:58;:::i;:::-;4061:4;4054:5;4050:16;4043:84;3971:167;4200:3;4242:58;4296:3;4287:6;4276:9;4272:22;4242:58;:::i;:::-;4235:4;4228:5;4224:16;4217:84;4148:164;4374:3;4416:58;4470:3;4461:6;4450:9;4446:22;4416:58;:::i;:::-;4409:4;4402:5;4398:16;4391:84;4322:164;3183:1310;;;;:::o;4557:813::-;4691:5;4716:108;4732:91;4816:6;4732:91;:::i;:::-;4716:108;:::i;:::-;4707:117;;4844:5;4873:6;4866:5;4859:21;4907:4;4900:5;4896:16;4889:23;;4960:4;4952:6;4948:17;4940:6;4936:30;4989:3;4981:6;4978:15;4975:122;;;5008:79;;:::i;:::-;4975:122;5123:6;5106:258;5140:6;5135:3;5132:15;5106:258;;;5215:3;5244:75;5315:3;5303:10;5244:75;:::i;:::-;5239:3;5232:88;5349:4;5344:3;5340:14;5333:21;;5182:182;5166:4;5161:3;5157:14;5150:21;;5106:258;;;5110:21;4697:673;;4557:813;;;;;:::o;5434:439::-;5543:5;5592:3;5585:4;5577:6;5573:17;5569:27;5559:122;;5600:79;;:::i;:::-;5559:122;5710:6;5704:13;5735:132;5863:3;5855:6;5848:4;5840:6;5836:17;5735:132;:::i;:::-;5726:141;;5549:324;5434:439;;;;:::o;5879:608::-;6001:6;6050:2;6038:9;6029:7;6025:23;6021:32;6018:119;;;6056:79;;:::i;:::-;6018:119;6197:1;6186:9;6182:17;6176:24;6227:18;6219:6;6216:30;6213:117;;;6249:79;;:::i;:::-;6213:117;6354:116;6462:7;6453:6;6442:9;6438:22;6354:116;:::i;:::-;6344:126;;6147:333;5879:608;;;;:::o;6493:180::-;6541:77;6538:1;6531:88;6638:4;6635:1;6628:15;6662:4;6659:1;6652:15;6679:180;6727:77;6724:1;6717:88;6824:4;6821:1;6814:15;6848:4;6845:1;6838:15;6865:311;6903:4;6923:18;6939:1;6923:18;:::i;:::-;6918:23;;6955:18;6971:1;6955:18;:::i;:::-;6950:23;;6997:1;6994;6990:9;6982:17;;7129:6;7123:4;7119:17;7038:66;7032:4;7028:77;7012:134;7009:160;;;7149:18;;:::i;:::-;7009:160;6865:311;;;;:::o;7182:77::-;7219:7;7248:5;7237:16;;7182:77;;;:::o;7265:191::-;7305:3;7324:20;7342:1;7324:20;:::i;:::-;7319:25;;7358:20;7376:1;7358:20;:::i;:::-;7353:25;;7401:1;7398;7394:9;7387:16;;7422:3;7419:1;7416:10;7413:36;;;7429:18;;:::i;:::-;7413:36;7265:191;;;;:::o;7462:410::-;7502:7;7525:20;7543:1;7525:20;:::i;:::-;7520:25;;7559:20;7577:1;7559:20;:::i;:::-;7554:25;;7614:1;7611;7607:9;7636:30;7654:11;7636:30;:::i;:::-;7625:41;;7815:1;7806:7;7802:15;7799:1;7796:22;7776:1;7769:9;7749:83;7726:139;;7845:18;;:::i;:::-;7726:139;7510:362;7462:410;;;;:::o;7878:112::-;7961:22;7977:5;7961:22;:::i;:::-;7956:3;7949:35;7878:112;;:::o;7996:214::-;8085:4;8123:2;8112:9;8108:18;8100:26;;8136:67;8200:1;8189:9;8185:17;8176:6;8136:67;:::i;:::-;7996:214;;;;:::o;8216:122::-;8289:24;8307:5;8289:24;:::i;:::-;8282:5;8279:35;8269:63;;8328:1;8325;8318:12;8269:63;8216:122;:::o;8344:143::-;8401:5;8432:6;8426:13;8417:22;;8448:33;8475:5;8448:33;:::i;:::-;8344:143;;;;:::o;8493:351::-;8563:6;8612:2;8600:9;8591:7;8587:23;8583:32;8580:119;;;8618:79;;:::i;:::-;8580:119;8738:1;8763:64;8819:7;8810:6;8799:9;8795:22;8763:64;:::i;:::-;8753:74;;8709:128;8493:351;;;;:::o;8850:112::-;8933:22;8949:5;8933:22;:::i;:::-;8928:3;8921:35;8850:112;;:::o;8968:214::-;9057:4;9095:2;9084:9;9080:18;9072:26;;9108:67;9172:1;9161:9;9157:17;9148:6;9108:67;:::i;:::-;8968:214;;;;:::o;9188:118::-;9225:7;9265:34;9258:5;9254:46;9243:57;;9188:118;;;:::o;9312:122::-;9385:24;9403:5;9385:24;:::i;:::-;9378:5;9375:35;9365:63;;9424:1;9421;9414:12;9365:63;9312:122;:::o;9440:143::-;9497:5;9528:6;9522:13;9513:22;;9544:33;9571:5;9544:33;:::i;:::-;9440:143;;;;:::o;9589:92::-;9625:7;9669:5;9665:2;9654:21;9643:32;;9589:92;;;:::o;9687:120::-;9759:23;9776:5;9759:23;:::i;:::-;9752:5;9749:34;9739:62;;9797:1;9794;9787:12;9739:62;9687:120;:::o;9813:141::-;9869:5;9900:6;9894:13;9885:22;;9916:32;9942:5;9916:32;:::i;:::-;9813:141;;;;:::o;9960:90::-;9995:7;10038:5;10035:1;10024:20;10013:31;;9960:90;;;:::o;10056:118::-;10127:22;10143:5;10127:22;:::i;:::-;10120:5;10117:33;10107:61;;10164:1;10161;10154:12;10107:61;10056:118;:::o;10180:139::-;10235:5;10266:6;10260:13;10251:22;;10282:31;10307:5;10282:31;:::i;:::-;10180:139;;;;:::o;10325:122::-;10398:24;10416:5;10398:24;:::i;:::-;10391:5;10388:35;10378:63;;10437:1;10434;10427:12;10378:63;10325:122;:::o;10453:143::-;10510:5;10541:6;10535:13;10526:22;;10557:33;10584:5;10557:33;:::i;:::-;10453:143;;;;:::o;10602:93::-;10638:7;10678:10;10671:5;10667:22;10656:33;;10602:93;;;:::o;10701:120::-;10773:23;10790:5;10773:23;:::i;:::-;10766:5;10763:34;10753:62;;10811:1;10808;10801:12;10753:62;10701:120;:::o;10827:141::-;10883:5;10914:6;10908:13;10899:22;;10930:32;10956:5;10930:32;:::i;:::-;10827:141;;;;:::o;10974:90::-;11008:7;11051:5;11044:13;11037:21;11026:32;;10974:90;;;:::o;11070:116::-;11140:21;11155:5;11140:21;:::i;:::-;11133:5;11130:32;11120:60;;11176:1;11173;11166:12;11120:60;11070:116;:::o;11192:137::-;11246:5;11277:6;11271:13;11262:22;;11293:30;11317:5;11293:30;:::i;:::-;11192:137;;;;:::o;11378:1754::-;11465:5;11509:6;11497:9;11492:3;11488:19;11484:32;11481:119;;;11519:79;;:::i;:::-;11481:119;11618:23;11634:6;11618:23;:::i;:::-;11609:32;;11710:1;11750:60;11806:3;11797:6;11786:9;11782:22;11750:60;:::i;:::-;11743:4;11736:5;11732:16;11725:86;11651:171;11889:2;11930:59;11985:3;11976:6;11965:9;11961:22;11930:59;:::i;:::-;11923:4;11916:5;11912:16;11905:85;11832:169;12077:2;12118:60;12174:3;12165:6;12154:9;12150:22;12118:60;:::i;:::-;12111:4;12104:5;12100:16;12093:86;12011:179;12266:2;12307:60;12363:3;12354:6;12343:9;12339:22;12307:60;:::i;:::-;12300:4;12293:5;12289:16;12282:86;12200:179;12455:3;12497:58;12551:3;12542:6;12531:9;12527:22;12497:58;:::i;:::-;12490:4;12483:5;12479:16;12472:84;12389:178;12652:3;12694:60;12750:3;12741:6;12730:9;12726:22;12694:60;:::i;:::-;12687:4;12680:5;12676:16;12669:86;12577:189;12835:3;12877:59;12932:3;12923:6;12912:9;12908:22;12877:59;:::i;:::-;12870:4;12863:5;12859:16;12852:85;12776:172;13014:3;13056:57;13109:3;13100:6;13089:9;13085:22;13056:57;:::i;:::-;13049:4;13042:5;13038:16;13031:83;12958:167;11378:1754;;;;:::o;13138:406::-;13235:6;13284:3;13272:9;13263:7;13259:23;13255:33;13252:120;;;13291:79;;:::i;:::-;13252:120;13411:1;13436:91;13519:7;13510:6;13499:9;13495:22;13436:91;:::i;:::-;13426:101;;13382:155;13138:406;;;;:::o;13550:233::-;13589:3;13612:24;13630:5;13612:24;:::i;:::-;13603:33;;13658:66;13651:5;13648:77;13645:103;;13728:18;;:::i;:::-;13645:103;13775:1;13768:5;13764:13;13757:20;;13550:233;;;:::o;13789:169::-;13826:3;13849:22;13865:5;13849:22;:::i;:::-;13840:31;;13893:6;13886:5;13883:17;13880:43;;13903:18;;:::i;:::-;13880:43;13950:1;13943:5;13939:13;13932:20;;13789:169;;;:::o;13964:141::-;14058:6;14092:5;14086:12;14076:22;;13964:141;;;:::o;14111:211::-;14237:11;14271:6;14266:3;14259:19;14311:4;14306:3;14302:14;14287:29;;14111:211;;;;:::o;14328:159::-;14422:4;14445:3;14437:11;;14475:4;14470:3;14466:14;14458:22;;14328:159;;;:::o;14493:114::-;14560:6;14594:5;14588:12;14578:22;;14493:114;;;:::o;14613:174::-;14702:11;14736:6;14731:3;14724:19;14776:4;14771:3;14767:14;14752:29;;14613:174;;;;:::o;14793:132::-;14860:4;14883:3;14875:11;;14913:4;14908:3;14904:14;14896:22;;14793:132;;;:::o;14931:108::-;15008:24;15026:5;15008:24;:::i;:::-;15003:3;14996:37;14931:108;;:::o;15045:179::-;15114:10;15135:46;15177:3;15169:6;15135:46;:::i;:::-;15213:4;15208:3;15204:14;15190:28;;15045:179;;;;:::o;15230:113::-;15300:4;15332;15327:3;15323:14;15315:22;;15230:113;;;:::o;15379:712::-;15488:3;15517:54;15565:5;15517:54;:::i;:::-;15587:76;15656:6;15651:3;15587:76;:::i;:::-;15580:83;;15687:56;15737:5;15687:56;:::i;:::-;15766:7;15797:1;15782:284;15807:6;15804:1;15801:13;15782:284;;;15883:6;15877:13;15910:63;15969:3;15954:13;15910:63;:::i;:::-;15903:70;;15996:60;16049:6;15996:60;:::i;:::-;15986:70;;15842:224;15829:1;15826;15822:9;15817:14;;15782:284;;;15786:14;16082:3;16075:10;;15493:598;;;15379:712;;;;:::o;16097:112::-;16162:6;16196:5;16190:12;16180:22;;16097:112;;;:::o;16215:172::-;16302:11;16336:6;16331:3;16324:19;16376:4;16371:3;16367:14;16352:29;;16215:172;;;;:::o;16393:130::-;16458:4;16481:3;16473:11;;16511:4;16506:3;16502:14;16494:22;;16393:130;;;:::o;16529:102::-;16602:22;16618:5;16602:22;:::i;:::-;16597:3;16590:35;16529:102;;:::o;16637:171::-;16702:10;16723:42;16761:3;16753:6;16723:42;:::i;:::-;16797:4;16792:3;16788:14;16774:28;;16637:171;;;;:::o;16814:111::-;16882:4;16914;16909:3;16905:14;16897:22;;16814:111;;;:::o;16957:696::-;17062:3;17091:52;17137:5;17091:52;:::i;:::-;17159:74;17226:6;17221:3;17159:74;:::i;:::-;17152:81;;17257:54;17305:5;17257:54;:::i;:::-;17334:7;17365:1;17350:278;17375:6;17372:1;17369:13;17350:278;;;17451:6;17445:13;17478:59;17533:3;17518:13;17478:59;:::i;:::-;17471:66;;17560:58;17611:6;17560:58;:::i;:::-;17550:68;;17410:218;17397:1;17394;17390:9;17385:14;;17350:278;;;17354:14;17644:3;17637:10;;17067:586;;;16957:696;;;;:::o;17659:141::-;17753:6;17787:5;17781:12;17771:22;;17659:141;;;:::o;17806:201::-;17922:11;17956:6;17951:3;17944:19;17996:4;17991:3;17987:14;17972:29;;17806:201;;;;:::o;18013:159::-;18107:4;18130:3;18122:11;;18160:4;18155:3;18151:14;18143:22;;18013:159;;;:::o;18178:108::-;18255:24;18273:5;18255:24;:::i;:::-;18250:3;18243:37;18178:108;;:::o;18292:105::-;18367:23;18384:5;18367:23;:::i;:::-;18362:3;18355:36;18292:105;;:::o;18403:99::-;18474:21;18489:5;18474:21;:::i;:::-;18469:3;18462:34;18403:99;;:::o;18616:692::-;18757:4;18752:3;18748:14;18854:4;18847:5;18843:16;18837:23;18873:63;18930:4;18925:3;18921:14;18907:12;18873:63;:::i;:::-;18772:174;19036:4;19029:5;19025:16;19019:23;19055:61;19110:4;19105:3;19101:14;19087:12;19055:61;:::i;:::-;18956:170;19215:4;19208:5;19204:16;19198:23;19234:57;19285:4;19280:3;19276:14;19262:12;19234:57;:::i;:::-;19136:165;18726:582;18616:692;;:::o;19314:287::-;19437:10;19458:100;19554:3;19546:6;19458:100;:::i;:::-;19590:4;19585:3;19581:14;19567:28;;19314:287;;;;:::o;19607:140::-;19704:4;19736;19731:3;19727:14;19719:22;;19607:140;;;:::o;19865:928::-;20028:3;20057:81;20132:5;20057:81;:::i;:::-;20154:103;20250:6;20245:3;20154:103;:::i;:::-;20147:110;;20281:83;20358:5;20281:83;:::i;:::-;20387:7;20418:1;20403:365;20428:6;20425:1;20422:13;20403:365;;;20504:6;20498:13;20531:117;20644:3;20629:13;20531:117;:::i;:::-;20524:124;;20671:87;20751:6;20671:87;:::i;:::-;20661:97;;20463:305;20450:1;20447;20443:9;20438:14;;20403:365;;;20407:14;20784:3;20777:10;;20033:760;;;19865:928;;;;:::o;20907:1070::-;21020:3;21056:4;21051:3;21047:14;21149:4;21142:5;21138:16;21132:23;21202:3;21196:4;21192:14;21185:4;21180:3;21176:14;21169:38;21228:103;21326:4;21312:12;21228:103;:::i;:::-;21220:111;;21071:271;21431:4;21424:5;21420:16;21414:23;21484:3;21478:4;21474:14;21467:4;21462:3;21458:14;21451:38;21510:99;21604:4;21590:12;21510:99;:::i;:::-;21502:107;;21352:268;21703:4;21696:5;21692:16;21686:23;21756:3;21750:4;21746:14;21739:4;21734:3;21730:14;21723:38;21782:157;21934:4;21920:12;21782:157;:::i;:::-;21774:165;;21630:320;21967:4;21960:11;;21025:952;20907:1070;;;;:::o;21983:264::-;22106:10;22141:100;22237:3;22229:6;22141:100;:::i;:::-;22127:114;;21983:264;;;;:::o;22253:140::-;22350:4;22382;22377:3;22373:14;22365:22;;22253:140;;;:::o;22511:1127::-;22684:3;22713:81;22788:5;22713:81;:::i;:::-;22810:113;22916:6;22911:3;22810:113;:::i;:::-;22803:120;;22949:3;22994:4;22986:6;22982:17;22977:3;22973:27;23024:83;23101:5;23024:83;:::i;:::-;23130:7;23161:1;23146:447;23171:6;23168:1;23165:13;23146:447;;;23242:9;23236:4;23232:20;23227:3;23220:33;23293:6;23287:13;23321:118;23434:4;23419:13;23321:118;:::i;:::-;23313:126;;23462:87;23542:6;23462:87;:::i;:::-;23452:97;;23578:4;23573:3;23569:14;23562:21;;23206:387;23193:1;23190;23186:9;23181:14;;23146:447;;;23150:14;23609:4;23602:11;;23629:3;23622:10;;22689:949;;;;;22511:1127;;;;:::o;23644:481::-;23841:4;23879:2;23868:9;23864:18;23856:26;;23928:9;23922:4;23918:20;23914:1;23903:9;23899:17;23892:47;23956:162;24113:4;24104:6;23956:162;:::i;:::-;23948:170;;23644:481;;;;:::o","linkReferences":{}},"deployedBytecode":{"object":"0x60806040525f5ffdfea164736f6c634300081c000a","sourceMap":"192:3422:29:-:0;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"int24\",\"name\":\"tickSpacing\",\"type\":\"int24\"},{\"internalType\":\"int16\",\"name\":\"minWord\",\"type\":\"int16\"},{\"internalType\":\"int16\",\"name\":\"maxWord\",\"type\":\"int16\"}],\"internalType\":\"struct GetUniswapV3PoolDataBatchRequest.PoolInfo[]\",\"name\":\"poolInfo\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}],\"devdoc\":{\"details\":\"This contract is not meant to be deployed. Instead, use a static call with the deployment bytecode as payload.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/UniswapV3/GetUniswapV3PoolDataBatchRequest.sol\":\"GetUniswapV3PoolDataBatchRequest\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":forge-std/=lib/forge-std/src/\"]},\"sources\":{\"src/UniswapV3/GetUniswapV3PoolDataBatchRequest.sol\":{\"keccak256\":\"0x9f934c25022edc48289bf9f793adbe0794afba25d7a32470176b71e50b81ce38\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d9bd62b4ce3f65115272abd4357021ffde6e57a93ddf27d0cb6787f6af51da13\",\"dweb:/ipfs/QmPuy5R7MUNHfpmxiTuEXvzjBN6RM8XBPTXeC5djotkTMJ\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"struct GetUniswapV3PoolDataBatchRequest.PoolInfo[]","name":"poolInfo","type":"tuple[]","components":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"int24","name":"tickSpacing","type":"int24"},{"internalType":"int16","name":"minWord","type":"int16"},{"internalType":"int16","name":"maxWord","type":"int16"}]}],"stateMutability":"nonpayable","type":"constructor"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["forge-std/=lib/forge-std/src/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"src/UniswapV3/GetUniswapV3PoolDataBatchRequest.sol":"GetUniswapV3PoolDataBatchRequest"},"evmVersion":"cancun","libraries":{}},"sources":{"src/UniswapV3/GetUniswapV3PoolDataBatchRequest.sol":{"keccak256":"0x9f934c25022edc48289bf9f793adbe0794afba25d7a32470176b71e50b81ce38","urls":["bzz-raw://d9bd62b4ce3f65115272abd4357021ffde6e57a93ddf27d0cb6787f6af51da13","dweb:/ipfs/QmPuy5R7MUNHfpmxiTuEXvzjBN6RM8XBPTXeC5djotkTMJ"],"license":"MIT"}},"version":1},"id":29} ================================================ FILE: src/amms/abi/GetUniswapV3PoolSlot0BatchRequest.json ================================================ {"abi":[{"type":"constructor","inputs":[{"name":"pools","type":"address[]","internalType":"address[]"}],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x608060405234801561000f575f5ffd5b5060405161082a38038061082a83398181016040528101906100319190610468565b5f815167ffffffffffffffff81111561004d5761004c6102d2565b5b60405190808252806020026020018201604052801561008657816020015b61007361027a565b81526020019060019003908161006b5790505b5090505f5f90505b825181101561024c575f8282815181106100ab576100aa6104af565b5b602002602001015190505f8483815181106100c9576100c86104af565b5b602002602001015190505f8190508073ffffffffffffffffffffffffffffffffffffffff16631a6865026040518163ffffffff1660e01b8152600401602060405180830381865afa158015610120573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101449190610521565b83602001906fffffffffffffffffffffffffffffffff1690816fffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa1580156101bc573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101e0919061064e565b8673ffffffffffffffffffffffffffffffffffffffff16965090919293509091925090915090505084604001855f018260020b60020b81525082815250505082858581518110610233576102326104af565b5b602002602001018190525050505080600101905061008e565b505f8160405160200161025f9190610809565b60405160208183030381529060405290506020810180590381f35b60405180606001604052805f60020b81526020015f6fffffffffffffffffffffffffffffffff1681526020015f81525090565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b610308826102c2565b810181811067ffffffffffffffff82111715610327576103266102d2565b5b80604052505050565b5f6103396102ad565b905061034582826102ff565b919050565b5f67ffffffffffffffff821115610364576103636102d2565b5b602082029050602081019050919050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6103a282610379565b9050919050565b6103b281610398565b81146103bc575f5ffd5b50565b5f815190506103cd816103a9565b92915050565b5f6103e56103e08461034a565b610330565b9050808382526020820190506020840283018581111561040857610407610375565b5b835b81811015610431578061041d88826103bf565b84526020840193505060208101905061040a565b5050509392505050565b5f82601f83011261044f5761044e6102be565b5b815161045f8482602086016103d3565b91505092915050565b5f6020828403121561047d5761047c6102b6565b5b5f82015167ffffffffffffffff81111561049a576104996102ba565b5b6104a68482850161043b565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6fffffffffffffffffffffffffffffffff82169050919050565b610500816104dc565b811461050a575f5ffd5b50565b5f8151905061051b816104f7565b92915050565b5f60208284031215610536576105356102b6565b5b5f6105438482850161050d565b91505092915050565b61055581610379565b811461055f575f5ffd5b50565b5f815190506105708161054c565b92915050565b5f8160020b9050919050565b61058b81610576565b8114610595575f5ffd5b50565b5f815190506105a681610582565b92915050565b5f61ffff82169050919050565b6105c2816105ac565b81146105cc575f5ffd5b50565b5f815190506105dd816105b9565b92915050565b5f60ff82169050919050565b6105f8816105e3565b8114610602575f5ffd5b50565b5f81519050610613816105ef565b92915050565b5f8115159050919050565b61062d81610619565b8114610637575f5ffd5b50565b5f8151905061064881610624565b92915050565b5f5f5f5f5f5f5f60e0888a031215610669576106686102b6565b5b5f6106768a828b01610562565b97505060206106878a828b01610598565b96505060406106988a828b016105cf565b95505060606106a98a828b016105cf565b94505060806106ba8a828b016105cf565b93505060a06106cb8a828b01610605565b92505060c06106dc8a828b0161063a565b91505092959891949750929550565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61071d81610576565b82525050565b61072c816104dc565b82525050565b5f819050919050565b61074481610732565b82525050565b606082015f82015161075e5f850182610714565b5060208201516107716020850182610723565b506040820151610784604085018261073b565b50505050565b5f610795838361074a565b60608301905092915050565b5f602082019050919050565b5f6107b7826106eb565b6107c181856106f5565b93506107cc83610705565b805f5b838110156107fc5781516107e3888261078a565b97506107ee836107a1565b9250506001810190506107cf565b5085935050505092915050565b5f6020820190508181035f83015261082181846107ad565b90509291505056fe","sourceMap":"192:1215:30:-:0;;;345:1060;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;391:31;441:5;:12;425:29;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;391:63;;470:9;482:1;470:13;;465:401;489:5;:12;485:1;:16;465:401;;;522:26;551:12;564:1;551:15;;;;;;;;:::i;:::-;;;;;;;;522:44;;580:19;602:5;608:1;602:8;;;;;;;;:::i;:::-;;;;;;;;580:30;;625:24;672:11;625:59;;720:4;:14;;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;698:9;:19;;:38;;;;;;;;;;;801:4;:10;;;:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;751:62;;;;;;;;;;;;;;;;;;;;752:9;:19;;773:9;:14;;751:62;;;;;;;;;;;;;;846:9;828:12;841:1;828:15;;;;;;;;:::i;:::-;;;;;;;:27;;;;508:358;;;503:3;;;;;465:401;;;;1068:27;1109:12;1098:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;1068:54;;1329:4;1313:14;1309:25;1378:9;1369:7;1365:23;1354:9;1347:42;192:1215;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;7:75:41:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:117;443:1;440;433:12;457:102;498:6;549:2;545:7;540:2;533:5;529:14;525:28;515:38;;457:102;;;:::o;565:180::-;613:77;610:1;603:88;710:4;707:1;700:15;734:4;731:1;724:15;751:281;834:27;856:4;834:27;:::i;:::-;826:6;822:40;964:6;952:10;949:22;928:18;916:10;913:34;910:62;907:88;;;975:18;;:::i;:::-;907:88;1015:10;1011:2;1004:22;794:238;751:281;;:::o;1038:129::-;1072:6;1099:20;;:::i;:::-;1089:30;;1128:33;1156:4;1148:6;1128:33;:::i;:::-;1038:129;;;:::o;1173:311::-;1250:4;1340:18;1332:6;1329:30;1326:56;;;1362:18;;:::i;:::-;1326:56;1412:4;1404:6;1400:17;1392:25;;1472:4;1466;1462:15;1454:23;;1173:311;;;:::o;1490:117::-;1599:1;1596;1589:12;1613:126;1650:7;1690:42;1683:5;1679:54;1668:65;;1613:126;;;:::o;1745:96::-;1782:7;1811:24;1829:5;1811:24;:::i;:::-;1800:35;;1745:96;;;:::o;1847:122::-;1920:24;1938:5;1920:24;:::i;:::-;1913:5;1910:35;1900:63;;1959:1;1956;1949:12;1900:63;1847:122;:::o;1975:143::-;2032:5;2063:6;2057:13;2048:22;;2079:33;2106:5;2079:33;:::i;:::-;1975:143;;;;:::o;2141:732::-;2248:5;2273:81;2289:64;2346:6;2289:64;:::i;:::-;2273:81;:::i;:::-;2264:90;;2374:5;2403:6;2396:5;2389:21;2437:4;2430:5;2426:16;2419:23;;2490:4;2482:6;2478:17;2470:6;2466:30;2519:3;2511:6;2508:15;2505:122;;;2538:79;;:::i;:::-;2505:122;2653:6;2636:231;2670:6;2665:3;2662:15;2636:231;;;2745:3;2774:48;2818:3;2806:10;2774:48;:::i;:::-;2769:3;2762:61;2852:4;2847:3;2843:14;2836:21;;2712:155;2696:4;2691:3;2687:14;2680:21;;2636:231;;;2640:21;2254:619;;2141:732;;;;;:::o;2896:385::-;2978:5;3027:3;3020:4;3012:6;3008:17;3004:27;2994:122;;3035:79;;:::i;:::-;2994:122;3145:6;3139:13;3170:105;3271:3;3263:6;3256:4;3248:6;3244:17;3170:105;:::i;:::-;3161:114;;2984:297;2896:385;;;;:::o;3287:554::-;3382:6;3431:2;3419:9;3410:7;3406:23;3402:32;3399:119;;;3437:79;;:::i;:::-;3399:119;3578:1;3567:9;3563:17;3557:24;3608:18;3600:6;3597:30;3594:117;;;3630:79;;:::i;:::-;3594:117;3735:89;3816:7;3807:6;3796:9;3792:22;3735:89;:::i;:::-;3725:99;;3528:306;3287:554;;;;:::o;3847:180::-;3895:77;3892:1;3885:88;3992:4;3989:1;3982:15;4016:4;4013:1;4006:15;4033:118;4070:7;4110:34;4103:5;4099:46;4088:57;;4033:118;;;:::o;4157:122::-;4230:24;4248:5;4230:24;:::i;:::-;4223:5;4220:35;4210:63;;4269:1;4266;4259:12;4210:63;4157:122;:::o;4285:143::-;4342:5;4373:6;4367:13;4358:22;;4389:33;4416:5;4389:33;:::i;:::-;4285:143;;;;:::o;4434:351::-;4504:6;4553:2;4541:9;4532:7;4528:23;4524:32;4521:119;;;4559:79;;:::i;:::-;4521:119;4679:1;4704:64;4760:7;4751:6;4740:9;4736:22;4704:64;:::i;:::-;4694:74;;4650:128;4434:351;;;;:::o;4791:122::-;4864:24;4882:5;4864:24;:::i;:::-;4857:5;4854:35;4844:63;;4903:1;4900;4893:12;4844:63;4791:122;:::o;4919:143::-;4976:5;5007:6;5001:13;4992:22;;5023:33;5050:5;5023:33;:::i;:::-;4919:143;;;;:::o;5068:90::-;5103:7;5146:5;5143:1;5132:20;5121:31;;5068:90;;;:::o;5164:118::-;5235:22;5251:5;5235:22;:::i;:::-;5228:5;5225:33;5215:61;;5272:1;5269;5262:12;5215:61;5164:118;:::o;5288:139::-;5343:5;5374:6;5368:13;5359:22;;5390:31;5415:5;5390:31;:::i;:::-;5288:139;;;;:::o;5433:89::-;5469:7;5509:6;5502:5;5498:18;5487:29;;5433:89;;;:::o;5528:120::-;5600:23;5617:5;5600:23;:::i;:::-;5593:5;5590:34;5580:62;;5638:1;5635;5628:12;5580:62;5528:120;:::o;5654:141::-;5710:5;5741:6;5735:13;5726:22;;5757:32;5783:5;5757:32;:::i;:::-;5654:141;;;;:::o;5801:86::-;5836:7;5876:4;5869:5;5865:16;5854:27;;5801:86;;;:::o;5893:118::-;5964:22;5980:5;5964:22;:::i;:::-;5957:5;5954:33;5944:61;;6001:1;5998;5991:12;5944:61;5893:118;:::o;6017:139::-;6072:5;6103:6;6097:13;6088:22;;6119:31;6144:5;6119:31;:::i;:::-;6017:139;;;;:::o;6162:90::-;6196:7;6239:5;6232:13;6225:21;6214:32;;6162:90;;;:::o;6258:116::-;6328:21;6343:5;6328:21;:::i;:::-;6321:5;6318:32;6308:60;;6364:1;6361;6354:12;6308:60;6258:116;:::o;6380:137::-;6434:5;6465:6;6459:13;6450:22;;6481:30;6505:5;6481:30;:::i;:::-;6380:137;;;;:::o;6523:1271::-;6637:6;6645;6653;6661;6669;6677;6685;6734:3;6722:9;6713:7;6709:23;6705:33;6702:120;;;6741:79;;:::i;:::-;6702:120;6861:1;6886:64;6942:7;6933:6;6922:9;6918:22;6886:64;:::i;:::-;6876:74;;6832:128;6999:2;7025:62;7079:7;7070:6;7059:9;7055:22;7025:62;:::i;:::-;7015:72;;6970:127;7136:2;7162:63;7217:7;7208:6;7197:9;7193:22;7162:63;:::i;:::-;7152:73;;7107:128;7274:2;7300:63;7355:7;7346:6;7335:9;7331:22;7300:63;:::i;:::-;7290:73;;7245:128;7412:3;7439:63;7494:7;7485:6;7474:9;7470:22;7439:63;:::i;:::-;7429:73;;7383:129;7551:3;7578:62;7632:7;7623:6;7612:9;7608:22;7578:62;:::i;:::-;7568:72;;7522:128;7689:3;7716:61;7769:7;7760:6;7749:9;7745:22;7716:61;:::i;:::-;7706:71;;7660:127;6523:1271;;;;;;;;;;:::o;7800:142::-;7895:6;7929:5;7923:12;7913:22;;7800:142;;;:::o;7948:212::-;8075:11;8109:6;8104:3;8097:19;8149:4;8144:3;8140:14;8125:29;;7948:212;;;;:::o;8166:160::-;8261:4;8284:3;8276:11;;8314:4;8309:3;8305:14;8297:22;;8166:160;;;:::o;8332:102::-;8405:22;8421:5;8405:22;:::i;:::-;8400:3;8393:35;8332:102;;:::o;8440:108::-;8517:24;8535:5;8517:24;:::i;:::-;8512:3;8505:37;8440:108;;:::o;8554:77::-;8591:7;8620:5;8609:16;;8554:77;;;:::o;8637:108::-;8714:24;8732:5;8714:24;:::i;:::-;8709:3;8702:37;8637:108;;:::o;8863:683::-;9006:4;9001:3;8997:14;9093:4;9086:5;9082:16;9076:23;9112:59;9165:4;9160:3;9156:14;9142:12;9112:59;:::i;:::-;9021:160;9268:4;9261:5;9257:16;9251:23;9287:63;9344:4;9339:3;9335:14;9321:12;9287:63;:::i;:::-;9191:169;9447:4;9440:5;9436:16;9430:23;9466:63;9523:4;9518:3;9514:14;9500:12;9466:63;:::i;:::-;9370:169;8975:571;8863:683;;:::o;9552:291::-;9677:10;9698:102;9796:3;9788:6;9698:102;:::i;:::-;9832:4;9827:3;9823:14;9809:28;;9552:291;;;;:::o;9849:141::-;9947:4;9979;9974:3;9970:14;9962:22;;9849:141;;;:::o;10112:956::-;10287:3;10316:82;10392:5;10316:82;:::i;:::-;10414:114;10521:6;10516:3;10414:114;:::i;:::-;10407:121;;10552:84;10630:5;10552:84;:::i;:::-;10659:7;10690:1;10675:368;10700:6;10697:1;10694:13;10675:368;;;10776:6;10770:13;10803:119;10918:3;10903:13;10803:119;:::i;:::-;10796:126;;10945:88;11026:6;10945:88;:::i;:::-;10935:98;;10735:308;10722:1;10719;10715:9;10710:14;;10675:368;;;10679:14;11059:3;11052:10;;10292:776;;;10112:956;;;;:::o;11074:485::-;11273:4;11311:2;11300:9;11296:18;11288:26;;11360:9;11354:4;11350:20;11346:1;11335:9;11331:17;11324:47;11388:164;11547:4;11538:6;11388:164;:::i;:::-;11380:172;;11074:485;;;;:::o","linkReferences":{}},"deployedBytecode":{"object":"0x60806040525f5ffdfea164736f6c634300081c000a","sourceMap":"192:1215:30:-:0;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"pools\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}],\"devdoc\":{\"details\":\"This contract is not meant to be deployed. Instead, use a static call with the deployment bytecode as payload.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/UniswapV3/GetUniswapV3PoolSlot0BatchRequest.sol\":\"GetUniswapV3PoolSlot0BatchRequest\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":forge-std/=lib/forge-std/src/\"]},\"sources\":{\"src/UniswapV3/GetUniswapV3PoolSlot0BatchRequest.sol\":{\"keccak256\":\"0xaf8a81b6f2f914fd54a9adbfe170f17e2d39b2bb1dc5a52d89f42477fe21c28d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://39a49464263df97fd16380057c325b99a91d5a6a24ef0720a844d0dec0e4098a\",\"dweb:/ipfs/QmPbDwPDsQ5n6SGJ5KNE3d47tXj3zosmebkXwEbagYPRH9\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address[]","name":"pools","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["forge-std/=lib/forge-std/src/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"src/UniswapV3/GetUniswapV3PoolSlot0BatchRequest.sol":"GetUniswapV3PoolSlot0BatchRequest"},"evmVersion":"cancun","libraries":{}},"sources":{"src/UniswapV3/GetUniswapV3PoolSlot0BatchRequest.sol":{"keccak256":"0xaf8a81b6f2f914fd54a9adbfe170f17e2d39b2bb1dc5a52d89f42477fe21c28d","urls":["bzz-raw://39a49464263df97fd16380057c325b99a91d5a6a24ef0720a844d0dec0e4098a","dweb:/ipfs/QmPbDwPDsQ5n6SGJ5KNE3d47tXj3zosmebkXwEbagYPRH9"],"license":"MIT"}},"version":1},"id":30} ================================================ FILE: src/amms/abi/GetUniswapV3PoolTickBitmapBatchRequest.json ================================================ {"abi":[{"type":"constructor","inputs":[{"name":"allPoolInfo","type":"tuple[]","internalType":"struct GetUniswapV3PoolTickBitmapBatchRequest.TickBitmapInfo[]","components":[{"name":"pool","type":"address","internalType":"address"},{"name":"minWord","type":"int16","internalType":"int16"},{"name":"maxWord","type":"int16","internalType":"int16"}]}],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x608060405234801561000f575f5ffd5b506040516108b43803806108b4833981810160405281019061003191906104ef565b5f815167ffffffffffffffff81111561004d5761004c6102be565b5b60405190808252806020026020018201604052801561008057816020015b606081526020019060019003908161006b5790505b5090505f5f90505b825181101561026b575f8382815181106100a5576100a4610536565b5b602002602001015190505f815f015190505f6001836020015184604001516100cd9190610590565b6100d791906105f6565b61ffff1667ffffffffffffffff8111156100f4576100f36102be565b5b6040519080825280602002602001820160405280156101225781602001602082028036833780820191505090505b5090505f5f90505f846020015190505b846040015160010b8160010b13610239575f8473ffffffffffffffffffffffffffffffffffffffff16635339c296836040518263ffffffff1660e01b815260040161017d919061063a565b602060405180830381865afa158015610198573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101bc9190610686565b90505f81036101cb5750610228565b8160010b8484815181106101e2576101e1610536565b5b602002602001018181525050826101f8906106b1565b92508084848151811061020e5761020d610536565b5b60200260200101818152505082610224906106b1565b9250505b80610232906106f8565b9050610132565b508082528186868151811061025157610250610536565b5b602002602001018190525050505050806001019050610088565b505f8160405160200161027e9190610893565b60405160208183030381529060405290506020810180590381f35b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6102f4826102ae565b810181811067ffffffffffffffff82111715610313576103126102be565b5b80604052505050565b5f610325610299565b905061033182826102eb565b919050565b5f67ffffffffffffffff8211156103505761034f6102be565b5b602082029050602081019050919050565b5f5ffd5b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61039282610369565b9050919050565b6103a281610388565b81146103ac575f5ffd5b50565b5f815190506103bd81610399565b92915050565b5f8160010b9050919050565b6103d8816103c3565b81146103e2575f5ffd5b50565b5f815190506103f3816103cf565b92915050565b5f6060828403121561040e5761040d610365565b5b610418606061031c565b90505f610427848285016103af565b5f83015250602061043a848285016103e5565b602083015250604061044e848285016103e5565b60408301525092915050565b5f61046c61046784610336565b61031c565b9050808382526020820190506060840283018581111561048f5761048e610361565b5b835b818110156104b857806104a488826103f9565b845260208401935050606081019050610491565b5050509392505050565b5f82601f8301126104d6576104d56102aa565b5b81516104e684826020860161045a565b91505092915050565b5f60208284031215610504576105036102a2565b5b5f82015167ffffffffffffffff811115610521576105206102a6565b5b61052d848285016104c2565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61059a826103c3565b91506105a5836103c3565b92508282039050617fff81137fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000821217156105e3576105e2610563565b5b92915050565b5f61ffff82169050919050565b5f610600826105e9565b915061060b836105e9565b9250828201905061ffff81111561062557610624610563565b5b92915050565b610634816103c3565b82525050565b5f60208201905061064d5f83018461062b565b92915050565b5f819050919050565b61066581610653565b811461066f575f5ffd5b50565b5f815190506106808161065c565b92915050565b5f6020828403121561069b5761069a6102a2565b5b5f6106a884828501610672565b91505092915050565b5f6106bb82610653565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036106ed576106ec610563565b5b600182019050919050565b5f610702826103c3565b9150617fff820361071657610715610563565b5b600182019050919050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61077c81610653565b82525050565b5f61078d8383610773565b60208301905092915050565b5f602082019050919050565b5f6107af8261074a565b6107b98185610754565b93506107c483610764565b805f5b838110156107f45781516107db8882610782565b97506107e683610799565b9250506001810190506107c7565b5085935050505092915050565b5f61080c83836107a5565b905092915050565b5f602082019050919050565b5f61082a82610721565b610834818561072b565b9350836020820285016108468561073b565b805f5b8581101561088157848403895281516108628582610801565b945061086d83610814565b925060208a01995050600181019050610849565b50829750879550505050505092915050565b5f6020820190508181035f8301526108ab8184610820565b90509291505056fe","sourceMap":"192:1778:31:-:0;;;443:1525;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;502:33;554:11;:18;538:35;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;502:71;;589:9;601:1;589:13;;584:843;608:11;:18;604:1;:22;584:843;;;647:26;676:11;688:1;676:14;;;;;;;;:::i;:::-;;;;;;;;647:43;;704:24;751:4;:9;;;704:57;;776:28;859:1;843:4;:12;;;828:4;:12;;;:27;;;;:::i;:::-;821:39;;;;:::i;:::-;807:54;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;776:85;;876:15;894:1;876:19;;914:7;924:4;:12;;;914:22;;909:379;943:4;:12;;;938:17;;:1;:17;;;909:379;;980:18;1001:4;:15;;;1017:1;1001:18;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;980:39;;1056:1;1042:10;:15;1038:70;;1081:8;;;1038:70;1164:1;1157:9;;1126:11;1138:7;1126:20;;;;;;;;:::i;:::-;;;;;;;:41;;;;;1185:9;;;;:::i;:::-;;;1236:10;1213:11;1225:7;1213:20;;;;;;;;:::i;:::-;;;;;;;:33;;;;;1264:9;;;;:::i;:::-;;;962:326;909:379;957:3;;;;:::i;:::-;;;909:379;;;;1349:7;1336:11;1329:28;1405:11;1385:14;1400:1;1385:17;;;;;;;;:::i;:::-;;;;;;;:31;;;;633:794;;;;628:3;;;;;584:843;;;;1629:27;1670:14;1659:26;;;;;;;;:::i;:::-;;;;;;;;;;;;;1629:56;;1892:4;1876:14;1872:25;1941:9;1932:7;1928:23;1917:9;1910:42;7:75:41;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:117;443:1;440;433:12;457:102;498:6;549:2;545:7;540:2;533:5;529:14;525:28;515:38;;457:102;;;:::o;565:180::-;613:77;610:1;603:88;710:4;707:1;700:15;734:4;731:1;724:15;751:281;834:27;856:4;834:27;:::i;:::-;826:6;822:40;964:6;952:10;949:22;928:18;916:10;913:34;910:62;907:88;;;975:18;;:::i;:::-;907:88;1015:10;1011:2;1004:22;794:238;751:281;;:::o;1038:129::-;1072:6;1099:20;;:::i;:::-;1089:30;;1128:33;1156:4;1148:6;1128:33;:::i;:::-;1038:129;;;:::o;1173:344::-;1283:4;1373:18;1365:6;1362:30;1359:56;;;1395:18;;:::i;:::-;1359:56;1445:4;1437:6;1433:17;1425:25;;1505:4;1499;1495:15;1487:23;;1173:344;;;:::o;1523:117::-;1632:1;1629;1622:12;1646:117;1755:1;1752;1745:12;1892:126;1929:7;1969:42;1962:5;1958:54;1947:65;;1892:126;;;:::o;2024:96::-;2061:7;2090:24;2108:5;2090:24;:::i;:::-;2079:35;;2024:96;;;:::o;2126:122::-;2199:24;2217:5;2199:24;:::i;:::-;2192:5;2189:35;2179:63;;2238:1;2235;2228:12;2179:63;2126:122;:::o;2254:143::-;2311:5;2342:6;2336:13;2327:22;;2358:33;2385:5;2358:33;:::i;:::-;2254:143;;;;:::o;2403:90::-;2438:7;2481:5;2478:1;2467:20;2456:31;;2403:90;;;:::o;2499:118::-;2570:22;2586:5;2570:22;:::i;:::-;2563:5;2560:33;2550:61;;2607:1;2604;2597:12;2550:61;2499:118;:::o;2623:139::-;2678:5;2709:6;2703:13;2694:22;;2725:31;2750:5;2725:31;:::i;:::-;2623:139;;;;:::o;2836:789::-;2929:5;2973:4;2961:9;2956:3;2952:19;2948:30;2945:117;;;2981:79;;:::i;:::-;2945:117;3080:21;3096:4;3080:21;:::i;:::-;3071:30;;3160:1;3200:60;3256:3;3247:6;3236:9;3232:22;3200:60;:::i;:::-;3193:4;3186:5;3182:16;3175:86;3111:161;3334:2;3375:58;3429:3;3420:6;3409:9;3405:22;3375:58;:::i;:::-;3368:4;3361:5;3357:16;3350:84;3282:163;3507:2;3548:58;3602:3;3593:6;3582:9;3578:22;3548:58;:::i;:::-;3541:4;3534:5;3530:16;3523:84;3455:163;2836:789;;;;:::o;3701:831::-;3841:5;3866:114;3882:97;3972:6;3882:97;:::i;:::-;3866:114;:::i;:::-;3857:123;;4000:5;4029:6;4022:5;4015:21;4063:4;4056:5;4052:16;4045:23;;4116:4;4108:6;4104:17;4096:6;4092:30;4145:3;4137:6;4134:15;4131:122;;;4164:79;;:::i;:::-;4131:122;4279:6;4262:264;4296:6;4291:3;4288:15;4262:264;;;4371:3;4400:81;4477:3;4465:10;4400:81;:::i;:::-;4395:3;4388:94;4511:4;4506:3;4502:14;4495:21;;4338:188;4322:4;4317:3;4313:14;4306:21;;4262:264;;;4266:21;3847:685;;3701:831;;;;;:::o;4608:451::-;4723:5;4772:3;4765:4;4757:6;4753:17;4749:27;4739:122;;4780:79;;:::i;:::-;4739:122;4890:6;4884:13;4915:138;5049:3;5041:6;5034:4;5026:6;5022:17;4915:138;:::i;:::-;4906:147;;4729:330;4608:451;;;;:::o;5065:620::-;5193:6;5242:2;5230:9;5221:7;5217:23;5213:32;5210:119;;;5248:79;;:::i;:::-;5210:119;5389:1;5378:9;5374:17;5368:24;5419:18;5411:6;5408:30;5405:117;;;5441:79;;:::i;:::-;5405:117;5546:122;5660:7;5651:6;5640:9;5636:22;5546:122;:::i;:::-;5536:132;;5339:339;5065:620;;;;:::o;5691:180::-;5739:77;5736:1;5729:88;5836:4;5833:1;5826:15;5860:4;5857:1;5850:15;5877:180;5925:77;5922:1;5915:88;6022:4;6019:1;6012:15;6046:4;6043:1;6036:15;6063:311;6101:4;6121:18;6137:1;6121:18;:::i;:::-;6116:23;;6153:18;6169:1;6153:18;:::i;:::-;6148:23;;6195:1;6192;6188:9;6180:17;;6327:6;6321:4;6317:17;6236:66;6230:4;6226:77;6210:134;6207:160;;;6347:18;;:::i;:::-;6207:160;6063:311;;;;:::o;6380:89::-;6416:7;6456:6;6449:5;6445:18;6434:29;;6380:89;;;:::o;6475:193::-;6514:3;6533:19;6550:1;6533:19;:::i;:::-;6528:24;;6566:19;6583:1;6566:19;:::i;:::-;6561:24;;6608:1;6605;6601:9;6594:16;;6631:6;6626:3;6623:15;6620:41;;;6641:18;;:::i;:::-;6620:41;6475:193;;;;:::o;6674:112::-;6757:22;6773:5;6757:22;:::i;:::-;6752:3;6745:35;6674:112;;:::o;6792:214::-;6881:4;6919:2;6908:9;6904:18;6896:26;;6932:67;6996:1;6985:9;6981:17;6972:6;6932:67;:::i;:::-;6792:214;;;;:::o;7012:77::-;7049:7;7078:5;7067:16;;7012:77;;;:::o;7095:122::-;7168:24;7186:5;7168:24;:::i;:::-;7161:5;7158:35;7148:63;;7207:1;7204;7197:12;7148:63;7095:122;:::o;7223:143::-;7280:5;7311:6;7305:13;7296:22;;7327:33;7354:5;7327:33;:::i;:::-;7223:143;;;;:::o;7372:351::-;7442:6;7491:2;7479:9;7470:7;7466:23;7462:32;7459:119;;;7497:79;;:::i;:::-;7459:119;7617:1;7642:64;7698:7;7689:6;7678:9;7674:22;7642:64;:::i;:::-;7632:74;;7588:128;7372:351;;;;:::o;7729:233::-;7768:3;7791:24;7809:5;7791:24;:::i;:::-;7782:33;;7837:66;7830:5;7827:77;7824:103;;7907:18;;:::i;:::-;7824:103;7954:1;7947:5;7943:13;7936:20;;7729:233;;;:::o;7968:169::-;8005:3;8028:22;8044:5;8028:22;:::i;:::-;8019:31;;8072:6;8065:5;8062:17;8059:43;;8082:18;;:::i;:::-;8059:43;8129:1;8122:5;8118:13;8111:20;;7968:169;;;:::o;8143:139::-;8235:6;8269:5;8263:12;8253:22;;8143:139;;;:::o;8288:209::-;8412:11;8446:6;8441:3;8434:19;8486:4;8481:3;8477:14;8462:29;;8288:209;;;;:::o;8503:157::-;8595:4;8618:3;8610:11;;8648:4;8643:3;8639:14;8631:22;;8503:157;;;:::o;8666:114::-;8733:6;8767:5;8761:12;8751:22;;8666:114;;;:::o;8786:174::-;8875:11;8909:6;8904:3;8897:19;8949:4;8944:3;8940:14;8925:29;;8786:174;;;;:::o;8966:132::-;9033:4;9056:3;9048:11;;9086:4;9081:3;9077:14;9069:22;;8966:132;;;:::o;9104:108::-;9181:24;9199:5;9181:24;:::i;:::-;9176:3;9169:37;9104:108;;:::o;9218:179::-;9287:10;9308:46;9350:3;9342:6;9308:46;:::i;:::-;9386:4;9381:3;9377:14;9363:28;;9218:179;;;;:::o;9403:113::-;9473:4;9505;9500:3;9496:14;9488:22;;9403:113;;;:::o;9552:712::-;9661:3;9690:54;9738:5;9690:54;:::i;:::-;9760:76;9829:6;9824:3;9760:76;:::i;:::-;9753:83;;9860:56;9910:5;9860:56;:::i;:::-;9939:7;9970:1;9955:284;9980:6;9977:1;9974:13;9955:284;;;10056:6;10050:13;10083:63;10142:3;10127:13;10083:63;:::i;:::-;10076:70;;10169:60;10222:6;10169:60;:::i;:::-;10159:70;;10015:224;10002:1;9999;9995:9;9990:14;;9955:284;;;9959:14;10255:3;10248:10;;9666:598;;;9552:712;;;;:::o;10270:256::-;10389:10;10424:96;10516:3;10508:6;10424:96;:::i;:::-;10410:110;;10270:256;;;;:::o;10532:138::-;10627:4;10659;10654:3;10650:14;10642:22;;10532:138;;;:::o;10710:1111::-;10879:3;10908:79;10981:5;10908:79;:::i;:::-;11003:111;11107:6;11102:3;11003:111;:::i;:::-;10996:118;;11140:3;11185:4;11177:6;11173:17;11168:3;11164:27;11215:81;11290:5;11215:81;:::i;:::-;11319:7;11350:1;11335:441;11360:6;11357:1;11354:13;11335:441;;;11431:9;11425:4;11421:20;11416:3;11409:33;11482:6;11476:13;11510:114;11619:4;11604:13;11510:114;:::i;:::-;11502:122;;11647:85;11725:6;11647:85;:::i;:::-;11637:95;;11761:4;11756:3;11752:14;11745:21;;11395:381;11382:1;11379;11375:9;11370:14;;11335:441;;;11339:14;11792:4;11785:11;;11812:3;11805:10;;10884:937;;;;;10710:1111;;;;:::o;11827:473::-;12020:4;12058:2;12047:9;12043:18;12035:26;;12107:9;12101:4;12097:20;12093:1;12082:9;12078:17;12071:47;12135:158;12288:4;12279:6;12135:158;:::i;:::-;12127:166;;11827:473;;;;:::o","linkReferences":{}},"deployedBytecode":{"object":"0x60806040525f5ffdfea164736f6c634300081c000a","sourceMap":"192:1778:31:-:0;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"int16\",\"name\":\"minWord\",\"type\":\"int16\"},{\"internalType\":\"int16\",\"name\":\"maxWord\",\"type\":\"int16\"}],\"internalType\":\"struct GetUniswapV3PoolTickBitmapBatchRequest.TickBitmapInfo[]\",\"name\":\"allPoolInfo\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}],\"devdoc\":{\"details\":\"This contract is not meant to be deployed. Instead, use a static call with the deployment bytecode as payload.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/UniswapV3/GetUniswapV3PoolTickBitmapBatchRequest.sol\":\"GetUniswapV3PoolTickBitmapBatchRequest\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":forge-std/=lib/forge-std/src/\"]},\"sources\":{\"src/UniswapV3/GetUniswapV3PoolTickBitmapBatchRequest.sol\":{\"keccak256\":\"0x1d72e66cf86ebcfc9b92460c7ef6b4964d191b3f6e67cd008cab226fd377af64\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f8364aaeb50f6d6809de6e95dab98260d7abe6b2b7bc4a5b5386f2a65f928184\",\"dweb:/ipfs/QmRJFENg5eFBoSqRgskPL354vRaNoYh5Vgyqp47QTmdcP5\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"struct GetUniswapV3PoolTickBitmapBatchRequest.TickBitmapInfo[]","name":"allPoolInfo","type":"tuple[]","components":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"int16","name":"minWord","type":"int16"},{"internalType":"int16","name":"maxWord","type":"int16"}]}],"stateMutability":"nonpayable","type":"constructor"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["forge-std/=lib/forge-std/src/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"src/UniswapV3/GetUniswapV3PoolTickBitmapBatchRequest.sol":"GetUniswapV3PoolTickBitmapBatchRequest"},"evmVersion":"cancun","libraries":{}},"sources":{"src/UniswapV3/GetUniswapV3PoolTickBitmapBatchRequest.sol":{"keccak256":"0x1d72e66cf86ebcfc9b92460c7ef6b4964d191b3f6e67cd008cab226fd377af64","urls":["bzz-raw://f8364aaeb50f6d6809de6e95dab98260d7abe6b2b7bc4a5b5386f2a65f928184","dweb:/ipfs/QmRJFENg5eFBoSqRgskPL354vRaNoYh5Vgyqp47QTmdcP5"],"license":"MIT"}},"version":1},"id":31} ================================================ FILE: src/amms/abi/GetUniswapV3PoolTickDataBatchRequest.json ================================================ {"abi":[{"type":"constructor","inputs":[{"name":"allPoolInfo","type":"tuple[]","internalType":"struct GetUniswapV3PoolTickDataBatchRequest.TickDataInfo[]","components":[{"name":"pool","type":"address","internalType":"address"},{"name":"ticks","type":"int24[]","internalType":"int24[]"}]}],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x608060405234801561000f575f5ffd5b50604051610b36380380610b368339818101604052810190610031919061063a565b5f815167ffffffffffffffff81111561004d5761004c61031f565b5b60405190808252806020026020018201604052801561008057816020015b606081526020019060019003908161006b5790505b5090505f5f90505b8251811015610297575f8382815181106100a5576100a4610681565b5b6020026020010151602001515167ffffffffffffffff8111156100cb576100ca61031f565b5b60405190808252806020026020018201604052801561010457816020015b6100f16102c5565b8152602001906001900390816100e95790505b5090505f5f90505b84838151811061011f5761011e610681565b5b6020026020010151602001515181101561026b575f85848151811061014757610146610681565b5b60200260200101515f015173ffffffffffffffffffffffffffffffffffffffff1663f30dba938786815181106101805761017f610681565b5b602002602001015160200151848151811061019e5761019d610681565b5b60200260200101516040518263ffffffff1660e01b81526004016101c291906106bd565b61010060405180830381865afa1580156101de573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102029190610919565b905060405180606001604052808260e0015115158152602001825f01516fffffffffffffffffffffffffffffffff1681526020018260200151600f0b81525083838151811061025457610253610681565b5b60200260200101819052505080600101905061010c565b50808383815181106102805761027f610681565b5b602002602001018190525050806001019050610088565b505f816040516020016102aa9190610b15565b60405160208183030381529060405290506020810180590381f35b60405180606001604052805f151581526020015f6fffffffffffffffffffffffffffffffff1681526020015f600f0b81525090565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6103558261030f565b810181811067ffffffffffffffff821117156103745761037361031f565b5b80604052505050565b5f6103866102fa565b9050610392828261034c565b919050565b5f67ffffffffffffffff8211156103b1576103b061031f565b5b602082029050602081019050919050565b5f5ffd5b5f5ffd5b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6103f7826103ce565b9050919050565b610407816103ed565b8114610411575f5ffd5b50565b5f81519050610422816103fe565b92915050565b5f67ffffffffffffffff8211156104425761044161031f565b5b602082029050602081019050919050565b5f8160020b9050919050565b61046881610453565b8114610472575f5ffd5b50565b5f815190506104838161045f565b92915050565b5f61049b61049684610428565b61037d565b905080838252602082019050602084028301858111156104be576104bd6103c2565b5b835b818110156104e757806104d38882610475565b8452602084019350506020810190506104c0565b5050509392505050565b5f82601f8301126105055761050461030b565b5b8151610515848260208601610489565b91505092915050565b5f60408284031215610533576105326103c6565b5b61053d604061037d565b90505f61054c84828501610414565b5f83015250602082015167ffffffffffffffff81111561056f5761056e6103ca565b5b61057b848285016104f1565b60208301525092915050565b5f61059961059484610397565b61037d565b905080838252602082019050602084028301858111156105bc576105bb6103c2565b5b835b8181101561060357805167ffffffffffffffff8111156105e1576105e061030b565b5b8086016105ee898261051e565b855260208501945050506020810190506105be565b5050509392505050565b5f82601f8301126106215761062061030b565b5b8151610631848260208601610587565b91505092915050565b5f6020828403121561064f5761064e610303565b5b5f82015167ffffffffffffffff81111561066c5761066b610307565b5b6106788482850161060d565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b6106b781610453565b82525050565b5f6020820190506106d05f8301846106ae565b92915050565b5f6fffffffffffffffffffffffffffffffff82169050919050565b6106fa816106d6565b8114610704575f5ffd5b50565b5f81519050610715816106f1565b92915050565b5f81600f0b9050919050565b6107308161071b565b811461073a575f5ffd5b50565b5f8151905061074b81610727565b92915050565b5f819050919050565b61076381610751565b811461076d575f5ffd5b50565b5f8151905061077e8161075a565b92915050565b5f8160060b9050919050565b61079981610784565b81146107a3575f5ffd5b50565b5f815190506107b481610790565b92915050565b6107c3816103ce565b81146107cd575f5ffd5b50565b5f815190506107de816107ba565b92915050565b5f63ffffffff82169050919050565b6107fc816107e4565b8114610806575f5ffd5b50565b5f81519050610817816107f3565b92915050565b5f8115159050919050565b6108318161081d565b811461083b575f5ffd5b50565b5f8151905061084c81610828565b92915050565b5f6101008284031215610868576108676103c6565b5b61087361010061037d565b90505f61088284828501610707565b5f8301525060206108958482850161073d565b60208301525060406108a984828501610770565b60408301525060606108bd84828501610770565b60608301525060806108d1848285016107a6565b60808301525060a06108e5848285016107d0565b60a08301525060c06108f984828501610809565b60c08301525060e061090d8482850161083e565b60e08301525092915050565b5f610100828403121561092f5761092e610303565b5b5f61093c84828501610852565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6109a08161081d565b82525050565b6109af816106d6565b82525050565b6109be8161071b565b82525050565b606082015f8201516109d85f850182610997565b5060208201516109eb60208501826109a6565b5060408201516109fe60408501826109b5565b50505050565b5f610a0f83836109c4565b60608301905092915050565b5f602082019050919050565b5f610a318261096e565b610a3b8185610978565b9350610a4683610988565b805f5b83811015610a76578151610a5d8882610a04565b9750610a6883610a1b565b925050600181019050610a49565b5085935050505092915050565b5f610a8e8383610a27565b905092915050565b5f602082019050919050565b5f610aac82610945565b610ab6818561094f565b935083602082028501610ac88561095f565b805f5b85811015610b035784840389528151610ae48582610a83565b9450610aef83610a96565b925060208a01995050600181019050610acb565b50829750879550505050505092915050565b5f6020820190508181035f830152610b2d8184610aa2565b90509291505056fe","sourceMap":"193:1568:32:-:0;;;435:1324;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;492:30;538:11;:18;525:32;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;492:65;;573:9;585:1;573:13;;568:650;592:11;:18;588:1;:22;568:650;;;631:22;667:11;679:1;667:14;;;;;;;;:::i;:::-;;;;;;;;:20;;;:27;656:39;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;631:64;;714:9;726:1;714:13;;709:457;733:11;745:1;733:14;;;;;;;;:::i;:::-;;;;;;;;:20;;;:27;729:1;:31;709:457;;;785:36;865:11;877:1;865:14;;;;;;;;:::i;:::-;;;;;;;;:19;;;824:84;;;909:11;921:1;909:14;;;;;;;;:::i;:::-;;;;;;;;:20;;;930:1;909:23;;;;;;;;:::i;:::-;;;;;;;;824:109;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;785:148;;966:185;;;;;;;;1116:4;:16;;;966:185;;;;;;1009:4;:19;;;966:185;;;;;;1064:4;:17;;;966:185;;;;;952:8;961:1;952:11;;;;;;;;:::i;:::-;;;;;;;:199;;;;767:399;762:3;;;;;709:457;;;;1199:8;1179:14;1194:1;1179:17;;;;;;;;:::i;:::-;;;;;;;:28;;;;617:601;612:3;;;;;568:650;;;;1420:27;1461:14;1450:26;;;;;;;;:::i;:::-;;;;;;;;;;;;;1420:56;;1683:4;1667:14;1663:25;1732:9;1723:7;1719:23;1708:9;1701:42;193:1568;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;7:75:41:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:117;443:1;440;433:12;457:102;498:6;549:2;545:7;540:2;533:5;529:14;525:28;515:38;;457:102;;;:::o;565:180::-;613:77;610:1;603:88;710:4;707:1;700:15;734:4;731:1;724:15;751:281;834:27;856:4;834:27;:::i;:::-;826:6;822:40;964:6;952:10;949:22;928:18;916:10;913:34;910:62;907:88;;;975:18;;:::i;:::-;907:88;1015:10;1011:2;1004:22;794:238;751:281;;:::o;1038:129::-;1072:6;1099:20;;:::i;:::-;1089:30;;1128:33;1156:4;1148:6;1128:33;:::i;:::-;1038:129;;;:::o;1173:342::-;1281:4;1371:18;1363:6;1360:30;1357:56;;;1393:18;;:::i;:::-;1357:56;1443:4;1435:6;1431:17;1423:25;;1503:4;1497;1493:15;1485:23;;1173:342;;;:::o;1521:117::-;1630:1;1627;1620:12;1644:117;1753:1;1750;1743:12;1767:117;1876:1;1873;1866:12;1890:126;1927:7;1967:42;1960:5;1956:54;1945:65;;1890:126;;;:::o;2022:96::-;2059:7;2088:24;2106:5;2088:24;:::i;:::-;2077:35;;2022:96;;;:::o;2124:122::-;2197:24;2215:5;2197:24;:::i;:::-;2190:5;2187:35;2177:63;;2236:1;2233;2226:12;2177:63;2124:122;:::o;2252:143::-;2309:5;2340:6;2334:13;2325:22;;2356:33;2383:5;2356:33;:::i;:::-;2252:143;;;;:::o;2401:309::-;2476:4;2566:18;2558:6;2555:30;2552:56;;;2588:18;;:::i;:::-;2552:56;2638:4;2630:6;2626:17;2618:25;;2698:4;2692;2688:15;2680:23;;2401:309;;;:::o;2716:90::-;2751:7;2794:5;2791:1;2780:20;2769:31;;2716:90;;;:::o;2812:118::-;2883:22;2899:5;2883:22;:::i;:::-;2876:5;2873:33;2863:61;;2920:1;2917;2910:12;2863:61;2812:118;:::o;2936:139::-;2991:5;3022:6;3016:13;3007:22;;3038:31;3063:5;3038:31;:::i;:::-;2936:139;;;;:::o;3096:726::-;3201:5;3226:79;3242:62;3297:6;3242:62;:::i;:::-;3226:79;:::i;:::-;3217:88;;3325:5;3354:6;3347:5;3340:21;3388:4;3381:5;3377:16;3370:23;;3441:4;3433:6;3429:17;3421:6;3417:30;3470:3;3462:6;3459:15;3456:122;;;3489:79;;:::i;:::-;3456:122;3604:6;3587:229;3621:6;3616:3;3613:15;3587:229;;;3696:3;3725:46;3767:3;3755:10;3725:46;:::i;:::-;3720:3;3713:59;3801:4;3796:3;3792:14;3785:21;;3663:153;3647:4;3642:3;3638:14;3631:21;;3587:229;;;3591:21;3207:615;;3096:726;;;;;:::o;3843:381::-;3923:5;3972:3;3965:4;3957:6;3953:17;3949:27;3939:122;;3980:79;;:::i;:::-;3939:122;4090:6;4084:13;4115:103;4214:3;4206:6;4199:4;4191:6;4187:17;4115:103;:::i;:::-;4106:112;;3929:295;3843:381;;;;:::o;4294:790::-;4385:5;4429:4;4417:9;4412:3;4408:19;4404:30;4401:117;;;4437:79;;:::i;:::-;4401:117;4536:21;4552:4;4536:21;:::i;:::-;4527:30;;4616:1;4656:60;4712:3;4703:6;4692:9;4688:22;4656:60;:::i;:::-;4649:4;4642:5;4638:16;4631:86;4567:161;4809:2;4798:9;4794:18;4788:25;4840:18;4832:6;4829:30;4826:117;;;4862:79;;:::i;:::-;4826:117;4982:83;5061:3;5052:6;5041:9;5037:22;4982:83;:::i;:::-;4975:4;4968:5;4964:16;4957:109;4738:339;4294:790;;;;:::o;5156:1023::-;5294:5;5319:112;5335:95;5423:6;5335:95;:::i;:::-;5319:112;:::i;:::-;5310:121;;5451:5;5480:6;5473:5;5466:21;5514:4;5507:5;5503:16;5496:23;;5567:4;5559:6;5555:17;5547:6;5543:30;5596:3;5588:6;5585:15;5582:122;;;5615:79;;:::i;:::-;5582:122;5730:6;5713:460;5747:6;5742:3;5739:15;5713:460;;;5829:3;5823:10;5865:18;5852:11;5849:35;5846:122;;;5887:79;;:::i;:::-;5846:122;6011:11;6003:6;5999:24;6049:79;6124:3;6112:10;6049:79;:::i;:::-;6044:3;6037:92;6158:4;6153:3;6149:14;6142:21;;5789:384;;5773:4;5768:3;5764:14;5757:21;;5713:460;;;5717:21;5300:879;;5156:1023;;;;;:::o;6251:447::-;6364:5;6413:3;6406:4;6398:6;6394:17;6390:27;6380:122;;6421:79;;:::i;:::-;6380:122;6531:6;6525:13;6556:136;6688:3;6680:6;6673:4;6665:6;6661:17;6556:136;:::i;:::-;6547:145;;6370:328;6251:447;;;;:::o;6704:616::-;6830:6;6879:2;6867:9;6858:7;6854:23;6850:32;6847:119;;;6885:79;;:::i;:::-;6847:119;7026:1;7015:9;7011:17;7005:24;7056:18;7048:6;7045:30;7042:117;;;7078:79;;:::i;:::-;7042:117;7183:120;7295:7;7286:6;7275:9;7271:22;7183:120;:::i;:::-;7173:130;;6976:337;6704:616;;;;:::o;7326:180::-;7374:77;7371:1;7364:88;7471:4;7468:1;7461:15;7495:4;7492:1;7485:15;7512:112;7595:22;7611:5;7595:22;:::i;:::-;7590:3;7583:35;7512:112;;:::o;7630:214::-;7719:4;7757:2;7746:9;7742:18;7734:26;;7770:67;7834:1;7823:9;7819:17;7810:6;7770:67;:::i;:::-;7630:214;;;;:::o;7850:118::-;7887:7;7927:34;7920:5;7916:46;7905:57;;7850:118;;;:::o;7974:122::-;8047:24;8065:5;8047:24;:::i;:::-;8040:5;8037:35;8027:63;;8086:1;8083;8076:12;8027:63;7974:122;:::o;8102:143::-;8159:5;8190:6;8184:13;8175:22;;8206:33;8233:5;8206:33;:::i;:::-;8102:143;;;;:::o;8251:92::-;8287:7;8331:5;8327:2;8316:21;8305:32;;8251:92;;;:::o;8349:120::-;8421:23;8438:5;8421:23;:::i;:::-;8414:5;8411:34;8401:62;;8459:1;8456;8449:12;8401:62;8349:120;:::o;8475:141::-;8531:5;8562:6;8556:13;8547:22;;8578:32;8604:5;8578:32;:::i;:::-;8475:141;;;;:::o;8622:77::-;8659:7;8688:5;8677:16;;8622:77;;;:::o;8705:122::-;8778:24;8796:5;8778:24;:::i;:::-;8771:5;8768:35;8758:63;;8817:1;8814;8807:12;8758:63;8705:122;:::o;8833:143::-;8890:5;8921:6;8915:13;8906:22;;8937:33;8964:5;8937:33;:::i;:::-;8833:143;;;;:::o;8982:90::-;9017:7;9060:5;9057:1;9046:20;9035:31;;8982:90;;;:::o;9078:118::-;9149:22;9165:5;9149:22;:::i;:::-;9142:5;9139:33;9129:61;;9186:1;9183;9176:12;9129:61;9078:118;:::o;9202:139::-;9257:5;9288:6;9282:13;9273:22;;9304:31;9329:5;9304:31;:::i;:::-;9202:139;;;;:::o;9347:122::-;9420:24;9438:5;9420:24;:::i;:::-;9413:5;9410:35;9400:63;;9459:1;9456;9449:12;9400:63;9347:122;:::o;9475:143::-;9532:5;9563:6;9557:13;9548:22;;9579:33;9606:5;9579:33;:::i;:::-;9475:143;;;;:::o;9624:93::-;9660:7;9700:10;9693:5;9689:22;9678:33;;9624:93;;;:::o;9723:120::-;9795:23;9812:5;9795:23;:::i;:::-;9788:5;9785:34;9775:62;;9833:1;9830;9823:12;9775:62;9723:120;:::o;9849:141::-;9905:5;9936:6;9930:13;9921:22;;9952:32;9978:5;9952:32;:::i;:::-;9849:141;;;;:::o;9996:90::-;10030:7;10073:5;10066:13;10059:21;10048:32;;9996:90;;;:::o;10092:116::-;10162:21;10177:5;10162:21;:::i;:::-;10155:5;10152:32;10142:60;;10198:1;10195;10188:12;10142:60;10092:116;:::o;10214:137::-;10268:5;10299:6;10293:13;10284:22;;10315:30;10339:5;10315:30;:::i;:::-;10214:137;;;;:::o;10396:1750::-;10479:5;10523:6;10511:9;10506:3;10502:19;10498:32;10495:119;;;10533:79;;:::i;:::-;10495:119;10632:23;10648:6;10632:23;:::i;:::-;10623:32;;10724:1;10764:60;10820:3;10811:6;10800:9;10796:22;10764:60;:::i;:::-;10757:4;10750:5;10746:16;10739:86;10665:171;10903:2;10944:59;10999:3;10990:6;10979:9;10975:22;10944:59;:::i;:::-;10937:4;10930:5;10926:16;10919:85;10846:169;11091:2;11132:60;11188:3;11179:6;11168:9;11164:22;11132:60;:::i;:::-;11125:4;11118:5;11114:16;11107:86;11025:179;11280:2;11321:60;11377:3;11368:6;11357:9;11353:22;11321:60;:::i;:::-;11314:4;11307:5;11303:16;11296:86;11214:179;11469:3;11511:58;11565:3;11556:6;11545:9;11541:22;11511:58;:::i;:::-;11504:4;11497:5;11493:16;11486:84;11403:178;11666:3;11708:60;11764:3;11755:6;11744:9;11740:22;11708:60;:::i;:::-;11701:4;11694:5;11690:16;11683:86;11591:189;11849:3;11891:59;11946:3;11937:6;11926:9;11922:22;11891:59;:::i;:::-;11884:4;11877:5;11873:16;11866:85;11790:172;12028:3;12070:57;12123:3;12114:6;12103:9;12099:22;12070:57;:::i;:::-;12063:4;12056:5;12052:16;12045:83;11972:167;10396:1750;;;;:::o;12152:398::-;12245:6;12294:3;12282:9;12273:7;12269:23;12265:33;12262:120;;;12301:79;;:::i;:::-;12262:120;12421:1;12446:87;12525:7;12516:6;12505:9;12501:22;12446:87;:::i;:::-;12436:97;;12392:151;12152:398;;;;:::o;12556:162::-;12671:6;12705:5;12699:12;12689:22;;12556:162;;;:::o;12724:232::-;12871:11;12905:6;12900:3;12893:19;12945:4;12940:3;12936:14;12921:29;;12724:232;;;;:::o;12962:180::-;13077:4;13100:3;13092:11;;13130:4;13125:3;13121:14;13113:22;;12962:180;;;:::o;13148:137::-;13238:6;13272:5;13266:12;13256:22;;13148:137;;;:::o;13291:197::-;13403:11;13437:6;13432:3;13425:19;13477:4;13472:3;13468:14;13453:29;;13291:197;;;;:::o;13494:155::-;13584:4;13607:3;13599:11;;13637:4;13632:3;13628:14;13620:22;;13494:155;;;:::o;13655:99::-;13726:21;13741:5;13726:21;:::i;:::-;13721:3;13714:34;13655:99;;:::o;13760:108::-;13837:24;13855:5;13837:24;:::i;:::-;13832:3;13825:37;13760:108;;:::o;13874:105::-;13949:23;13966:5;13949:23;:::i;:::-;13944:3;13937:36;13874:105;;:::o;14093:684::-;14226:4;14221:3;14217:14;14320:4;14313:5;14309:16;14303:23;14339:57;14390:4;14385:3;14381:14;14367:12;14339:57;:::i;:::-;14241:165;14498:4;14491:5;14487:16;14481:23;14517:63;14574:4;14569:3;14565:14;14551:12;14517:63;:::i;:::-;14416:174;14680:4;14673:5;14669:16;14663:23;14699:61;14754:4;14749:3;14745:14;14731:12;14699:61;:::i;:::-;14600:170;14195:582;14093:684;;:::o;14783:271::-;14898:10;14919:92;15007:3;14999:6;14919:92;:::i;:::-;15043:4;15038:3;15034:14;15020:28;;14783:271;;;;:::o;15060:136::-;15153:4;15185;15180:3;15176:14;15168:22;;15060:136;;;:::o;15314:896::-;15469:3;15498:77;15569:5;15498:77;:::i;:::-;15591:99;15683:6;15678:3;15591:99;:::i;:::-;15584:106;;15714:79;15787:5;15714:79;:::i;:::-;15816:7;15847:1;15832:353;15857:6;15854:1;15851:13;15832:353;;;15933:6;15927:13;15960:109;16065:3;16050:13;15960:109;:::i;:::-;15953:116;;16092:83;16168:6;16092:83;:::i;:::-;16082:93;;15892:293;15879:1;15876;15872:9;15867:14;;15832:353;;;15836:14;16201:3;16194:10;;15474:736;;;15314:896;;;;:::o;16216:348::-;16381:10;16416:142;16554:3;16546:6;16416:142;:::i;:::-;16402:156;;16216:348;;;;:::o;16570:161::-;16688:4;16720;16715:3;16711:14;16703:22;;16570:161;;;:::o;16853:1295::-;17068:3;17097:102;17193:5;17097:102;:::i;:::-;17215:134;17342:6;17337:3;17215:134;:::i;:::-;17208:141;;17375:3;17420:4;17412:6;17408:17;17403:3;17399:27;17450:104;17548:5;17450:104;:::i;:::-;17577:7;17608:1;17593:510;17618:6;17615:1;17612:13;17593:510;;;17689:9;17683:4;17679:20;17674:3;17667:33;17740:6;17734:13;17768:160;17923:4;17908:13;17768:160;:::i;:::-;17760:168;;17951:108;18052:6;17951:108;:::i;:::-;17941:118;;18088:4;18083:3;18079:14;18072:21;;17653:450;17640:1;17637;17633:9;17628:14;;17593:510;;;17597:14;18119:4;18112:11;;18139:3;18132:10;;17073:1075;;;;;16853:1295;;;;:::o;18154:565::-;18393:4;18431:2;18420:9;18416:18;18408:26;;18480:9;18474:4;18470:20;18466:1;18455:9;18451:17;18444:47;18508:204;18707:4;18698:6;18508:204;:::i;:::-;18500:212;;18154:565;;;;:::o","linkReferences":{}},"deployedBytecode":{"object":"0x60806040525f5ffdfea164736f6c634300081c000a","sourceMap":"193:1568:32:-:0;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"int24[]\",\"name\":\"ticks\",\"type\":\"int24[]\"}],\"internalType\":\"struct GetUniswapV3PoolTickDataBatchRequest.TickDataInfo[]\",\"name\":\"allPoolInfo\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}],\"devdoc\":{\"details\":\"This contract is not meant to be deployed. Instead, use a static call with the deployment bytecode as payload.\",\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/UniswapV3/GetUniswapV3PoolTickDataBatchRequest.sol\":\"GetUniswapV3PoolTickDataBatchRequest\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":forge-std/=lib/forge-std/src/\"]},\"sources\":{\"src/UniswapV3/GetUniswapV3PoolTickDataBatchRequest.sol\":{\"keccak256\":\"0x5b2cc6ab5e91e7c5bd7b550d6cfafa8bbbdbb5b6a2afb90bb134f92d426a2e96\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fce3ca5bb4914fb725fa595eb7583419b4727d0cdf2a32adf07593be3fe7b064\",\"dweb:/ipfs/QmXCTfPYyJXbhzC3zPvCJNNC8FcpJaAkkmVwzyEsscdHrr\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"struct GetUniswapV3PoolTickDataBatchRequest.TickDataInfo[]","name":"allPoolInfo","type":"tuple[]","components":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"int24[]","name":"ticks","type":"int24[]"}]}],"stateMutability":"nonpayable","type":"constructor"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["forge-std/=lib/forge-std/src/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"src/UniswapV3/GetUniswapV3PoolTickDataBatchRequest.sol":"GetUniswapV3PoolTickDataBatchRequest"},"evmVersion":"cancun","libraries":{}},"sources":{"src/UniswapV3/GetUniswapV3PoolTickDataBatchRequest.sol":{"keccak256":"0x5b2cc6ab5e91e7c5bd7b550d6cfafa8bbbdbb5b6a2afb90bb134f92d426a2e96","urls":["bzz-raw://fce3ca5bb4914fb725fa595eb7583419b4727d0cdf2a32adf07593be3fe7b064","dweb:/ipfs/QmXCTfPYyJXbhzC3zPvCJNNC8FcpJaAkkmVwzyEsscdHrr"],"license":"MIT"}},"version":1},"id":32} ================================================ FILE: src/amms/abi/WethValueInPools.json ================================================ {"abi":[{"type":"constructor","inputs":[{"name":"_uniswapV2Factory","type":"address","internalType":"address"},{"name":"_uniswapV3Factory","type":"address","internalType":"address"},{"name":"_weth","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"getWethValueInPools","inputs":[{"name":"pools","type":"tuple[]","internalType":"struct WethValueInPools.PoolInfo[]","components":[{"name":"poolType","type":"uint8","internalType":"enum WethValueInPools.PoolType"},{"name":"poolAddress","type":"address","internalType":"address"}]}],"outputs":[{"name":"","type":"tuple[]","internalType":"struct WethValueInPools.PoolInfoReturn[]","components":[{"name":"poolType","type":"uint8","internalType":"enum WethValueInPools.PoolType"},{"name":"poolAddress","type":"address","internalType":"address"},{"name":"wethValue","type":"uint256","internalType":"uint256"}]}],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x608060405234801561000f575f5ffd5b5060405161269338038061269383398181016040528101906100319190610156565b825f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050506101a6565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610125826100fc565b9050919050565b6101358161011b565b811461013f575f5ffd5b50565b5f815190506101508161012c565b92915050565b5f5f5f6060848603121561016d5761016c6100f8565b5b5f61017a86828701610142565b935050602061018b86828701610142565b925050604061019c86828701610142565b9150509250925092565b6124e0806101b35f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063339173fd1461002d575b5f5ffd5b61004760048036038101906100429190611a7a565b61005d565b6040516100549190611c43565b60405180910390f35b60605f825167ffffffffffffffff81111561007b5761007a611870565b5b6040519080825280602002602001820160405280156100b457816020015b6100a1611805565b8152602001906001900390816100995790505b5090505f5f90505b83518110156102f4575f8482815181106100d9576100d8611c63565b5b602002602001015190505f60028111156100f6576100f5611aea565b5b815f0151600281111561010c5761010b611aea565b5b0361018f575f61011f82602001516102fe565b90506040518060600160405280835f0151600281111561014257610141611aea565b5b8152602001836020015173ffffffffffffffffffffffffffffffffffffffff1681526020018281525084848151811061017e5761017d611c63565b5b6020026020010181905250506102e6565b600160028111156101a3576101a2611aea565b5b815f015160028111156101b9576101b8611aea565b5b0361023c575f6101cc8260200151610587565b90506040518060600160405280835f015160028111156101ef576101ee611aea565b5b8152602001836020015173ffffffffffffffffffffffffffffffffffffffff1681526020018281525084848151811061022b5761022a611c63565b5b6020026020010181905250506102e5565b60028081111561024f5761024e611aea565b5b815f0151600281111561026557610264611aea565b5b036102e4575f6102788260200151610825565b90506040518060600160405280835f0151600281111561029b5761029a611aea565b5b8152602001836020015173ffffffffffffffffffffffffffffffffffffffff168152602001828152508484815181106102d7576102d6611c63565b5b6020026020010181905250505b5b5b5080806001019150506100bc565b5080915050919050565b5f60608273ffffffffffffffffffffffffffffffffffffffff1663cc77828d6040518163ffffffff1660e01b81526004015f604051808303815f875af192505050801561036d57506040513d5f823e3d601f19601f8201168201806040525081019061036a9190611d64565b60015b61037a575f915050610582565b809150505f5f90505b81518110156104ba5760025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168282815181106103d7576103d6611c63565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16036104ad578373ffffffffffffffffffffffffffffffffffffffff1663f8b2cb4f83838151811061042957610428611c63565b5b60200260200101516040518263ffffffff1660e01b815260040161044d9190611dba565b6020604051808303815f875af192505050801561048857506040513d601f19601f820116820180604052508101906104859190611dfd565b60015b610496575f92505050610582565b8251816104a39190611e55565b9350505050610582565b8080600101915050610383565b505f815f815181106104cf576104ce611c63565b5b602002602001015190505f8473ffffffffffffffffffffffffffffffffffffffff1663f8b2cb4f836040518263ffffffff1660e01b81526004016105139190611dba565b6020604051808303815f875af192505050801561054e57506040513d601f19601f8201168201806040525081019061054b9190611dfd565b60015b61055d575f9350505050610582565b809150505f61056c8383610b9a565b905083518161057b9190611e55565b9450505050505b919050565b5f5f8273ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156105f157506040513d601f19601f820116820180604052508101906105ee9190611e96565b60015b6105fe575f915050610820565b809150505f8373ffffffffffffffffffffffffffffffffffffffff1663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561066b57506040513d601f19601f820116820180604052508101906106689190611e96565b60015b610679575f92505050610820565b809150508373ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa9250505080156106e557506040513d601f19601f820116820180604052508101906106e29190611f3d565b60015b6106f3575f92505050610820565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610770576002836107549190611f8d565b6dffffffffffffffffffffffffffff1695505050505050610820565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036107ed576002826107d19190611f8d565b6dffffffffffffffffffffffffffff1695505050505050610820565b5f61080886856dffffffffffffffffffffffffffff16610b9a565b90506002816108179190611e55565b96505050505050505b919050565b5f5f8273ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561088f57506040513d601f19601f8201168201806040525081019061088c9190611e96565b60015b61089c575f915050610b95565b809150505f8373ffffffffffffffffffffffffffffffffffffffff1663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561090957506040513d601f19601f820116820180604052508101906109069190611e96565b60015b610917575f92505050610b95565b8091505060025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a07578173ffffffffffffffffffffffffffffffffffffffff166370a08231856040518263ffffffff1660e01b81526004016109a89190611dba565b602060405180830381865afa9250505080156109e257506040513d601f19601f820116820180604052508101906109df9190611dfd565b60015b6109f0575f92505050610b95565b6002816109fd9190611e55565b9350505050610b95565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610af3578073ffffffffffffffffffffffffffffffffffffffff166370a08231856040518263ffffffff1660e01b8152600401610a949190611dba565b602060405180830381865afa925050508015610ace57506040513d601f19601f82011682018060405250810190610acb9190611dfd565b60015b610adc575f92505050610b95565b600281610ae99190611e55565b9350505050610b95565b8173ffffffffffffffffffffffffffffffffffffffff166370a08231856040518263ffffffff1660e01b8152600401610b2c9190611dba565b602060405180830381865afa925050508015610b6657506040513d601f19601f82011682018060405250810190610b639190611dfd565b60015b610b74575f92505050610b95565b5f610b7f8483610b9a565b9050600281610b8e9190611e55565b9450505050505b919050565b5f5f610ba584610bf0565b90505f816fffffffffffffffffffffffffffffffff161115610bd357610bcb8184610c35565b915050610bea565b806fffffffffffffffffffffffffffffffff169150505b92915050565b5f5f610bfb83610d1f565b90505f816fffffffffffffffffffffffffffffffff161115610c205780915050610c30565b610c2983611070565b9050809150505b919050565b5f5f821480610c5557505f836fffffffffffffffffffffffffffffffff16145b15610c62575f9050610d19565b5f60406fffffffffffffffffffffffffffffffff8416856fffffffffffffffffffffffffffffffff1602901c90505f608084901c856fffffffffffffffffffffffffffffffff1602905077ffffffffffffffffffffffffffffffffffffffffffffffff811115610cd6575f92505050610d19565b604081901b9050817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03811115610d11575f92505050610d19565b818101925050505b92915050565b5f5f5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e6a439058460025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518363ffffffff1660e01b8152600401610d9d929190611fc9565b602060405180830381865afa158015610db8573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ddc9190611e96565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610e1a575f91505061106b565b5f5f8273ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa925050508015610e8457506040513d601f19601f82011682018060405250810190610e819190611f3d565b60015b610e93575f935050505061106b565b8294508193505050505f826dffffffffffffffffffffffffffff161480610ec957505f816dffffffffffffffffffffffffffff16145b15610ed9575f935050505061106b565b5f5f610ee48761133d565b9150915080610efa575f9550505050505061106b565b5f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1610610f555784610f57565b835b90505f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1610610fb45784610fb6565b855b9050601260ff168460ff16111561100057601284610fd49190611ffc565b600a610fe0919061215f565b816dffffffffffffffffffffffffffff16610ffb91906121d6565b611035565b83601261100d9190611ffc565b600a611019919061215f565b816dffffffffffffffffffffffffffff166110349190611e55565b5b9050611061826dffffffffffffffffffffffffffff16826dffffffffffffffffffffffffffff166114a1565b9750505050505050505b919050565b5f5f60405180606001604052806101f461ffff168152602001610bb861ffff16815260200161271061ffff1681525090505f5f5f90505b60038110156111d0575f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631698ee828760025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1687866003811061112457611123611c63565b5b60200201516040518463ffffffff1660e01b81526004016111479392919061225a565b602060405180830381865afa158015611162573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111869190611e96565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146111c457809250506111d0565b508060010190506110a7565b505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361120e575f92505050611338565b5f8173ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa92505050801561127757506040513d601f19601f820116820180604052508101906112749190612378565b60015b611286575f9350505050611338565b869750505050505050505f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161090505f5f6112ee8861133d565b9150915080611305575f9650505050505050611338565b604061132d85858661131857601261131a565b855b876113255786611328565b60125b611683565b901c96505050505050505b919050565b5f5f5f5f8473ffffffffffffffffffffffffffffffffffffffff16614e206040516024016040516020818303038152906040527f313ce567000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516113eb9190612467565b5f604051808303815f8787f1925050503d805f8114611425576040519150601f19603f3d011682016040523d82523d5f602084013e61142a565b606091505b50915091508115611493575f602082510361148557818060200190518101906114539190611dfd565b90505f811480611463575060ff81115b15611476575f5f9450945050505061149c565b8060019450945050505061149c565b5f5f9450945050505061149c565b5f5f9350935050505b915091565b5f5f82036114b1575f905061167d565b5f77ffffffffffffffffffffffffffffffffffffffffffffffff84116114ed5782604085901b816114e5576114e46121a9565b5b049050611657565b5f60c090505f60c086901c9050640100000000811061151457602081901c90506020820191505b62010000811061152c57601081901c90506010820191505b610100811061154357600881901c90506008820191505b6010811061155957600481901c90506004820191505b6004811061156f57600281901c90506002820191505b6002811061157e576001820191505b600160bf830360018703901c018260ff0387901b816115a05761159f6121a9565b5b0492506fffffffffffffffffffffffffffffffff8311156115c6575f935050505061167d565b5f608086901c840290505f6fffffffffffffffffffffffffffffffff8716850290505f60c089901c90505f60408a901b905082811015611607576001820391505b8281039050608084901b925082811015611622576001820391505b8281039050608084901c821461163b5761163a61247d565b5b88818161164b5761164a6121a9565b5b04870196505050505050505b6fffffffffffffffffffffffffffffffff811115611678575f91505061167d565b809150505b92915050565b5f5f82840390505f5f825f0b126116bb578160ff16600a0a60028873ffffffffffffffffffffffffffffffffffffffff160a026116ee565b815f0360ff16600a0a60028873ffffffffffffffffffffffffffffffffffffffff160a816116ec576116eb6121a9565b5b045b9050806c01000000000000000000000000111561170f575f925050506117fd565b5f86611767576c010000000000000000000000008281611732576117316121a9565b5b046fffffffffffffffffffffffffffffffff6c010000000000000000000000000281611761576117606121a9565b5b04611786565b6c010000000000000000000000008281611784576117836121a9565b5b045b90508661179357806117c4565b6c010000000000000000000000006fffffffffffffffffffffffffffffffff8202816117c2576117c16121a9565b5b045b93507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8411156117f9575f93505050506117fd565b5050505b949350505050565b60405180606001604052805f600281111561182357611822611aea565b5b81526020015f73ffffffffffffffffffffffffffffffffffffffff1681526020015f81525090565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6118a682611860565b810181811067ffffffffffffffff821117156118c5576118c4611870565b5b80604052505050565b5f6118d761184b565b90506118e3828261189d565b919050565b5f67ffffffffffffffff82111561190257611901611870565b5b602082029050602081019050919050565b5f5ffd5b5f5ffd5b60038110611927575f5ffd5b50565b5f813590506119388161191b565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6119678261193e565b9050919050565b6119778161195d565b8114611981575f5ffd5b50565b5f813590506119928161196e565b92915050565b5f604082840312156119ad576119ac611917565b5b6119b760406118ce565b90505f6119c68482850161192a565b5f8301525060206119d984828501611984565b60208301525092915050565b5f6119f76119f2846118e8565b6118ce565b90508083825260208201905060408402830185811115611a1a57611a19611913565b5b835b81811015611a435780611a2f8882611998565b845260208401935050604081019050611a1c565b5050509392505050565b5f82601f830112611a6157611a6061185c565b5b8135611a718482602086016119e5565b91505092915050565b5f60208284031215611a8f57611a8e611854565b5b5f82013567ffffffffffffffff811115611aac57611aab611858565b5b611ab884828501611a4d565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60038110611b2857611b27611aea565b5b50565b5f819050611b3882611b17565b919050565b5f611b4782611b2b565b9050919050565b611b5781611b3d565b82525050565b611b668161195d565b82525050565b5f819050919050565b611b7e81611b6c565b82525050565b606082015f820151611b985f850182611b4e565b506020820151611bab6020850182611b5d565b506040820151611bbe6040850182611b75565b50505050565b5f611bcf8383611b84565b60608301905092915050565b5f602082019050919050565b5f611bf182611ac1565b611bfb8185611acb565b9350611c0683611adb565b805f5b83811015611c36578151611c1d8882611bc4565b9750611c2883611bdb565b925050600181019050611c09565b5085935050505092915050565b5f6020820190508181035f830152611c5b8184611be7565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f67ffffffffffffffff821115611caa57611ca9611870565b5b602082029050602081019050919050565b5f81519050611cc98161196e565b92915050565b5f611ce1611cdc84611c90565b6118ce565b90508083825260208201905060208402830185811115611d0457611d03611913565b5b835b81811015611d2d5780611d198882611cbb565b845260208401935050602081019050611d06565b5050509392505050565b5f82601f830112611d4b57611d4a61185c565b5b8151611d5b848260208601611ccf565b91505092915050565b5f60208284031215611d7957611d78611854565b5b5f82015167ffffffffffffffff811115611d9657611d95611858565b5b611da284828501611d37565b91505092915050565b611db48161195d565b82525050565b5f602082019050611dcd5f830184611dab565b92915050565b611ddc81611b6c565b8114611de6575f5ffd5b50565b5f81519050611df781611dd3565b92915050565b5f60208284031215611e1257611e11611854565b5b5f611e1f84828501611de9565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f611e5f82611b6c565b9150611e6a83611b6c565b9250828202611e7881611b6c565b91508282048414831517611e8f57611e8e611e28565b5b5092915050565b5f60208284031215611eab57611eaa611854565b5b5f611eb884828501611cbb565b91505092915050565b5f6dffffffffffffffffffffffffffff82169050919050565b611ee381611ec1565b8114611eed575f5ffd5b50565b5f81519050611efe81611eda565b92915050565b5f63ffffffff82169050919050565b611f1c81611f04565b8114611f26575f5ffd5b50565b5f81519050611f3781611f13565b92915050565b5f5f5f60608486031215611f5457611f53611854565b5b5f611f6186828701611ef0565b9350506020611f7286828701611ef0565b9250506040611f8386828701611f29565b9150509250925092565b5f611f9782611ec1565b9150611fa283611ec1565b9250828202611fb081611ec1565b9150808214611fc257611fc1611e28565b5b5092915050565b5f604082019050611fdc5f830185611dab565b611fe96020830184611dab565b9392505050565b5f60ff82169050919050565b5f61200682611ff0565b915061201183611ff0565b9250828203905060ff81111561202a57612029611e28565b5b92915050565b5f8160011c9050919050565b5f5f8291508390505b60018511156120855780860481111561206157612060611e28565b5b60018516156120705780820291505b808102905061207e85612030565b9450612045565b94509492505050565b5f8261209d5760019050612158565b816120aa575f9050612158565b81600181146120c057600281146120ca576120f9565b6001915050612158565b60ff8411156120dc576120db611e28565b5b8360020a9150848211156120f3576120f2611e28565b5b50612158565b5060208310610133831016604e8410600b841016171561212e5782820a90508381111561212957612128611e28565b5b612158565b61213b848484600161203c565b9250905081840481111561215257612151611e28565b5b81810290505b9392505050565b5f61216982611b6c565b915061217483611ff0565b92506121a17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff848461208e565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6121e082611b6c565b91506121eb83611b6c565b9250826121fb576121fa6121a9565b5b828204905092915050565b5f61ffff82169050919050565b5f62ffffff82169050919050565b5f819050919050565b5f61224461223f61223a84612206565b612221565b612213565b9050919050565b6122548161222a565b82525050565b5f60608201905061226d5f830186611dab565b61227a6020830185611dab565b612287604083018461224b565b949350505050565b6122988161193e565b81146122a2575f5ffd5b50565b5f815190506122b38161228f565b92915050565b5f8160020b9050919050565b6122ce816122b9565b81146122d8575f5ffd5b50565b5f815190506122e9816122c5565b92915050565b6122f881612206565b8114612302575f5ffd5b50565b5f81519050612313816122ef565b92915050565b61232281611ff0565b811461232c575f5ffd5b50565b5f8151905061233d81612319565b92915050565b5f8115159050919050565b61235781612343565b8114612361575f5ffd5b50565b5f815190506123728161234e565b92915050565b5f5f5f5f5f5f5f60e0888a03121561239357612392611854565b5b5f6123a08a828b016122a5565b97505060206123b18a828b016122db565b96505060406123c28a828b01612305565b95505060606123d38a828b01612305565b94505060806123e48a828b01612305565b93505060a06123f58a828b0161232f565b92505060c06124068a828b01612364565b91505092959891949750929550565b5f81519050919050565b5f81905092915050565b8281835e5f83830152505050565b5f61244182612415565b61244b818561241f565b935061245b818560208601612429565b80840191505092915050565b5f6124728284612437565b915081905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffdfea2646970667358221220fbecc7363fddc240183f228cc94d576c055fde0c1de0f8e7ea8b7ba822558b2264736f6c634300081e0033","sourceMap":"468:10235:37:-:0;;;1079:206;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1191:17;1170:18;;:38;;;;;;;;;;;;;;;;;;1239:17;1218:18;;:38;;;;;;;;;;;;;;;;;;1273:5;1266:4;;:12;;;;;;;;;;;;;;;;;;1079:206;;;468:10235;;88:117:46;197:1;194;187:12;334:126;371:7;411:42;404:5;400:54;389:65;;334:126;;;:::o;466:96::-;503:7;532:24;550:5;532:24;:::i;:::-;521:35;;466:96;;;:::o;568:122::-;641:24;659:5;641:24;:::i;:::-;634:5;631:35;621:63;;680:1;677;670:12;621:63;568:122;:::o;696:143::-;753:5;784:6;778:13;769:22;;800:33;827:5;800:33;:::i;:::-;696:143;;;;:::o;845:663::-;933:6;941;949;998:2;986:9;977:7;973:23;969:32;966:119;;;1004:79;;:::i;:::-;966:119;1124:1;1149:64;1205:7;1196:6;1185:9;1181:22;1149:64;:::i;:::-;1139:74;;1095:128;1262:2;1288:64;1344:7;1335:6;1324:9;1320:22;1288:64;:::i;:::-;1278:74;;1233:129;1401:2;1427:64;1483:7;1474:6;1463:9;1459:22;1427:64;:::i;:::-;1417:74;;1372:129;845:663;;;;;:::o;468:10235:37:-;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063339173fd1461002d575b5f5ffd5b61004760048036038101906100429190611a7a565b61005d565b6040516100549190611c43565b60405180910390f35b60605f825167ffffffffffffffff81111561007b5761007a611870565b5b6040519080825280602002602001820160405280156100b457816020015b6100a1611805565b8152602001906001900390816100995790505b5090505f5f90505b83518110156102f4575f8482815181106100d9576100d8611c63565b5b602002602001015190505f60028111156100f6576100f5611aea565b5b815f0151600281111561010c5761010b611aea565b5b0361018f575f61011f82602001516102fe565b90506040518060600160405280835f0151600281111561014257610141611aea565b5b8152602001836020015173ffffffffffffffffffffffffffffffffffffffff1681526020018281525084848151811061017e5761017d611c63565b5b6020026020010181905250506102e6565b600160028111156101a3576101a2611aea565b5b815f015160028111156101b9576101b8611aea565b5b0361023c575f6101cc8260200151610587565b90506040518060600160405280835f015160028111156101ef576101ee611aea565b5b8152602001836020015173ffffffffffffffffffffffffffffffffffffffff1681526020018281525084848151811061022b5761022a611c63565b5b6020026020010181905250506102e5565b60028081111561024f5761024e611aea565b5b815f0151600281111561026557610264611aea565b5b036102e4575f6102788260200151610825565b90506040518060600160405280835f0151600281111561029b5761029a611aea565b5b8152602001836020015173ffffffffffffffffffffffffffffffffffffffff168152602001828152508484815181106102d7576102d6611c63565b5b6020026020010181905250505b5b5b5080806001019150506100bc565b5080915050919050565b5f60608273ffffffffffffffffffffffffffffffffffffffff1663cc77828d6040518163ffffffff1660e01b81526004015f604051808303815f875af192505050801561036d57506040513d5f823e3d601f19601f8201168201806040525081019061036a9190611d64565b60015b61037a575f915050610582565b809150505f5f90505b81518110156104ba5760025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168282815181106103d7576103d6611c63565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16036104ad578373ffffffffffffffffffffffffffffffffffffffff1663f8b2cb4f83838151811061042957610428611c63565b5b60200260200101516040518263ffffffff1660e01b815260040161044d9190611dba565b6020604051808303815f875af192505050801561048857506040513d601f19601f820116820180604052508101906104859190611dfd565b60015b610496575f92505050610582565b8251816104a39190611e55565b9350505050610582565b8080600101915050610383565b505f815f815181106104cf576104ce611c63565b5b602002602001015190505f8473ffffffffffffffffffffffffffffffffffffffff1663f8b2cb4f836040518263ffffffff1660e01b81526004016105139190611dba565b6020604051808303815f875af192505050801561054e57506040513d601f19601f8201168201806040525081019061054b9190611dfd565b60015b61055d575f9350505050610582565b809150505f61056c8383610b9a565b905083518161057b9190611e55565b9450505050505b919050565b5f5f8273ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156105f157506040513d601f19601f820116820180604052508101906105ee9190611e96565b60015b6105fe575f915050610820565b809150505f8373ffffffffffffffffffffffffffffffffffffffff1663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561066b57506040513d601f19601f820116820180604052508101906106689190611e96565b60015b610679575f92505050610820565b809150508373ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa9250505080156106e557506040513d601f19601f820116820180604052508101906106e29190611f3d565b60015b6106f3575f92505050610820565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610770576002836107549190611f8d565b6dffffffffffffffffffffffffffff1695505050505050610820565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036107ed576002826107d19190611f8d565b6dffffffffffffffffffffffffffff1695505050505050610820565b5f61080886856dffffffffffffffffffffffffffff16610b9a565b90506002816108179190611e55565b96505050505050505b919050565b5f5f8273ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561088f57506040513d601f19601f8201168201806040525081019061088c9190611e96565b60015b61089c575f915050610b95565b809150505f8373ffffffffffffffffffffffffffffffffffffffff1663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561090957506040513d601f19601f820116820180604052508101906109069190611e96565b60015b610917575f92505050610b95565b8091505060025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a07578173ffffffffffffffffffffffffffffffffffffffff166370a08231856040518263ffffffff1660e01b81526004016109a89190611dba565b602060405180830381865afa9250505080156109e257506040513d601f19601f820116820180604052508101906109df9190611dfd565b60015b6109f0575f92505050610b95565b6002816109fd9190611e55565b9350505050610b95565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610af3578073ffffffffffffffffffffffffffffffffffffffff166370a08231856040518263ffffffff1660e01b8152600401610a949190611dba565b602060405180830381865afa925050508015610ace57506040513d601f19601f82011682018060405250810190610acb9190611dfd565b60015b610adc575f92505050610b95565b600281610ae99190611e55565b9350505050610b95565b8173ffffffffffffffffffffffffffffffffffffffff166370a08231856040518263ffffffff1660e01b8152600401610b2c9190611dba565b602060405180830381865afa925050508015610b6657506040513d601f19601f82011682018060405250810190610b639190611dfd565b60015b610b74575f92505050610b95565b5f610b7f8483610b9a565b9050600281610b8e9190611e55565b9450505050505b919050565b5f5f610ba584610bf0565b90505f816fffffffffffffffffffffffffffffffff161115610bd357610bcb8184610c35565b915050610bea565b806fffffffffffffffffffffffffffffffff169150505b92915050565b5f5f610bfb83610d1f565b90505f816fffffffffffffffffffffffffffffffff161115610c205780915050610c30565b610c2983611070565b9050809150505b919050565b5f5f821480610c5557505f836fffffffffffffffffffffffffffffffff16145b15610c62575f9050610d19565b5f60406fffffffffffffffffffffffffffffffff8416856fffffffffffffffffffffffffffffffff1602901c90505f608084901c856fffffffffffffffffffffffffffffffff1602905077ffffffffffffffffffffffffffffffffffffffffffffffff811115610cd6575f92505050610d19565b604081901b9050817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03811115610d11575f92505050610d19565b818101925050505b92915050565b5f5f5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e6a439058460025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518363ffffffff1660e01b8152600401610d9d929190611fc9565b602060405180830381865afa158015610db8573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ddc9190611e96565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610e1a575f91505061106b565b5f5f8273ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa925050508015610e8457506040513d601f19601f82011682018060405250810190610e819190611f3d565b60015b610e93575f935050505061106b565b8294508193505050505f826dffffffffffffffffffffffffffff161480610ec957505f816dffffffffffffffffffffffffffff16145b15610ed9575f935050505061106b565b5f5f610ee48761133d565b9150915080610efa575f9550505050505061106b565b5f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1610610f555784610f57565b835b90505f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1610610fb45784610fb6565b855b9050601260ff168460ff16111561100057601284610fd49190611ffc565b600a610fe0919061215f565b816dffffffffffffffffffffffffffff16610ffb91906121d6565b611035565b83601261100d9190611ffc565b600a611019919061215f565b816dffffffffffffffffffffffffffff166110349190611e55565b5b9050611061826dffffffffffffffffffffffffffff16826dffffffffffffffffffffffffffff166114a1565b9750505050505050505b919050565b5f5f60405180606001604052806101f461ffff168152602001610bb861ffff16815260200161271061ffff1681525090505f5f5f90505b60038110156111d0575f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631698ee828760025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1687866003811061112457611123611c63565b5b60200201516040518463ffffffff1660e01b81526004016111479392919061225a565b602060405180830381865afa158015611162573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111869190611e96565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146111c457809250506111d0565b508060010190506110a7565b505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361120e575f92505050611338565b5f8173ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa92505050801561127757506040513d601f19601f820116820180604052508101906112749190612378565b60015b611286575f9350505050611338565b869750505050505050505f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161090505f5f6112ee8861133d565b9150915080611305575f9650505050505050611338565b604061132d85858661131857601261131a565b855b876113255786611328565b60125b611683565b901c96505050505050505b919050565b5f5f5f5f8473ffffffffffffffffffffffffffffffffffffffff16614e206040516024016040516020818303038152906040527f313ce567000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516113eb9190612467565b5f604051808303815f8787f1925050503d805f8114611425576040519150601f19603f3d011682016040523d82523d5f602084013e61142a565b606091505b50915091508115611493575f602082510361148557818060200190518101906114539190611dfd565b90505f811480611463575060ff81115b15611476575f5f9450945050505061149c565b8060019450945050505061149c565b5f5f9450945050505061149c565b5f5f9350935050505b915091565b5f5f82036114b1575f905061167d565b5f77ffffffffffffffffffffffffffffffffffffffffffffffff84116114ed5782604085901b816114e5576114e46121a9565b5b049050611657565b5f60c090505f60c086901c9050640100000000811061151457602081901c90506020820191505b62010000811061152c57601081901c90506010820191505b610100811061154357600881901c90506008820191505b6010811061155957600481901c90506004820191505b6004811061156f57600281901c90506002820191505b6002811061157e576001820191505b600160bf830360018703901c018260ff0387901b816115a05761159f6121a9565b5b0492506fffffffffffffffffffffffffffffffff8311156115c6575f935050505061167d565b5f608086901c840290505f6fffffffffffffffffffffffffffffffff8716850290505f60c089901c90505f60408a901b905082811015611607576001820391505b8281039050608084901b925082811015611622576001820391505b8281039050608084901c821461163b5761163a61247d565b5b88818161164b5761164a6121a9565b5b04870196505050505050505b6fffffffffffffffffffffffffffffffff811115611678575f91505061167d565b809150505b92915050565b5f5f82840390505f5f825f0b126116bb578160ff16600a0a60028873ffffffffffffffffffffffffffffffffffffffff160a026116ee565b815f0360ff16600a0a60028873ffffffffffffffffffffffffffffffffffffffff160a816116ec576116eb6121a9565b5b045b9050806c01000000000000000000000000111561170f575f925050506117fd565b5f86611767576c010000000000000000000000008281611732576117316121a9565b5b046fffffffffffffffffffffffffffffffff6c010000000000000000000000000281611761576117606121a9565b5b04611786565b6c010000000000000000000000008281611784576117836121a9565b5b045b90508661179357806117c4565b6c010000000000000000000000006fffffffffffffffffffffffffffffffff8202816117c2576117c16121a9565b5b045b93507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8411156117f9575f93505050506117fd565b5050505b949350505050565b60405180606001604052805f600281111561182357611822611aea565b5b81526020015f73ffffffffffffffffffffffffffffffffffffffff1681526020015f81525090565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6118a682611860565b810181811067ffffffffffffffff821117156118c5576118c4611870565b5b80604052505050565b5f6118d761184b565b90506118e3828261189d565b919050565b5f67ffffffffffffffff82111561190257611901611870565b5b602082029050602081019050919050565b5f5ffd5b5f5ffd5b60038110611927575f5ffd5b50565b5f813590506119388161191b565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6119678261193e565b9050919050565b6119778161195d565b8114611981575f5ffd5b50565b5f813590506119928161196e565b92915050565b5f604082840312156119ad576119ac611917565b5b6119b760406118ce565b90505f6119c68482850161192a565b5f8301525060206119d984828501611984565b60208301525092915050565b5f6119f76119f2846118e8565b6118ce565b90508083825260208201905060408402830185811115611a1a57611a19611913565b5b835b81811015611a435780611a2f8882611998565b845260208401935050604081019050611a1c565b5050509392505050565b5f82601f830112611a6157611a6061185c565b5b8135611a718482602086016119e5565b91505092915050565b5f60208284031215611a8f57611a8e611854565b5b5f82013567ffffffffffffffff811115611aac57611aab611858565b5b611ab884828501611a4d565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60038110611b2857611b27611aea565b5b50565b5f819050611b3882611b17565b919050565b5f611b4782611b2b565b9050919050565b611b5781611b3d565b82525050565b611b668161195d565b82525050565b5f819050919050565b611b7e81611b6c565b82525050565b606082015f820151611b985f850182611b4e565b506020820151611bab6020850182611b5d565b506040820151611bbe6040850182611b75565b50505050565b5f611bcf8383611b84565b60608301905092915050565b5f602082019050919050565b5f611bf182611ac1565b611bfb8185611acb565b9350611c0683611adb565b805f5b83811015611c36578151611c1d8882611bc4565b9750611c2883611bdb565b925050600181019050611c09565b5085935050505092915050565b5f6020820190508181035f830152611c5b8184611be7565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f67ffffffffffffffff821115611caa57611ca9611870565b5b602082029050602081019050919050565b5f81519050611cc98161196e565b92915050565b5f611ce1611cdc84611c90565b6118ce565b90508083825260208201905060208402830185811115611d0457611d03611913565b5b835b81811015611d2d5780611d198882611cbb565b845260208401935050602081019050611d06565b5050509392505050565b5f82601f830112611d4b57611d4a61185c565b5b8151611d5b848260208601611ccf565b91505092915050565b5f60208284031215611d7957611d78611854565b5b5f82015167ffffffffffffffff811115611d9657611d95611858565b5b611da284828501611d37565b91505092915050565b611db48161195d565b82525050565b5f602082019050611dcd5f830184611dab565b92915050565b611ddc81611b6c565b8114611de6575f5ffd5b50565b5f81519050611df781611dd3565b92915050565b5f60208284031215611e1257611e11611854565b5b5f611e1f84828501611de9565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f611e5f82611b6c565b9150611e6a83611b6c565b9250828202611e7881611b6c565b91508282048414831517611e8f57611e8e611e28565b5b5092915050565b5f60208284031215611eab57611eaa611854565b5b5f611eb884828501611cbb565b91505092915050565b5f6dffffffffffffffffffffffffffff82169050919050565b611ee381611ec1565b8114611eed575f5ffd5b50565b5f81519050611efe81611eda565b92915050565b5f63ffffffff82169050919050565b611f1c81611f04565b8114611f26575f5ffd5b50565b5f81519050611f3781611f13565b92915050565b5f5f5f60608486031215611f5457611f53611854565b5b5f611f6186828701611ef0565b9350506020611f7286828701611ef0565b9250506040611f8386828701611f29565b9150509250925092565b5f611f9782611ec1565b9150611fa283611ec1565b9250828202611fb081611ec1565b9150808214611fc257611fc1611e28565b5b5092915050565b5f604082019050611fdc5f830185611dab565b611fe96020830184611dab565b9392505050565b5f60ff82169050919050565b5f61200682611ff0565b915061201183611ff0565b9250828203905060ff81111561202a57612029611e28565b5b92915050565b5f8160011c9050919050565b5f5f8291508390505b60018511156120855780860481111561206157612060611e28565b5b60018516156120705780820291505b808102905061207e85612030565b9450612045565b94509492505050565b5f8261209d5760019050612158565b816120aa575f9050612158565b81600181146120c057600281146120ca576120f9565b6001915050612158565b60ff8411156120dc576120db611e28565b5b8360020a9150848211156120f3576120f2611e28565b5b50612158565b5060208310610133831016604e8410600b841016171561212e5782820a90508381111561212957612128611e28565b5b612158565b61213b848484600161203c565b9250905081840481111561215257612151611e28565b5b81810290505b9392505050565b5f61216982611b6c565b915061217483611ff0565b92506121a17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff848461208e565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6121e082611b6c565b91506121eb83611b6c565b9250826121fb576121fa6121a9565b5b828204905092915050565b5f61ffff82169050919050565b5f62ffffff82169050919050565b5f819050919050565b5f61224461223f61223a84612206565b612221565b612213565b9050919050565b6122548161222a565b82525050565b5f60608201905061226d5f830186611dab565b61227a6020830185611dab565b612287604083018461224b565b949350505050565b6122988161193e565b81146122a2575f5ffd5b50565b5f815190506122b38161228f565b92915050565b5f8160020b9050919050565b6122ce816122b9565b81146122d8575f5ffd5b50565b5f815190506122e9816122c5565b92915050565b6122f881612206565b8114612302575f5ffd5b50565b5f81519050612313816122ef565b92915050565b61232281611ff0565b811461232c575f5ffd5b50565b5f8151905061233d81612319565b92915050565b5f8115159050919050565b61235781612343565b8114612361575f5ffd5b50565b5f815190506123728161234e565b92915050565b5f5f5f5f5f5f5f60e0888a03121561239357612392611854565b5b5f6123a08a828b016122a5565b97505060206123b18a828b016122db565b96505060406123c28a828b01612305565b95505060606123d38a828b01612305565b94505060806123e48a828b01612305565b93505060a06123f58a828b0161232f565b92505060c06124068a828b01612364565b91505092959891949750929550565b5f81519050919050565b5f81905092915050565b8281835e5f83830152505050565b5f61244182612415565b61244b818561241f565b935061245b818560208601612429565b80840191505092915050565b5f6124728284612437565b915081905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffdfea2646970667358221220fbecc7363fddc240183f228cc94d576c055fde0c1de0f8e7ea8b7ba822558b2264736f6c634300081e0033","sourceMap":"468:10235:37:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1908:1035;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;1978:23;2013:39;2076:5;:12;2055:34;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;2013:76;;2104:9;2116:1;2104:13;;2099:806;2123:5;:12;2119:1;:16;2099:806;;;2156:20;2179:5;2185:1;2179:8;;;;;;;;:::i;:::-;;;;;;;;2156:31;;2222:17;2205:34;;;;;;;;:::i;:::-;;:4;:13;;;:34;;;;;;;;:::i;:::-;;;2201:694;;2259:17;2279:36;2298:4;:16;;;2279:18;:36::i;:::-;2259:56;;2354:58;;;;;;;;2369:4;:13;;;2354:58;;;;;;;;:::i;:::-;;;;;;2384:4;:16;;;2354:58;;;;;;2402:9;2354:58;;;2333:15;2349:1;2333:18;;;;;;;;:::i;:::-;;;;;;;:79;;;;2241:186;2201:694;;;2454:18;2437:35;;;;;;;;:::i;:::-;;:4;:13;;;:35;;;;;;;;:::i;:::-;;;2433:462;;2492:17;2512:37;2532:4;:16;;;2512:19;:37::i;:::-;2492:57;;2588:58;;;;;;;;2603:4;:13;;;2588:58;;;;;;;;:::i;:::-;;;;;;2618:4;:16;;;2588:58;;;;;;2636:9;2588:58;;;2567:15;2583:1;2567:18;;;;;;;;:::i;:::-;;;;;;;:79;;;;2474:187;2433:462;;;2688:18;2671:35;;;;;;;;:::i;:::-;;:4;:13;;;:35;;;;;;;;:::i;:::-;;;2667:228;;2726:17;2746:37;2766:4;:16;;;2746:19;:37::i;:::-;2726:57;;2822:58;;;;;;;;2837:4;:13;;;2822:58;;;;;;;;:::i;:::-;;;;;;2852:4;:16;;;2822:58;;;;;;2870:9;2822:58;;;2801:15;2817:1;2801:18;;;;;;;;:::i;:::-;;;;;;;:79;;;;2708:187;2667:228;2433:462;2201:694;2142:763;2137:3;;;;;;;2099:806;;;;2921:15;2914:22;;;1908:1035;;;:::o;2949:1221::-;3009:7;3055:23;3099:4;3092:29;;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;3088:152;;3228:1;3221:8;;;;;3088:152;3182:7;3173:16;;3124:76;3359:9;3371:1;3359:13;;3354:473;3378:6;:13;3374:1;:17;3354:473;;;3429:4;;;;;;;;;;;3416:17;;:6;3423:1;3416:9;;;;;;;;:::i;:::-;;;;;;;;:17;;;3412:405;;3464:4;3457:23;;;3481:6;3488:1;3481:9;;;;;;;;:::i;:::-;;;;;;;;3457:34;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;3453:350;;3783:1;3776:8;;;;;;3453:350;3715:6;:13;3704:8;:24;;;;:::i;:::-;3697:31;;;;;;;3412:405;3393:3;;;;;;;3354:473;;;;3837:17;3857:6;3864:1;3857:9;;;;;;;;:::i;:::-;;;;;;;;3837:29;;3876:15;3912:4;3905:23;;;3929:9;3905:34;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;3901:149;;4038:1;4031:8;;;;;;;3901:149;3991:8;3981:18;;3940:70;4060:17;4080:41;4102:9;4113:7;4080:21;:41::i;:::-;4060:61;;4150:6;:13;4138:9;:25;;;;:::i;:::-;4131:32;;;;;;2949:1221;;;;:::o;4176:896::-;4237:7;4256:14;4299:4;4284:27;;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;4280:141;;4409:1;4402:8;;;;;4280:141;4363:7;4354:16;;4314:67;4430:14;4473:4;4458:27;;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;4454:141;;4583:1;4576:8;;;;;;4454:141;4537:7;4528:16;;4488:67;4623:4;4608:32;;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;4604:462;;5054:1;5047:8;;;;;;4604:462;4724:4;;;;;;;;;;;4714:14;;:6;:14;;;4710:150;;4766:1;4755:8;:12;;;;:::i;:::-;4748:19;;;;;;;;;;;4710:150;4802:4;;;;;;;;;;;4792:14;;:6;:14;;;4788:72;;4844:1;4833:8;:12;;;;:::i;:::-;4826:19;;;;;;;;;;;4788:72;4922:17;4942:39;4964:6;4972:8;4942:39;;:21;:39::i;:::-;4922:59;;5014:1;5002:9;:13;;;;:::i;:::-;4995:20;;;;;;;;4176:896;;;;:::o;5078:1167::-;5139:7;5158:14;5209:4;5186:36;;;:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;5182:150;;5320:1;5313:8;;;;;5182:150;5274:7;5265:16;;5225:67;5341:14;5392:4;5369:36;;;:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;5365:150;;5503:1;5496:8;;;;;;5365:150;5457:7;5448:16;;5408:67;5539:4;;;;;;;;;;;5529:14;;:6;:14;;;5525:432;;5570:6;5563:24;;;5596:4;5563:39;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;5559:169;;5712:1;5705:8;;;;;;5559:169;5664:1;5654:7;:11;;;;:::i;:::-;5647:18;;;;;;;5525:432;5758:4;;;;;;;;;;;5748:14;;:6;:14;;;5744:213;;5789:6;5782:24;;;5815:4;5782:39;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;5778:169;;5931:1;5924:8;;;;;;5778:169;5883:1;5873:7;:11;;;;:::i;:::-;5866:18;;;;;;;5744:213;6023:6;6016:24;;;6049:4;6016:39;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;6012:227;;6227:1;6220:8;;;;;;6012:227;6096:17;6116:38;6138:6;6146:7;6116:21;:38::i;:::-;6096:58;;6187:1;6175:9;:13;;;;:::i;:::-;6168:20;;;;;;5078:1167;;;;:::o;6323:301::-;6403:7;6449:13;6465:17;6476:5;6465:10;:17::i;:::-;6449:33;;6504:1;6496:5;:9;;;6492:126;;;6528:36;6550:5;6557:6;6528:21;:36::i;:::-;6521:43;;;;;6492:126;6602:5;6595:12;;;;;6323:301;;;;;:::o;6691:351::-;6744:7;6797:13;6855:26;6875:5;6855:19;:26::i;:::-;6847:34;;6903:1;6895:5;:9;;;6891:52;;;6927:5;6920:12;;;;;6891:52;6987:26;7007:5;6987:19;:26::i;:::-;6979:34;;7030:5;7023:12;;;6691:351;;;;:::o;369:626:28:-;430:7;482:1;477;:6;:16;;;;492:1;487;:6;;;477:16;473:63;;;520:1;513:8;;;;473:63;550:10;622:2;582:34;578:1;:38;572:1;564:10;;:53;563:61;;550:74;;638:10;670:3;665:1;:8;;659:1;651:10;;:23;638:36;;698:50;693:2;:55;689:102;;;775:1;768:8;;;;;;689:102;811:2;804:9;;;;;906:2;837:66;:71;832:2;:76;828:123;;;935:1;928:8;;;;;;828:123;976:2;971;:7;964:14;;;;369:626;;;;;:::o;7048:1376:37:-;7110:13;7159:19;7214:18;;;;;;;;;;;7196:45;;;7242:5;7249:4;;;;;;;;;;;7196:58;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7159:96;;1022:1;7269:29;;7277:4;7269:29;;;7265:68;;7321:1;7314:8;;;;;7265:68;7443:16;7469;7499:4;:16;;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;7495:197;;7680:1;7673:8;;;;;;;7495:197;7598:9;7587:20;;7632:9;7621:20;;7518:134;;;7717:1;7705:8;:13;;;:30;;;;7734:1;7722:8;:13;;;7705:30;7701:69;;;7758:1;7751:8;;;;;;;7701:69;7819:19;7840:25;7869:29;7892:5;7869:22;:29::i;:::-;7818:80;;;;7913:20;7908:60;;7956:1;7949:8;;;;;;;;;7908:60;8021:19;8051:4;;;;;;;;;;;8043:12;;:5;:12;;;:34;;8069:8;8043:34;;;8058:8;8043:34;8021:56;;8087:20;8118:4;;;;;;;;;;;8110:12;;:5;:12;;;:34;;8136:8;8110:34;;;8125:8;8110:34;8087:57;;1070:2;8170:30;;:13;:30;;;;:182;;1070:2;8321:13;:29;;;;:::i;:::-;8314:2;:37;;;;:::i;:::-;8299:12;:52;;;;;;:::i;:::-;8170:182;;;8261:13;1070:2;8245:29;;;;:::i;:::-;8238:2;:37;;;;:::i;:::-;8223:12;:52;;;;;;:::i;:::-;8170:182;8155:197;;8370:47;8391:11;8370:47;;8404:12;8370:47;;:20;:47::i;:::-;8362:55;;7125:1299;;;;;;;7048:1376;;;;:::o;8430:1395::-;8492:7;8511:25;:46;;;;;;;;8540:3;8511:46;;;;;;8545:4;8511:46;;;;;;8551:5;8511:46;;;;;;;8567:19;8601:9;8613:1;8601:13;;8596:339;8620:15;8616:1;:19;8596:339;;;8684:19;8755:18;;;;;;;;;;;8737:45;;;8783:5;8790:4;;;;;;;;;;;8796:8;8805:1;8796:11;;;;;;;:::i;:::-;;;;;;8737:71;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8684:125;;1022:1;8827:29;;8835:4;8827:29;;;8823:102;;8883:4;8876:11;;8905:5;;;8823:102;8642:293;8637:3;;;;;8596:339;;;;1022:1;8949:29;;8957:4;8949:29;;;8945:68;;9001:1;8994:8;;;;;;8945:68;9058:20;9092:4;:10;;;:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;9088:186;;9262:1;9255:8;;;;;;;9088:186;9210:13;9195:28;;9105:129;;;;;;;9284:21;9316:4;;;;;;;;;;;9308:12;;:5;:12;;;9284:36;;9331:19;9352:26;9382:29;9405:5;9382:22;:29::i;:::-;9330:81;;;;9426:21;9421:61;;9470:1;9463:8;;;;;;;;;;9421:61;9806:2;9542:260;9586:12;9616:16;9650;:60;;1070:2;9650:60;;;9674:13;9650:60;9728:16;:60;;9774:13;9728:60;;;1070:2;9728:60;9542:26;:260::i;:::-;:266;;9514:304;;;;;;;;8430:1395;;;;:::o;9939:762::-;10004:5;10011:4;10028:25;10055:30;10101:5;:10;;10117:5;10124:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10101:61;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10027:135;;;;10177:20;10173:522;;;10213:21;10281:2;10253:17;:24;:30;10249:388;;10332:17;10321:40;;;;;;;;;;;;:::i;:::-;10303:58;;10401:1;10384:13;:18;:41;;;;10422:3;10406:13;:19;10384:41;10380:187;;;10457:1;10460:5;10449:17;;;;;;;;;10380:187;10527:13;10543:4;10513:35;;;;;;;;;10249:388;10613:1;10616:5;10605:17;;;;;;;;;10173:522;10675:1;10678:5;10667:17;;;;;;9939:762;;;;:::o;1190:2514:28:-;1250:7;1302:1;1297;:6;1293:20;;1312:1;1305:8;;;;1293:20;1328:14;1366:50;1361:1;:55;1357:1967;;1457:1;1451:2;1446:1;:7;;1445:13;;;;;:::i;:::-;;;1436:22;;1357:1967;;;1497:11;1511:3;1497:17;;1532:10;1550:3;1545:1;:8;;1532:21;;1581:11;1575:2;:17;1571:104;;1623:2;1616:9;;;;;1654:2;1647:9;;;;1571:104;1702:7;1696:2;:13;1692:100;;1740:2;1733:9;;;;;1771:2;1764:9;;;;1692:100;1819:5;1813:2;:11;1809:96;;1855:1;1848:8;;;;;1885:1;1878:8;;;;1809:96;1932:4;1926:2;:10;1922:95;;1967:1;1960:8;;;;;1997:1;1990:8;;;;1922:95;2044:3;2038:2;:9;2034:94;;2078:1;2071:8;;;;;2108:1;2101:8;;;;2034:94;2155:3;2149:2;:9;2145:23;;2167:1;2160:8;;;;2145:23;2276:1;2268:3;2262;:9;2255:1;2251;:5;2250:22;;2249:28;2240:3;2234;:9;2228:1;:16;;2227:51;;;;;:::i;:::-;;;2218:60;;2704:34;2695:6;:43;2691:98;;;2769:1;2762:8;;;;;;;2691:98;2807:10;2835:3;2830:1;:8;;2820:6;:19;2807:32;;2857:10;2884:34;2880:1;:38;2870:6;:49;2857:62;;2938:10;2956:3;2951:1;:8;;2938:21;;2977:10;2995:2;2990:1;:7;;2977:20;;3025:2;3020;:7;3016:20;;;3035:1;3029:7;;;;3016:20;3060:2;3054:8;;;;3128:3;3122:2;:9;;3117:14;;3158:2;3153;:7;3149:20;;;3168:1;3162:7;;;;3149:20;3193:2;3187:8;;;;3270:3;3264:2;:9;;3258:2;:15;3251:23;;;;:::i;:::-;;3308:1;3303:2;:6;;;;;:::i;:::-;;;3293:16;;;;1479:1845;;;;;;1357:1967;3574:34;3565:6;:43;3561:90;;;3635:1;3628:8;;;;;3561:90;3680:6;3665:22;;;1190:2514;;;;;:::o;3710:1606::-;3865:17;4094;4131:14;4114;:31;4094:51;;4256:23;4297:1;4282:12;:16;;;:174;;4443:12;4431:25;;:2;:25;4427:1;4410:12;4402:21;;:26;:54;4282:174;;;4369:12;4368:13;;4346:37;;4354:2;4346:37;4342:1;4325:12;4317:21;;:26;:66;;;;;:::i;:::-;;;4282:174;4256:200;;4480:15;117:27;4474:21;4470:68;;;4522:1;4515:8;;;;;;4470:68;4686:28;4717:16;:143;;117:27;4838:15;:21;;;;;:::i;:::-;;;4799:34;117:27;4793:40;4792:68;;;;;:::i;:::-;;;4717:143;;;117:27;4752:15;:21;;;;;:::i;:::-;;;4717:143;4686:174;;5017:16;:148;;5145:20;5017:148;;;117:27;5085:34;5061:20;5053:66;5052:74;;;;;:::i;:::-;;;5017:148;5005:160;;5196:17;5184:9;:29;5180:120;;;5284:1;5277:8;;;;;;;5180:120;3898:1412;;;3710:1606;;;;;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::o;7:75:46:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:117;443:1;440;433:12;457:102;498:6;549:2;545:7;540:2;533:5;529:14;525:28;515:38;;457:102;;;:::o;565:180::-;613:77;610:1;603:88;710:4;707:1;700:15;734:4;731:1;724:15;751:281;834:27;856:4;834:27;:::i;:::-;826:6;822:40;964:6;952:10;949:22;928:18;916:10;913:34;910:62;907:88;;;975:18;;:::i;:::-;907:88;1015:10;1011:2;1004:22;794:238;751:281;;:::o;1038:129::-;1072:6;1099:20;;:::i;:::-;1089:30;;1128:33;1156:4;1148:6;1128:33;:::i;:::-;1038:129;;;:::o;1173:338::-;1277:4;1367:18;1359:6;1356:30;1353:56;;;1389:18;;:::i;:::-;1353:56;1439:4;1431:6;1427:17;1419:25;;1499:4;1493;1489:15;1481:23;;1173:338;;;:::o;1517:117::-;1626:1;1623;1616:12;1640:117;1749:1;1746;1739:12;1886:113;1973:1;1966:5;1963:12;1953:40;;1989:1;1986;1979:12;1953:40;1886:113;:::o;2005:167::-;2065:5;2103:6;2090:20;2081:29;;2119:47;2160:5;2119:47;:::i;:::-;2005:167;;;;:::o;2178:126::-;2215:7;2255:42;2248:5;2244:54;2233:65;;2178:126;;;:::o;2310:96::-;2347:7;2376:24;2394:5;2376:24;:::i;:::-;2365:35;;2310:96;;;:::o;2412:122::-;2485:24;2503:5;2485:24;:::i;:::-;2478:5;2475:35;2465:63;;2524:1;2521;2514:12;2465:63;2412:122;:::o;2540:139::-;2586:5;2624:6;2611:20;2602:29;;2640:33;2667:5;2640:33;:::i;:::-;2540:139;;;;:::o;2725:601::-;2801:5;2845:4;2833:9;2828:3;2824:19;2820:30;2817:117;;;2853:79;;:::i;:::-;2817:117;2952:21;2968:4;2952:21;:::i;:::-;2943:30;;3036:1;3076:63;3135:3;3126:6;3115:9;3111:22;3076:63;:::i;:::-;3069:4;3062:5;3058:16;3051:89;2983:168;3217:2;3258:49;3303:3;3294:6;3283:9;3279:22;3258:49;:::i;:::-;3251:4;3244:5;3240:16;3233:75;3161:158;2725:601;;;;:::o;3374:791::-;3497:5;3522:108;3538:91;3622:6;3538:91;:::i;:::-;3522:108;:::i;:::-;3513:117;;3650:5;3679:6;3672:5;3665:21;3713:4;3706:5;3702:16;3695:23;;3766:4;3758:6;3754:17;3746:6;3742:30;3795:3;3787:6;3784:15;3781:122;;;3814:79;;:::i;:::-;3781:122;3929:6;3912:247;3946:6;3941:3;3938:15;3912:247;;;4021:3;4050:64;4110:3;4098:10;4050:64;:::i;:::-;4045:3;4038:77;4144:4;4139:3;4135:14;4128:21;;3988:171;3972:4;3967:3;3963:14;3956:21;;3912:247;;;3916:21;3503:662;;3374:791;;;;;:::o;4213:424::-;4311:5;4360:3;4353:4;4345:6;4341:17;4337:27;4327:122;;4368:79;;:::i;:::-;4327:122;4485:6;4472:20;4510:121;4627:3;4619:6;4612:4;4604:6;4600:17;4510:121;:::i;:::-;4501:130;;4317:320;4213:424;;;;:::o;4643:593::-;4754:6;4803:2;4791:9;4782:7;4778:23;4774:32;4771:119;;;4809:79;;:::i;:::-;4771:119;4957:1;4946:9;4942:17;4929:31;4987:18;4979:6;4976:30;4973:117;;;5009:79;;:::i;:::-;4973:117;5114:105;5211:7;5202:6;5191:9;5187:22;5114:105;:::i;:::-;5104:115;;4900:329;4643:593;;;;:::o;5242:147::-;5342:6;5376:5;5370:12;5360:22;;5242:147;;;:::o;5395:217::-;5527:11;5561:6;5556:3;5549:19;5601:4;5596:3;5592:14;5577:29;;5395:217;;;;:::o;5618:165::-;5718:4;5741:3;5733:11;;5771:4;5766:3;5762:14;5754:22;;5618:165;;;:::o;5789:180::-;5837:77;5834:1;5827:88;5934:4;5931:1;5924:15;5958:4;5955:1;5948:15;5975:119;6062:1;6055:5;6052:12;6042:46;;6068:18;;:::i;:::-;6042:46;5975:119;:::o;6100:139::-;6151:7;6180:5;6169:16;;6186:47;6227:5;6186:47;:::i;:::-;6100:139;;;:::o;6245:::-;6307:9;6340:38;6372:5;6340:38;:::i;:::-;6327:51;;6245:139;;;:::o;6390:145::-;6479:49;6522:5;6479:49;:::i;:::-;6474:3;6467:62;6390:145;;:::o;6541:108::-;6618:24;6636:5;6618:24;:::i;:::-;6613:3;6606:37;6541:108;;:::o;6655:77::-;6692:7;6721:5;6710:16;;6655:77;;;:::o;6738:108::-;6815:24;6833:5;6815:24;:::i;:::-;6810:3;6803:37;6738:108;;:::o;6940:715::-;7093:4;7088:3;7084:14;7184:4;7177:5;7173:16;7167:23;7203:75;7272:4;7267:3;7263:14;7249:12;7203:75;:::i;:::-;7108:180;7377:4;7370:5;7366:16;7360:23;7396:63;7453:4;7448:3;7444:14;7430:12;7396:63;:::i;:::-;7298:171;7556:4;7549:5;7545:16;7539:23;7575:63;7632:4;7627:3;7623:14;7609:12;7575:63;:::i;:::-;7479:169;7062:593;6940:715;;:::o;7661:311::-;7796:10;7817:112;7925:3;7917:6;7817:112;:::i;:::-;7961:4;7956:3;7952:14;7938:28;;7661:311;;;;:::o;7978:146::-;8081:4;8113;8108:3;8104:14;8096:22;;7978:146;;;:::o;8222:996::-;8407:3;8436:87;8517:5;8436:87;:::i;:::-;8539:119;8651:6;8646:3;8539:119;:::i;:::-;8532:126;;8682:89;8765:5;8682:89;:::i;:::-;8794:7;8825:1;8810:383;8835:6;8832:1;8829:13;8810:383;;;8911:6;8905:13;8938:129;9063:3;9048:13;8938:129;:::i;:::-;8931:136;;9090:93;9176:6;9090:93;:::i;:::-;9080:103;;8870:323;8857:1;8854;8850:9;8845:14;;8810:383;;;8814:14;9209:3;9202:10;;8412:806;;;8222:996;;;;:::o;9224:505::-;9433:4;9471:2;9460:9;9456:18;9448:26;;9520:9;9514:4;9510:20;9506:1;9495:9;9491:17;9484:47;9548:174;9717:4;9708:6;9548:174;:::i;:::-;9540:182;;9224:505;;;;:::o;9735:180::-;9783:77;9780:1;9773:88;9880:4;9877:1;9870:15;9904:4;9901:1;9894:15;9921:311;9998:4;10088:18;10080:6;10077:30;10074:56;;;10110:18;;:::i;:::-;10074:56;10160:4;10152:6;10148:17;10140:25;;10220:4;10214;10210:15;10202:23;;9921:311;;;:::o;10238:143::-;10295:5;10326:6;10320:13;10311:22;;10342:33;10369:5;10342:33;:::i;:::-;10238:143;;;;:::o;10404:732::-;10511:5;10536:81;10552:64;10609:6;10552:64;:::i;:::-;10536:81;:::i;:::-;10527:90;;10637:5;10666:6;10659:5;10652:21;10700:4;10693:5;10689:16;10682:23;;10753:4;10745:6;10741:17;10733:6;10729:30;10782:3;10774:6;10771:15;10768:122;;;10801:79;;:::i;:::-;10768:122;10916:6;10899:231;10933:6;10928:3;10925:15;10899:231;;;11008:3;11037:48;11081:3;11069:10;11037:48;:::i;:::-;11032:3;11025:61;11115:4;11110:3;11106:14;11099:21;;10975:155;10959:4;10954:3;10950:14;10943:21;;10899:231;;;10903:21;10517:619;;10404:732;;;;;:::o;11159:385::-;11241:5;11290:3;11283:4;11275:6;11271:17;11267:27;11257:122;;11298:79;;:::i;:::-;11257:122;11408:6;11402:13;11433:105;11534:3;11526:6;11519:4;11511:6;11507:17;11433:105;:::i;:::-;11424:114;;11247:297;11159:385;;;;:::o;11550:554::-;11645:6;11694:2;11682:9;11673:7;11669:23;11665:32;11662:119;;;11700:79;;:::i;:::-;11662:119;11841:1;11830:9;11826:17;11820:24;11871:18;11863:6;11860:30;11857:117;;;11893:79;;:::i;:::-;11857:117;11998:89;12079:7;12070:6;12059:9;12055:22;11998:89;:::i;:::-;11988:99;;11791:306;11550:554;;;;:::o;12110:118::-;12197:24;12215:5;12197:24;:::i;:::-;12192:3;12185:37;12110:118;;:::o;12234:222::-;12327:4;12365:2;12354:9;12350:18;12342:26;;12378:71;12446:1;12435:9;12431:17;12422:6;12378:71;:::i;:::-;12234:222;;;;:::o;12462:122::-;12535:24;12553:5;12535:24;:::i;:::-;12528:5;12525:35;12515:63;;12574:1;12571;12564:12;12515:63;12462:122;:::o;12590:143::-;12647:5;12678:6;12672:13;12663:22;;12694:33;12721:5;12694:33;:::i;:::-;12590:143;;;;:::o;12739:351::-;12809:6;12858:2;12846:9;12837:7;12833:23;12829:32;12826:119;;;12864:79;;:::i;:::-;12826:119;12984:1;13009:64;13065:7;13056:6;13045:9;13041:22;13009:64;:::i;:::-;12999:74;;12955:128;12739:351;;;;:::o;13096:180::-;13144:77;13141:1;13134:88;13241:4;13238:1;13231:15;13265:4;13262:1;13255:15;13282:410;13322:7;13345:20;13363:1;13345:20;:::i;:::-;13340:25;;13379:20;13397:1;13379:20;:::i;:::-;13374:25;;13434:1;13431;13427:9;13456:30;13474:11;13456:30;:::i;:::-;13445:41;;13635:1;13626:7;13622:15;13619:1;13616:22;13596:1;13589:9;13569:83;13546:139;;13665:18;;:::i;:::-;13546:139;13330:362;13282:410;;;;:::o;13698:351::-;13768:6;13817:2;13805:9;13796:7;13792:23;13788:32;13785:119;;;13823:79;;:::i;:::-;13785:119;13943:1;13968:64;14024:7;14015:6;14004:9;14000:22;13968:64;:::i;:::-;13958:74;;13914:128;13698:351;;;;:::o;14055:114::-;14092:7;14132:30;14125:5;14121:42;14110:53;;14055:114;;;:::o;14175:122::-;14248:24;14266:5;14248:24;:::i;:::-;14241:5;14238:35;14228:63;;14287:1;14284;14277:12;14228:63;14175:122;:::o;14303:143::-;14360:5;14391:6;14385:13;14376:22;;14407:33;14434:5;14407:33;:::i;:::-;14303:143;;;;:::o;14452:93::-;14488:7;14528:10;14521:5;14517:22;14506:33;;14452:93;;;:::o;14551:120::-;14623:23;14640:5;14623:23;:::i;:::-;14616:5;14613:34;14603:62;;14661:1;14658;14651:12;14603:62;14551:120;:::o;14677:141::-;14733:5;14764:6;14758:13;14749:22;;14780:32;14806:5;14780:32;:::i;:::-;14677:141;;;;:::o;14824:661::-;14911:6;14919;14927;14976:2;14964:9;14955:7;14951:23;14947:32;14944:119;;;14982:79;;:::i;:::-;14944:119;15102:1;15127:64;15183:7;15174:6;15163:9;15159:22;15127:64;:::i;:::-;15117:74;;15073:128;15240:2;15266:64;15322:7;15313:6;15302:9;15298:22;15266:64;:::i;:::-;15256:74;;15211:129;15379:2;15405:63;15460:7;15451:6;15440:9;15436:22;15405:63;:::i;:::-;15395:73;;15350:128;14824:661;;;;;:::o;15491:279::-;15531:7;15554:20;15572:1;15554:20;:::i;:::-;15549:25;;15588:20;15606:1;15588:20;:::i;:::-;15583:25;;15643:1;15640;15636:9;15665:30;15683:11;15665:30;:::i;:::-;15654:41;;15727:11;15718:7;15715:24;15705:58;;15743:18;;:::i;:::-;15705:58;15539:231;15491:279;;;;:::o;15776:332::-;15897:4;15935:2;15924:9;15920:18;15912:26;;15948:71;16016:1;16005:9;16001:17;15992:6;15948:71;:::i;:::-;16029:72;16097:2;16086:9;16082:18;16073:6;16029:72;:::i;:::-;15776:332;;;;;:::o;16114:86::-;16149:7;16189:4;16182:5;16178:16;16167:27;;16114:86;;;:::o;16206:191::-;16244:4;16264:18;16280:1;16264:18;:::i;:::-;16259:23;;16296:18;16312:1;16296:18;:::i;:::-;16291:23;;16338:1;16335;16331:9;16323:17;;16362:4;16356;16353:14;16350:40;;;16370:18;;:::i;:::-;16350:40;16206:191;;;;:::o;16403:102::-;16445:8;16492:5;16489:1;16485:13;16464:34;;16403:102;;;:::o;16511:848::-;16572:5;16579:4;16603:6;16594:15;;16627:5;16618:14;;16641:712;16662:1;16652:8;16649:15;16641:712;;;16757:4;16752:3;16748:14;16742:4;16739:24;16736:50;;;16766:18;;:::i;:::-;16736:50;16816:1;16806:8;16802:16;16799:451;;;17231:4;17224:5;17220:16;17211:25;;16799:451;17281:4;17275;17271:15;17263:23;;17311:32;17334:8;17311:32;:::i;:::-;17299:44;;16641:712;;;16511:848;;;;;;;:::o;17365:1073::-;17419:5;17610:8;17600:40;;17631:1;17622:10;;17633:5;;17600:40;17659:4;17649:36;;17676:1;17667:10;;17678:5;;17649:36;17745:4;17793:1;17788:27;;;;17829:1;17824:191;;;;17738:277;;17788:27;17806:1;17797:10;;17808:5;;;17824:191;17869:3;17859:8;17856:17;17853:43;;;17876:18;;:::i;:::-;17853:43;17925:8;17922:1;17918:16;17909:25;;17960:3;17953:5;17950:14;17947:40;;;17967:18;;:::i;:::-;17947:40;18000:5;;;17738:277;;18124:2;18114:8;18111:16;18105:3;18099:4;18096:13;18092:36;18074:2;18064:8;18061:16;18056:2;18050:4;18047:12;18043:35;18027:111;18024:246;;;18180:8;18174:4;18170:19;18161:28;;18215:3;18208:5;18205:14;18202:40;;;18222:18;;:::i;:::-;18202:40;18255:5;;18024:246;18295:42;18333:3;18323:8;18317:4;18314:1;18295:42;:::i;:::-;18280:57;;;;18369:4;18364:3;18360:14;18353:5;18350:25;18347:51;;;18378:18;;:::i;:::-;18347:51;18427:4;18420:5;18416:16;18407:25;;17365:1073;;;;;;:::o;18444:281::-;18502:5;18526:23;18544:4;18526:23;:::i;:::-;18518:31;;18570:25;18586:8;18570:25;:::i;:::-;18558:37;;18614:104;18651:66;18641:8;18635:4;18614:104;:::i;:::-;18605:113;;18444:281;;;;:::o;18731:180::-;18779:77;18776:1;18769:88;18876:4;18873:1;18866:15;18900:4;18897:1;18890:15;18917:185;18957:1;18974:20;18992:1;18974:20;:::i;:::-;18969:25;;19008:20;19026:1;19008:20;:::i;:::-;19003:25;;19047:1;19037:35;;19052:18;;:::i;:::-;19037:35;19094:1;19091;19087:9;19082:14;;18917:185;;;;:::o;19108:89::-;19144:7;19184:6;19177:5;19173:18;19162:29;;19108:89;;;:::o;19203:91::-;19239:7;19279:8;19272:5;19268:20;19257:31;;19203:91;;;:::o;19300:60::-;19328:3;19349:5;19342:12;;19300:60;;;:::o;19366:138::-;19414:9;19447:51;19464:33;19473:23;19490:5;19473:23;:::i;:::-;19464:33;:::i;:::-;19447:51;:::i;:::-;19434:64;;19366:138;;;:::o;19510:127::-;19595:35;19624:5;19595:35;:::i;:::-;19590:3;19583:48;19510:127;;:::o;19643:438::-;19790:4;19828:2;19817:9;19813:18;19805:26;;19841:71;19909:1;19898:9;19894:17;19885:6;19841:71;:::i;:::-;19922:72;19990:2;19979:9;19975:18;19966:6;19922:72;:::i;:::-;20004:70;20070:2;20059:9;20055:18;20046:6;20004:70;:::i;:::-;19643:438;;;;;;:::o;20087:122::-;20160:24;20178:5;20160:24;:::i;:::-;20153:5;20150:35;20140:63;;20199:1;20196;20189:12;20140:63;20087:122;:::o;20215:143::-;20272:5;20303:6;20297:13;20288:22;;20319:33;20346:5;20319:33;:::i;:::-;20215:143;;;;:::o;20364:90::-;20399:7;20442:5;20439:1;20428:20;20417:31;;20364:90;;;:::o;20460:118::-;20531:22;20547:5;20531:22;:::i;:::-;20524:5;20521:33;20511:61;;20568:1;20565;20558:12;20511:61;20460:118;:::o;20584:139::-;20639:5;20670:6;20664:13;20655:22;;20686:31;20711:5;20686:31;:::i;:::-;20584:139;;;;:::o;20729:120::-;20801:23;20818:5;20801:23;:::i;:::-;20794:5;20791:34;20781:62;;20839:1;20836;20829:12;20781:62;20729:120;:::o;20855:141::-;20911:5;20942:6;20936:13;20927:22;;20958:32;20984:5;20958:32;:::i;:::-;20855:141;;;;:::o;21002:118::-;21073:22;21089:5;21073:22;:::i;:::-;21066:5;21063:33;21053:61;;21110:1;21107;21100:12;21053:61;21002:118;:::o;21126:139::-;21181:5;21212:6;21206:13;21197:22;;21228:31;21253:5;21228:31;:::i;:::-;21126:139;;;;:::o;21271:90::-;21305:7;21348:5;21341:13;21334:21;21323:32;;21271:90;;;:::o;21367:116::-;21437:21;21452:5;21437:21;:::i;:::-;21430:5;21427:32;21417:60;;21473:1;21470;21463:12;21417:60;21367:116;:::o;21489:137::-;21543:5;21574:6;21568:13;21559:22;;21590:30;21614:5;21590:30;:::i;:::-;21489:137;;;;:::o;21632:1271::-;21746:6;21754;21762;21770;21778;21786;21794;21843:3;21831:9;21822:7;21818:23;21814:33;21811:120;;;21850:79;;:::i;:::-;21811:120;21970:1;21995:64;22051:7;22042:6;22031:9;22027:22;21995:64;:::i;:::-;21985:74;;21941:128;22108:2;22134:62;22188:7;22179:6;22168:9;22164:22;22134:62;:::i;:::-;22124:72;;22079:127;22245:2;22271:63;22326:7;22317:6;22306:9;22302:22;22271:63;:::i;:::-;22261:73;;22216:128;22383:2;22409:63;22464:7;22455:6;22444:9;22440:22;22409:63;:::i;:::-;22399:73;;22354:128;22521:3;22548:63;22603:7;22594:6;22583:9;22579:22;22548:63;:::i;:::-;22538:73;;22492:129;22660:3;22687:62;22741:7;22732:6;22721:9;22717:22;22687:62;:::i;:::-;22677:72;;22631:128;22798:3;22825:61;22878:7;22869:6;22858:9;22854:22;22825:61;:::i;:::-;22815:71;;22769:127;21632:1271;;;;;;;;;;:::o;22909:98::-;22960:6;22994:5;22988:12;22978:22;;22909:98;;;:::o;23013:147::-;23114:11;23151:3;23136:18;;23013:147;;;;:::o;23166:139::-;23255:6;23250:3;23245;23239:23;23296:1;23287:6;23282:3;23278:16;23271:27;23166:139;;;:::o;23311:386::-;23415:3;23443:38;23475:5;23443:38;:::i;:::-;23497:88;23578:6;23573:3;23497:88;:::i;:::-;23490:95;;23594:65;23652:6;23647:3;23640:4;23633:5;23629:16;23594:65;:::i;:::-;23684:6;23679:3;23675:16;23668:23;;23419:278;23311:386;;;;:::o;23703:271::-;23833:3;23855:93;23944:3;23935:6;23855:93;:::i;:::-;23848:100;;23965:3;23958:10;;23703:271;;;;:::o;23980:180::-;24028:77;24025:1;24018:88;24125:4;24122:1;24115:15;24149:4;24146:1;24139:15","linkReferences":{}},"methodIdentifiers":{"getWethValueInPools((uint8,address)[])":"339173fd"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.30+commit.73712a01\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_uniswapV2Factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_uniswapV3Factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"components\":[{\"internalType\":\"enum WethValueInPools.PoolType\",\"name\":\"poolType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"poolAddress\",\"type\":\"address\"}],\"internalType\":\"struct WethValueInPools.PoolInfo[]\",\"name\":\"pools\",\"type\":\"tuple[]\"}],\"name\":\"getWethValueInPools\",\"outputs\":[{\"components\":[{\"internalType\":\"enum WethValueInPools.PoolType\",\"name\":\"poolType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"poolAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"wethValue\",\"type\":\"uint256\"}],\"internalType\":\"struct WethValueInPools.PoolInfoReturn[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getWethValueInPools((uint8,address)[])\":{\"details\":\"We require a 1 ETH minimum liquidity in the quoting pool for it to be considered.\"}},\"stateVariables\":{\"UNISWAP_V2_FACTORY\":{\"details\":\"Used as the first priority for quoting WETH value\"},\"UNISWAP_V3_FACTORY\":{\"details\":\"Used as the second priority for quoting WETH value\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getWethValueInPools((uint8,address)[])\":{\"notice\":\"Returns an array of `PoolInfoReturn` for the consumer to determine wether to filter or not to save gas.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/filters/WethValueInPools.sol\":\"WethValueInPools\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":forge-std/=lib/forge-std/src/\"]},\"sources\":{\"src/UniswapV3/FixedPoint.sol\":{\"keccak256\":\"0xf82873fe78051afcf0446c27f5c5857816d1129e2bc84855dee8275d764b49d0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5d1b9704466cdf93f446ac2330ef89752c2bcc1f271a70c296f54e0d9291467f\",\"dweb:/ipfs/QmaQd3DUAdJMVQD422o2HyAwhTDyLo33znMgRDU5NaZegE\"]},\"src/filters/WethValueInPools.sol\":{\"keccak256\":\"0x1bd98caec9df680366948f8e1f24ed7262021aeb841ea155efafb05648152c4b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3f88558f892e5441c824e1d6973036e1196445b99c7e24fcfa6a399af64e2ace\",\"dweb:/ipfs/QmT7KqFaR9pysM94AAbSgeJrb1XsQickV6kyowBWc5vYgT\"]},\"src/interfaces/IBalancer.sol\":{\"keccak256\":\"0xe7ca1e7f70a16d6919334b612a584e5d42692a802f4d92686c564a4ab1550c27\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://2e0cf4540fca9dbf3650d22d1d927b43bcd8333a988c7575c6618b633bff082f\",\"dweb:/ipfs/QmYAcUnqBauhiXJNfMLta4Bj1dntGmNJ3cxaHq18LnBDAQ\"]},\"src/interfaces/IUniswapV2.sol\":{\"keccak256\":\"0x067d9c125da6fdbe44d6ce7d498c42460d7347317413f8317bf80bd25c08898d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1ad58162042aa8d1eb7451af3ccc3b1df64e720aeeb69a6843507aec0e5d146\",\"dweb:/ipfs/QmdvEJYkfWaGWrGXtKajZSDdfNYJ3sDFpzsV4f1X4KQYZM\"]},\"src/interfaces/IUniswapV3.sol\":{\"keccak256\":\"0x914ac5f4d9e6b6d0345c89e769f1a2d9784d047e8cac6f3265b229afd9363729\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://19a3f9d71839d62cea60562c57cdfe582821da7bfe17a1d6ca26597db51a3762\",\"dweb:/ipfs/QmdWoVo3J7tcSKCk5cCADvjvMtmczcGbsmKx5v9AFjQANz\"]},\"src/interfaces/Token.sol\":{\"keccak256\":\"0x2f7118f6cba8e0303e66028f738463e025a19ec0186a5462523692f44330e113\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ca6355f3ce4aec77f281142db4cb0a63d5e1b3b4b12836ac9a3ed251069801d0\",\"dweb:/ipfs/QmWTt8HyEuzTdKVWCzBDxVMWL3tptkxsTfsssbEMVA818A\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.30+commit.73712a01"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address","name":"_uniswapV2Factory","type":"address"},{"internalType":"address","name":"_uniswapV3Factory","type":"address"},{"internalType":"address","name":"_weth","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"struct WethValueInPools.PoolInfo[]","name":"pools","type":"tuple[]","components":[{"internalType":"enum WethValueInPools.PoolType","name":"poolType","type":"uint8"},{"internalType":"address","name":"poolAddress","type":"address"}]}],"stateMutability":"nonpayable","type":"function","name":"getWethValueInPools","outputs":[{"internalType":"struct WethValueInPools.PoolInfoReturn[]","name":"","type":"tuple[]","components":[{"internalType":"enum WethValueInPools.PoolType","name":"poolType","type":"uint8"},{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"uint256","name":"wethValue","type":"uint256"}]}]}],"devdoc":{"kind":"dev","methods":{"getWethValueInPools((uint8,address)[])":{"details":"We require a 1 ETH minimum liquidity in the quoting pool for it to be considered."}},"version":1},"userdoc":{"kind":"user","methods":{"getWethValueInPools((uint8,address)[])":{"notice":"Returns an array of `PoolInfoReturn` for the consumer to determine wether to filter or not to save gas."}},"version":1}},"settings":{"remappings":["forge-std/=lib/forge-std/src/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/filters/WethValueInPools.sol":"WethValueInPools"},"evmVersion":"cancun","libraries":{}},"sources":{"src/UniswapV3/FixedPoint.sol":{"keccak256":"0xf82873fe78051afcf0446c27f5c5857816d1129e2bc84855dee8275d764b49d0","urls":["bzz-raw://5d1b9704466cdf93f446ac2330ef89752c2bcc1f271a70c296f54e0d9291467f","dweb:/ipfs/QmaQd3DUAdJMVQD422o2HyAwhTDyLo33znMgRDU5NaZegE"],"license":"MIT"},"src/filters/WethValueInPools.sol":{"keccak256":"0x1bd98caec9df680366948f8e1f24ed7262021aeb841ea155efafb05648152c4b","urls":["bzz-raw://3f88558f892e5441c824e1d6973036e1196445b99c7e24fcfa6a399af64e2ace","dweb:/ipfs/QmT7KqFaR9pysM94AAbSgeJrb1XsQickV6kyowBWc5vYgT"],"license":"MIT"},"src/interfaces/IBalancer.sol":{"keccak256":"0xe7ca1e7f70a16d6919334b612a584e5d42692a802f4d92686c564a4ab1550c27","urls":["bzz-raw://2e0cf4540fca9dbf3650d22d1d927b43bcd8333a988c7575c6618b633bff082f","dweb:/ipfs/QmYAcUnqBauhiXJNfMLta4Bj1dntGmNJ3cxaHq18LnBDAQ"],"license":"MIT"},"src/interfaces/IUniswapV2.sol":{"keccak256":"0x067d9c125da6fdbe44d6ce7d498c42460d7347317413f8317bf80bd25c08898d","urls":["bzz-raw://b1ad58162042aa8d1eb7451af3ccc3b1df64e720aeeb69a6843507aec0e5d146","dweb:/ipfs/QmdvEJYkfWaGWrGXtKajZSDdfNYJ3sDFpzsV4f1X4KQYZM"],"license":"MIT"},"src/interfaces/IUniswapV3.sol":{"keccak256":"0x914ac5f4d9e6b6d0345c89e769f1a2d9784d047e8cac6f3265b229afd9363729","urls":["bzz-raw://19a3f9d71839d62cea60562c57cdfe582821da7bfe17a1d6ca26597db51a3762","dweb:/ipfs/QmdWoVo3J7tcSKCk5cCADvjvMtmczcGbsmKx5v9AFjQANz"],"license":"MIT"},"src/interfaces/Token.sol":{"keccak256":"0x2f7118f6cba8e0303e66028f738463e025a19ec0186a5462523692f44330e113","urls":["bzz-raw://ca6355f3ce4aec77f281142db4cb0a63d5e1b3b4b12836ac9a3ed251069801d0","dweb:/ipfs/QmWTt8HyEuzTdKVWCzBDxVMWL3tptkxsTfsssbEMVA818A"],"license":"MIT"}},"version":1},"id":37} ================================================ FILE: src/amms/abi/WethValueInPoolsBatchRequest.json ================================================ {"abi":[{"type":"constructor","inputs":[{"name":"_uniswapV2Factory","type":"address","internalType":"address"},{"name":"_uniswapV3Factory","type":"address","internalType":"address"},{"name":"_weth","type":"address","internalType":"address"},{"name":"pools","type":"tuple[]","internalType":"struct WethValueInPools.PoolInfo[]","components":[{"name":"poolType","type":"uint8","internalType":"enum WethValueInPools.PoolType"},{"name":"poolAddress","type":"address","internalType":"address"}]}],"stateMutability":"nonpayable"},{"type":"function","name":"getWethValueInPools","inputs":[{"name":"pools","type":"tuple[]","internalType":"struct WethValueInPools.PoolInfo[]","components":[{"name":"poolType","type":"uint8","internalType":"enum WethValueInPools.PoolType"},{"name":"poolAddress","type":"address","internalType":"address"}]}],"outputs":[{"name":"","type":"tuple[]","internalType":"struct WethValueInPools.PoolInfoReturn[]","components":[{"name":"poolType","type":"uint8","internalType":"enum WethValueInPools.PoolType"},{"name":"poolAddress","type":"address","internalType":"address"},{"name":"wethValue","type":"uint256","internalType":"uint256"}]}],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x608060405234801561000f575f5ffd5b506040516125fc3803806125fc83398181016040528101906100319190611ba6565b838383825f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505f6101068261013560201b60201c565b90505f8160405160200161011a9190611da8565b60405160208183030381529060405290506020810180590381f35b60605f825167ffffffffffffffff811115610153576101526119f6565b5b60405190808252806020026020018201604052801561018c57816020015b610179611931565b8152602001906001900390816101715790505b5090505f5f90505b83518110156103de575f8482815181106101b1576101b0611dc8565b5b602002602001015190505f60028111156101ce576101cd611c4f565b5b815f015160028111156101e4576101e3611c4f565b5b0361026d575f6101fd82602001516103e860201b60201c565b90506040518060600160405280835f015160028111156102205761021f611c4f565b5b8152602001836020015173ffffffffffffffffffffffffffffffffffffffff1681526020018281525084848151811061025c5761025b611dc8565b5b6020026020010181905250506103d0565b6001600281111561028157610280611c4f565b5b815f0151600281111561029757610296611c4f565b5b03610320575f6102b0826020015161067760201b60201c565b90506040518060600160405280835f015160028111156102d3576102d2611c4f565b5b8152602001836020015173ffffffffffffffffffffffffffffffffffffffff1681526020018281525084848151811061030f5761030e611dc8565b5b6020026020010181905250506103cf565b60028081111561033357610332611c4f565b5b815f0151600281111561034957610348611c4f565b5b036103ce575f610362826020015161091b60201b60201c565b90506040518060600160405280835f0151600281111561038557610384611c4f565b5b8152602001836020015173ffffffffffffffffffffffffffffffffffffffff168152602001828152508484815181106103c1576103c0611dc8565b5b6020026020010181905250505b5b5b508080600101915050610194565b5080915050919050565b5f60608273ffffffffffffffffffffffffffffffffffffffff1663cc77828d6040518163ffffffff1660e01b81526004015f604051808303815f875af192505050801561045757506040513d5f823e3d601f19601f820116820180604052508101906104549190611eb5565b60015b610464575f915050610672565b809150505f5f90505b81518110156105a45760025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168282815181106104c1576104c0611dc8565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603610597578373ffffffffffffffffffffffffffffffffffffffff1663f8b2cb4f83838151811061051357610512611dc8565b5b60200260200101516040518263ffffffff1660e01b81526004016105379190611f0b565b6020604051808303815f875af192505050801561057257506040513d601f19601f8201168201806040525081019061056f9190611f4e565b60015b610580575f92505050610672565b82518161058d9190611fa6565b9350505050610672565b808060010191505061046d565b505f815f815181106105b9576105b8611dc8565b5b602002602001015190505f8473ffffffffffffffffffffffffffffffffffffffff1663f8b2cb4f836040518263ffffffff1660e01b81526004016105fd9190611f0b565b6020604051808303815f875af192505050801561063857506040513d601f19601f820116820180604052508101906106359190611f4e565b60015b610647575f9350505050610672565b809150505f61065c8383610c9660201b60201c565b905083518161066b9190611fa6565b9450505050505b919050565b5f5f8273ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156106e157506040513d601f19601f820116820180604052508101906106de9190611fe7565b60015b6106ee575f915050610916565b809150505f8373ffffffffffffffffffffffffffffffffffffffff1663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561075b57506040513d601f19601f820116820180604052508101906107589190611fe7565b60015b610769575f92505050610916565b809150508373ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa9250505080156107d557506040513d601f19601f820116820180604052508101906107d2919061208e565b60015b6107e3575f92505050610916565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036108605760028361084491906120de565b6dffffffffffffffffffffffffffff1695505050505050610916565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036108dd576002826108c191906120de565b6dffffffffffffffffffffffffffff1695505050505050610916565b5f6108fe86856dffffffffffffffffffffffffffff16610c9660201b60201c565b905060028161090d9190611fa6565b96505050505050505b919050565b5f5f8273ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561098557506040513d601f19601f820116820180604052508101906109829190611fe7565b60015b610992575f915050610c91565b809150505f8373ffffffffffffffffffffffffffffffffffffffff1663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156109ff57506040513d601f19601f820116820180604052508101906109fc9190611fe7565b60015b610a0d575f92505050610c91565b8091505060025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610afd578173ffffffffffffffffffffffffffffffffffffffff166370a08231856040518263ffffffff1660e01b8152600401610a9e9190611f0b565b602060405180830381865afa925050508015610ad857506040513d601f19601f82011682018060405250810190610ad59190611f4e565b60015b610ae6575f92505050610c91565b600281610af39190611fa6565b9350505050610c91565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610be9578073ffffffffffffffffffffffffffffffffffffffff166370a08231856040518263ffffffff1660e01b8152600401610b8a9190611f0b565b602060405180830381865afa925050508015610bc457506040513d601f19601f82011682018060405250810190610bc19190611f4e565b60015b610bd2575f92505050610c91565b600281610bdf9190611fa6565b9350505050610c91565b8173ffffffffffffffffffffffffffffffffffffffff166370a08231856040518263ffffffff1660e01b8152600401610c229190611f0b565b602060405180830381865afa925050508015610c5c57506040513d601f19601f82011682018060405250810190610c599190611f4e565b60015b610c6a575f92505050610c91565b5f610c7b8483610c9660201b60201c565b9050600281610c8a9190611fa6565b9450505050505b919050565b5f5f610ca784610cf860201b60201c565b90505f816fffffffffffffffffffffffffffffffff161115610cdb57610cd38184610d4960201b60201c565b915050610cf2565b806fffffffffffffffffffffffffffffffff169150505b92915050565b5f5f610d0983610e3360201b60201c565b90505f816fffffffffffffffffffffffffffffffff161115610d2e5780915050610d44565b610d3d8361119060201b60201c565b9050809150505b919050565b5f5f821480610d6957505f836fffffffffffffffffffffffffffffffff16145b15610d76575f9050610e2d565b5f60406fffffffffffffffffffffffffffffffff8416856fffffffffffffffffffffffffffffffff1602901c90505f608084901c856fffffffffffffffffffffffffffffffff1602905077ffffffffffffffffffffffffffffffffffffffffffffffff811115610dea575f92505050610e2d565b604081901b9050817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03811115610e25575f92505050610e2d565b818101925050505b92915050565b5f5f5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e6a439058460025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518363ffffffff1660e01b8152600401610eb192919061211a565b602060405180830381865afa158015610ecc573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ef09190611fe7565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610f2e575f91505061118b565b5f5f8273ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa925050508015610f9857506040513d601f19601f82011682018060405250810190610f95919061208e565b60015b610fa7575f935050505061118b565b8294508193505050505f826dffffffffffffffffffffffffffff161480610fdd57505f816dffffffffffffffffffffffffffff16145b15610fed575f935050505061118b565b5f5f610ffe8761146960201b60201c565b9150915080611014575f9550505050505061118b565b5f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161061106f5784611071565b835b90505f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff16106110ce57846110d0565b855b9050601260ff168460ff16111561111a576012846110ee919061214d565b600a6110fa91906122b0565b816dffffffffffffffffffffffffffff166111159190612327565b61114f565b836012611127919061214d565b600a61113391906122b0565b816dffffffffffffffffffffffffffff1661114e9190611fa6565b5b9050611181826dffffffffffffffffffffffffffff16826dffffffffffffffffffffffffffff166115cd60201b60201c565b9750505050505050505b919050565b5f5f60405180606001604052806101f461ffff168152602001610bb861ffff16815260200161271061ffff1681525090505f5f5f90505b60038110156112f0575f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631698ee828760025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1687866003811061124457611243611dc8565b5b60200201516040518463ffffffff1660e01b8152600401611267939291906123ab565b602060405180830381865afa158015611282573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112a69190611fe7565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146112e457809250506112f0565b508060010190506111c7565b505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361132e575f92505050611464565b5f8173ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa92505050801561139757506040513d601f19601f8201168201806040525081019061139491906124c9565b60015b6113a6575f9350505050611464565b869750505050505050505f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161090505f5f6114148861146960201b60201c565b915091508061142b575f9650505050505050611464565b604061145985858661143e576012611440565b855b8761144b578661144e565b60125b6117af60201b60201c565b901c96505050505050505b919050565b5f5f5f5f8473ffffffffffffffffffffffffffffffffffffffff16614e206040516024016040516020818303038152906040527f313ce567000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161151791906125b8565b5f604051808303815f8787f1925050503d805f8114611551576040519150601f19603f3d011682016040523d82523d5f602084013e611556565b606091505b509150915081156115bf575f60208251036115b1578180602001905181019061157f9190611f4e565b90505f81148061158f575060ff81115b156115a2575f5f945094505050506115c8565b806001945094505050506115c8565b5f5f945094505050506115c8565b5f5f9350935050505b915091565b5f5f82036115dd575f90506117a9565b5f77ffffffffffffffffffffffffffffffffffffffffffffffff84116116195782604085901b81611611576116106122fa565b5b049050611783565b5f60c090505f60c086901c9050640100000000811061164057602081901c90506020820191505b62010000811061165857601081901c90506010820191505b610100811061166f57600881901c90506008820191505b6010811061168557600481901c90506004820191505b6004811061169b57600281901c90506002820191505b600281106116aa576001820191505b600160bf830360018703901c018260ff0387901b816116cc576116cb6122fa565b5b0492506fffffffffffffffffffffffffffffffff8311156116f2575f93505050506117a9565b5f608086901c840290505f6fffffffffffffffffffffffffffffffff8716850290505f60c089901c90505f60408a901b905082811015611733576001820391505b8281039050608084901b92508281101561174e576001820391505b8281039050608084901c8214611767576117666125ce565b5b888181611777576117766122fa565b5b04870196505050505050505b6fffffffffffffffffffffffffffffffff8111156117a4575f9150506117a9565b809150505b92915050565b5f5f82840390505f5f825f0b126117e7578160ff16600a0a60028873ffffffffffffffffffffffffffffffffffffffff160a0261181a565b815f0360ff16600a0a60028873ffffffffffffffffffffffffffffffffffffffff160a81611818576118176122fa565b5b045b9050806c01000000000000000000000000111561183b575f92505050611929565b5f86611893576c01000000000000000000000000828161185e5761185d6122fa565b5b046fffffffffffffffffffffffffffffffff6c01000000000000000000000000028161188d5761188c6122fa565b5b046118b2565b6c0100000000000000000000000082816118b0576118af6122fa565b5b045b9050866118bf57806118f0565b6c010000000000000000000000006fffffffffffffffffffffffffffffffff8202816118ee576118ed6122fa565b5b045b93507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841115611925575f9350505050611929565b5050505b949350505050565b60405180606001604052805f600281111561194f5761194e611c4f565b5b81526020015f73ffffffffffffffffffffffffffffffffffffffff1681526020015f81525090565b5f604051905090565b5f5ffd5b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6119b182611988565b9050919050565b6119c1816119a7565b81146119cb575f5ffd5b50565b5f815190506119dc816119b8565b92915050565b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b611a2c826119e6565b810181811067ffffffffffffffff82111715611a4b57611a4a6119f6565b5b80604052505050565b5f611a5d611977565b9050611a698282611a23565b919050565b5f67ffffffffffffffff821115611a8857611a876119f6565b5b602082029050602081019050919050565b5f5ffd5b5f5ffd5b60038110611aad575f5ffd5b50565b5f81519050611abe81611aa1565b92915050565b5f60408284031215611ad957611ad8611a9d565b5b611ae36040611a54565b90505f611af284828501611ab0565b5f830152506020611b05848285016119ce565b60208301525092915050565b5f611b23611b1e84611a6e565b611a54565b90508083825260208201905060408402830185811115611b4657611b45611a99565b5b835b81811015611b6f5780611b5b8882611ac4565b845260208401935050604081019050611b48565b5050509392505050565b5f82601f830112611b8d57611b8c6119e2565b5b8151611b9d848260208601611b11565b91505092915050565b5f5f5f5f60808587031215611bbe57611bbd611980565b5b5f611bcb878288016119ce565b9450506020611bdc878288016119ce565b9350506040611bed878288016119ce565b925050606085015167ffffffffffffffff811115611c0e57611c0d611984565b5b611c1a87828801611b79565b91505092959194509250565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60038110611c8d57611c8c611c4f565b5b50565b5f819050611c9d82611c7c565b919050565b5f611cac82611c90565b9050919050565b611cbc81611ca2565b82525050565b611ccb816119a7565b82525050565b5f819050919050565b611ce381611cd1565b82525050565b606082015f820151611cfd5f850182611cb3565b506020820151611d106020850182611cc2565b506040820151611d236040850182611cda565b50505050565b5f611d348383611ce9565b60608301905092915050565b5f602082019050919050565b5f611d5682611c26565b611d608185611c30565b9350611d6b83611c40565b805f5b83811015611d9b578151611d828882611d29565b9750611d8d83611d40565b925050600181019050611d6e565b5085935050505092915050565b5f6020820190508181035f830152611dc08184611d4c565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f67ffffffffffffffff821115611e0f57611e0e6119f6565b5b602082029050602081019050919050565b5f611e32611e2d84611df5565b611a54565b90508083825260208201905060208402830185811115611e5557611e54611a99565b5b835b81811015611e7e5780611e6a88826119ce565b845260208401935050602081019050611e57565b5050509392505050565b5f82601f830112611e9c57611e9b6119e2565b5b8151611eac848260208601611e20565b91505092915050565b5f60208284031215611eca57611ec9611980565b5b5f82015167ffffffffffffffff811115611ee757611ee6611984565b5b611ef384828501611e88565b91505092915050565b611f05816119a7565b82525050565b5f602082019050611f1e5f830184611efc565b92915050565b611f2d81611cd1565b8114611f37575f5ffd5b50565b5f81519050611f4881611f24565b92915050565b5f60208284031215611f6357611f62611980565b5b5f611f7084828501611f3a565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f611fb082611cd1565b9150611fbb83611cd1565b9250828202611fc981611cd1565b91508282048414831517611fe057611fdf611f79565b5b5092915050565b5f60208284031215611ffc57611ffb611980565b5b5f612009848285016119ce565b91505092915050565b5f6dffffffffffffffffffffffffffff82169050919050565b61203481612012565b811461203e575f5ffd5b50565b5f8151905061204f8161202b565b92915050565b5f63ffffffff82169050919050565b61206d81612055565b8114612077575f5ffd5b50565b5f8151905061208881612064565b92915050565b5f5f5f606084860312156120a5576120a4611980565b5b5f6120b286828701612041565b93505060206120c386828701612041565b92505060406120d48682870161207a565b9150509250925092565b5f6120e882612012565b91506120f383612012565b925082820261210181612012565b915080821461211357612112611f79565b5b5092915050565b5f60408201905061212d5f830185611efc565b61213a6020830184611efc565b9392505050565b5f60ff82169050919050565b5f61215782612141565b915061216283612141565b9250828203905060ff81111561217b5761217a611f79565b5b92915050565b5f8160011c9050919050565b5f5f8291508390505b60018511156121d6578086048111156121b2576121b1611f79565b5b60018516156121c15780820291505b80810290506121cf85612181565b9450612196565b94509492505050565b5f826121ee57600190506122a9565b816121fb575f90506122a9565b8160018114612211576002811461221b5761224a565b60019150506122a9565b60ff84111561222d5761222c611f79565b5b8360020a91508482111561224457612243611f79565b5b506122a9565b5060208310610133831016604e8410600b841016171561227f5782820a90508381111561227a57612279611f79565b5b6122a9565b61228c848484600161218d565b925090508184048111156122a3576122a2611f79565b5b81810290505b9392505050565b5f6122ba82611cd1565b91506122c583612141565b92506122f27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846121df565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61233182611cd1565b915061233c83611cd1565b92508261234c5761234b6122fa565b5b828204905092915050565b5f61ffff82169050919050565b5f62ffffff82169050919050565b5f819050919050565b5f61239561239061238b84612357565b612372565b612364565b9050919050565b6123a58161237b565b82525050565b5f6060820190506123be5f830186611efc565b6123cb6020830185611efc565b6123d8604083018461239c565b949350505050565b6123e981611988565b81146123f3575f5ffd5b50565b5f81519050612404816123e0565b92915050565b5f8160020b9050919050565b61241f8161240a565b8114612429575f5ffd5b50565b5f8151905061243a81612416565b92915050565b61244981612357565b8114612453575f5ffd5b50565b5f8151905061246481612440565b92915050565b61247381612141565b811461247d575f5ffd5b50565b5f8151905061248e8161246a565b92915050565b5f8115159050919050565b6124a881612494565b81146124b2575f5ffd5b50565b5f815190506124c38161249f565b92915050565b5f5f5f5f5f5f5f60e0888a0312156124e4576124e3611980565b5b5f6124f18a828b016123f6565b97505060206125028a828b0161242c565b96505060406125138a828b01612456565b95505060606125248a828b01612456565b94505060806125358a828b01612456565b93505060a06125468a828b01612480565b92505060c06125578a828b016124b5565b91505092959891949750929550565b5f81519050919050565b5f81905092915050565b8281835e5f83830152505050565b5f61259282612566565b61259c8185612570565b93506125ac81856020860161257a565b80840191505092915050565b5f6125c38284612588565b915081905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffdfe","sourceMap":"91:923:34:-:0;;;155:857;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;333:17;352;371:5;1191:17:33;1170:18;;:38;;;;;;;;;;;;;;;;;;1239:17;1218:18;;:38;;;;;;;;;;;;;;;;;;1273:5;1266:4;;:12;;;;;;;;;;;;;;;;;;1079:206;;;388:55:34::1;446:26;466:5;446:19;;;:26;;:::i;:::-;388:84;;674:27;715:14;704:26;;;;;;;;:::i;:::-;;;;;;;;;;;;;674:56;;936:4;920:14;916:25;985:9;976:7;972:23;961:9;954:42;1908:1035:33::0;1978:23;2013:39;2076:5;:12;2055:34;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;2013:76;;2104:9;2116:1;2104:13;;2099:806;2123:5;:12;2119:1;:16;2099:806;;;2156:20;2179:5;2185:1;2179:8;;;;;;;;:::i;:::-;;;;;;;;2156:31;;2222:17;2205:34;;;;;;;;:::i;:::-;;:4;:13;;;:34;;;;;;;;:::i;:::-;;;2201:694;;2259:17;2279:36;2298:4;:16;;;2279:18;;;:36;;:::i;:::-;2259:56;;2354:58;;;;;;;;2369:4;:13;;;2354:58;;;;;;;;:::i;:::-;;;;;;2384:4;:16;;;2354:58;;;;;;2402:9;2354:58;;;2333:15;2349:1;2333:18;;;;;;;;:::i;:::-;;;;;;;:79;;;;2241:186;2201:694;;;2454:18;2437:35;;;;;;;;:::i;:::-;;:4;:13;;;:35;;;;;;;;:::i;:::-;;;2433:462;;2492:17;2512:37;2532:4;:16;;;2512:19;;;:37;;:::i;:::-;2492:57;;2588:58;;;;;;;;2603:4;:13;;;2588:58;;;;;;;;:::i;:::-;;;;;;2618:4;:16;;;2588:58;;;;;;2636:9;2588:58;;;2567:15;2583:1;2567:18;;;;;;;;:::i;:::-;;;;;;;:79;;;;2474:187;2433:462;;;2688:18;2671:35;;;;;;;;:::i;:::-;;:4;:13;;;:35;;;;;;;;:::i;:::-;;;2667:228;;2726:17;2746:37;2766:4;:16;;;2746:19;;;:37;;:::i;:::-;2726:57;;2822:58;;;;;;;;2837:4;:13;;;2822:58;;;;;;;;:::i;:::-;;;;;;2852:4;:16;;;2822:58;;;;;;2870:9;2822:58;;;2801:15;2817:1;2801:18;;;;;;;;:::i;:::-;;;;;;;:79;;;;2708:187;2667:228;2433:462;2201:694;2142:763;2137:3;;;;;;;2099:806;;;;2921:15;2914:22;;;1908:1035;;;:::o;2949:1221::-;3009:7;3055:23;3099:4;3092:29;;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;3088:152;;3228:1;3221:8;;;;;3088:152;3182:7;3173:16;;3124:76;3359:9;3371:1;3359:13;;3354:473;3378:6;:13;3374:1;:17;3354:473;;;3429:4;;;;;;;;;;;3416:17;;:6;3423:1;3416:9;;;;;;;;:::i;:::-;;;;;;;;:17;;;3412:405;;3464:4;3457:23;;;3481:6;3488:1;3481:9;;;;;;;;:::i;:::-;;;;;;;;3457:34;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;3453:350;;3783:1;3776:8;;;;;;3453:350;3715:6;:13;3704:8;:24;;;;:::i;:::-;3697:31;;;;;;;3412:405;3393:3;;;;;;;3354:473;;;;3837:17;3857:6;3864:1;3857:9;;;;;;;;:::i;:::-;;;;;;;;3837:29;;3876:15;3912:4;3905:23;;;3929:9;3905:34;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;3901:149;;4038:1;4031:8;;;;;;;3901:149;3991:8;3981:18;;3940:70;4060:17;4080:41;4102:9;4113:7;4080:21;;;:41;;:::i;:::-;4060:61;;4150:6;:13;4138:9;:25;;;;:::i;:::-;4131:32;;;;;;2949:1221;;;;:::o;4176:896::-;4237:7;4256:14;4299:4;4284:27;;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;4280:141;;4409:1;4402:8;;;;;4280:141;4363:7;4354:16;;4314:67;4430:14;4473:4;4458:27;;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;4454:141;;4583:1;4576:8;;;;;;4454:141;4537:7;4528:16;;4488:67;4623:4;4608:32;;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;4604:462;;5054:1;5047:8;;;;;;4604:462;4724:4;;;;;;;;;;;4714:14;;:6;:14;;;4710:150;;4766:1;4755:8;:12;;;;:::i;:::-;4748:19;;;;;;;;;;;4710:150;4802:4;;;;;;;;;;;4792:14;;:6;:14;;;4788:72;;4844:1;4833:8;:12;;;;:::i;:::-;4826:19;;;;;;;;;;;4788:72;4922:17;4942:39;4964:6;4972:8;4942:39;;:21;;;:39;;:::i;:::-;4922:59;;5014:1;5002:9;:13;;;;:::i;:::-;4995:20;;;;;;;;4176:896;;;;:::o;5078:1167::-;5139:7;5158:14;5209:4;5186:36;;;:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;5182:150;;5320:1;5313:8;;;;;5182:150;5274:7;5265:16;;5225:67;5341:14;5392:4;5369:36;;;:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;5365:150;;5503:1;5496:8;;;;;;5365:150;5457:7;5448:16;;5408:67;5539:4;;;;;;;;;;;5529:14;;:6;:14;;;5525:432;;5570:6;5563:24;;;5596:4;5563:39;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;5559:169;;5712:1;5705:8;;;;;;5559:169;5664:1;5654:7;:11;;;;:::i;:::-;5647:18;;;;;;;5525:432;5758:4;;;;;;;;;;;5748:14;;:6;:14;;;5744:213;;5789:6;5782:24;;;5815:4;5782:39;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;5778:169;;5931:1;5924:8;;;;;;5778:169;5883:1;5873:7;:11;;;;:::i;:::-;5866:18;;;;;;;5744:213;6023:6;6016:24;;;6049:4;6016:39;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;6012:227;;6227:1;6220:8;;;;;;6012:227;6096:17;6116:38;6138:6;6146:7;6116:21;;;:38;;:::i;:::-;6096:58;;6187:1;6175:9;:13;;;;:::i;:::-;6168:20;;;;;;5078:1167;;;;:::o;6323:301::-;6403:7;6449:13;6465:17;6476:5;6465:10;;;:17;;:::i;:::-;6449:33;;6504:1;6496:5;:9;;;6492:126;;;6528:36;6550:5;6557:6;6528:21;;;:36;;:::i;:::-;6521:43;;;;;6492:126;6602:5;6595:12;;;;;6323:301;;;;;:::o;6691:351::-;6744:7;6797:13;6855:26;6875:5;6855:19;;;:26;;:::i;:::-;6847:34;;6903:1;6895:5;:9;;;6891:52;;;6927:5;6920:12;;;;;6891:52;6987:26;7007:5;6987:19;;;:26;;:::i;:::-;6979:34;;7030:5;7023:12;;;6691:351;;;;:::o;369:626:28:-;430:7;482:1;477;:6;:16;;;;492:1;487;:6;;;477:16;473:63;;;520:1;513:8;;;;473:63;550:10;622:2;582:34;578:1;:38;572:1;564:10;;:53;563:61;;550:74;;638:10;670:3;665:1;:8;;659:1;651:10;;:23;638:36;;698:50;693:2;:55;689:102;;;775:1;768:8;;;;;;689:102;811:2;804:9;;;;;906:2;837:66;:71;832:2;:76;828:123;;;935:1;928:8;;;;;;828:123;976:2;971;:7;964:14;;;;369:626;;;;;:::o;7048:1376:33:-;7110:13;7159:19;7214:18;;;;;;;;;;;7196:45;;;7242:5;7249:4;;;;;;;;;;;7196:58;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7159:96;;1022:1;7269:29;;7277:4;7269:29;;;7265:68;;7321:1;7314:8;;;;;7265:68;7443:16;7469;7499:4;:16;;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;7495:197;;7680:1;7673:8;;;;;;;7495:197;7598:9;7587:20;;7632:9;7621:20;;7518:134;;;7717:1;7705:8;:13;;;:30;;;;7734:1;7722:8;:13;;;7705:30;7701:69;;;7758:1;7751:8;;;;;;;7701:69;7819:19;7840:25;7869:29;7892:5;7869:22;;;:29;;:::i;:::-;7818:80;;;;7913:20;7908:60;;7956:1;7949:8;;;;;;;;;7908:60;8021:19;8051:4;;;;;;;;;;;8043:12;;:5;:12;;;:34;;8069:8;8043:34;;;8058:8;8043:34;8021:56;;8087:20;8118:4;;;;;;;;;;;8110:12;;:5;:12;;;:34;;8136:8;8110:34;;;8125:8;8110:34;8087:57;;1070:2;8170:30;;:13;:30;;;;:182;;1070:2;8321:13;:29;;;;:::i;:::-;8314:2;:37;;;;:::i;:::-;8299:12;:52;;;;;;:::i;:::-;8170:182;;;8261:13;1070:2;8245:29;;;;:::i;:::-;8238:2;:37;;;;:::i;:::-;8223:12;:52;;;;;;:::i;:::-;8170:182;8155:197;;8370:47;8391:11;8370:47;;8404:12;8370:47;;:20;;;:47;;:::i;:::-;8362:55;;7125:1299;;;;;;;7048:1376;;;;:::o;8430:1395::-;8492:7;8511:25;:46;;;;;;;;8540:3;8511:46;;;;;;8545:4;8511:46;;;;;;8551:5;8511:46;;;;;;;8567:19;8601:9;8613:1;8601:13;;8596:339;8620:15;8616:1;:19;8596:339;;;8684:19;8755:18;;;;;;;;;;;8737:45;;;8783:5;8790:4;;;;;;;;;;;8796:8;8805:1;8796:11;;;;;;;:::i;:::-;;;;;;8737:71;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8684:125;;1022:1;8827:29;;8835:4;8827:29;;;8823:102;;8883:4;8876:11;;8905:5;;;8823:102;8642:293;8637:3;;;;;8596:339;;;;1022:1;8949:29;;8957:4;8949:29;;;8945:68;;9001:1;8994:8;;;;;;8945:68;9058:20;9092:4;:10;;;:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;9088:186;;9262:1;9255:8;;;;;;;9088:186;9210:13;9195:28;;9105:129;;;;;;;9284:21;9316:4;;;;;;;;;;;9308:12;;:5;:12;;;9284:36;;9331:19;9352:26;9382:29;9405:5;9382:22;;;:29;;:::i;:::-;9330:81;;;;9426:21;9421:61;;9470:1;9463:8;;;;;;;;;;9421:61;9806:2;9542:260;9586:12;9616:16;9650;:60;;1070:2;9650:60;;;9674:13;9650:60;9728:16;:60;;9774:13;9728:60;;;1070:2;9728:60;9542:26;;;:260;;:::i;:::-;:266;;9514:304;;;;;;;;8430:1395;;;;:::o;9939:762::-;10004:5;10011:4;10028:25;10055:30;10101:5;:10;;10117:5;10124:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10101:61;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10027:135;;;;10177:20;10173:522;;;10213:21;10281:2;10253:17;:24;:30;10249:388;;10332:17;10321:40;;;;;;;;;;;;:::i;:::-;10303:58;;10401:1;10384:13;:18;:41;;;;10422:3;10406:13;:19;10384:41;10380:187;;;10457:1;10460:5;10449:17;;;;;;;;;10380:187;10527:13;10543:4;10513:35;;;;;;;;;10249:388;10613:1;10616:5;10605:17;;;;;;;;;10173:522;10675:1;10678:5;10667:17;;;;;;9939:762;;;;:::o;1190:2514:28:-;1250:7;1302:1;1297;:6;1293:20;;1312:1;1305:8;;;;1293:20;1328:14;1366:50;1361:1;:55;1357:1967;;1457:1;1451:2;1446:1;:7;;1445:13;;;;;:::i;:::-;;;1436:22;;1357:1967;;;1497:11;1511:3;1497:17;;1532:10;1550:3;1545:1;:8;;1532:21;;1581:11;1575:2;:17;1571:104;;1623:2;1616:9;;;;;1654:2;1647:9;;;;1571:104;1702:7;1696:2;:13;1692:100;;1740:2;1733:9;;;;;1771:2;1764:9;;;;1692:100;1819:5;1813:2;:11;1809:96;;1855:1;1848:8;;;;;1885:1;1878:8;;;;1809:96;1932:4;1926:2;:10;1922:95;;1967:1;1960:8;;;;;1997:1;1990:8;;;;1922:95;2044:3;2038:2;:9;2034:94;;2078:1;2071:8;;;;;2108:1;2101:8;;;;2034:94;2155:3;2149:2;:9;2145:23;;2167:1;2160:8;;;;2145:23;2276:1;2268:3;2262;:9;2255:1;2251;:5;2250:22;;2249:28;2240:3;2234;:9;2228:1;:16;;2227:51;;;;;:::i;:::-;;;2218:60;;2704:34;2695:6;:43;2691:98;;;2769:1;2762:8;;;;;;;2691:98;2807:10;2835:3;2830:1;:8;;2820:6;:19;2807:32;;2857:10;2884:34;2880:1;:38;2870:6;:49;2857:62;;2938:10;2956:3;2951:1;:8;;2938:21;;2977:10;2995:2;2990:1;:7;;2977:20;;3025:2;3020;:7;3016:20;;;3035:1;3029:7;;;;3016:20;3060:2;3054:8;;;;3128:3;3122:2;:9;;3117:14;;3158:2;3153;:7;3149:20;;;3168:1;3162:7;;;;3149:20;3193:2;3187:8;;;;3270:3;3264:2;:9;;3258:2;:15;3251:23;;;;:::i;:::-;;3308:1;3303:2;:6;;;;;:::i;:::-;;;3293:16;;;;1479:1845;;;;;;1357:1967;3574:34;3565:6;:43;3561:90;;;3635:1;3628:8;;;;;3561:90;3680:6;3665:22;;;1190:2514;;;;;:::o;3710:1606::-;3865:17;4094;4131:14;4114;:31;4094:51;;4256:23;4297:1;4282:12;:16;;;:174;;4443:12;4431:25;;:2;:25;4427:1;4410:12;4402:21;;:26;:54;4282:174;;;4369:12;4368:13;;4346:37;;4354:2;4346:37;4342:1;4325:12;4317:21;;:26;:66;;;;;:::i;:::-;;;4282:174;4256:200;;4480:15;117:27;4474:21;4470:68;;;4522:1;4515:8;;;;;;4470:68;4686:28;4717:16;:143;;117:27;4838:15;:21;;;;;:::i;:::-;;;4799:34;117:27;4793:40;4792:68;;;;;:::i;:::-;;;4717:143;;;117:27;4752:15;:21;;;;;:::i;:::-;;;4717:143;4686:174;;5017:16;:148;;5145:20;5017:148;;;117:27;5085:34;5061:20;5053:66;5052:74;;;;;:::i;:::-;;;5017:148;5005:160;;5196:17;5184:9;:29;5180:120;;;5284:1;5277:8;;;;;;;5180:120;3898:1412;;;3710:1606;;;;;;;:::o;91:923:34:-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::o;7:75:41:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:126;371:7;411:42;404:5;400:54;389:65;;334:126;;;:::o;466:96::-;503:7;532:24;550:5;532:24;:::i;:::-;521:35;;466:96;;;:::o;568:122::-;641:24;659:5;641:24;:::i;:::-;634:5;631:35;621:63;;680:1;677;670:12;621:63;568:122;:::o;696:143::-;753:5;784:6;778:13;769:22;;800:33;827:5;800:33;:::i;:::-;696:143;;;;:::o;845:117::-;954:1;951;944:12;968:102;1009:6;1060:2;1056:7;1051:2;1044:5;1040:14;1036:28;1026:38;;968:102;;;:::o;1076:180::-;1124:77;1121:1;1114:88;1221:4;1218:1;1211:15;1245:4;1242:1;1235:15;1262:281;1345:27;1367:4;1345:27;:::i;:::-;1337:6;1333:40;1475:6;1463:10;1460:22;1439:18;1427:10;1424:34;1421:62;1418:88;;;1486:18;;:::i;:::-;1418:88;1526:10;1522:2;1515:22;1305:238;1262:281;;:::o;1549:129::-;1583:6;1610:20;;:::i;:::-;1600:30;;1639:33;1667:4;1659:6;1639:33;:::i;:::-;1549:129;;;:::o;1684:338::-;1788:4;1878:18;1870:6;1867:30;1864:56;;;1900:18;;:::i;:::-;1864:56;1950:4;1942:6;1938:17;1930:25;;2010:4;2004;2000:15;1992:23;;1684:338;;;:::o;2028:117::-;2137:1;2134;2127:12;2151:117;2260:1;2257;2250:12;2397:113;2484:1;2477:5;2474:12;2464:40;;2500:1;2497;2490:12;2464:40;2397:113;:::o;2516:171::-;2587:5;2618:6;2612:13;2603:22;;2634:47;2675:5;2634:47;:::i;:::-;2516:171;;;;:::o;2733:634::-;2820:5;2864:4;2852:9;2847:3;2843:19;2839:30;2836:117;;;2872:79;;:::i;:::-;2836:117;2971:21;2987:4;2971:21;:::i;:::-;2962:30;;3055:1;3095:74;3165:3;3156:6;3145:9;3141:22;3095:74;:::i;:::-;3088:4;3081:5;3077:16;3070:100;3002:179;3247:2;3288:60;3344:3;3335:6;3324:9;3320:22;3288:60;:::i;:::-;3281:4;3274:5;3270:16;3263:86;3191:169;2733:634;;;;:::o;3415:813::-;3549:5;3574:108;3590:91;3674:6;3590:91;:::i;:::-;3574:108;:::i;:::-;3565:117;;3702:5;3731:6;3724:5;3717:21;3765:4;3758:5;3754:16;3747:23;;3818:4;3810:6;3806:17;3798:6;3794:30;3847:3;3839:6;3836:15;3833:122;;;3866:79;;:::i;:::-;3833:122;3981:6;3964:258;3998:6;3993:3;3990:15;3964:258;;;4073:3;4102:75;4173:3;4161:10;4102:75;:::i;:::-;4097:3;4090:88;4207:4;4202:3;4198:14;4191:21;;4040:182;4024:4;4019:3;4015:14;4008:21;;3964:258;;;3968:21;3555:673;;3415:813;;;;;:::o;4276:439::-;4385:5;4434:3;4427:4;4419:6;4415:17;4411:27;4401:122;;4442:79;;:::i;:::-;4401:122;4552:6;4546:13;4577:132;4705:3;4697:6;4690:4;4682:6;4678:17;4577:132;:::i;:::-;4568:141;;4391:324;4276:439;;;;:::o;4721:1077::-;4870:6;4878;4886;4894;4943:3;4931:9;4922:7;4918:23;4914:33;4911:120;;;4950:79;;:::i;:::-;4911:120;5070:1;5095:64;5151:7;5142:6;5131:9;5127:22;5095:64;:::i;:::-;5085:74;;5041:128;5208:2;5234:64;5290:7;5281:6;5270:9;5266:22;5234:64;:::i;:::-;5224:74;;5179:129;5347:2;5373:64;5429:7;5420:6;5409:9;5405:22;5373:64;:::i;:::-;5363:74;;5318:129;5507:2;5496:9;5492:18;5486:25;5538:18;5530:6;5527:30;5524:117;;;5560:79;;:::i;:::-;5524:117;5665:116;5773:7;5764:6;5753:9;5749:22;5665:116;:::i;:::-;5655:126;;5457:334;4721:1077;;;;;;;:::o;5804:147::-;5904:6;5938:5;5932:12;5922:22;;5804:147;;;:::o;5957:217::-;6089:11;6123:6;6118:3;6111:19;6163:4;6158:3;6154:14;6139:29;;5957:217;;;;:::o;6180:165::-;6280:4;6303:3;6295:11;;6333:4;6328:3;6324:14;6316:22;;6180:165;;;:::o;6351:180::-;6399:77;6396:1;6389:88;6496:4;6493:1;6486:15;6520:4;6517:1;6510:15;6537:119;6624:1;6617:5;6614:12;6604:46;;6630:18;;:::i;:::-;6604:46;6537:119;:::o;6662:139::-;6713:7;6742:5;6731:16;;6748:47;6789:5;6748:47;:::i;:::-;6662:139;;;:::o;6807:::-;6869:9;6902:38;6934:5;6902:38;:::i;:::-;6889:51;;6807:139;;;:::o;6952:145::-;7041:49;7084:5;7041:49;:::i;:::-;7036:3;7029:62;6952:145;;:::o;7103:108::-;7180:24;7198:5;7180:24;:::i;:::-;7175:3;7168:37;7103:108;;:::o;7217:77::-;7254:7;7283:5;7272:16;;7217:77;;;:::o;7300:108::-;7377:24;7395:5;7377:24;:::i;:::-;7372:3;7365:37;7300:108;;:::o;7502:715::-;7655:4;7650:3;7646:14;7746:4;7739:5;7735:16;7729:23;7765:75;7834:4;7829:3;7825:14;7811:12;7765:75;:::i;:::-;7670:180;7939:4;7932:5;7928:16;7922:23;7958:63;8015:4;8010:3;8006:14;7992:12;7958:63;:::i;:::-;7860:171;8118:4;8111:5;8107:16;8101:23;8137:63;8194:4;8189:3;8185:14;8171:12;8137:63;:::i;:::-;8041:169;7624:593;7502:715;;:::o;8223:311::-;8358:10;8379:112;8487:3;8479:6;8379:112;:::i;:::-;8523:4;8518:3;8514:14;8500:28;;8223:311;;;;:::o;8540:146::-;8643:4;8675;8670:3;8666:14;8658:22;;8540:146;;;:::o;8784:996::-;8969:3;8998:87;9079:5;8998:87;:::i;:::-;9101:119;9213:6;9208:3;9101:119;:::i;:::-;9094:126;;9244:89;9327:5;9244:89;:::i;:::-;9356:7;9387:1;9372:383;9397:6;9394:1;9391:13;9372:383;;;9473:6;9467:13;9500:129;9625:3;9610:13;9500:129;:::i;:::-;9493:136;;9652:93;9738:6;9652:93;:::i;:::-;9642:103;;9432:323;9419:1;9416;9412:9;9407:14;;9372:383;;;9376:14;9771:3;9764:10;;8974:806;;;8784:996;;;;:::o;9786:505::-;9995:4;10033:2;10022:9;10018:18;10010:26;;10082:9;10076:4;10072:20;10068:1;10057:9;10053:17;10046:47;10110:174;10279:4;10270:6;10110:174;:::i;:::-;10102:182;;9786:505;;;;:::o;10297:180::-;10345:77;10342:1;10335:88;10442:4;10439:1;10432:15;10466:4;10463:1;10456:15;10483:311;10560:4;10650:18;10642:6;10639:30;10636:56;;;10672:18;;:::i;:::-;10636:56;10722:4;10714:6;10710:17;10702:25;;10782:4;10776;10772:15;10764:23;;10483:311;;;:::o;10817:732::-;10924:5;10949:81;10965:64;11022:6;10965:64;:::i;:::-;10949:81;:::i;:::-;10940:90;;11050:5;11079:6;11072:5;11065:21;11113:4;11106:5;11102:16;11095:23;;11166:4;11158:6;11154:17;11146:6;11142:30;11195:3;11187:6;11184:15;11181:122;;;11214:79;;:::i;:::-;11181:122;11329:6;11312:231;11346:6;11341:3;11338:15;11312:231;;;11421:3;11450:48;11494:3;11482:10;11450:48;:::i;:::-;11445:3;11438:61;11528:4;11523:3;11519:14;11512:21;;11388:155;11372:4;11367:3;11363:14;11356:21;;11312:231;;;11316:21;10930:619;;10817:732;;;;;:::o;11572:385::-;11654:5;11703:3;11696:4;11688:6;11684:17;11680:27;11670:122;;11711:79;;:::i;:::-;11670:122;11821:6;11815:13;11846:105;11947:3;11939:6;11932:4;11924:6;11920:17;11846:105;:::i;:::-;11837:114;;11660:297;11572:385;;;;:::o;11963:554::-;12058:6;12107:2;12095:9;12086:7;12082:23;12078:32;12075:119;;;12113:79;;:::i;:::-;12075:119;12254:1;12243:9;12239:17;12233:24;12284:18;12276:6;12273:30;12270:117;;;12306:79;;:::i;:::-;12270:117;12411:89;12492:7;12483:6;12472:9;12468:22;12411:89;:::i;:::-;12401:99;;12204:306;11963:554;;;;:::o;12523:118::-;12610:24;12628:5;12610:24;:::i;:::-;12605:3;12598:37;12523:118;;:::o;12647:222::-;12740:4;12778:2;12767:9;12763:18;12755:26;;12791:71;12859:1;12848:9;12844:17;12835:6;12791:71;:::i;:::-;12647:222;;;;:::o;12875:122::-;12948:24;12966:5;12948:24;:::i;:::-;12941:5;12938:35;12928:63;;12987:1;12984;12977:12;12928:63;12875:122;:::o;13003:143::-;13060:5;13091:6;13085:13;13076:22;;13107:33;13134:5;13107:33;:::i;:::-;13003:143;;;;:::o;13152:351::-;13222:6;13271:2;13259:9;13250:7;13246:23;13242:32;13239:119;;;13277:79;;:::i;:::-;13239:119;13397:1;13422:64;13478:7;13469:6;13458:9;13454:22;13422:64;:::i;:::-;13412:74;;13368:128;13152:351;;;;:::o;13509:180::-;13557:77;13554:1;13547:88;13654:4;13651:1;13644:15;13678:4;13675:1;13668:15;13695:410;13735:7;13758:20;13776:1;13758:20;:::i;:::-;13753:25;;13792:20;13810:1;13792:20;:::i;:::-;13787:25;;13847:1;13844;13840:9;13869:30;13887:11;13869:30;:::i;:::-;13858:41;;14048:1;14039:7;14035:15;14032:1;14029:22;14009:1;14002:9;13982:83;13959:139;;14078:18;;:::i;:::-;13959:139;13743:362;13695:410;;;;:::o;14111:351::-;14181:6;14230:2;14218:9;14209:7;14205:23;14201:32;14198:119;;;14236:79;;:::i;:::-;14198:119;14356:1;14381:64;14437:7;14428:6;14417:9;14413:22;14381:64;:::i;:::-;14371:74;;14327:128;14111:351;;;;:::o;14468:114::-;14505:7;14545:30;14538:5;14534:42;14523:53;;14468:114;;;:::o;14588:122::-;14661:24;14679:5;14661:24;:::i;:::-;14654:5;14651:35;14641:63;;14700:1;14697;14690:12;14641:63;14588:122;:::o;14716:143::-;14773:5;14804:6;14798:13;14789:22;;14820:33;14847:5;14820:33;:::i;:::-;14716:143;;;;:::o;14865:93::-;14901:7;14941:10;14934:5;14930:22;14919:33;;14865:93;;;:::o;14964:120::-;15036:23;15053:5;15036:23;:::i;:::-;15029:5;15026:34;15016:62;;15074:1;15071;15064:12;15016:62;14964:120;:::o;15090:141::-;15146:5;15177:6;15171:13;15162:22;;15193:32;15219:5;15193:32;:::i;:::-;15090:141;;;;:::o;15237:661::-;15324:6;15332;15340;15389:2;15377:9;15368:7;15364:23;15360:32;15357:119;;;15395:79;;:::i;:::-;15357:119;15515:1;15540:64;15596:7;15587:6;15576:9;15572:22;15540:64;:::i;:::-;15530:74;;15486:128;15653:2;15679:64;15735:7;15726:6;15715:9;15711:22;15679:64;:::i;:::-;15669:74;;15624:129;15792:2;15818:63;15873:7;15864:6;15853:9;15849:22;15818:63;:::i;:::-;15808:73;;15763:128;15237:661;;;;;:::o;15904:279::-;15944:7;15967:20;15985:1;15967:20;:::i;:::-;15962:25;;16001:20;16019:1;16001:20;:::i;:::-;15996:25;;16056:1;16053;16049:9;16078:30;16096:11;16078:30;:::i;:::-;16067:41;;16140:11;16131:7;16128:24;16118:58;;16156:18;;:::i;:::-;16118:58;15952:231;15904:279;;;;:::o;16189:332::-;16310:4;16348:2;16337:9;16333:18;16325:26;;16361:71;16429:1;16418:9;16414:17;16405:6;16361:71;:::i;:::-;16442:72;16510:2;16499:9;16495:18;16486:6;16442:72;:::i;:::-;16189:332;;;;;:::o;16527:86::-;16562:7;16602:4;16595:5;16591:16;16580:27;;16527:86;;;:::o;16619:191::-;16657:4;16677:18;16693:1;16677:18;:::i;:::-;16672:23;;16709:18;16725:1;16709:18;:::i;:::-;16704:23;;16751:1;16748;16744:9;16736:17;;16775:4;16769;16766:14;16763:40;;;16783:18;;:::i;:::-;16763:40;16619:191;;;;:::o;16816:102::-;16858:8;16905:5;16902:1;16898:13;16877:34;;16816:102;;;:::o;16924:848::-;16985:5;16992:4;17016:6;17007:15;;17040:5;17031:14;;17054:712;17075:1;17065:8;17062:15;17054:712;;;17170:4;17165:3;17161:14;17155:4;17152:24;17149:50;;;17179:18;;:::i;:::-;17149:50;17229:1;17219:8;17215:16;17212:451;;;17644:4;17637:5;17633:16;17624:25;;17212:451;17694:4;17688;17684:15;17676:23;;17724:32;17747:8;17724:32;:::i;:::-;17712:44;;17054:712;;;16924:848;;;;;;;:::o;17778:1073::-;17832:5;18023:8;18013:40;;18044:1;18035:10;;18046:5;;18013:40;18072:4;18062:36;;18089:1;18080:10;;18091:5;;18062:36;18158:4;18206:1;18201:27;;;;18242:1;18237:191;;;;18151:277;;18201:27;18219:1;18210:10;;18221:5;;;18237:191;18282:3;18272:8;18269:17;18266:43;;;18289:18;;:::i;:::-;18266:43;18338:8;18335:1;18331:16;18322:25;;18373:3;18366:5;18363:14;18360:40;;;18380:18;;:::i;:::-;18360:40;18413:5;;;18151:277;;18537:2;18527:8;18524:16;18518:3;18512:4;18509:13;18505:36;18487:2;18477:8;18474:16;18469:2;18463:4;18460:12;18456:35;18440:111;18437:246;;;18593:8;18587:4;18583:19;18574:28;;18628:3;18621:5;18618:14;18615:40;;;18635:18;;:::i;:::-;18615:40;18668:5;;18437:246;18708:42;18746:3;18736:8;18730:4;18727:1;18708:42;:::i;:::-;18693:57;;;;18782:4;18777:3;18773:14;18766:5;18763:25;18760:51;;;18791:18;;:::i;:::-;18760:51;18840:4;18833:5;18829:16;18820:25;;17778:1073;;;;;;:::o;18857:281::-;18915:5;18939:23;18957:4;18939:23;:::i;:::-;18931:31;;18983:25;18999:8;18983:25;:::i;:::-;18971:37;;19027:104;19064:66;19054:8;19048:4;19027:104;:::i;:::-;19018:113;;18857:281;;;;:::o;19144:180::-;19192:77;19189:1;19182:88;19289:4;19286:1;19279:15;19313:4;19310:1;19303:15;19330:185;19370:1;19387:20;19405:1;19387:20;:::i;:::-;19382:25;;19421:20;19439:1;19421:20;:::i;:::-;19416:25;;19460:1;19450:35;;19465:18;;:::i;:::-;19450:35;19507:1;19504;19500:9;19495:14;;19330:185;;;;:::o;19521:89::-;19557:7;19597:6;19590:5;19586:18;19575:29;;19521:89;;;:::o;19616:91::-;19652:7;19692:8;19685:5;19681:20;19670:31;;19616:91;;;:::o;19713:60::-;19741:3;19762:5;19755:12;;19713:60;;;:::o;19779:138::-;19827:9;19860:51;19877:33;19886:23;19903:5;19886:23;:::i;:::-;19877:33;:::i;:::-;19860:51;:::i;:::-;19847:64;;19779:138;;;:::o;19923:127::-;20008:35;20037:5;20008:35;:::i;:::-;20003:3;19996:48;19923:127;;:::o;20056:438::-;20203:4;20241:2;20230:9;20226:18;20218:26;;20254:71;20322:1;20311:9;20307:17;20298:6;20254:71;:::i;:::-;20335:72;20403:2;20392:9;20388:18;20379:6;20335:72;:::i;:::-;20417:70;20483:2;20472:9;20468:18;20459:6;20417:70;:::i;:::-;20056:438;;;;;;:::o;20500:122::-;20573:24;20591:5;20573:24;:::i;:::-;20566:5;20563:35;20553:63;;20612:1;20609;20602:12;20553:63;20500:122;:::o;20628:143::-;20685:5;20716:6;20710:13;20701:22;;20732:33;20759:5;20732:33;:::i;:::-;20628:143;;;;:::o;20777:90::-;20812:7;20855:5;20852:1;20841:20;20830:31;;20777:90;;;:::o;20873:118::-;20944:22;20960:5;20944:22;:::i;:::-;20937:5;20934:33;20924:61;;20981:1;20978;20971:12;20924:61;20873:118;:::o;20997:139::-;21052:5;21083:6;21077:13;21068:22;;21099:31;21124:5;21099:31;:::i;:::-;20997:139;;;;:::o;21142:120::-;21214:23;21231:5;21214:23;:::i;:::-;21207:5;21204:34;21194:62;;21252:1;21249;21242:12;21194:62;21142:120;:::o;21268:141::-;21324:5;21355:6;21349:13;21340:22;;21371:32;21397:5;21371:32;:::i;:::-;21268:141;;;;:::o;21415:118::-;21486:22;21502:5;21486:22;:::i;:::-;21479:5;21476:33;21466:61;;21523:1;21520;21513:12;21466:61;21415:118;:::o;21539:139::-;21594:5;21625:6;21619:13;21610:22;;21641:31;21666:5;21641:31;:::i;:::-;21539:139;;;;:::o;21684:90::-;21718:7;21761:5;21754:13;21747:21;21736:32;;21684:90;;;:::o;21780:116::-;21850:21;21865:5;21850:21;:::i;:::-;21843:5;21840:32;21830:60;;21886:1;21883;21876:12;21830:60;21780:116;:::o;21902:137::-;21956:5;21987:6;21981:13;21972:22;;22003:30;22027:5;22003:30;:::i;:::-;21902:137;;;;:::o;22045:1271::-;22159:6;22167;22175;22183;22191;22199;22207;22256:3;22244:9;22235:7;22231:23;22227:33;22224:120;;;22263:79;;:::i;:::-;22224:120;22383:1;22408:64;22464:7;22455:6;22444:9;22440:22;22408:64;:::i;:::-;22398:74;;22354:128;22521:2;22547:62;22601:7;22592:6;22581:9;22577:22;22547:62;:::i;:::-;22537:72;;22492:127;22658:2;22684:63;22739:7;22730:6;22719:9;22715:22;22684:63;:::i;:::-;22674:73;;22629:128;22796:2;22822:63;22877:7;22868:6;22857:9;22853:22;22822:63;:::i;:::-;22812:73;;22767:128;22934:3;22961:63;23016:7;23007:6;22996:9;22992:22;22961:63;:::i;:::-;22951:73;;22905:129;23073:3;23100:62;23154:7;23145:6;23134:9;23130:22;23100:62;:::i;:::-;23090:72;;23044:128;23211:3;23238:61;23291:7;23282:6;23271:9;23267:22;23238:61;:::i;:::-;23228:71;;23182:127;22045:1271;;;;;;;;;;:::o;23322:98::-;23373:6;23407:5;23401:12;23391:22;;23322:98;;;:::o;23426:147::-;23527:11;23564:3;23549:18;;23426:147;;;;:::o;23579:139::-;23668:6;23663:3;23658;23652:23;23709:1;23700:6;23695:3;23691:16;23684:27;23579:139;;;:::o;23724:386::-;23828:3;23856:38;23888:5;23856:38;:::i;:::-;23910:88;23991:6;23986:3;23910:88;:::i;:::-;23903:95;;24007:65;24065:6;24060:3;24053:4;24046:5;24042:16;24007:65;:::i;:::-;24097:6;24092:3;24088:16;24081:23;;23832:278;23724:386;;;;:::o;24116:271::-;24246:3;24268:93;24357:3;24348:6;24268:93;:::i;:::-;24261:100;;24378:3;24371:10;;24116:271;;;;:::o;24393:180::-;24441:77;24438:1;24431:88;24538:4;24535:1;24528:15;24562:4;24559:1;24552:15","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063339173fd1461002d575b5f5ffd5b61004760048036038101906100429190611a7a565b61005d565b6040516100549190611c43565b60405180910390f35b60605f825167ffffffffffffffff81111561007b5761007a611870565b5b6040519080825280602002602001820160405280156100b457816020015b6100a1611805565b8152602001906001900390816100995790505b5090505f5f90505b83518110156102f4575f8482815181106100d9576100d8611c63565b5b602002602001015190505f60028111156100f6576100f5611aea565b5b815f0151600281111561010c5761010b611aea565b5b0361018f575f61011f82602001516102fe565b90506040518060600160405280835f0151600281111561014257610141611aea565b5b8152602001836020015173ffffffffffffffffffffffffffffffffffffffff1681526020018281525084848151811061017e5761017d611c63565b5b6020026020010181905250506102e6565b600160028111156101a3576101a2611aea565b5b815f015160028111156101b9576101b8611aea565b5b0361023c575f6101cc8260200151610587565b90506040518060600160405280835f015160028111156101ef576101ee611aea565b5b8152602001836020015173ffffffffffffffffffffffffffffffffffffffff1681526020018281525084848151811061022b5761022a611c63565b5b6020026020010181905250506102e5565b60028081111561024f5761024e611aea565b5b815f0151600281111561026557610264611aea565b5b036102e4575f6102788260200151610825565b90506040518060600160405280835f0151600281111561029b5761029a611aea565b5b8152602001836020015173ffffffffffffffffffffffffffffffffffffffff168152602001828152508484815181106102d7576102d6611c63565b5b6020026020010181905250505b5b5b5080806001019150506100bc565b5080915050919050565b5f60608273ffffffffffffffffffffffffffffffffffffffff1663cc77828d6040518163ffffffff1660e01b81526004015f604051808303815f875af192505050801561036d57506040513d5f823e3d601f19601f8201168201806040525081019061036a9190611d64565b60015b61037a575f915050610582565b809150505f5f90505b81518110156104ba5760025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168282815181106103d7576103d6611c63565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16036104ad578373ffffffffffffffffffffffffffffffffffffffff1663f8b2cb4f83838151811061042957610428611c63565b5b60200260200101516040518263ffffffff1660e01b815260040161044d9190611dba565b6020604051808303815f875af192505050801561048857506040513d601f19601f820116820180604052508101906104859190611dfd565b60015b610496575f92505050610582565b8251816104a39190611e55565b9350505050610582565b8080600101915050610383565b505f815f815181106104cf576104ce611c63565b5b602002602001015190505f8473ffffffffffffffffffffffffffffffffffffffff1663f8b2cb4f836040518263ffffffff1660e01b81526004016105139190611dba565b6020604051808303815f875af192505050801561054e57506040513d601f19601f8201168201806040525081019061054b9190611dfd565b60015b61055d575f9350505050610582565b809150505f61056c8383610b9a565b905083518161057b9190611e55565b9450505050505b919050565b5f5f8273ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156105f157506040513d601f19601f820116820180604052508101906105ee9190611e96565b60015b6105fe575f915050610820565b809150505f8373ffffffffffffffffffffffffffffffffffffffff1663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561066b57506040513d601f19601f820116820180604052508101906106689190611e96565b60015b610679575f92505050610820565b809150508373ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa9250505080156106e557506040513d601f19601f820116820180604052508101906106e29190611f3d565b60015b6106f3575f92505050610820565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610770576002836107549190611f8d565b6dffffffffffffffffffffffffffff1695505050505050610820565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036107ed576002826107d19190611f8d565b6dffffffffffffffffffffffffffff1695505050505050610820565b5f61080886856dffffffffffffffffffffffffffff16610b9a565b90506002816108179190611e55565b96505050505050505b919050565b5f5f8273ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561088f57506040513d601f19601f8201168201806040525081019061088c9190611e96565b60015b61089c575f915050610b95565b809150505f8373ffffffffffffffffffffffffffffffffffffffff1663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561090957506040513d601f19601f820116820180604052508101906109069190611e96565b60015b610917575f92505050610b95565b8091505060025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a07578173ffffffffffffffffffffffffffffffffffffffff166370a08231856040518263ffffffff1660e01b81526004016109a89190611dba565b602060405180830381865afa9250505080156109e257506040513d601f19601f820116820180604052508101906109df9190611dfd565b60015b6109f0575f92505050610b95565b6002816109fd9190611e55565b9350505050610b95565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610af3578073ffffffffffffffffffffffffffffffffffffffff166370a08231856040518263ffffffff1660e01b8152600401610a949190611dba565b602060405180830381865afa925050508015610ace57506040513d601f19601f82011682018060405250810190610acb9190611dfd565b60015b610adc575f92505050610b95565b600281610ae99190611e55565b9350505050610b95565b8173ffffffffffffffffffffffffffffffffffffffff166370a08231856040518263ffffffff1660e01b8152600401610b2c9190611dba565b602060405180830381865afa925050508015610b6657506040513d601f19601f82011682018060405250810190610b639190611dfd565b60015b610b74575f92505050610b95565b5f610b7f8483610b9a565b9050600281610b8e9190611e55565b9450505050505b919050565b5f5f610ba584610bf0565b90505f816fffffffffffffffffffffffffffffffff161115610bd357610bcb8184610c35565b915050610bea565b806fffffffffffffffffffffffffffffffff169150505b92915050565b5f5f610bfb83610d1f565b90505f816fffffffffffffffffffffffffffffffff161115610c205780915050610c30565b610c2983611070565b9050809150505b919050565b5f5f821480610c5557505f836fffffffffffffffffffffffffffffffff16145b15610c62575f9050610d19565b5f60406fffffffffffffffffffffffffffffffff8416856fffffffffffffffffffffffffffffffff1602901c90505f608084901c856fffffffffffffffffffffffffffffffff1602905077ffffffffffffffffffffffffffffffffffffffffffffffff811115610cd6575f92505050610d19565b604081901b9050817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03811115610d11575f92505050610d19565b818101925050505b92915050565b5f5f5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e6a439058460025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518363ffffffff1660e01b8152600401610d9d929190611fc9565b602060405180830381865afa158015610db8573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ddc9190611e96565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610e1a575f91505061106b565b5f5f8273ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa925050508015610e8457506040513d601f19601f82011682018060405250810190610e819190611f3d565b60015b610e93575f935050505061106b565b8294508193505050505f826dffffffffffffffffffffffffffff161480610ec957505f816dffffffffffffffffffffffffffff16145b15610ed9575f935050505061106b565b5f5f610ee48761133d565b9150915080610efa575f9550505050505061106b565b5f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1610610f555784610f57565b835b90505f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1610610fb45784610fb6565b855b9050601260ff168460ff16111561100057601284610fd49190611ffc565b600a610fe0919061215f565b816dffffffffffffffffffffffffffff16610ffb91906121d6565b611035565b83601261100d9190611ffc565b600a611019919061215f565b816dffffffffffffffffffffffffffff166110349190611e55565b5b9050611061826dffffffffffffffffffffffffffff16826dffffffffffffffffffffffffffff166114a1565b9750505050505050505b919050565b5f5f60405180606001604052806101f461ffff168152602001610bb861ffff16815260200161271061ffff1681525090505f5f5f90505b60038110156111d0575f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631698ee828760025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1687866003811061112457611123611c63565b5b60200201516040518463ffffffff1660e01b81526004016111479392919061225a565b602060405180830381865afa158015611162573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111869190611e96565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146111c457809250506111d0565b508060010190506110a7565b505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361120e575f92505050611338565b5f8173ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa92505050801561127757506040513d601f19601f820116820180604052508101906112749190612378565b60015b611286575f9350505050611338565b869750505050505050505f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161090505f5f6112ee8861133d565b9150915080611305575f9650505050505050611338565b604061132d85858661131857601261131a565b855b876113255786611328565b60125b611683565b901c96505050505050505b919050565b5f5f5f5f8473ffffffffffffffffffffffffffffffffffffffff16614e206040516024016040516020818303038152906040527f313ce567000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516113eb9190612467565b5f604051808303815f8787f1925050503d805f8114611425576040519150601f19603f3d011682016040523d82523d5f602084013e61142a565b606091505b50915091508115611493575f602082510361148557818060200190518101906114539190611dfd565b90505f811480611463575060ff81115b15611476575f5f9450945050505061149c565b8060019450945050505061149c565b5f5f9450945050505061149c565b5f5f9350935050505b915091565b5f5f82036114b1575f905061167d565b5f77ffffffffffffffffffffffffffffffffffffffffffffffff84116114ed5782604085901b816114e5576114e46121a9565b5b049050611657565b5f60c090505f60c086901c9050640100000000811061151457602081901c90506020820191505b62010000811061152c57601081901c90506010820191505b610100811061154357600881901c90506008820191505b6010811061155957600481901c90506004820191505b6004811061156f57600281901c90506002820191505b6002811061157e576001820191505b600160bf830360018703901c018260ff0387901b816115a05761159f6121a9565b5b0492506fffffffffffffffffffffffffffffffff8311156115c6575f935050505061167d565b5f608086901c840290505f6fffffffffffffffffffffffffffffffff8716850290505f60c089901c90505f60408a901b905082811015611607576001820391505b8281039050608084901b925082811015611622576001820391505b8281039050608084901c821461163b5761163a61247d565b5b88818161164b5761164a6121a9565b5b04870196505050505050505b6fffffffffffffffffffffffffffffffff811115611678575f91505061167d565b809150505b92915050565b5f5f82840390505f5f825f0b126116bb578160ff16600a0a60028873ffffffffffffffffffffffffffffffffffffffff160a026116ee565b815f0360ff16600a0a60028873ffffffffffffffffffffffffffffffffffffffff160a816116ec576116eb6121a9565b5b045b9050806c01000000000000000000000000111561170f575f925050506117fd565b5f86611767576c010000000000000000000000008281611732576117316121a9565b5b046fffffffffffffffffffffffffffffffff6c010000000000000000000000000281611761576117606121a9565b5b04611786565b6c010000000000000000000000008281611784576117836121a9565b5b045b90508661179357806117c4565b6c010000000000000000000000006fffffffffffffffffffffffffffffffff8202816117c2576117c16121a9565b5b045b93507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8411156117f9575f93505050506117fd565b5050505b949350505050565b60405180606001604052805f600281111561182357611822611aea565b5b81526020015f73ffffffffffffffffffffffffffffffffffffffff1681526020015f81525090565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6118a682611860565b810181811067ffffffffffffffff821117156118c5576118c4611870565b5b80604052505050565b5f6118d761184b565b90506118e3828261189d565b919050565b5f67ffffffffffffffff82111561190257611901611870565b5b602082029050602081019050919050565b5f5ffd5b5f5ffd5b60038110611927575f5ffd5b50565b5f813590506119388161191b565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6119678261193e565b9050919050565b6119778161195d565b8114611981575f5ffd5b50565b5f813590506119928161196e565b92915050565b5f604082840312156119ad576119ac611917565b5b6119b760406118ce565b90505f6119c68482850161192a565b5f8301525060206119d984828501611984565b60208301525092915050565b5f6119f76119f2846118e8565b6118ce565b90508083825260208201905060408402830185811115611a1a57611a19611913565b5b835b81811015611a435780611a2f8882611998565b845260208401935050604081019050611a1c565b5050509392505050565b5f82601f830112611a6157611a6061185c565b5b8135611a718482602086016119e5565b91505092915050565b5f60208284031215611a8f57611a8e611854565b5b5f82013567ffffffffffffffff811115611aac57611aab611858565b5b611ab884828501611a4d565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60038110611b2857611b27611aea565b5b50565b5f819050611b3882611b17565b919050565b5f611b4782611b2b565b9050919050565b611b5781611b3d565b82525050565b611b668161195d565b82525050565b5f819050919050565b611b7e81611b6c565b82525050565b606082015f820151611b985f850182611b4e565b506020820151611bab6020850182611b5d565b506040820151611bbe6040850182611b75565b50505050565b5f611bcf8383611b84565b60608301905092915050565b5f602082019050919050565b5f611bf182611ac1565b611bfb8185611acb565b9350611c0683611adb565b805f5b83811015611c36578151611c1d8882611bc4565b9750611c2883611bdb565b925050600181019050611c09565b5085935050505092915050565b5f6020820190508181035f830152611c5b8184611be7565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f67ffffffffffffffff821115611caa57611ca9611870565b5b602082029050602081019050919050565b5f81519050611cc98161196e565b92915050565b5f611ce1611cdc84611c90565b6118ce565b90508083825260208201905060208402830185811115611d0457611d03611913565b5b835b81811015611d2d5780611d198882611cbb565b845260208401935050602081019050611d06565b5050509392505050565b5f82601f830112611d4b57611d4a61185c565b5b8151611d5b848260208601611ccf565b91505092915050565b5f60208284031215611d7957611d78611854565b5b5f82015167ffffffffffffffff811115611d9657611d95611858565b5b611da284828501611d37565b91505092915050565b611db48161195d565b82525050565b5f602082019050611dcd5f830184611dab565b92915050565b611ddc81611b6c565b8114611de6575f5ffd5b50565b5f81519050611df781611dd3565b92915050565b5f60208284031215611e1257611e11611854565b5b5f611e1f84828501611de9565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f611e5f82611b6c565b9150611e6a83611b6c565b9250828202611e7881611b6c565b91508282048414831517611e8f57611e8e611e28565b5b5092915050565b5f60208284031215611eab57611eaa611854565b5b5f611eb884828501611cbb565b91505092915050565b5f6dffffffffffffffffffffffffffff82169050919050565b611ee381611ec1565b8114611eed575f5ffd5b50565b5f81519050611efe81611eda565b92915050565b5f63ffffffff82169050919050565b611f1c81611f04565b8114611f26575f5ffd5b50565b5f81519050611f3781611f13565b92915050565b5f5f5f60608486031215611f5457611f53611854565b5b5f611f6186828701611ef0565b9350506020611f7286828701611ef0565b9250506040611f8386828701611f29565b9150509250925092565b5f611f9782611ec1565b9150611fa283611ec1565b9250828202611fb081611ec1565b9150808214611fc257611fc1611e28565b5b5092915050565b5f604082019050611fdc5f830185611dab565b611fe96020830184611dab565b9392505050565b5f60ff82169050919050565b5f61200682611ff0565b915061201183611ff0565b9250828203905060ff81111561202a57612029611e28565b5b92915050565b5f8160011c9050919050565b5f5f8291508390505b60018511156120855780860481111561206157612060611e28565b5b60018516156120705780820291505b808102905061207e85612030565b9450612045565b94509492505050565b5f8261209d5760019050612158565b816120aa575f9050612158565b81600181146120c057600281146120ca576120f9565b6001915050612158565b60ff8411156120dc576120db611e28565b5b8360020a9150848211156120f3576120f2611e28565b5b50612158565b5060208310610133831016604e8410600b841016171561212e5782820a90508381111561212957612128611e28565b5b612158565b61213b848484600161203c565b9250905081840481111561215257612151611e28565b5b81810290505b9392505050565b5f61216982611b6c565b915061217483611ff0565b92506121a17fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff848461208e565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6121e082611b6c565b91506121eb83611b6c565b9250826121fb576121fa6121a9565b5b828204905092915050565b5f61ffff82169050919050565b5f62ffffff82169050919050565b5f819050919050565b5f61224461223f61223a84612206565b612221565b612213565b9050919050565b6122548161222a565b82525050565b5f60608201905061226d5f830186611dab565b61227a6020830185611dab565b612287604083018461224b565b949350505050565b6122988161193e565b81146122a2575f5ffd5b50565b5f815190506122b38161228f565b92915050565b5f8160020b9050919050565b6122ce816122b9565b81146122d8575f5ffd5b50565b5f815190506122e9816122c5565b92915050565b6122f881612206565b8114612302575f5ffd5b50565b5f81519050612313816122ef565b92915050565b61232281611ff0565b811461232c575f5ffd5b50565b5f8151905061233d81612319565b92915050565b5f8115159050919050565b61235781612343565b8114612361575f5ffd5b50565b5f815190506123728161234e565b92915050565b5f5f5f5f5f5f5f60e0888a03121561239357612392611854565b5b5f6123a08a828b016122a5565b97505060206123b18a828b016122db565b96505060406123c28a828b01612305565b95505060606123d38a828b01612305565b94505060806123e48a828b01612305565b93505060a06123f58a828b0161232f565b92505060c06124068a828b01612364565b91505092959891949750929550565b5f81519050919050565b5f81905092915050565b8281835e5f83830152505050565b5f61244182612415565b61244b818561241f565b935061245b818560208601612429565b80840191505092915050565b5f6124728284612437565b915081905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffdfea164736f6c634300081c000a","sourceMap":"91:923:34:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1908:1035:33;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;1978:23;2013:39;2076:5;:12;2055:34;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;2013:76;;2104:9;2116:1;2104:13;;2099:806;2123:5;:12;2119:1;:16;2099:806;;;2156:20;2179:5;2185:1;2179:8;;;;;;;;:::i;:::-;;;;;;;;2156:31;;2222:17;2205:34;;;;;;;;:::i;:::-;;:4;:13;;;:34;;;;;;;;:::i;:::-;;;2201:694;;2259:17;2279:36;2298:4;:16;;;2279:18;:36::i;:::-;2259:56;;2354:58;;;;;;;;2369:4;:13;;;2354:58;;;;;;;;:::i;:::-;;;;;;2384:4;:16;;;2354:58;;;;;;2402:9;2354:58;;;2333:15;2349:1;2333:18;;;;;;;;:::i;:::-;;;;;;;:79;;;;2241:186;2201:694;;;2454:18;2437:35;;;;;;;;:::i;:::-;;:4;:13;;;:35;;;;;;;;:::i;:::-;;;2433:462;;2492:17;2512:37;2532:4;:16;;;2512:19;:37::i;:::-;2492:57;;2588:58;;;;;;;;2603:4;:13;;;2588:58;;;;;;;;:::i;:::-;;;;;;2618:4;:16;;;2588:58;;;;;;2636:9;2588:58;;;2567:15;2583:1;2567:18;;;;;;;;:::i;:::-;;;;;;;:79;;;;2474:187;2433:462;;;2688:18;2671:35;;;;;;;;:::i;:::-;;:4;:13;;;:35;;;;;;;;:::i;:::-;;;2667:228;;2726:17;2746:37;2766:4;:16;;;2746:19;:37::i;:::-;2726:57;;2822:58;;;;;;;;2837:4;:13;;;2822:58;;;;;;;;:::i;:::-;;;;;;2852:4;:16;;;2822:58;;;;;;2870:9;2822:58;;;2801:15;2817:1;2801:18;;;;;;;;:::i;:::-;;;;;;;:79;;;;2708:187;2667:228;2433:462;2201:694;2142:763;2137:3;;;;;;;2099:806;;;;2921:15;2914:22;;;1908:1035;;;:::o;2949:1221::-;3009:7;3055:23;3099:4;3092:29;;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;3088:152;;3228:1;3221:8;;;;;3088:152;3182:7;3173:16;;3124:76;3359:9;3371:1;3359:13;;3354:473;3378:6;:13;3374:1;:17;3354:473;;;3429:4;;;;;;;;;;;3416:17;;:6;3423:1;3416:9;;;;;;;;:::i;:::-;;;;;;;;:17;;;3412:405;;3464:4;3457:23;;;3481:6;3488:1;3481:9;;;;;;;;:::i;:::-;;;;;;;;3457:34;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;3453:350;;3783:1;3776:8;;;;;;3453:350;3715:6;:13;3704:8;:24;;;;:::i;:::-;3697:31;;;;;;;3412:405;3393:3;;;;;;;3354:473;;;;3837:17;3857:6;3864:1;3857:9;;;;;;;;:::i;:::-;;;;;;;;3837:29;;3876:15;3912:4;3905:23;;;3929:9;3905:34;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;3901:149;;4038:1;4031:8;;;;;;;3901:149;3991:8;3981:18;;3940:70;4060:17;4080:41;4102:9;4113:7;4080:21;:41::i;:::-;4060:61;;4150:6;:13;4138:9;:25;;;;:::i;:::-;4131:32;;;;;;2949:1221;;;;:::o;4176:896::-;4237:7;4256:14;4299:4;4284:27;;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;4280:141;;4409:1;4402:8;;;;;4280:141;4363:7;4354:16;;4314:67;4430:14;4473:4;4458:27;;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;4454:141;;4583:1;4576:8;;;;;;4454:141;4537:7;4528:16;;4488:67;4623:4;4608:32;;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;4604:462;;5054:1;5047:8;;;;;;4604:462;4724:4;;;;;;;;;;;4714:14;;:6;:14;;;4710:150;;4766:1;4755:8;:12;;;;:::i;:::-;4748:19;;;;;;;;;;;4710:150;4802:4;;;;;;;;;;;4792:14;;:6;:14;;;4788:72;;4844:1;4833:8;:12;;;;:::i;:::-;4826:19;;;;;;;;;;;4788:72;4922:17;4942:39;4964:6;4972:8;4942:39;;:21;:39::i;:::-;4922:59;;5014:1;5002:9;:13;;;;:::i;:::-;4995:20;;;;;;;;4176:896;;;;:::o;5078:1167::-;5139:7;5158:14;5209:4;5186:36;;;:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;5182:150;;5320:1;5313:8;;;;;5182:150;5274:7;5265:16;;5225:67;5341:14;5392:4;5369:36;;;:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;5365:150;;5503:1;5496:8;;;;;;5365:150;5457:7;5448:16;;5408:67;5539:4;;;;;;;;;;;5529:14;;:6;:14;;;5525:432;;5570:6;5563:24;;;5596:4;5563:39;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;5559:169;;5712:1;5705:8;;;;;;5559:169;5664:1;5654:7;:11;;;;:::i;:::-;5647:18;;;;;;;5525:432;5758:4;;;;;;;;;;;5748:14;;:6;:14;;;5744:213;;5789:6;5782:24;;;5815:4;5782:39;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;5778:169;;5931:1;5924:8;;;;;;5778:169;5883:1;5873:7;:11;;;;:::i;:::-;5866:18;;;;;;;5744:213;6023:6;6016:24;;;6049:4;6016:39;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;6012:227;;6227:1;6220:8;;;;;;6012:227;6096:17;6116:38;6138:6;6146:7;6116:21;:38::i;:::-;6096:58;;6187:1;6175:9;:13;;;;:::i;:::-;6168:20;;;;;;5078:1167;;;;:::o;6323:301::-;6403:7;6449:13;6465:17;6476:5;6465:10;:17::i;:::-;6449:33;;6504:1;6496:5;:9;;;6492:126;;;6528:36;6550:5;6557:6;6528:21;:36::i;:::-;6521:43;;;;;6492:126;6602:5;6595:12;;;;;6323:301;;;;;:::o;6691:351::-;6744:7;6797:13;6855:26;6875:5;6855:19;:26::i;:::-;6847:34;;6903:1;6895:5;:9;;;6891:52;;;6927:5;6920:12;;;;;6891:52;6987:26;7007:5;6987:19;:26::i;:::-;6979:34;;7030:5;7023:12;;;6691:351;;;;:::o;369:626:28:-;430:7;482:1;477;:6;:16;;;;492:1;487;:6;;;477:16;473:63;;;520:1;513:8;;;;473:63;550:10;622:2;582:34;578:1;:38;572:1;564:10;;:53;563:61;;550:74;;638:10;670:3;665:1;:8;;659:1;651:10;;:23;638:36;;698:50;693:2;:55;689:102;;;775:1;768:8;;;;;;689:102;811:2;804:9;;;;;906:2;837:66;:71;832:2;:76;828:123;;;935:1;928:8;;;;;;828:123;976:2;971;:7;964:14;;;;369:626;;;;;:::o;7048:1376:33:-;7110:13;7159:19;7214:18;;;;;;;;;;;7196:45;;;7242:5;7249:4;;;;;;;;;;;7196:58;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7159:96;;1022:1;7269:29;;7277:4;7269:29;;;7265:68;;7321:1;7314:8;;;;;7265:68;7443:16;7469;7499:4;:16;;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;7495:197;;7680:1;7673:8;;;;;;;7495:197;7598:9;7587:20;;7632:9;7621:20;;7518:134;;;7717:1;7705:8;:13;;;:30;;;;7734:1;7722:8;:13;;;7705:30;7701:69;;;7758:1;7751:8;;;;;;;7701:69;7819:19;7840:25;7869:29;7892:5;7869:22;:29::i;:::-;7818:80;;;;7913:20;7908:60;;7956:1;7949:8;;;;;;;;;7908:60;8021:19;8051:4;;;;;;;;;;;8043:12;;:5;:12;;;:34;;8069:8;8043:34;;;8058:8;8043:34;8021:56;;8087:20;8118:4;;;;;;;;;;;8110:12;;:5;:12;;;:34;;8136:8;8110:34;;;8125:8;8110:34;8087:57;;1070:2;8170:30;;:13;:30;;;;:182;;1070:2;8321:13;:29;;;;:::i;:::-;8314:2;:37;;;;:::i;:::-;8299:12;:52;;;;;;:::i;:::-;8170:182;;;8261:13;1070:2;8245:29;;;;:::i;:::-;8238:2;:37;;;;:::i;:::-;8223:12;:52;;;;;;:::i;:::-;8170:182;8155:197;;8370:47;8391:11;8370:47;;8404:12;8370:47;;:20;:47::i;:::-;8362:55;;7125:1299;;;;;;;7048:1376;;;;:::o;8430:1395::-;8492:7;8511:25;:46;;;;;;;;8540:3;8511:46;;;;;;8545:4;8511:46;;;;;;8551:5;8511:46;;;;;;;8567:19;8601:9;8613:1;8601:13;;8596:339;8620:15;8616:1;:19;8596:339;;;8684:19;8755:18;;;;;;;;;;;8737:45;;;8783:5;8790:4;;;;;;;;;;;8796:8;8805:1;8796:11;;;;;;;:::i;:::-;;;;;;8737:71;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8684:125;;1022:1;8827:29;;8835:4;8827:29;;;8823:102;;8883:4;8876:11;;8905:5;;;8823:102;8642:293;8637:3;;;;;8596:339;;;;1022:1;8949:29;;8957:4;8949:29;;;8945:68;;9001:1;8994:8;;;;;;8945:68;9058:20;9092:4;:10;;;:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;9088:186;;9262:1;9255:8;;;;;;;9088:186;9210:13;9195:28;;9105:129;;;;;;;9284:21;9316:4;;;;;;;;;;;9308:12;;:5;:12;;;9284:36;;9331:19;9352:26;9382:29;9405:5;9382:22;:29::i;:::-;9330:81;;;;9426:21;9421:61;;9470:1;9463:8;;;;;;;;;;9421:61;9806:2;9542:260;9586:12;9616:16;9650;:60;;1070:2;9650:60;;;9674:13;9650:60;9728:16;:60;;9774:13;9728:60;;;1070:2;9728:60;9542:26;:260::i;:::-;:266;;9514:304;;;;;;;;8430:1395;;;;:::o;9939:762::-;10004:5;10011:4;10028:25;10055:30;10101:5;:10;;10117:5;10124:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10101:61;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10027:135;;;;10177:20;10173:522;;;10213:21;10281:2;10253:17;:24;:30;10249:388;;10332:17;10321:40;;;;;;;;;;;;:::i;:::-;10303:58;;10401:1;10384:13;:18;:41;;;;10422:3;10406:13;:19;10384:41;10380:187;;;10457:1;10460:5;10449:17;;;;;;;;;10380:187;10527:13;10543:4;10513:35;;;;;;;;;10249:388;10613:1;10616:5;10605:17;;;;;;;;;10173:522;10675:1;10678:5;10667:17;;;;;;9939:762;;;;:::o;1190:2514:28:-;1250:7;1302:1;1297;:6;1293:20;;1312:1;1305:8;;;;1293:20;1328:14;1366:50;1361:1;:55;1357:1967;;1457:1;1451:2;1446:1;:7;;1445:13;;;;;:::i;:::-;;;1436:22;;1357:1967;;;1497:11;1511:3;1497:17;;1532:10;1550:3;1545:1;:8;;1532:21;;1581:11;1575:2;:17;1571:104;;1623:2;1616:9;;;;;1654:2;1647:9;;;;1571:104;1702:7;1696:2;:13;1692:100;;1740:2;1733:9;;;;;1771:2;1764:9;;;;1692:100;1819:5;1813:2;:11;1809:96;;1855:1;1848:8;;;;;1885:1;1878:8;;;;1809:96;1932:4;1926:2;:10;1922:95;;1967:1;1960:8;;;;;1997:1;1990:8;;;;1922:95;2044:3;2038:2;:9;2034:94;;2078:1;2071:8;;;;;2108:1;2101:8;;;;2034:94;2155:3;2149:2;:9;2145:23;;2167:1;2160:8;;;;2145:23;2276:1;2268:3;2262;:9;2255:1;2251;:5;2250:22;;2249:28;2240:3;2234;:9;2228:1;:16;;2227:51;;;;;:::i;:::-;;;2218:60;;2704:34;2695:6;:43;2691:98;;;2769:1;2762:8;;;;;;;2691:98;2807:10;2835:3;2830:1;:8;;2820:6;:19;2807:32;;2857:10;2884:34;2880:1;:38;2870:6;:49;2857:62;;2938:10;2956:3;2951:1;:8;;2938:21;;2977:10;2995:2;2990:1;:7;;2977:20;;3025:2;3020;:7;3016:20;;;3035:1;3029:7;;;;3016:20;3060:2;3054:8;;;;3128:3;3122:2;:9;;3117:14;;3158:2;3153;:7;3149:20;;;3168:1;3162:7;;;;3149:20;3193:2;3187:8;;;;3270:3;3264:2;:9;;3258:2;:15;3251:23;;;;:::i;:::-;;3308:1;3303:2;:6;;;;;:::i;:::-;;;3293:16;;;;1479:1845;;;;;;1357:1967;3574:34;3565:6;:43;3561:90;;;3635:1;3628:8;;;;;3561:90;3680:6;3665:22;;;1190:2514;;;;;:::o;3710:1606::-;3865:17;4094;4131:14;4114;:31;4094:51;;4256:23;4297:1;4282:12;:16;;;:174;;4443:12;4431:25;;:2;:25;4427:1;4410:12;4402:21;;:26;:54;4282:174;;;4369:12;4368:13;;4346:37;;4354:2;4346:37;4342:1;4325:12;4317:21;;:26;:66;;;;;:::i;:::-;;;4282:174;4256:200;;4480:15;117:27;4474:21;4470:68;;;4522:1;4515:8;;;;;;4470:68;4686:28;4717:16;:143;;117:27;4838:15;:21;;;;;:::i;:::-;;;4799:34;117:27;4793:40;4792:68;;;;;:::i;:::-;;;4717:143;;;117:27;4752:15;:21;;;;;:::i;:::-;;;4717:143;4686:174;;5017:16;:148;;5145:20;5017:148;;;117:27;5085:34;5061:20;5053:66;5052:74;;;;;:::i;:::-;;;5017:148;5005:160;;5196:17;5184:9;:29;5180:120;;;5284:1;5277:8;;;;;;;5180:120;3898:1412;;;3710:1606;;;;;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::o;7:75:41:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:117;443:1;440;433:12;457:102;498:6;549:2;545:7;540:2;533:5;529:14;525:28;515:38;;457:102;;;:::o;565:180::-;613:77;610:1;603:88;710:4;707:1;700:15;734:4;731:1;724:15;751:281;834:27;856:4;834:27;:::i;:::-;826:6;822:40;964:6;952:10;949:22;928:18;916:10;913:34;910:62;907:88;;;975:18;;:::i;:::-;907:88;1015:10;1011:2;1004:22;794:238;751:281;;:::o;1038:129::-;1072:6;1099:20;;:::i;:::-;1089:30;;1128:33;1156:4;1148:6;1128:33;:::i;:::-;1038:129;;;:::o;1173:338::-;1277:4;1367:18;1359:6;1356:30;1353:56;;;1389:18;;:::i;:::-;1353:56;1439:4;1431:6;1427:17;1419:25;;1499:4;1493;1489:15;1481:23;;1173:338;;;:::o;1517:117::-;1626:1;1623;1616:12;1640:117;1749:1;1746;1739:12;1886:113;1973:1;1966:5;1963:12;1953:40;;1989:1;1986;1979:12;1953:40;1886:113;:::o;2005:167::-;2065:5;2103:6;2090:20;2081:29;;2119:47;2160:5;2119:47;:::i;:::-;2005:167;;;;:::o;2178:126::-;2215:7;2255:42;2248:5;2244:54;2233:65;;2178:126;;;:::o;2310:96::-;2347:7;2376:24;2394:5;2376:24;:::i;:::-;2365:35;;2310:96;;;:::o;2412:122::-;2485:24;2503:5;2485:24;:::i;:::-;2478:5;2475:35;2465:63;;2524:1;2521;2514:12;2465:63;2412:122;:::o;2540:139::-;2586:5;2624:6;2611:20;2602:29;;2640:33;2667:5;2640:33;:::i;:::-;2540:139;;;;:::o;2725:601::-;2801:5;2845:4;2833:9;2828:3;2824:19;2820:30;2817:117;;;2853:79;;:::i;:::-;2817:117;2952:21;2968:4;2952:21;:::i;:::-;2943:30;;3036:1;3076:63;3135:3;3126:6;3115:9;3111:22;3076:63;:::i;:::-;3069:4;3062:5;3058:16;3051:89;2983:168;3217:2;3258:49;3303:3;3294:6;3283:9;3279:22;3258:49;:::i;:::-;3251:4;3244:5;3240:16;3233:75;3161:158;2725:601;;;;:::o;3374:791::-;3497:5;3522:108;3538:91;3622:6;3538:91;:::i;:::-;3522:108;:::i;:::-;3513:117;;3650:5;3679:6;3672:5;3665:21;3713:4;3706:5;3702:16;3695:23;;3766:4;3758:6;3754:17;3746:6;3742:30;3795:3;3787:6;3784:15;3781:122;;;3814:79;;:::i;:::-;3781:122;3929:6;3912:247;3946:6;3941:3;3938:15;3912:247;;;4021:3;4050:64;4110:3;4098:10;4050:64;:::i;:::-;4045:3;4038:77;4144:4;4139:3;4135:14;4128:21;;3988:171;3972:4;3967:3;3963:14;3956:21;;3912:247;;;3916:21;3503:662;;3374:791;;;;;:::o;4213:424::-;4311:5;4360:3;4353:4;4345:6;4341:17;4337:27;4327:122;;4368:79;;:::i;:::-;4327:122;4485:6;4472:20;4510:121;4627:3;4619:6;4612:4;4604:6;4600:17;4510:121;:::i;:::-;4501:130;;4317:320;4213:424;;;;:::o;4643:593::-;4754:6;4803:2;4791:9;4782:7;4778:23;4774:32;4771:119;;;4809:79;;:::i;:::-;4771:119;4957:1;4946:9;4942:17;4929:31;4987:18;4979:6;4976:30;4973:117;;;5009:79;;:::i;:::-;4973:117;5114:105;5211:7;5202:6;5191:9;5187:22;5114:105;:::i;:::-;5104:115;;4900:329;4643:593;;;;:::o;5242:147::-;5342:6;5376:5;5370:12;5360:22;;5242:147;;;:::o;5395:217::-;5527:11;5561:6;5556:3;5549:19;5601:4;5596:3;5592:14;5577:29;;5395:217;;;;:::o;5618:165::-;5718:4;5741:3;5733:11;;5771:4;5766:3;5762:14;5754:22;;5618:165;;;:::o;5789:180::-;5837:77;5834:1;5827:88;5934:4;5931:1;5924:15;5958:4;5955:1;5948:15;5975:119;6062:1;6055:5;6052:12;6042:46;;6068:18;;:::i;:::-;6042:46;5975:119;:::o;6100:139::-;6151:7;6180:5;6169:16;;6186:47;6227:5;6186:47;:::i;:::-;6100:139;;;:::o;6245:::-;6307:9;6340:38;6372:5;6340:38;:::i;:::-;6327:51;;6245:139;;;:::o;6390:145::-;6479:49;6522:5;6479:49;:::i;:::-;6474:3;6467:62;6390:145;;:::o;6541:108::-;6618:24;6636:5;6618:24;:::i;:::-;6613:3;6606:37;6541:108;;:::o;6655:77::-;6692:7;6721:5;6710:16;;6655:77;;;:::o;6738:108::-;6815:24;6833:5;6815:24;:::i;:::-;6810:3;6803:37;6738:108;;:::o;6940:715::-;7093:4;7088:3;7084:14;7184:4;7177:5;7173:16;7167:23;7203:75;7272:4;7267:3;7263:14;7249:12;7203:75;:::i;:::-;7108:180;7377:4;7370:5;7366:16;7360:23;7396:63;7453:4;7448:3;7444:14;7430:12;7396:63;:::i;:::-;7298:171;7556:4;7549:5;7545:16;7539:23;7575:63;7632:4;7627:3;7623:14;7609:12;7575:63;:::i;:::-;7479:169;7062:593;6940:715;;:::o;7661:311::-;7796:10;7817:112;7925:3;7917:6;7817:112;:::i;:::-;7961:4;7956:3;7952:14;7938:28;;7661:311;;;;:::o;7978:146::-;8081:4;8113;8108:3;8104:14;8096:22;;7978:146;;;:::o;8222:996::-;8407:3;8436:87;8517:5;8436:87;:::i;:::-;8539:119;8651:6;8646:3;8539:119;:::i;:::-;8532:126;;8682:89;8765:5;8682:89;:::i;:::-;8794:7;8825:1;8810:383;8835:6;8832:1;8829:13;8810:383;;;8911:6;8905:13;8938:129;9063:3;9048:13;8938:129;:::i;:::-;8931:136;;9090:93;9176:6;9090:93;:::i;:::-;9080:103;;8870:323;8857:1;8854;8850:9;8845:14;;8810:383;;;8814:14;9209:3;9202:10;;8412:806;;;8222:996;;;;:::o;9224:505::-;9433:4;9471:2;9460:9;9456:18;9448:26;;9520:9;9514:4;9510:20;9506:1;9495:9;9491:17;9484:47;9548:174;9717:4;9708:6;9548:174;:::i;:::-;9540:182;;9224:505;;;;:::o;9735:180::-;9783:77;9780:1;9773:88;9880:4;9877:1;9870:15;9904:4;9901:1;9894:15;9921:311;9998:4;10088:18;10080:6;10077:30;10074:56;;;10110:18;;:::i;:::-;10074:56;10160:4;10152:6;10148:17;10140:25;;10220:4;10214;10210:15;10202:23;;9921:311;;;:::o;10238:143::-;10295:5;10326:6;10320:13;10311:22;;10342:33;10369:5;10342:33;:::i;:::-;10238:143;;;;:::o;10404:732::-;10511:5;10536:81;10552:64;10609:6;10552:64;:::i;:::-;10536:81;:::i;:::-;10527:90;;10637:5;10666:6;10659:5;10652:21;10700:4;10693:5;10689:16;10682:23;;10753:4;10745:6;10741:17;10733:6;10729:30;10782:3;10774:6;10771:15;10768:122;;;10801:79;;:::i;:::-;10768:122;10916:6;10899:231;10933:6;10928:3;10925:15;10899:231;;;11008:3;11037:48;11081:3;11069:10;11037:48;:::i;:::-;11032:3;11025:61;11115:4;11110:3;11106:14;11099:21;;10975:155;10959:4;10954:3;10950:14;10943:21;;10899:231;;;10903:21;10517:619;;10404:732;;;;;:::o;11159:385::-;11241:5;11290:3;11283:4;11275:6;11271:17;11267:27;11257:122;;11298:79;;:::i;:::-;11257:122;11408:6;11402:13;11433:105;11534:3;11526:6;11519:4;11511:6;11507:17;11433:105;:::i;:::-;11424:114;;11247:297;11159:385;;;;:::o;11550:554::-;11645:6;11694:2;11682:9;11673:7;11669:23;11665:32;11662:119;;;11700:79;;:::i;:::-;11662:119;11841:1;11830:9;11826:17;11820:24;11871:18;11863:6;11860:30;11857:117;;;11893:79;;:::i;:::-;11857:117;11998:89;12079:7;12070:6;12059:9;12055:22;11998:89;:::i;:::-;11988:99;;11791:306;11550:554;;;;:::o;12110:118::-;12197:24;12215:5;12197:24;:::i;:::-;12192:3;12185:37;12110:118;;:::o;12234:222::-;12327:4;12365:2;12354:9;12350:18;12342:26;;12378:71;12446:1;12435:9;12431:17;12422:6;12378:71;:::i;:::-;12234:222;;;;:::o;12462:122::-;12535:24;12553:5;12535:24;:::i;:::-;12528:5;12525:35;12515:63;;12574:1;12571;12564:12;12515:63;12462:122;:::o;12590:143::-;12647:5;12678:6;12672:13;12663:22;;12694:33;12721:5;12694:33;:::i;:::-;12590:143;;;;:::o;12739:351::-;12809:6;12858:2;12846:9;12837:7;12833:23;12829:32;12826:119;;;12864:79;;:::i;:::-;12826:119;12984:1;13009:64;13065:7;13056:6;13045:9;13041:22;13009:64;:::i;:::-;12999:74;;12955:128;12739:351;;;;:::o;13096:180::-;13144:77;13141:1;13134:88;13241:4;13238:1;13231:15;13265:4;13262:1;13255:15;13282:410;13322:7;13345:20;13363:1;13345:20;:::i;:::-;13340:25;;13379:20;13397:1;13379:20;:::i;:::-;13374:25;;13434:1;13431;13427:9;13456:30;13474:11;13456:30;:::i;:::-;13445:41;;13635:1;13626:7;13622:15;13619:1;13616:22;13596:1;13589:9;13569:83;13546:139;;13665:18;;:::i;:::-;13546:139;13330:362;13282:410;;;;:::o;13698:351::-;13768:6;13817:2;13805:9;13796:7;13792:23;13788:32;13785:119;;;13823:79;;:::i;:::-;13785:119;13943:1;13968:64;14024:7;14015:6;14004:9;14000:22;13968:64;:::i;:::-;13958:74;;13914:128;13698:351;;;;:::o;14055:114::-;14092:7;14132:30;14125:5;14121:42;14110:53;;14055:114;;;:::o;14175:122::-;14248:24;14266:5;14248:24;:::i;:::-;14241:5;14238:35;14228:63;;14287:1;14284;14277:12;14228:63;14175:122;:::o;14303:143::-;14360:5;14391:6;14385:13;14376:22;;14407:33;14434:5;14407:33;:::i;:::-;14303:143;;;;:::o;14452:93::-;14488:7;14528:10;14521:5;14517:22;14506:33;;14452:93;;;:::o;14551:120::-;14623:23;14640:5;14623:23;:::i;:::-;14616:5;14613:34;14603:62;;14661:1;14658;14651:12;14603:62;14551:120;:::o;14677:141::-;14733:5;14764:6;14758:13;14749:22;;14780:32;14806:5;14780:32;:::i;:::-;14677:141;;;;:::o;14824:661::-;14911:6;14919;14927;14976:2;14964:9;14955:7;14951:23;14947:32;14944:119;;;14982:79;;:::i;:::-;14944:119;15102:1;15127:64;15183:7;15174:6;15163:9;15159:22;15127:64;:::i;:::-;15117:74;;15073:128;15240:2;15266:64;15322:7;15313:6;15302:9;15298:22;15266:64;:::i;:::-;15256:74;;15211:129;15379:2;15405:63;15460:7;15451:6;15440:9;15436:22;15405:63;:::i;:::-;15395:73;;15350:128;14824:661;;;;;:::o;15491:279::-;15531:7;15554:20;15572:1;15554:20;:::i;:::-;15549:25;;15588:20;15606:1;15588:20;:::i;:::-;15583:25;;15643:1;15640;15636:9;15665:30;15683:11;15665:30;:::i;:::-;15654:41;;15727:11;15718:7;15715:24;15705:58;;15743:18;;:::i;:::-;15705:58;15539:231;15491:279;;;;:::o;15776:332::-;15897:4;15935:2;15924:9;15920:18;15912:26;;15948:71;16016:1;16005:9;16001:17;15992:6;15948:71;:::i;:::-;16029:72;16097:2;16086:9;16082:18;16073:6;16029:72;:::i;:::-;15776:332;;;;;:::o;16114:86::-;16149:7;16189:4;16182:5;16178:16;16167:27;;16114:86;;;:::o;16206:191::-;16244:4;16264:18;16280:1;16264:18;:::i;:::-;16259:23;;16296:18;16312:1;16296:18;:::i;:::-;16291:23;;16338:1;16335;16331:9;16323:17;;16362:4;16356;16353:14;16350:40;;;16370:18;;:::i;:::-;16350:40;16206:191;;;;:::o;16403:102::-;16445:8;16492:5;16489:1;16485:13;16464:34;;16403:102;;;:::o;16511:848::-;16572:5;16579:4;16603:6;16594:15;;16627:5;16618:14;;16641:712;16662:1;16652:8;16649:15;16641:712;;;16757:4;16752:3;16748:14;16742:4;16739:24;16736:50;;;16766:18;;:::i;:::-;16736:50;16816:1;16806:8;16802:16;16799:451;;;17231:4;17224:5;17220:16;17211:25;;16799:451;17281:4;17275;17271:15;17263:23;;17311:32;17334:8;17311:32;:::i;:::-;17299:44;;16641:712;;;16511:848;;;;;;;:::o;17365:1073::-;17419:5;17610:8;17600:40;;17631:1;17622:10;;17633:5;;17600:40;17659:4;17649:36;;17676:1;17667:10;;17678:5;;17649:36;17745:4;17793:1;17788:27;;;;17829:1;17824:191;;;;17738:277;;17788:27;17806:1;17797:10;;17808:5;;;17824:191;17869:3;17859:8;17856:17;17853:43;;;17876:18;;:::i;:::-;17853:43;17925:8;17922:1;17918:16;17909:25;;17960:3;17953:5;17950:14;17947:40;;;17967:18;;:::i;:::-;17947:40;18000:5;;;17738:277;;18124:2;18114:8;18111:16;18105:3;18099:4;18096:13;18092:36;18074:2;18064:8;18061:16;18056:2;18050:4;18047:12;18043:35;18027:111;18024:246;;;18180:8;18174:4;18170:19;18161:28;;18215:3;18208:5;18205:14;18202:40;;;18222:18;;:::i;:::-;18202:40;18255:5;;18024:246;18295:42;18333:3;18323:8;18317:4;18314:1;18295:42;:::i;:::-;18280:57;;;;18369:4;18364:3;18360:14;18353:5;18350:25;18347:51;;;18378:18;;:::i;:::-;18347:51;18427:4;18420:5;18416:16;18407:25;;17365:1073;;;;;;:::o;18444:281::-;18502:5;18526:23;18544:4;18526:23;:::i;:::-;18518:31;;18570:25;18586:8;18570:25;:::i;:::-;18558:37;;18614:104;18651:66;18641:8;18635:4;18614:104;:::i;:::-;18605:113;;18444:281;;;;:::o;18731:180::-;18779:77;18776:1;18769:88;18876:4;18873:1;18866:15;18900:4;18897:1;18890:15;18917:185;18957:1;18974:20;18992:1;18974:20;:::i;:::-;18969:25;;19008:20;19026:1;19008:20;:::i;:::-;19003:25;;19047:1;19037:35;;19052:18;;:::i;:::-;19037:35;19094:1;19091;19087:9;19082:14;;18917:185;;;;:::o;19108:89::-;19144:7;19184:6;19177:5;19173:18;19162:29;;19108:89;;;:::o;19203:91::-;19239:7;19279:8;19272:5;19268:20;19257:31;;19203:91;;;:::o;19300:60::-;19328:3;19349:5;19342:12;;19300:60;;;:::o;19366:138::-;19414:9;19447:51;19464:33;19473:23;19490:5;19473:23;:::i;:::-;19464:33;:::i;:::-;19447:51;:::i;:::-;19434:64;;19366:138;;;:::o;19510:127::-;19595:35;19624:5;19595:35;:::i;:::-;19590:3;19583:48;19510:127;;:::o;19643:438::-;19790:4;19828:2;19817:9;19813:18;19805:26;;19841:71;19909:1;19898:9;19894:17;19885:6;19841:71;:::i;:::-;19922:72;19990:2;19979:9;19975:18;19966:6;19922:72;:::i;:::-;20004:70;20070:2;20059:9;20055:18;20046:6;20004:70;:::i;:::-;19643:438;;;;;;:::o;20087:122::-;20160:24;20178:5;20160:24;:::i;:::-;20153:5;20150:35;20140:63;;20199:1;20196;20189:12;20140:63;20087:122;:::o;20215:143::-;20272:5;20303:6;20297:13;20288:22;;20319:33;20346:5;20319:33;:::i;:::-;20215:143;;;;:::o;20364:90::-;20399:7;20442:5;20439:1;20428:20;20417:31;;20364:90;;;:::o;20460:118::-;20531:22;20547:5;20531:22;:::i;:::-;20524:5;20521:33;20511:61;;20568:1;20565;20558:12;20511:61;20460:118;:::o;20584:139::-;20639:5;20670:6;20664:13;20655:22;;20686:31;20711:5;20686:31;:::i;:::-;20584:139;;;;:::o;20729:120::-;20801:23;20818:5;20801:23;:::i;:::-;20794:5;20791:34;20781:62;;20839:1;20836;20829:12;20781:62;20729:120;:::o;20855:141::-;20911:5;20942:6;20936:13;20927:22;;20958:32;20984:5;20958:32;:::i;:::-;20855:141;;;;:::o;21002:118::-;21073:22;21089:5;21073:22;:::i;:::-;21066:5;21063:33;21053:61;;21110:1;21107;21100:12;21053:61;21002:118;:::o;21126:139::-;21181:5;21212:6;21206:13;21197:22;;21228:31;21253:5;21228:31;:::i;:::-;21126:139;;;;:::o;21271:90::-;21305:7;21348:5;21341:13;21334:21;21323:32;;21271:90;;;:::o;21367:116::-;21437:21;21452:5;21437:21;:::i;:::-;21430:5;21427:32;21417:60;;21473:1;21470;21463:12;21417:60;21367:116;:::o;21489:137::-;21543:5;21574:6;21568:13;21559:22;;21590:30;21614:5;21590:30;:::i;:::-;21489:137;;;;:::o;21632:1271::-;21746:6;21754;21762;21770;21778;21786;21794;21843:3;21831:9;21822:7;21818:23;21814:33;21811:120;;;21850:79;;:::i;:::-;21811:120;21970:1;21995:64;22051:7;22042:6;22031:9;22027:22;21995:64;:::i;:::-;21985:74;;21941:128;22108:2;22134:62;22188:7;22179:6;22168:9;22164:22;22134:62;:::i;:::-;22124:72;;22079:127;22245:2;22271:63;22326:7;22317:6;22306:9;22302:22;22271:63;:::i;:::-;22261:73;;22216:128;22383:2;22409:63;22464:7;22455:6;22444:9;22440:22;22409:63;:::i;:::-;22399:73;;22354:128;22521:3;22548:63;22603:7;22594:6;22583:9;22579:22;22548:63;:::i;:::-;22538:73;;22492:129;22660:3;22687:62;22741:7;22732:6;22721:9;22717:22;22687:62;:::i;:::-;22677:72;;22631:128;22798:3;22825:61;22878:7;22869:6;22858:9;22854:22;22825:61;:::i;:::-;22815:71;;22769:127;21632:1271;;;;;;;;;;:::o;22909:98::-;22960:6;22994:5;22988:12;22978:22;;22909:98;;;:::o;23013:147::-;23114:11;23151:3;23136:18;;23013:147;;;;:::o;23166:139::-;23255:6;23250:3;23245;23239:23;23296:1;23287:6;23282:3;23278:16;23271:27;23166:139;;;:::o;23311:386::-;23415:3;23443:38;23475:5;23443:38;:::i;:::-;23497:88;23578:6;23573:3;23497:88;:::i;:::-;23490:95;;23594:65;23652:6;23647:3;23640:4;23633:5;23629:16;23594:65;:::i;:::-;23684:6;23679:3;23675:16;23668:23;;23419:278;23311:386;;;;:::o;23703:271::-;23833:3;23855:93;23944:3;23935:6;23855:93;:::i;:::-;23848:100;;23965:3;23958:10;;23703:271;;;;:::o;23980:180::-;24028:77;24025:1;24018:88;24125:4;24122:1;24115:15;24149:4;24146:1;24139:15","linkReferences":{}},"methodIdentifiers":{"getWethValueInPools((uint8,address)[])":"339173fd"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_uniswapV2Factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_uniswapV3Factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_weth\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"enum WethValueInPools.PoolType\",\"name\":\"poolType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"poolAddress\",\"type\":\"address\"}],\"internalType\":\"struct WethValueInPools.PoolInfo[]\",\"name\":\"pools\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"components\":[{\"internalType\":\"enum WethValueInPools.PoolType\",\"name\":\"poolType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"poolAddress\",\"type\":\"address\"}],\"internalType\":\"struct WethValueInPools.PoolInfo[]\",\"name\":\"pools\",\"type\":\"tuple[]\"}],\"name\":\"getWethValueInPools\",\"outputs\":[{\"components\":[{\"internalType\":\"enum WethValueInPools.PoolType\",\"name\":\"poolType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"poolAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"wethValue\",\"type\":\"uint256\"}],\"internalType\":\"struct WethValueInPools.PoolInfoReturn[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getWethValueInPools((uint8,address)[])\":{\"details\":\"We require a 1 ETH minimum liquidity in the quoting pool for it to be considered.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getWethValueInPools((uint8,address)[])\":{\"notice\":\"Returns an array of `PoolInfoReturn` for the consumer to determine wether to filter or not to save gas.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/filters/WethValueInPoolsBatchRequest.sol\":\"WethValueInPoolsBatchRequest\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[\":forge-std/=lib/forge-std/src/\"]},\"sources\":{\"src/UniswapV3/FixedPoint.sol\":{\"keccak256\":\"0xf82873fe78051afcf0446c27f5c5857816d1129e2bc84855dee8275d764b49d0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5d1b9704466cdf93f446ac2330ef89752c2bcc1f271a70c296f54e0d9291467f\",\"dweb:/ipfs/QmaQd3DUAdJMVQD422o2HyAwhTDyLo33znMgRDU5NaZegE\"]},\"src/filters/WethValueInPools.sol\":{\"keccak256\":\"0x1bd98caec9df680366948f8e1f24ed7262021aeb841ea155efafb05648152c4b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3f88558f892e5441c824e1d6973036e1196445b99c7e24fcfa6a399af64e2ace\",\"dweb:/ipfs/QmT7KqFaR9pysM94AAbSgeJrb1XsQickV6kyowBWc5vYgT\"]},\"src/filters/WethValueInPoolsBatchRequest.sol\":{\"keccak256\":\"0xb071e547407d4ca1cf0ca9582b7620e786edadf5b45188f4f9d4619d7ad672ae\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e17ca6f4eb9ff0e5bfe77a0d5b3c31fa3cab43c98b49fddf126b854bd23ece8b\",\"dweb:/ipfs/QmWHeJiaPFYswRn5HwyC4yj7w521KBSP2KQUMzg1Ktru6u\"]},\"src/interfaces/IBalancer.sol\":{\"keccak256\":\"0xe7ca1e7f70a16d6919334b612a584e5d42692a802f4d92686c564a4ab1550c27\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://2e0cf4540fca9dbf3650d22d1d927b43bcd8333a988c7575c6618b633bff082f\",\"dweb:/ipfs/QmYAcUnqBauhiXJNfMLta4Bj1dntGmNJ3cxaHq18LnBDAQ\"]},\"src/interfaces/IUniswapV2.sol\":{\"keccak256\":\"0x067d9c125da6fdbe44d6ce7d498c42460d7347317413f8317bf80bd25c08898d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1ad58162042aa8d1eb7451af3ccc3b1df64e720aeeb69a6843507aec0e5d146\",\"dweb:/ipfs/QmdvEJYkfWaGWrGXtKajZSDdfNYJ3sDFpzsV4f1X4KQYZM\"]},\"src/interfaces/IUniswapV3.sol\":{\"keccak256\":\"0x914ac5f4d9e6b6d0345c89e769f1a2d9784d047e8cac6f3265b229afd9363729\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://19a3f9d71839d62cea60562c57cdfe582821da7bfe17a1d6ca26597db51a3762\",\"dweb:/ipfs/QmdWoVo3J7tcSKCk5cCADvjvMtmczcGbsmKx5v9AFjQANz\"]},\"src/interfaces/Token.sol\":{\"keccak256\":\"0x2f7118f6cba8e0303e66028f738463e025a19ec0186a5462523692f44330e113\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ca6355f3ce4aec77f281142db4cb0a63d5e1b3b4b12836ac9a3ed251069801d0\",\"dweb:/ipfs/QmWTt8HyEuzTdKVWCzBDxVMWL3tptkxsTfsssbEMVA818A\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.28+commit.7893614a"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address","name":"_uniswapV2Factory","type":"address"},{"internalType":"address","name":"_uniswapV3Factory","type":"address"},{"internalType":"address","name":"_weth","type":"address"},{"internalType":"struct WethValueInPools.PoolInfo[]","name":"pools","type":"tuple[]","components":[{"internalType":"enum WethValueInPools.PoolType","name":"poolType","type":"uint8"},{"internalType":"address","name":"poolAddress","type":"address"}]}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"struct WethValueInPools.PoolInfo[]","name":"pools","type":"tuple[]","components":[{"internalType":"enum WethValueInPools.PoolType","name":"poolType","type":"uint8"},{"internalType":"address","name":"poolAddress","type":"address"}]}],"stateMutability":"nonpayable","type":"function","name":"getWethValueInPools","outputs":[{"internalType":"struct WethValueInPools.PoolInfoReturn[]","name":"","type":"tuple[]","components":[{"internalType":"enum WethValueInPools.PoolType","name":"poolType","type":"uint8"},{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"uint256","name":"wethValue","type":"uint256"}]}]}],"devdoc":{"kind":"dev","methods":{"getWethValueInPools((uint8,address)[])":{"details":"We require a 1 ETH minimum liquidity in the quoting pool for it to be considered."}},"version":1},"userdoc":{"kind":"user","methods":{"getWethValueInPools((uint8,address)[])":{"notice":"Returns an array of `PoolInfoReturn` for the consumer to determine wether to filter or not to save gas."}},"version":1}},"settings":{"remappings":["forge-std/=lib/forge-std/src/"],"optimizer":{"enabled":false,"runs":200},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"src/filters/WethValueInPoolsBatchRequest.sol":"WethValueInPoolsBatchRequest"},"evmVersion":"cancun","libraries":{}},"sources":{"src/UniswapV3/FixedPoint.sol":{"keccak256":"0xf82873fe78051afcf0446c27f5c5857816d1129e2bc84855dee8275d764b49d0","urls":["bzz-raw://5d1b9704466cdf93f446ac2330ef89752c2bcc1f271a70c296f54e0d9291467f","dweb:/ipfs/QmaQd3DUAdJMVQD422o2HyAwhTDyLo33znMgRDU5NaZegE"],"license":"MIT"},"src/filters/WethValueInPools.sol":{"keccak256":"0x1bd98caec9df680366948f8e1f24ed7262021aeb841ea155efafb05648152c4b","urls":["bzz-raw://3f88558f892e5441c824e1d6973036e1196445b99c7e24fcfa6a399af64e2ace","dweb:/ipfs/QmT7KqFaR9pysM94AAbSgeJrb1XsQickV6kyowBWc5vYgT"],"license":"MIT"},"src/filters/WethValueInPoolsBatchRequest.sol":{"keccak256":"0xb071e547407d4ca1cf0ca9582b7620e786edadf5b45188f4f9d4619d7ad672ae","urls":["bzz-raw://e17ca6f4eb9ff0e5bfe77a0d5b3c31fa3cab43c98b49fddf126b854bd23ece8b","dweb:/ipfs/QmWHeJiaPFYswRn5HwyC4yj7w521KBSP2KQUMzg1Ktru6u"],"license":"MIT"},"src/interfaces/IBalancer.sol":{"keccak256":"0xe7ca1e7f70a16d6919334b612a584e5d42692a802f4d92686c564a4ab1550c27","urls":["bzz-raw://2e0cf4540fca9dbf3650d22d1d927b43bcd8333a988c7575c6618b633bff082f","dweb:/ipfs/QmYAcUnqBauhiXJNfMLta4Bj1dntGmNJ3cxaHq18LnBDAQ"],"license":"MIT"},"src/interfaces/IUniswapV2.sol":{"keccak256":"0x067d9c125da6fdbe44d6ce7d498c42460d7347317413f8317bf80bd25c08898d","urls":["bzz-raw://b1ad58162042aa8d1eb7451af3ccc3b1df64e720aeeb69a6843507aec0e5d146","dweb:/ipfs/QmdvEJYkfWaGWrGXtKajZSDdfNYJ3sDFpzsV4f1X4KQYZM"],"license":"MIT"},"src/interfaces/IUniswapV3.sol":{"keccak256":"0x914ac5f4d9e6b6d0345c89e769f1a2d9784d047e8cac6f3265b229afd9363729","urls":["bzz-raw://19a3f9d71839d62cea60562c57cdfe582821da7bfe17a1d6ca26597db51a3762","dweb:/ipfs/QmdWoVo3J7tcSKCk5cCADvjvMtmczcGbsmKx5v9AFjQANz"],"license":"MIT"},"src/interfaces/Token.sol":{"keccak256":"0x2f7118f6cba8e0303e66028f738463e025a19ec0186a5462523692f44330e113","urls":["bzz-raw://ca6355f3ce4aec77f281142db4cb0a63d5e1b3b4b12836ac9a3ed251069801d0","dweb:/ipfs/QmWTt8HyEuzTdKVWCzBDxVMWL3tptkxsTfsssbEMVA818A"],"license":"MIT"}},"version":1},"id":34} ================================================ FILE: src/amms/amm.rs ================================================ use super::{ balancer::BalancerPool, erc_4626::ERC4626Vault, error::AMMError, uniswap_v2::UniswapV2Pool, uniswap_v3::UniswapV3Pool, }; use alloy::{ eips::BlockId, network::Network, primitives::{Address, B256, U256}, providers::Provider, rpc::types::Log, }; use eyre::Result; use serde::{Deserialize, Serialize}; use std::hash::{Hash, Hasher}; #[allow(async_fn_in_trait)] pub trait AutomatedMarketMaker { /// Address of the AMM fn address(&self) -> Address; /// Event signatures that indicate when the AMM should be synced fn sync_events(&self) -> Vec; /// Syncs the AMM state fn sync(&mut self, log: &Log) -> Result<(), AMMError>; /// Returns a list of token addresses used in the AMM fn tokens(&self) -> Vec
; /// Calculates the price of `base_token` in terms of `quote_token` fn calculate_price(&self, base_token: Address, quote_token: Address) -> Result; /// Simulate a swap /// Returns the amount_out in `quote token` for a given `amount_in` of `base_token` fn simulate_swap( &self, base_token: Address, quote_token: Address, amount_in: U256, ) -> Result; /// Simulate a swap, mutating the AMM state /// Returns the amount_out in `quote token` for a given `amount_in` of `base_token` fn simulate_swap_mut( &mut self, base_token: Address, quote_token: Address, amount_in: U256, ) -> Result; // Initializes an empty pool and syncs state up to `block_number` async fn init(self, block_number: BlockId, provider: P) -> Result where Self: Sized, N: Network, P: Provider + Clone; } macro_rules! amm { ($($pool_type:ident),+ $(,)?) => { #[derive(Debug, Clone, Serialize, Deserialize)] pub enum AMM { $($pool_type($pool_type),)+ } impl AutomatedMarketMaker for AMM { fn address(&self) -> Address{ match self { $(AMM::$pool_type(pool) => pool.address(),)+ } } fn sync_events(&self) -> Vec { match self { $(AMM::$pool_type(pool) => pool.sync_events(),)+ } } fn sync(&mut self, log: &Log) -> Result<(), AMMError> { match self { $(AMM::$pool_type(pool) => pool.sync(log),)+ } } fn simulate_swap(&self, base_token: Address, quote_token: Address,amount_in: U256) -> Result { match self { $(AMM::$pool_type(pool) => pool.simulate_swap(base_token, quote_token, amount_in),)+ } } fn simulate_swap_mut(&mut self, base_token: Address, quote_token: Address, amount_in: U256) -> Result { match self { $(AMM::$pool_type(pool) => pool.simulate_swap_mut(base_token, quote_token, amount_in),)+ } } fn tokens(&self) -> Vec
{ match self { $(AMM::$pool_type(pool) => pool.tokens(),)+ } } fn calculate_price(&self, base_token: Address, quote_token: Address) -> Result { match self { $(AMM::$pool_type(pool) => pool.calculate_price(base_token, quote_token),)+ } } async fn init(self, block_number: BlockId, provider: P) -> Result where Self: Sized, N: Network, P: Provider + Clone, { match self { $(AMM::$pool_type(pool) => pool.init(block_number, provider).await.map(AMM::$pool_type),)+ } } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Variant { $($pool_type,)+ } impl AMM { pub fn variant(&self) -> Variant { match self { $(AMM::$pool_type(_) => Variant::$pool_type,)+ } } } impl Hash for AMM { fn hash(&self, state: &mut H) { self.address().hash(state); } } impl PartialEq for AMM { fn eq(&self, other: &Self) -> bool { self.address() == other.address() } } impl Eq for AMM {} $( impl From<$pool_type> for AMM { fn from(amm: $pool_type) -> Self { AMM::$pool_type(amm) } } )+ }; } amm!(UniswapV2Pool, UniswapV3Pool, ERC4626Vault, BalancerPool); ================================================ FILE: src/amms/balancer/bmath.rs ================================================ use alloy::primitives::U256; use crate::amms::consts::{BONE, U256_1, U256_10E_10, U256_2}; use super::BalancerError; pub fn btoi(a: U256) -> U256 { a / BONE } #[inline] pub fn badd(a: U256, b: U256) -> Result { let c = a + b; if c < a { return Err(BalancerError::AddOverflow); } Ok(c) } #[inline] pub fn bpowi(a: U256, n: U256) -> Result { let mut z = if n % U256_2 != U256::ZERO { a } else { BONE }; let mut a = a; let mut n = n / U256_2; while n != U256::ZERO { a = bmul(a, a)?; if n % U256_2 != U256::ZERO { z = bmul(z, a)?; } n /= U256_2; } Ok(z) } #[inline] pub fn bpow(base: U256, exp: U256) -> Result { let whole = bfloor(exp); let remain = bsub(exp, whole)?; let whole_pow = bpowi(base, btoi(whole))?; if remain == U256::ZERO { return Ok(whole_pow); } let precision = BONE / U256_10E_10; let partial_result = bpow_approx(base, remain, precision)?; bmul(whole_pow, partial_result) } #[inline] pub fn bpow_approx(base: U256, exp: U256, precision: U256) -> Result { let a = exp; let (x, xneg) = bsub_sign(base, BONE); let mut term = BONE; let mut sum = term; let mut negative = false; let mut i = U256_1; while term >= precision { let big_k = U256::from(i) * BONE; let (c, cneg) = bsub_sign(a, bsub(big_k, BONE)?); term = bmul(term, bmul(c, x)?)?; term = bdiv(term, big_k)?; if term == U256::ZERO { break; } negative ^= xneg ^ cneg; if negative { sum = bsub(sum, term)?; } else { sum = badd(sum, term)?; } i += U256_1; } Ok(sum) } #[inline] pub fn bfloor(a: U256) -> U256 { btoi(a) * BONE } // Reference: // https://github.com/balancer/balancer-core/blob/f4ed5d65362a8d6cec21662fb6eae233b0babc1f/contracts/BNum.sol#L75 #[inline] pub fn bdiv(a: U256, b: U256) -> Result { if b == U256::ZERO { return Err(BalancerError::DivZero); } let c0 = a * BONE; if a != U256::ZERO && c0 / a != BONE { return Err(BalancerError::DivInternal); } let c1 = c0 + (b / U256_2); if c1 < c0 { return Err(BalancerError::DivInternal); } Ok(c1 / b) } // Reference: // https://github.com/balancer/balancer-core/blob/f4ed5d65362a8d6cec21662fb6eae233b0babc1f/contracts/BNum.sol#L43 #[inline] pub fn bsub(a: U256, b: U256) -> Result { let (c, flag) = bsub_sign(a, b); if flag { return Err(BalancerError::SubUnderflow); } Ok(c) } // Reference: // https://github.com/balancer/balancer-core/blob/f4ed5d65362a8d6cec21662fb6eae233b0babc1f/contracts/BNum.sol#L52 #[inline] pub fn bsub_sign(a: U256, b: U256) -> (U256, bool) { if a >= b { (a - b, false) } else { (b - a, true) } } // Reference: // https://github.com/balancer/balancer-core/blob/f4ed5d65362a8d6cec21662fb6eae233b0babc1f/contracts/BNum.sol#L63C4-L73C6 #[inline] pub fn bmul(a: U256, b: U256) -> Result { let c0 = a * b; if a != U256::ZERO && c0 / a != b { return Err(BalancerError::MulOverflow); } let c1 = c0 + (BONE / U256_2); if c1 < c0 { return Err(BalancerError::MulOverflow); } Ok(c1 / BONE) } /********************************************************************************************** // calcSpotPrice // // sP = spotPrice // // bI = tokenBalanceIn ( bI / wI ) 1 // // bO = tokenBalanceOut sP = ----------- * ---------- // // wI = tokenWeightIn ( bO / wO ) ( 1 - sF ) // // wO = tokenWeightOut // // sF = swapFee // **********************************************************************************************/ pub fn calculate_price( b_i: U256, w_i: U256, b_o: U256, w_o: U256, s_f: U256, ) -> Result { let numer = bdiv(b_i, w_i)?; let denom = bdiv(b_o, w_o)?; let ratio = bdiv(numer, denom)?; let scale = bdiv(BONE, bsub(BONE, s_f)?)?; bmul(ratio, scale) } /********************************************************************************************** // calcOutGivenIn // // aO = tokenAmountOut // // bO = tokenBalanceOut // // bI = tokenBalanceIn / / bI \ (wI / wO) \ // // aI = tokenAmountIn aO = bO * | 1 - | -------------------------- | ^ | // // wI = tokenWeightIn \ \ ( bI + ( aI * ( 1 - sF )) / / // // wO = tokenWeightOut // // sF = swapFee // **********************************************************************************************/ pub fn calculate_out_given_in( token_balance_in: U256, token_weight_in: U256, token_balance_out: U256, token_weight_out: U256, token_amount_in: U256, swap_fee: U256, ) -> Result { let weight_ratio = bdiv(token_weight_in, token_weight_out)?; let adjusted_in = bsub(BONE, swap_fee)?; let adjusted_in = bmul(token_amount_in, adjusted_in)?; let y = bdiv(token_balance_in, badd(token_balance_in, adjusted_in)?)?; let x = bpow(y, weight_ratio)?; let z = bsub(BONE, x)?; bmul(token_balance_out, z) } ================================================ FILE: src/amms/balancer/mod.rs ================================================ pub mod bmath; use std::{collections::HashMap, future::Future}; use alloy::{ eips::BlockId, network::Network, primitives::{Address, B256, U256}, providers::Provider, rpc::types::{Filter, FilterSet, Log}, sol, sol_types::{SolEvent, SolValue}, }; use async_trait::async_trait; use futures::{stream::FuturesUnordered, StreamExt}; use itertools::Itertools; use rug::{float::Round, Float}; use serde::{Deserialize, Serialize}; use thiserror::Error; use tracing::info; use super::{ amm::{AutomatedMarketMaker, AMM}, consts::{BONE, MPFR_T_PRECISION}, error::AMMError, factory::{AutomatedMarketMakerFactory, DiscoverySync}, float::u256_to_float, Token, }; sol! { #[derive(Debug, PartialEq, Eq)] #[sol(rpc)] contract IBPool { event LOG_SWAP( address indexed caller, address indexed tokenIn, address indexed tokenOut, uint256 tokenAmountIn, uint256 tokenAmountOut ); event LOG_JOIN( address indexed caller, address indexed tokenIn, uint256 tokenAmountIn ); event LOG_EXIT( address indexed caller, address indexed tokenOut, uint256 tokenAmountOut ); function getSpotPrice(address tokenIn, address tokenOut) external returns (uint256); function calcOutGivenIn( uint tokenBalanceIn, uint tokenWeightIn, uint tokenBalanceOut, uint tokenWeightOut, uint tokenAmountIn, uint swapFee ) external returns (uint); } #[derive(Debug, PartialEq, Eq)] #[sol(rpc)] contract IBFactory { event LOG_NEW_POOL( address indexed caller, address indexed pool ); } } sol!( #[allow(missing_docs)] #[sol(rpc)] IGetBalancerPoolDataBatchRequest, "src/amms/abi/GetBalancerPoolDataBatchRequest.json" ); #[derive(Error, Debug)] pub enum BalancerError { #[error("Error initializing Balancer Pool")] InitializationError, #[error("Token in does not exist")] TokenInDoesNotExist, #[error("Token out does not exist")] TokenOutDoesNotExist, #[error("Division by zero")] DivZero, #[error("Error during division")] DivInternal, #[error("Addition overflow")] AddOverflow, #[error("Subtraction underflow")] SubUnderflow, #[error("Multiplication overflow")] MulOverflow, } #[derive(Default, Debug, Serialize, Deserialize, Clone)] pub struct BalancerPool { /// The Pool Address. address: Address, state: HashMap, /// The Swap Fee on the Pool. fee: u32, } #[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] pub struct TokenPoolState { pub liquidity: U256, pub weight: U256, pub token: Token, } impl AutomatedMarketMaker for BalancerPool { /// Returns the address of the AMM. fn address(&self) -> Address { self.address } fn sync_events(&self) -> Vec { vec![ IBPool::LOG_SWAP::SIGNATURE_HASH, IBPool::LOG_JOIN::SIGNATURE_HASH, IBPool::LOG_EXIT::SIGNATURE_HASH, ] } fn sync(&mut self, log: &Log) -> Result<(), AMMError> { let signature = log.topics()[0]; if IBPool::LOG_SWAP::SIGNATURE_HASH == signature { let swap_event = IBPool::LOG_SWAP::decode_log(log.as_ref())?; self.state .get_mut(&swap_event.tokenIn) .ok_or(BalancerError::TokenInDoesNotExist)? .liquidity += swap_event.tokenAmountIn; self.state .get_mut(&swap_event.tokenOut) .ok_or(BalancerError::TokenOutDoesNotExist)? .liquidity += swap_event.tokenAmountOut; info!( target = "amm::balancer::sync", address = ?self.address, state = ?self.state, "Sync" ); } else if IBPool::LOG_JOIN::SIGNATURE_HASH == signature { let join_event = IBPool::LOG_JOIN::decode_log(log.as_ref())?; self.state .get_mut(&join_event.tokenIn) .ok_or(BalancerError::TokenInDoesNotExist)? .liquidity += join_event.tokenAmountIn; info!( target = "amm::balancer::sync", address = ?self.address, state = ?self.state, "Join" ); } else if IBPool::LOG_EXIT::SIGNATURE_HASH == signature { let exit_event = IBPool::LOG_JOIN::decode_log(log.as_ref())?; self.state .get_mut(&exit_event.tokenIn) .ok_or(BalancerError::TokenInDoesNotExist)? .liquidity -= exit_event.tokenAmountIn; info!( target = "amm::balancer::sync", address = ?self.address, state = ?self.state, "Exit" ); } else { return Err(AMMError::UnrecognizedEventSignature(signature)); } Ok(()) } /// Returns a vector of tokens in the AMM. fn tokens(&self) -> Vec
{ self.state.keys().cloned().collect() } /// Calculates a f64 representation of base token price in the AMM. This is a "tax inclusive" spot approximation. /// ********************************************************************************************** /// calcSpotPrice // /// sP = spotPrice // /// bI = tokenBalanceIn ( bI / wI ) 1 // /// bO = tokenBalanceOut sP = ----------- * ---------- // /// wI = tokenWeightIn ( bO / wO ) ( 1 - sF ) // /// wO = tokenWeightOut // /// sF = swapFee // ///**********************************************************************************************/ fn calculate_price(&self, base_token: Address, quote_token: Address) -> Result { let token_in = self .state .get(&base_token) .ok_or(BalancerError::TokenInDoesNotExist)?; let token_out = self .state .get("e_token) .ok_or(BalancerError::TokenOutDoesNotExist)?; let bone = u256_to_float(BONE)?; let norm_base = if token_in.token.decimals < 18 { Float::with_val( MPFR_T_PRECISION, 10_u64.pow(18 - token_in.token.decimals as u32), ) } else { Float::with_val(MPFR_T_PRECISION, 1) }; let norm_quote = if token_out.token.decimals < 18 { Float::with_val( MPFR_T_PRECISION, 10_u64.pow(18 - token_out.token.decimals as u32), ) } else { Float::with_val(MPFR_T_PRECISION, 1) }; let norm_weight_base = u256_to_float(token_in.weight)? / norm_base; let norm_weight_quote = u256_to_float(token_out.weight)? / norm_quote; let balance_base = u256_to_float(token_in.liquidity)?; let balance_quote = u256_to_float(token_out.liquidity)?; let dividend = (balance_quote / norm_weight_quote) * bone.clone(); let divisor = (balance_base / norm_weight_base) * (bone - Float::with_val(MPFR_T_PRECISION, self.fee)); let ratio = dividend / divisor; Ok(ratio.to_f64_round(Round::Nearest)) } /// Locally simulates a swap in the AMM. /// /// # Returns /// The amount received for `amount_in` of `token_in`. fn simulate_swap( &self, base_token: Address, quote_token: Address, amount_in: U256, ) -> Result { let token_in = self .state .get(&base_token) .ok_or(BalancerError::TokenInDoesNotExist)?; let token_out = self .state .get("e_token) .ok_or(BalancerError::TokenOutDoesNotExist)?; Ok(bmath::calculate_out_given_in( token_in.liquidity, token_in.weight, token_out.liquidity, token_out.weight, amount_in, U256::from(self.fee), )?) } /// Locally simulates a swap in the AMM. /// Mutates the AMM state to the state of the AMM after swapping. /// /// # Returns /// The amount received for `amount_in` of `token_in`. fn simulate_swap_mut( &mut self, base_token: Address, quote_token: Address, amount_in: U256, ) -> Result { let token_in = self .state .get(&base_token) .ok_or(BalancerError::TokenInDoesNotExist)?; let token_out = self .state .get("e_token) .ok_or(BalancerError::TokenOutDoesNotExist)?; let out = bmath::calculate_out_given_in( token_in.liquidity, token_in.weight, token_out.liquidity, token_out.weight, amount_in, U256::from(self.fee), )?; self.state.get_mut(&base_token).unwrap().liquidity += amount_in; self.state.get_mut("e_token).unwrap().liquidity -= out; Ok(out) } async fn init(mut self, block_number: BlockId, provider: P) -> Result where N: Network, P: Provider + Clone, { let deployer = IGetBalancerPoolDataBatchRequest::deploy_builder(provider, vec![self.address]); let res = deployer.block(block_number).call_raw().await?; let mut data = , Vec, Vec, Vec, u32)> as SolValue>::abi_decode( &res, )?; let (tokens, decimals, liquidity, weights, fee) = if !data.is_empty() { data.remove(0) } else { return Err(BalancerError::InitializationError.into()); }; let token_state = tokens .into_iter() .zip(decimals) .zip(liquidity) .zip(weights) .map(|(((token, decimals), liquidity), weight)| { ( token, TokenPoolState { liquidity, weight, token: Token::new_with_decimals(token, decimals as u8), }, ) }) .collect::>(); self.state = token_state; self.fee = fee; Ok(self) } } impl BalancerPool { #[allow(clippy::too_many_arguments)] pub fn new(address: Address) -> BalancerPool { BalancerPool { address, ..Default::default() } } } #[derive(Default, Debug, Clone, Copy, Serialize, Deserialize)] pub struct BalancerFactory { pub address: Address, pub creation_block: u64, } #[async_trait] impl AutomatedMarketMakerFactory for BalancerFactory { type PoolVariant = BalancerPool; /// Address of the factory contract fn address(&self) -> Address { self.address } /// Creates an unsynced pool from a creation log. fn create_pool(&self, log: Log) -> Result { let pool_data = IBFactory::LOG_NEW_POOL::decode_log(&log.inner)?; Ok(AMM::BalancerPool(BalancerPool { address: pool_data.pool, ..Default::default() })) } /// Returns the block number at which the factory was created. fn creation_block(&self) -> u64 { self.creation_block } /// Event signature that indicates when a new pool was created fn pool_creation_event(&self) -> B256 { IBFactory::LOG_NEW_POOL::SIGNATURE_HASH } } impl DiscoverySync for BalancerFactory { fn discover( &self, to_block: BlockId, provider: P, ) -> impl Future, AMMError>> where N: Network, P: Provider + Clone, { info!( target = "amms::balancer::discover", address = ?self.address, "Discovering all pools" ); self.get_all_pools(to_block, provider) } fn sync( &self, amms: Vec, to_block: BlockId, provider: P, ) -> impl Future, AMMError>> where N: Network, P: Provider + Clone, { info!( target = "amms::balancer::sync", address = ?self.address, "Syncing all pools" ); Self::sync_all_pools(amms, to_block, provider) } } impl BalancerFactory { pub fn new(address: Address, creation_block: u64) -> BalancerFactory { BalancerFactory { address, creation_block, } } pub async fn get_all_pools( &self, block_number: BlockId, provider: P, ) -> Result, AMMError> where N: Network, P: Provider + Clone + Clone, { let disc_filter = Filter::new() .event_signature(FilterSet::from(vec![self.pool_creation_event()])) .address(vec![self.address()]); let sync_provider = provider.clone(); let mut futures = FuturesUnordered::new(); let sync_step = 100_000; let mut latest_block = self.creation_block; while latest_block < block_number.as_u64().unwrap_or_default() { let mut block_filter = disc_filter.clone(); let from_block = latest_block; let to_block = (from_block + sync_step).min(block_number.as_u64().unwrap_or_default()); block_filter = block_filter.from_block(from_block); block_filter = block_filter.to_block(to_block); let sync_provider = sync_provider.clone(); futures.push(async move { sync_provider.get_logs(&block_filter).await }); latest_block = to_block + 1; } let mut pools = vec![]; while let Some(res) = futures.next().await { let logs = res?; for log in logs { pools.push(self.create_pool(log)?); } } Ok(pools) } pub async fn sync_all_pools( amms: Vec, block_number: BlockId, provider: P, ) -> Result, AMMError> where N: Network, P: Provider + Clone, { let step = 120; let pairs = amms .iter() .chunks(step) .into_iter() .map(|chunk| chunk.map(|amm| amm.address()).collect()) .collect::>>(); let mut futures_unordered = FuturesUnordered::new(); for group in pairs { let deployer = IGetBalancerPoolDataBatchRequest::deploy_builder(provider.clone(), group.clone()); futures_unordered.push(async move { let res = deployer.call_raw().block(block_number).await?; let return_data = , Vec, Vec, Vec, u32)> as SolValue>::abi_decode( &res, )?; Ok::<(Vec
, Vec<(Vec
, Vec, Vec, Vec, u32)>), AMMError>(( group, return_data, )) }); } let mut amms = amms .into_iter() .map(|amm| (amm.address(), amm)) .collect::>(); while let Some(res) = futures_unordered.next().await { let (group, return_data) = res?; for (pool_data, pool_address) in return_data.iter().zip(group.iter()) { let amm = amms.get_mut(pool_address).unwrap(); let AMM::BalancerPool(pool) = amm else { panic!("Unexpected pool type") }; let tokens = pool_data.0.clone(); let decimals = pool_data.1.clone(); let liquidity = pool_data.2.clone(); let weights = pool_data.3.clone(); let token_state = tokens .into_iter() .zip(decimals) .zip(liquidity) .zip(weights) .map(|(((token, decimals), liquidity), weight)| { ( token, TokenPoolState { liquidity, weight, token: Token::new_with_decimals(token, decimals as u8), }, ) }) .collect::>(); pool.state = token_state; pool.fee = pool_data.4; } } let amms = amms .into_iter() .filter_map(|(_, amm)| { if amm.tokens().iter().any(|t| t.is_zero()) { None } else { Some(amm) } }) .collect(); Ok(amms) } } #[cfg(test)] mod tests { use std::sync::Arc; use alloy::{ primitives::{address, U256}, providers::ProviderBuilder, }; use eyre::Ok; use crate::amms::{ amm::AutomatedMarketMaker, balancer::{BalancerPool, IBPool::IBPoolInstance}, }; use crate::amms::{balancer::TokenPoolState, Token}; #[tokio::test] pub async fn test_populate_data() -> eyre::Result<()> { let provider = Arc::new( ProviderBuilder::new() .connect_http(std::env::var("ETHEREUM_PROVIDER")?.parse().unwrap()), ); let balancer_pool = BalancerPool::new(address!("8a649274E4d777FFC6851F13d23A86BBFA2f2Fbf")) .init(22000236.into(), provider.clone()) .await?; let weth = Token::new_with_decimals(address!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"), 18); let usdc = Token::new_with_decimals(address!("a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"), 6); let weth_state = balancer_pool.state.get(weth.address()).unwrap(); assert_eq!( *weth_state, TokenPoolState { liquidity: U256::from(10512868599101770417_u128), weight: U256::from(25000000000000000000_u128), token: weth, } ); let usdc_state = balancer_pool.state.get(usdc.address()).unwrap(); assert_eq!( *usdc_state, TokenPoolState { liquidity: U256::from(22394300283_u128), weight: U256::from(25000000000000000000_u128), token: usdc, } ); // Validate the fee let expected_fee = 640942080; assert_eq!( balancer_pool.fee, expected_fee, "Fee does not match expected value" ); Ok(()) } #[tokio::test] pub async fn test_calculate_price() -> eyre::Result<()> { let provider = Arc::new( ProviderBuilder::new() .connect_http(std::env::var("ETHEREUM_PROVIDER")?.parse().unwrap()), ); let balancer_pool = BalancerPool::new(address!("8a649274E4d777FFC6851F13d23A86BBFA2f2Fbf")) .init(20487793.into(), provider.clone()) .await?; let calculated = balancer_pool .calculate_price( address!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"), address!("a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"), ) .unwrap(); assert_eq!(calculated, 2662.153859723404_f64); Ok(()) } #[tokio::test] pub async fn test_simulate_swap() -> eyre::Result<()> { let provider = Arc::new( ProviderBuilder::new() .connect_http(std::env::var("ETHEREUM_PROVIDER")?.parse().unwrap()), ); let balancer_pool = BalancerPool::new(address!("8a649274E4d777FFC6851F13d23A86BBFA2f2Fbf")) .init(20487793.into(), provider.clone()) .await?; println!("Balancer V2 Pool: {:?}", balancer_pool); let token_in = address!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"); let token_out = address!("a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"); let amount_in = U256::from(10_u64.pow(18)); let calculated = balancer_pool.simulate_swap(token_in, token_out, amount_in)?; let b_pool_quoter = IBPoolInstance::new( address!("8a649274E4d777FFC6851F13d23A86BBFA2f2Fbf"), provider.clone(), ); let token_in = balancer_pool.state.get(&token_in).unwrap(); let token_out = balancer_pool.state.get(&token_out).unwrap(); let expected = b_pool_quoter .calcOutGivenIn( token_in.liquidity, token_in.weight, token_out.liquidity, token_out.weight, amount_in, U256::from(balancer_pool.fee), ) .call() .await .unwrap(); assert_eq!(calculated, expected); Ok(()) } } ================================================ FILE: src/amms/consts.rs ================================================ use alloy::primitives::U256; // commonly used U256s pub const U256_10E_10: U256 = U256::from_limbs([10000000000, 0, 0, 0]); pub const U256_0X100000000: U256 = U256::from_limbs([4294967296, 0, 0, 0]); pub const U256_0X10000: U256 = U256::from_limbs([65536, 0, 0, 0]); pub const U256_0X100: U256 = U256::from_limbs([256, 0, 0, 0]); pub const U256_1000: U256 = U256::from_limbs([1000, 0, 0, 0]); pub const U256_10000: U256 = U256::from_limbs([10000, 0, 0, 0]); pub const U256_100000: U256 = U256::from_limbs([100000, 0, 0, 0]); pub const U256_255: U256 = U256::from_limbs([255, 0, 0, 0]); pub const U256_192: U256 = U256::from_limbs([192, 0, 0, 0]); pub const U256_191: U256 = U256::from_limbs([191, 0, 0, 0]); pub const U256_128: U256 = U256::from_limbs([128, 0, 0, 0]); pub const U256_64: U256 = U256::from_limbs([64, 0, 0, 0]); pub const U256_32: U256 = U256::from_limbs([32, 0, 0, 0]); pub const U256_16: U256 = U256::from_limbs([16, 0, 0, 0]); pub const U256_10: U256 = U256::from_limbs([10, 0, 0, 0]); pub const U256_8: U256 = U256::from_limbs([8, 0, 0, 0]); pub const U256_4: U256 = U256::from_limbs([4, 0, 0, 0]); pub const U256_2: U256 = U256::from_limbs([2, 0, 0, 0]); pub const U256_1: U256 = U256::from_limbs([1, 0, 0, 0]); // Uniswap V3 specific pub const POPULATE_TICK_DATA_STEP: u64 = 100000; pub const Q128: U256 = U256::from_limbs([0, 0, 1, 0]); pub const Q224: U256 = U256::from_limbs([0, 0, 0, 4294967296]); // Balancer V2 specific pub const BONE: U256 = U256::from_limbs([0xDE0B6B3A7640000, 0, 0, 0]); // Others pub const U128_0X10000000000000000: u128 = 18446744073709551616; pub const U256_0XFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF: U256 = U256::from_limbs([ 18446744073709551615, 18446744073709551615, 18446744073709551615, 0, ]); pub const U256_0XFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF: U256 = U256::from_limbs([18446744073709551615, 18446744073709551615, 0, 0]); pub const DECIMAL_RADIX: i32 = 10; pub const MPFR_T_PRECISION: u32 = 70; ================================================ FILE: src/amms/erc_4626/mod.rs ================================================ use super::{ amm::AutomatedMarketMaker, consts::{U128_0X10000000000000000, U256_10000, U256_2}, error::AMMError, float::q64_to_float, uniswap_v2::div_uu, }; use alloy::{ eips::BlockId, network::Network, primitives::{Address, B256, U256}, providers::Provider, rpc::types::Log, sol, sol_types::{SolEvent, SolValue}, }; use serde::{Deserialize, Serialize}; use std::cmp::Ordering; use thiserror::Error; use tracing::info; sol! { /// Interface of the IERC4626Valut contract #[derive(Debug, PartialEq, Eq)] #[sol(rpc)] contract IERC4626Vault { event Withdraw(address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares); event Deposit(address indexed sender,address indexed owner, uint256 assets, uint256 shares); function totalAssets() external view returns (uint256); function totalSupply() external view returns (uint256); } } sol! { #[allow(missing_docs)] #[sol(rpc)] IGetERC4626VaultDataBatchRequest, "src/amms/abi/GetERC4626VaultDataBatchRequest.json", } #[derive(Error, Debug)] pub enum ERC4626VaultError { #[error("Non relative or zero fee")] NonRelativeOrZeroFee, #[error("Division by zero")] DivisionByZero, #[error("Initialization error")] InitializationError, } #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct ERC4626Vault { /// Token received from depositing, i.e. shares token pub vault_token: Address, pub vault_token_decimals: u8, /// Token received from withdrawing, i.e. underlying token pub asset_token: Address, pub asset_token_decimals: u8, /// Total supply of vault tokens pub vault_reserve: U256, /// Total balance of asset tokens held by vault pub asset_reserve: U256, /// Deposit fee in basis points pub deposit_fee: u32, /// Withdrawal fee in basis points pub withdraw_fee: u32, } impl AutomatedMarketMaker for ERC4626Vault { fn address(&self) -> Address { self.vault_token } fn sync_events(&self) -> Vec { vec![ IERC4626Vault::Deposit::SIGNATURE_HASH, IERC4626Vault::Withdraw::SIGNATURE_HASH, ] } fn sync(&mut self, log: &Log) -> Result<(), AMMError> { let event_signature = log.data().topics()[0]; match event_signature { IERC4626Vault::Deposit::SIGNATURE_HASH => { let deposit_event = IERC4626Vault::Deposit::decode_log(log.as_ref())?; self.asset_reserve += deposit_event.assets; self.vault_reserve += deposit_event.shares; info!( target = "amms::erc_4626::sync", address = ?self.vault_token, asset_reserve = ?self.asset_reserve, vault_reserve = ?self.vault_reserve, "Deposit" ); } IERC4626Vault::Withdraw::SIGNATURE_HASH => { let withdraw_event = IERC4626Vault::Withdraw::decode_log(log.as_ref())?; self.asset_reserve -= withdraw_event.assets; self.vault_reserve -= withdraw_event.shares; info!( target = "amms::erc_4626::sync", address = ?self.vault_token, asset_reserve = ?self.asset_reserve, vault_reserve = ?self.vault_reserve, "Withdraw" ); } _ => { return Err(AMMError::UnrecognizedEventSignature(event_signature)); } } Ok(()) } fn tokens(&self) -> Vec
{ vec![self.vault_token, self.asset_token] } fn calculate_price(&self, base_token: Address, _quote_token: Address) -> Result { q64_to_float(self.calculate_price_64_x_64(base_token)?) } fn simulate_swap( &self, base_token: Address, _quote_token: Address, amount_in: U256, ) -> Result { if self.vault_token == base_token { Ok(self.get_amount_out(amount_in, self.vault_reserve, self.asset_reserve)?) } else { Ok(self.get_amount_out(amount_in, self.asset_reserve, self.vault_reserve)?) } } fn simulate_swap_mut( &mut self, base_token: Address, _quote_token: Address, amount_in: U256, ) -> Result { if self.vault_token == base_token { let amount_out = self.get_amount_out(amount_in, self.vault_reserve, self.asset_reserve)?; self.vault_reserve -= amount_in; self.asset_reserve -= amount_out; Ok(amount_out) } else { let amount_out = self.get_amount_out(amount_in, self.asset_reserve, self.vault_reserve)?; self.asset_reserve += amount_in; self.vault_reserve += amount_out; Ok(amount_out) } } // TODO: clean up this function async fn init(mut self, block_number: BlockId, provider: P) -> Result where N: Network, P: Provider + Clone, { let deployer = IGetERC4626VaultDataBatchRequest::deploy_builder(provider, vec![self.vault_token]); let res = deployer.call_raw().block(block_number).await?; let data = as SolValue>::abi_decode(&res)?; let ( vault_token, vault_token_dec, asset_token, asset_token_dec, vault_reserve, asset_reserve, deposit_fee_delta_1, deposit_fee_delta_2, deposit_no_fee, withdraw_fee_delta_1, withdraw_fee_delta_2, withdraw_no_fee, ) = if !data.is_empty() { data[0] } else { return Err(ERC4626VaultError::InitializationError)?; }; // If both deltas are zero, the fee is zero if deposit_fee_delta_1.is_zero() && deposit_fee_delta_2.is_zero() { self.deposit_fee = 0; // Assuming 18 decimals, if the delta of 1e20 is half the delta of 2e20, relative fee. // Delta / (amount without fee / 10000) to give us the fee in basis points } else if deposit_fee_delta_1 * U256_2 == deposit_fee_delta_2 { self.deposit_fee = (deposit_fee_delta_1 / (deposit_no_fee / U256::from(10_000))).to(); } else { todo!("Handle error") } // If both deltas are zero, the fee is zero if withdraw_fee_delta_1.is_zero() && withdraw_fee_delta_2.is_zero() { self.withdraw_fee = 0; // Assuming 18 decimals, if the delta of 1e20 is half the delta of 2e20, relative fee. // Delta / (amount without fee / 10000) to give us the fee in basis points } else if withdraw_fee_delta_1 * U256::from(2) == withdraw_fee_delta_2 { self.withdraw_fee = (withdraw_fee_delta_1 / (withdraw_no_fee / U256::from(10_000))).to(); } else { // If not a relative fee or zero, ignore vault return Err(ERC4626VaultError::NonRelativeOrZeroFee.into()); } // if above does not error => populate the vault self.vault_token = vault_token; self.vault_token_decimals = vault_token_dec as u8; self.asset_token = asset_token; self.asset_token_decimals = asset_token_dec as u8; self.vault_reserve = vault_reserve; self.asset_reserve = asset_reserve; Ok(self) } } // TODO: swap calldata impl ERC4626Vault { // Returns a new, unsynced ERC4626 vault pub fn new(address: Address) -> Self { Self { vault_token: address, ..Default::default() } } pub fn get_amount_out( &self, amount_in: U256, reserve_in: U256, reserve_out: U256, ) -> Result { if amount_in.is_zero() { return Ok(U256::ZERO); } if self.vault_reserve.is_zero() { return Ok(amount_in); } let fee = if reserve_in == self.vault_reserve { self.withdraw_fee } else { self.deposit_fee }; if reserve_in.is_zero() || 10000 - fee == 0 { return Err(ERC4626VaultError::DivisionByZero.into()); } Ok(amount_in * reserve_out / reserve_in * U256::from(10000 - fee) / U256_10000) } pub fn calculate_price_64_x_64(&self, base_token: Address) -> Result { let decimal_shift = self.vault_token_decimals as i8 - self.asset_token_decimals as i8; // Normalize reserves by decimal shift let (r_v, r_a) = match decimal_shift.cmp(&0) { Ordering::Less => ( self.vault_reserve * U256::from(10u128.pow(decimal_shift.unsigned_abs() as u32)), self.asset_reserve, ), _ => ( self.vault_reserve, self.asset_reserve * U256::from(10u128.pow(decimal_shift as u32)), ), }; // Withdraw if base_token == self.vault_token { if r_v.is_zero() { // Return 1 in Q64 Ok(U128_0X10000000000000000) } else { Ok(div_uu(r_a, r_v)?) } // Deposit } else if r_a.is_zero() { // Return 1 in Q64 Ok(U128_0X10000000000000000) } else { Ok(div_uu(r_v, r_a)?) } } pub async fn get_reserves( &self, provider: P, block_number: BlockId, ) -> Result<(U256, U256), AMMError> where N: Network, P: Provider + Clone + Clone, { let vault = IERC4626Vault::new(self.vault_token, provider); let total_assets = vault.totalAssets().block(block_number).call().await?; let total_supply = vault.totalSupply().block(block_number).call().await?; Ok((total_supply, total_assets)) } } ================================================ FILE: src/amms/error.rs ================================================ use super::{ balancer::BalancerError, erc_4626::ERC4626VaultError, uniswap_v2::UniswapV2Error, uniswap_v3::UniswapV3Error, }; use alloy::{primitives::FixedBytes, transports::TransportErrorKind}; use thiserror::Error; #[derive(Error, Debug)] pub enum AMMError { #[error(transparent)] TransportError(#[from] alloy::transports::RpcError), #[error(transparent)] ContractError(#[from] alloy::contract::Error), #[error(transparent)] ABIError(#[from] alloy::dyn_abi::Error), #[error(transparent)] SolTypesError(#[from] alloy::sol_types::Error), #[error(transparent)] UniswapV2Error(#[from] UniswapV2Error), #[error(transparent)] UniswapV3Error(#[from] UniswapV3Error), #[error(transparent)] BalancerError(#[from] BalancerError), #[error(transparent)] ERC4626VaultError(#[from] ERC4626VaultError), #[error(transparent)] BatchContractError(#[from] BatchContractError), #[error(transparent)] ParseFloatError(#[from] rug::float::ParseFloatError), #[error("Unrecognized Event Signature {0}")] UnrecognizedEventSignature(FixedBytes<32>), #[error(transparent)] JoinError(#[from] tokio::task::JoinError), } #[derive(Error, Debug)] pub enum BatchContractError { #[error(transparent)] ContractError(#[from] alloy::contract::Error), #[error(transparent)] DynABIError(#[from] alloy::dyn_abi::Error), } ================================================ FILE: src/amms/factory.rs ================================================ use super::{amm::Variant, uniswap_v2::UniswapV2Factory, uniswap_v3::UniswapV3Factory}; use super::{ amm::{AutomatedMarketMaker, AMM}, balancer::BalancerFactory, error::AMMError, }; use alloy::{ eips::BlockId, network::Network, primitives::{Address, B256, U256}, providers::Provider, rpc::types::eth::Log, }; use eyre::Result; use serde::{Deserialize, Serialize}; use std::{ future::Future, hash::{Hash, Hasher}, }; pub trait DiscoverySync { fn discover( &self, to_block: BlockId, provider: P, ) -> impl Future, AMMError>> where N: Network, P: Provider + Clone; fn sync( &self, amms: Vec, to_block: BlockId, provider: P, ) -> impl Future, AMMError>> where N: Network, P: Provider + Clone; } pub trait AutomatedMarketMakerFactory: DiscoverySync { type PoolVariant: AutomatedMarketMaker + Default; /// Address of the factory contract fn address(&self) -> Address; /// Creates an unsynced pool from a creation log. fn create_pool(&self, log: Log) -> Result; /// Returns the block number at which the factory was created. fn creation_block(&self) -> u64; /// Event signature that indicates when a new pool was created fn pool_creation_event(&self) -> B256; /// Event signatures signifying when a pool created by the factory should be synced fn pool_events(&self) -> Vec { Self::PoolVariant::default().sync_events() } fn pool_variant(&self) -> Self::PoolVariant { Self::PoolVariant::default() } } macro_rules! factory { ($($factory_type:ident),+ $(,)?) => { #[derive(Debug, Clone, Serialize, Deserialize)] pub enum Factory { $($factory_type($factory_type),)+ } impl Factory { pub fn address(&self) -> Address { match self { $(Factory::$factory_type(factory) => factory.address(),)+ } } pub fn discovery_event(&self) -> B256 { match self { $(Factory::$factory_type(factory) => factory.pool_creation_event(),)+ } } pub fn create_pool(&self, log: Log) -> Result { match self { $(Factory::$factory_type(factory) => factory.create_pool(log),)+ } } pub fn creation_block(&self) -> u64 { match self { $(Factory::$factory_type(factory) => factory.creation_block(),)+ } } pub fn pool_events(&self) -> Vec { match self { $(Factory::$factory_type(factory) => factory.pool_events(),)+ } } pub fn variant(&self) -> Variant { match self { $(Factory::$factory_type(factory) => AMM::from(factory.pool_variant()).variant(),)+ } } } impl Hash for Factory { fn hash(&self, state: &mut H) { self.address().hash(state); } } impl PartialEq for Factory { fn eq(&self, other: &Self) -> bool { self.address() == other.address() } } impl Eq for Factory {} impl Factory { pub async fn discover< N, P>(&self, to_block: BlockId, provider: P) -> Result, AMMError> where N: Network, P: Provider + Clone, { match self { $(Factory::$factory_type(factory) => factory.discover(to_block, provider).await,)+ } } pub async fn sync< N, P>(&self, amms: Vec, to_block: BlockId, provider: P) -> Result, AMMError> where N: Network, P: Provider + Clone, { match self { $(Factory::$factory_type(factory) => factory.sync(amms, to_block, provider).await,)+ } } } $( impl From<$factory_type> for Factory { fn from(factory: $factory_type) -> Self { Factory::$factory_type(factory) } } )+ }; } factory!(UniswapV2Factory, UniswapV3Factory, BalancerFactory); #[derive(Default)] pub struct NoopAMM; impl AutomatedMarketMaker for NoopAMM { fn address(&self) -> Address { unreachable!() } fn sync_events(&self) -> Vec { unreachable!() } fn sync(&mut self, _log: &Log) -> Result<(), AMMError> { unreachable!() } fn simulate_swap( &self, _base_token: Address, _quote_token: Address, _amount_in: U256, ) -> Result { unreachable!() } fn simulate_swap_mut( &mut self, _base_token: Address, _quote_token: Address, _amount_in: U256, ) -> Result { unreachable!() } fn calculate_price( &self, _base_token: Address, _quote_token: Address, ) -> Result { unreachable!() } fn tokens(&self) -> Vec
{ unreachable!() } async fn init(self, _block_number: BlockId, _provider: P) -> Result where N: Network, P: Provider + Clone, { unreachable!() } } ================================================ FILE: src/amms/float.rs ================================================ use alloy::primitives::U256; use rug::Float; use super::{ consts::{MPFR_T_PRECISION, U128_0X10000000000000000}, error::AMMError, }; pub fn q64_to_float(num: u128) -> Result { let float_num = u128_to_float(num)?; let divisor = u128_to_float(U128_0X10000000000000000)?; Ok((float_num / divisor).to_f64()) } pub fn u128_to_float(num: u128) -> Result { let value_string = num.to_string(); let parsed_value = Float::parse_radix(value_string, 10)?; Ok(Float::with_val(MPFR_T_PRECISION, parsed_value)) } pub fn u256_to_float(num: U256) -> Result { let value_string = num.to_string(); let parsed_value = Float::parse_radix(value_string, 10)?; Ok(Float::with_val(MPFR_T_PRECISION, parsed_value)) } ================================================ FILE: src/amms/mod.rs ================================================ use std::{ collections::HashMap, hash::{Hash, Hasher}, }; use alloy::{dyn_abi::DynSolType, network::Network, primitives::Address, providers::Provider, sol}; use error::{AMMError, BatchContractError}; use futures::{stream::FuturesUnordered, StreamExt}; use serde::{Deserialize, Serialize}; pub mod amm; pub mod balancer; pub mod consts; pub mod erc_4626; pub mod error; pub mod factory; pub mod float; pub mod uniswap_v2; pub mod uniswap_v3; sol! { #[sol(rpc)] GetTokenDecimalsBatchRequest, "src/amms/abi/GetTokenDecimalsBatchRequest.json", } sol!( #[derive(Debug, PartialEq, Eq)] #[sol(rpc)] contract IERC20 { function decimals() external view returns (uint8); }); #[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)] pub struct Token { pub address: Address, pub decimals: u8, // TODO: add optional tax } impl Token { pub async fn new(address: Address, provider: P) -> Result where N: Network, P: Provider + Clone, { let decimals = IERC20::new(address, provider).decimals().call().await?; Ok(Self { address, decimals }) } pub const fn new_with_decimals(address: Address, decimals: u8) -> Self { Self { address, decimals } } pub const fn address(&self) -> &Address { &self.address } pub const fn decimals(&self) -> u8 { self.decimals } } impl From
for Token { fn from(address: Address) -> Self { Self { address, decimals: 0, } } } impl Hash for Token { fn hash(&self, state: &mut H) { self.address.hash(state); } } /// Fetches the decimal precision for a list of ERC-20 tokens. /// /// # Returns /// A map of token addresses to their decimal precision. pub async fn get_token_decimals( tokens: Vec
, provider: P, ) -> Result, BatchContractError> where N: Network, P: Provider + Clone + Clone, { let step = 765; let mut futures = FuturesUnordered::new(); tokens.chunks(step).for_each(|group| { let provider = provider.clone(); futures.push(async move { ( group, GetTokenDecimalsBatchRequest::deploy_builder(provider, group.to_vec()) .call_raw() .await, ) }); }); let mut token_decimals = HashMap::new(); let return_type = DynSolType::Array(Box::new(DynSolType::Uint(8))); while let Some(res) = futures.next().await { let (token_addresses, return_data) = res; let return_data = return_type.abi_decode_sequence(&return_data?)?; if let Some(tokens_arr) = return_data.as_array() { for (decimals, token_address) in tokens_arr.iter().zip(token_addresses.iter()) { token_decimals.insert( *token_address, decimals.as_uint().expect("Could not get uint").0.to::(), ); } } } Ok(token_decimals) } ================================================ FILE: src/amms/uniswap_v2/mod.rs ================================================ use super::{ amm::{AutomatedMarketMaker, AMM}, consts::{ MPFR_T_PRECISION, U128_0X10000000000000000, U256_0X100, U256_0X10000, U256_0X100000000, U256_0XFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, U256_0XFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, U256_1, U256_100000, U256_128, U256_16, U256_191, U256_192, U256_2, U256_255, U256_32, U256_4, U256_64, U256_8, }, error::AMMError, factory::{AutomatedMarketMakerFactory, DiscoverySync}, float::q64_to_float, Token, }; use alloy::{ eips::BlockId, network::Network, primitives::{Address, Bytes, B256, U256}, providers::Provider, rpc::types::Log, sol, sol_types::{SolCall, SolEvent, SolValue}, }; use futures::{stream::FuturesUnordered, StreamExt}; use itertools::Itertools; use rug::Float; use serde::{Deserialize, Serialize}; use std::{collections::HashMap, future::Future, hash::Hash}; use thiserror::Error; use tracing::info; use IGetUniswapV2PoolDataBatchRequest::IGetUniswapV2PoolDataBatchRequestInstance; use IUniswapV2Factory::IUniswapV2FactoryInstance; sol!( // UniswapV2Factory #[allow(missing_docs)] #[derive(Debug)] #[sol(rpc)] contract IUniswapV2Factory { event PairCreated(address indexed token0, address indexed token1, address pair, uint256); function allPairs(uint256) external view returns (address pair); function allPairsLength() external view returns (uint256); } #[derive(Debug, PartialEq, Eq)] #[sol(rpc)] contract IUniswapV2Pair { event Sync(uint112 reserve0, uint112 reserve1); function token0() external view returns (address); function token1() external view returns (address); function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data); function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); }); sol!( #[allow(missing_docs)] #[sol(rpc)] IGetUniswapV2PairsBatchRequest, "src/amms/abi/GetUniswapV2PairsBatchRequest.json" ); sol!( #[allow(missing_docs)] #[sol(rpc)] IGetUniswapV2PoolDataBatchRequest, "src/amms/abi/GetUniswapV2PoolDataBatchRequest.json" ); #[derive(Error, Debug)] pub enum UniswapV2Error { #[error("Division by zero")] DivisionByZero, #[error("Rounding Error")] RoundingError, } #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct UniswapV2Pool { pub address: Address, pub token_a: Token, pub token_b: Token, pub reserve_0: u128, pub reserve_1: u128, pub fee: usize, } impl AutomatedMarketMaker for UniswapV2Pool { fn address(&self) -> Address { self.address } fn sync_events(&self) -> Vec { vec![IUniswapV2Pair::Sync::SIGNATURE_HASH] } fn sync(&mut self, log: &Log) -> Result<(), AMMError> { let sync_event = IUniswapV2Pair::Sync::decode_log(&log.inner)?; let (reserve_0, reserve_1) = ( sync_event.reserve0.to::(), sync_event.reserve1.to::(), ); info!( target = "amm::uniswap_v2::sync", address = ?self.address, reserve_0, reserve_1, "Sync" ); self.reserve_0 = reserve_0; self.reserve_1 = reserve_1; Ok(()) } fn simulate_swap( &self, base_token: Address, _quote_token: Address, amount_in: U256, ) -> Result { if self.token_a.address == base_token { Ok(self.get_amount_out( amount_in, U256::from(self.reserve_0), U256::from(self.reserve_1), )) } else { Ok(self.get_amount_out( amount_in, U256::from(self.reserve_1), U256::from(self.reserve_0), )) } } fn simulate_swap_mut( &mut self, base_token: Address, _quote_token: Address, amount_in: U256, ) -> Result { if self.token_a.address == base_token { let amount_out = self.get_amount_out( amount_in, U256::from(self.reserve_0), U256::from(self.reserve_1), ); self.reserve_0 += amount_in.to::(); self.reserve_1 -= amount_out.to::(); Ok(amount_out) } else { let amount_out = self.get_amount_out( amount_in, U256::from(self.reserve_1), U256::from(self.reserve_0), ); self.reserve_0 -= amount_out.to::(); self.reserve_1 += amount_in.to::(); Ok(amount_out) } } fn tokens(&self) -> Vec
{ vec![self.token_a.address, self.token_b.address] } fn calculate_price(&self, base_token: Address, _quote_token: Address) -> Result { let price = self.calculate_price_64_x_64(base_token)?; q64_to_float(price) } async fn init(mut self, block_number: BlockId, provider: P) -> Result where N: Network, P: Provider + Clone, { let deployer = IGetUniswapV2PoolDataBatchRequestInstance::deploy_builder( provider.clone(), vec![self.address()], ); let res = deployer.call_raw().block(block_number).await?; let pool_data = as SolValue>::abi_decode(&res)?[0]; if pool_data.0.is_zero() { todo!("Return error"); } self.token_a = Token::new_with_decimals(pool_data.0, pool_data.4 as u8); self.token_b = Token::new_with_decimals(pool_data.1, pool_data.5 as u8); self.reserve_0 = pool_data.2; self.reserve_1 = pool_data.3; // TODO: populate fee? Ok(self) } } pub fn u128_to_float(num: u128) -> Result { let value_string = num.to_string(); let parsed_value = Float::parse_radix(value_string, 10)?; Ok(Float::with_val(MPFR_T_PRECISION, parsed_value)) } impl UniswapV2Pool { // Create a new, unsynced UniswapV2 pool // TODO: update the init function to derive the fee pub fn new(address: Address, fee: usize) -> Self { Self { address, fee, ..Default::default() } } /// Calculates the amount received for a given `amount_in` `reserve_in` and `reserve_out`. pub fn get_amount_out(&self, amount_in: U256, reserve_in: U256, reserve_out: U256) -> U256 { if amount_in.is_zero() || reserve_in.is_zero() || reserve_out.is_zero() { return U256::ZERO; } let fee = U256_100000 - U256::from(self.fee); let amount_in = amount_in * fee; let numerator = amount_in * reserve_out; let denominator = reserve_in * U256_100000 + amount_in; numerator / denominator } /// Calculates the price of the base token in terms of the quote token. /// /// Returned as a Q64 fixed point number. pub fn calculate_price_64_x_64(&self, base_token: Address) -> Result { let decimal_shift = self.token_a.decimals as i8 - self.token_b.decimals as i8; let (r_0, r_1) = if decimal_shift < 0 { ( U256::from(self.reserve_0) * U256::from(10u128.pow(decimal_shift.unsigned_abs() as u32)), U256::from(self.reserve_1), ) } else { ( U256::from(self.reserve_0), U256::from(self.reserve_1) * U256::from(10u128.pow(decimal_shift as u32)), ) }; if base_token == self.token_a.address { if r_0.is_zero() { Ok(U128_0X10000000000000000) } else { div_uu(r_1, r_0) } } else if r_1.is_zero() { Ok(U128_0X10000000000000000) } else { div_uu(r_0, r_1) } } pub fn swap_calldata( &self, amount_0_out: U256, amount_1_out: U256, to: Address, calldata: Vec, ) -> Result { Ok(IUniswapV2Pair::swapCall { amount0Out: amount_0_out, amount1Out: amount_1_out, to, data: calldata.into(), } .abi_encode() .into()) } } pub fn div_uu(x: U256, y: U256) -> Result { if !y.is_zero() { let mut answer; if x <= U256_0XFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF { answer = (x << U256_64) / y; } else { let mut msb = U256_192; let mut xc = x >> U256_192; if xc >= U256_0X100000000 { xc >>= U256_32; msb += U256_32; } if xc >= U256_0X10000 { xc >>= U256_16; msb += U256_16; } if xc >= U256_0X100 { xc >>= U256_8; msb += U256_8; } if xc >= U256_16 { xc >>= U256_4; msb += U256_4; } if xc >= U256_4 { xc >>= U256_2; msb += U256_2; } if xc >= U256_2 { msb += U256_1; } answer = (x << (U256_255 - msb)) / (((y - U256_1) >> (msb - U256_191)) + U256_1); } if answer > U256_0XFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF { return Ok(0); } let hi = answer * (y >> U256_128); let mut lo = answer * (y & U256_0XFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); let mut xh = x >> U256_192; let mut xl = x << U256_64; if xl < lo { xh -= U256_1; } xl = xl.overflowing_sub(lo).0; lo = hi << U256_128; if xl < lo { xh -= U256_1; } xl = xl.overflowing_sub(lo).0; if xh != hi >> U256_128 { return Err(UniswapV2Error::RoundingError.into()); } answer += xl / y; if answer > U256_0XFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF { return Ok(0_u128); } Ok(answer.to::()) } else { Err(UniswapV2Error::DivisionByZero.into()) } } #[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)] pub struct UniswapV2Factory { pub address: Address, pub fee: usize, pub creation_block: u64, } impl UniswapV2Factory { pub fn new(address: Address, fee: usize, creation_block: u64) -> Self { Self { address, creation_block, fee, } } pub async fn get_all_pairs( factory_address: Address, block_number: BlockId, provider: P, ) -> Result, AMMError> where N: Network, P: Provider + Clone, { let factory = IUniswapV2FactoryInstance::new(factory_address, provider.clone()); let pairs_length = factory .allPairsLength() .call() .block(block_number) .await? .to::(); let step = 766; let mut futures_unordered = FuturesUnordered::new(); for i in (0..pairs_length).step_by(step) { // Note that the batch contract handles if the step is greater than the pairs length // So we can pass the step in as is without checking for this condition let deployer = IGetUniswapV2PairsBatchRequest::deploy_builder( provider.clone(), U256::from(i), U256::from(step), factory_address, ); futures_unordered.push(async move { let res = deployer.call_raw().block(block_number).await?; let return_data = as SolValue>::abi_decode(&res)?; Ok::, AMMError>(return_data) }); } let mut pairs = Vec::new(); while let Some(res) = futures_unordered.next().await { let tokens = res?; for token in tokens { if !token.is_zero() { pairs.push(token); } } } Ok(pairs) } pub async fn sync_all_pools( amms: Vec, block_number: BlockId, provider: P, ) -> Result, AMMError> where N: Network, P: Provider + Clone, { let step = 120; let pairs = amms .iter() .chunks(step) .into_iter() .map(|chunk| chunk.map(|amm| amm.address()).collect()) .collect::>>(); let mut futures_unordered = FuturesUnordered::new(); for group in pairs { let deployer = IGetUniswapV2PoolDataBatchRequestInstance::deploy_builder( provider.clone(), group.clone(), ); futures_unordered.push(async move { let res = deployer.call_raw().block(block_number).await?; let return_data = as SolValue>::abi_decode(&res)?; Ok::<(Vec
, Vec<(Address, Address, u128, u128, u32, u32)>), AMMError>(( group, return_data, )) }); } let mut amms = amms .into_iter() .map(|amm| (amm.address(), amm)) .collect::>(); while let Some(res) = futures_unordered.next().await { let (group, return_data) = res?; for (pool_data, pool_address) in return_data.iter().zip(group.iter()) { // If the pool token A is not zero, signaling that the pool data was polulated if pool_data.0.is_zero() { continue; } let amm = amms.get_mut(pool_address).unwrap(); let AMM::UniswapV2Pool(pool) = amm else { // TODO:: We should never receive a non UniswapV2Pool AMM here, we can handle this more gracefully in the future panic!("Unexpected pool type") }; pool.token_a = Token::new_with_decimals(pool_data.0, pool_data.4 as u8); pool.token_b = Token::new_with_decimals(pool_data.1, pool_data.5 as u8); pool.reserve_0 = pool_data.2; pool.reserve_1 = pool_data.3; } } let amms = amms .into_iter() .filter_map(|(_, amm)| { if amm.tokens().iter().any(|t| t.is_zero()) { None } else { Some(amm) } }) .collect(); Ok(amms) } } impl AutomatedMarketMakerFactory for UniswapV2Factory { type PoolVariant = UniswapV2Pool; fn address(&self) -> Address { self.address } fn pool_creation_event(&self) -> B256 { IUniswapV2Factory::PairCreated::SIGNATURE_HASH } fn create_pool(&self, log: Log) -> Result { let event = IUniswapV2Factory::PairCreated::decode_log(&log.inner)?; Ok(AMM::UniswapV2Pool(UniswapV2Pool { address: event.pair, token_a: event.token0.into(), token_b: event.token1.into(), reserve_0: 0, reserve_1: 0, fee: self.fee, })) } fn creation_block(&self) -> u64 { self.creation_block } } impl DiscoverySync for UniswapV2Factory { fn discover( &self, to_block: BlockId, provider: P, ) -> impl Future, AMMError>> where N: Network, P: Provider + Clone, { info!( target = "amms::uniswap_v2::discover", address = ?self.address, "Discovering all pools" ); let provider = provider.clone(); async move { let pairs = UniswapV2Factory::get_all_pairs(self.address, to_block, provider.clone()).await?; Ok(pairs .into_iter() .map(|pair| { AMM::UniswapV2Pool(UniswapV2Pool { address: pair, token_a: Address::default().into(), token_b: Address::default().into(), reserve_0: 0, reserve_1: 0, fee: self.fee, }) }) .collect()) } } fn sync( &self, amms: Vec, to_block: BlockId, provider: P, ) -> impl Future, AMMError>> where N: Network, P: Provider + Clone, { info!( target = "amms::uniswap_v2::sync", address = ?self.address, "Syncing all pools" ); UniswapV2Factory::sync_all_pools(amms, to_block, provider) } } #[cfg(test)] mod tests { use crate::amms::{ amm::AutomatedMarketMaker, consts::U256_100000, uniswap_v2::UniswapV2Pool, Token, }; use alloy::primitives::{address, Address, U256}; #[test] fn test_get_amount_out() { let fees = [125, 150, 300, 1000]; // 0.125%, 0.15%, 0.3%, 1% let amount_in = U256::from(10).pow(U256::from(18)); let reserve_in = U256::from(100).pow(U256::from(18)); let reserve_out = U256::from(100).pow(U256::from(18)); let amount_out_no_fee = (reserve_out * amount_in) / (reserve_in + amount_in); for fee in fees { let pool = UniswapV2Pool { fee, ..Default::default() }; let res = pool.get_amount_out(amount_in, reserve_in, reserve_out); assert!(amount_out_no_fee * (U256_100000 - U256::from(fee)) / U256_100000 == res); } } #[test] fn test_calculate_price_edge_case() { let token_a = address!("0d500b1d8e8ef31e21c99d1db9a6444d3adf1270"); let token_b = address!("8f18dc399594b451eda8c5da02d0563c0b2d0f16"); let pool = UniswapV2Pool { address: address!("B4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc"), token_a: Token::new_with_decimals( address!("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), 6, ), token_b: Token::new_with_decimals( address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), 18, ), reserve_0: 23595096345912178729927, reserve_1: 154664232014390554564, fee: 300, }; assert!(pool.calculate_price(token_a, Address::default()).unwrap() != 0.0); assert!(pool.calculate_price(token_b, Address::default()).unwrap() != 0.0); } #[tokio::test] async fn test_calculate_price() { let pool = UniswapV2Pool { address: address!("B4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc"), token_a: Token::new_with_decimals( address!("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), 6, ), token_b: Token::new_with_decimals( address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), 18, ), reserve_0: 47092140895915, reserve_1: 28396598565590008529300, fee: 300, }; let price_a_64_x = pool .calculate_price(pool.token_a.address, Address::default()) .unwrap(); let price_b_64_x = pool .calculate_price(pool.token_b.address, Address::default()) .unwrap(); // No precision loss: 30591574867092394336528 / 2**64 assert_eq!(1658.3725965327264, price_b_64_x); // Precision loss: 11123401407064628 / 2**64 assert_eq!(0.0006030007985483893, price_a_64_x); } #[tokio::test] async fn test_calculate_price_64_x_64() { let pool = UniswapV2Pool { address: address!("B4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc"), token_a: Token::new_with_decimals( address!("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), 6, ), token_b: Token::new_with_decimals( address!("C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), 18, ), reserve_0: 47092140895915, reserve_1: 28396598565590008529300, fee: 300, }; let price_a_64_x = pool.calculate_price_64_x_64(pool.token_a.address).unwrap(); let price_b_64_x = pool.calculate_price_64_x_64(pool.token_b.address).unwrap(); assert_eq!(30591574867092394336528, price_b_64_x); assert_eq!(11123401407064628, price_a_64_x); } } ================================================ FILE: src/amms/uniswap_v3/mod.rs ================================================ use super::{ amm::{AutomatedMarketMaker, AMM}, error::{AMMError, BatchContractError}, factory::{AutomatedMarketMakerFactory, DiscoverySync}, get_token_decimals, Token, }; use crate::amms::{ consts::U256_1, uniswap_v3::GetUniswapV3PoolTickBitmapBatchRequest::TickBitmapInfo, }; use alloy::{ eips::BlockId, network::Network, primitives::{Address, Bytes, Signed, B256, I256, U256}, providers::Provider, rpc::types::{Filter, FilterSet, Log}, sol, sol_types::{SolCall, SolEvent, SolValue}, transports::BoxFuture, }; use futures::{stream::FuturesUnordered, StreamExt}; use rayon::iter::{IntoParallelRefIterator, ParallelDrainRange, ParallelIterator}; use serde::{Deserialize, Serialize}; use std::{ cmp::Ordering, collections::{HashMap, HashSet}, future::Future, hash::Hash, str::FromStr, }; use thiserror::Error; use tracing::info; use uniswap_v3_math::error::UniswapV3MathError; use uniswap_v3_math::tick_math::{MAX_SQRT_RATIO, MAX_TICK, MIN_SQRT_RATIO, MIN_TICK}; use GetUniswapV3PoolTickDataBatchRequest::TickDataInfo; sol! { // UniswapV3Factory #[allow(missing_docs)] #[derive(Debug)] #[sol(rpc)] contract IUniswapV3Factory { /// @notice Emitted when a pool is created event PoolCreated( address indexed token0, address indexed token1, uint24 indexed fee, int24 tickSpacing, address pool ); } #[derive(Debug, PartialEq, Eq)] #[sol(rpc)] contract IUniswapV3PoolEvents { /// @notice Emitted when liquidity is minted for a given position event Mint( address sender, address indexed owner, int24 indexed tickLower, int24 indexed tickUpper, uint128 amount, uint256 amount0, uint256 amount1 ); /// @notice Emitted when a position's liquidity is removed event Burn( address indexed owner, int24 indexed tickLower, int24 indexed tickUpper, uint128 amount, uint256 amount0, uint256 amount1 ); /// @notice Emitted by the pool for any swaps between token0 and token1 event Swap( address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick ); } #[derive(Debug, PartialEq, Eq)] #[sol(rpc)] contract IUniswapV3Pool { function swap(address recipient, bool zeroForOne, int256 amountSpecified, uint160 sqrtPriceLimitX96, bytes calldata data) external returns (int256, int256); function tickSpacing() external view returns (int24); function fee() external view returns (uint24); function token0() external view returns (address); function token1() external view returns (address); } } sol! { #[sol(rpc)] GetUniswapV3PoolSlot0BatchRequest, "src/amms/abi/GetUniswapV3PoolSlot0BatchRequest.json", } sol! { #[sol(rpc)] GetUniswapV3PoolTickBitmapBatchRequest, "src/amms/abi/GetUniswapV3PoolTickBitmapBatchRequest.json", } sol! { #[sol(rpc)] GetUniswapV3PoolTickDataBatchRequest, "src/amms/abi/GetUniswapV3PoolTickDataBatchRequest.json" } #[derive(Error, Debug)] pub enum UniswapV3Error { #[error(transparent)] UniswapV3MathError(#[from] UniswapV3MathError), #[error("Liquidity Underflow")] LiquidityUnderflow, } #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct UniswapV3Pool { pub address: Address, pub token_a: Token, pub token_b: Token, pub liquidity: u128, pub sqrt_price: U256, pub fee: u32, pub tick: i32, pub tick_spacing: i32, // TODO: we can make this a u8, tick spacing will never exceed 200 pub tick_bitmap: HashMap, pub ticks: HashMap, } #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct Info { pub liquidity_gross: u128, pub liquidity_net: i128, pub initialized: bool, } impl Info { pub fn new(liquidity_gross: u128, liquidity_net: i128, initialized: bool) -> Self { Info { liquidity_gross, liquidity_net, initialized, } } } pub struct CurrentState { amount_specified_remaining: I256, amount_calculated: I256, sqrt_price_x_96: U256, tick: i32, liquidity: u128, } #[derive(Default)] pub struct StepComputations { pub sqrt_price_start_x_96: U256, pub tick_next: i32, pub initialized: bool, pub sqrt_price_next_x96: U256, pub amount_in: U256, pub amount_out: U256, pub fee_amount: U256, } pub struct Tick { pub liquidity_gross: u128, pub liquidity_net: i128, pub fee_growth_outside_0_x_128: U256, pub fee_growth_outside_1_x_128: U256, pub tick_cumulative_outside: U256, pub seconds_per_liquidity_outside_x_128: U256, pub seconds_outside: u32, pub initialized: bool, } impl AutomatedMarketMaker for UniswapV3Pool { fn address(&self) -> Address { self.address } fn sync_events(&self) -> Vec { vec![ IUniswapV3PoolEvents::Mint::SIGNATURE_HASH, IUniswapV3PoolEvents::Burn::SIGNATURE_HASH, IUniswapV3PoolEvents::Swap::SIGNATURE_HASH, ] } fn sync(&mut self, log: &Log) -> Result<(), AMMError> { let event_signature = log.topics()[0]; match event_signature { IUniswapV3PoolEvents::Swap::SIGNATURE_HASH => { let swap_event = IUniswapV3PoolEvents::Swap::decode_log(log.as_ref())?; self.sqrt_price = swap_event.sqrtPriceX96.to(); self.liquidity = swap_event.liquidity; self.tick = swap_event.tick.unchecked_into(); info!( target = "amms::uniswap_v3::sync", address = ?self.address, sqrt_price = ?self.sqrt_price, liquidity = ?self.liquidity, tick = ?self.tick, "Swap" ); } IUniswapV3PoolEvents::Mint::SIGNATURE_HASH => { let mint_event = IUniswapV3PoolEvents::Mint::decode_log(log.as_ref())?; self.modify_position( mint_event.tickLower.unchecked_into(), mint_event.tickUpper.unchecked_into(), mint_event.amount as i128, )?; info!( target = "amms::uniswap_v3::sync", address = ?self.address, sqrt_price = ?self.sqrt_price, liquidity = ?self.liquidity, tick = ?self.tick, "Mint" ); } IUniswapV3PoolEvents::Burn::SIGNATURE_HASH => { let burn_event = IUniswapV3PoolEvents::Burn::decode_log(log.as_ref())?; self.modify_position( burn_event.tickLower.unchecked_into(), burn_event.tickUpper.unchecked_into(), -(burn_event.amount as i128), )?; info!( target = "amms::uniswap_v3::sync", address = ?self.address, sqrt_price = ?self.sqrt_price, liquidity = ?self.liquidity, tick = ?self.tick, "Burn" ); } _ => { return Err(AMMError::UnrecognizedEventSignature(event_signature)); } } Ok(()) } fn simulate_swap( &self, base_token: Address, _quote_token: Address, amount_in: U256, ) -> Result { if amount_in.is_zero() { return Ok(U256::ZERO); } let zero_for_one = base_token == self.token_a.address; // Set sqrt_price_limit_x_96 to the max or min sqrt price in the pool depending on zero_for_one let sqrt_price_limit_x_96 = if zero_for_one { MIN_SQRT_RATIO + U256_1 } else { MAX_SQRT_RATIO - U256_1 }; // Initialize a mutable state state struct to hold the dynamic simulated state of the pool let mut current_state = CurrentState { sqrt_price_x_96: self.sqrt_price, // Active price on the pool amount_calculated: I256::ZERO, // Amount of token_out that has been calculated amount_specified_remaining: I256::from_raw(amount_in), // Amount of token_in that has not been swapped tick: self.tick, // Current i24 tick of the pool liquidity: self.liquidity, // Current available liquidity in the tick range }; while current_state.amount_specified_remaining != I256::ZERO && current_state.sqrt_price_x_96 != sqrt_price_limit_x_96 { // Initialize a new step struct to hold the dynamic state of the pool at each step let mut step = StepComputations { // Set the sqrt_price_start_x_96 to the current sqrt_price_x_96 sqrt_price_start_x_96: current_state.sqrt_price_x_96, ..Default::default() }; // Get the next tick from the current tick (step.tick_next, step.initialized) = uniswap_v3_math::tick_bitmap::next_initialized_tick_within_one_word( &self.tick_bitmap, current_state.tick, self.tick_spacing, zero_for_one, ) .map_err(UniswapV3Error::from)?; // ensure that we do not overshoot the min/max tick, as the tick bitmap is not aware of these bounds // Note: this could be removed as we are clamping in the batch contract step.tick_next = step.tick_next.clamp(MIN_TICK, MAX_TICK); // Get the next sqrt price from the input amount step.sqrt_price_next_x96 = uniswap_v3_math::tick_math::get_sqrt_ratio_at_tick(step.tick_next) .map_err(UniswapV3Error::from)?; // Target spot price let swap_target_sqrt_ratio = if zero_for_one { if step.sqrt_price_next_x96 < sqrt_price_limit_x_96 { sqrt_price_limit_x_96 } else { step.sqrt_price_next_x96 } } else if step.sqrt_price_next_x96 > sqrt_price_limit_x_96 { sqrt_price_limit_x_96 } else { step.sqrt_price_next_x96 }; // Compute swap step and update the current state ( current_state.sqrt_price_x_96, step.amount_in, step.amount_out, step.fee_amount, ) = uniswap_v3_math::swap_math::compute_swap_step( current_state.sqrt_price_x_96, swap_target_sqrt_ratio, current_state.liquidity, current_state.amount_specified_remaining, self.fee, ) .map_err(UniswapV3Error::from)?; // Decrement the amount remaining to be swapped and amount received from the step current_state.amount_specified_remaining = current_state .amount_specified_remaining .overflowing_sub(I256::from_raw( step.amount_in.overflowing_add(step.fee_amount).0, )) .0; current_state.amount_calculated -= I256::from_raw(step.amount_out); // TODO: adjust for fee protocol // If the price moved all the way to the next price, recompute the liquidity change for the next iteration if current_state.sqrt_price_x_96 == step.sqrt_price_next_x96 { if step.initialized { let mut liquidity_net = if let Some(info) = self.ticks.get(&step.tick_next) { info.liquidity_net } else { 0 }; // we are on a tick boundary, and the next tick is initialized, so we must charge a protocol fee if zero_for_one { liquidity_net = -liquidity_net; } current_state.liquidity = if liquidity_net < 0 { if current_state.liquidity < (-liquidity_net as u128) { return Err(UniswapV3Error::LiquidityUnderflow.into()); } else { current_state.liquidity - (-liquidity_net as u128) } } else { current_state.liquidity + (liquidity_net as u128) }; } // Increment the current tick current_state.tick = if zero_for_one { step.tick_next.wrapping_sub(1) } else { step.tick_next } // If the current_state sqrt price is not equal to the step sqrt price, then we are not on the same tick. // Update the current_state.tick to the tick at the current_state.sqrt_price_x_96 } else if current_state.sqrt_price_x_96 != step.sqrt_price_start_x_96 { current_state.tick = uniswap_v3_math::tick_math::get_tick_at_sqrt_ratio( current_state.sqrt_price_x_96, ) .map_err(UniswapV3Error::from)?; } } let amount_out = (-current_state.amount_calculated).into_raw(); tracing::trace!(?amount_out); Ok(amount_out) } fn simulate_swap_mut( &mut self, base_token: Address, _quote_token: Address, amount_in: U256, ) -> Result { if amount_in.is_zero() { return Ok(U256::ZERO); } let zero_for_one = base_token == self.token_a.address; // Set sqrt_price_limit_x_96 to the max or min sqrt price in the pool depending on zero_for_one let sqrt_price_limit_x_96 = if zero_for_one { MIN_SQRT_RATIO + U256_1 } else { MAX_SQRT_RATIO - U256_1 }; // Initialize a mutable state state struct to hold the dynamic simulated state of the pool let mut current_state = CurrentState { // Active price on the pool sqrt_price_x_96: self.sqrt_price, // Amount of token_out that has been calculated amount_calculated: I256::ZERO, // Amount of token_in that has not been swapped amount_specified_remaining: I256::from_raw(amount_in), // Current i24 tick of the pool tick: self.tick, // Current available liquidity in the tick range liquidity: self.liquidity, }; while current_state.amount_specified_remaining != I256::ZERO && current_state.sqrt_price_x_96 != sqrt_price_limit_x_96 { // Initialize a new step struct to hold the dynamic state of the pool at each step let mut step = StepComputations { // Set the sqrt_price_start_x_96 to the current sqrt_price_x_96 sqrt_price_start_x_96: current_state.sqrt_price_x_96, ..Default::default() }; // Get the next tick from the current tick (step.tick_next, step.initialized) = uniswap_v3_math::tick_bitmap::next_initialized_tick_within_one_word( &self.tick_bitmap, current_state.tick, self.tick_spacing, zero_for_one, ) .map_err(UniswapV3Error::from)?; // ensure that we do not overshoot the min/max tick, as the tick bitmap is not aware of these bounds // Note: this could be removed as we are clamping in the batch contract step.tick_next = step.tick_next.clamp(MIN_TICK, MAX_TICK); // Get the next sqrt price from the input amount step.sqrt_price_next_x96 = uniswap_v3_math::tick_math::get_sqrt_ratio_at_tick(step.tick_next) .map_err(UniswapV3Error::from)?; // Target spot price let swap_target_sqrt_ratio = if zero_for_one { if step.sqrt_price_next_x96 < sqrt_price_limit_x_96 { sqrt_price_limit_x_96 } else { step.sqrt_price_next_x96 } } else if step.sqrt_price_next_x96 > sqrt_price_limit_x_96 { sqrt_price_limit_x_96 } else { step.sqrt_price_next_x96 }; // Compute swap step and update the current state ( current_state.sqrt_price_x_96, step.amount_in, step.amount_out, step.fee_amount, ) = uniswap_v3_math::swap_math::compute_swap_step( current_state.sqrt_price_x_96, swap_target_sqrt_ratio, current_state.liquidity, current_state.amount_specified_remaining, self.fee, ) .map_err(UniswapV3Error::from)?; // Decrement the amount remaining to be swapped and amount received from the step current_state.amount_specified_remaining = current_state .amount_specified_remaining .overflowing_sub(I256::from_raw( step.amount_in.overflowing_add(step.fee_amount).0, )) .0; current_state.amount_calculated -= I256::from_raw(step.amount_out); // If the price moved all the way to the next price, recompute the liquidity change for the next iteration if current_state.sqrt_price_x_96 == step.sqrt_price_next_x96 { if step.initialized { let mut liquidity_net = if let Some(info) = self.ticks.get(&step.tick_next) { info.liquidity_net } else { 0 }; // we are on a tick boundary, and the next tick is initialized, so we must charge a protocol fee if zero_for_one { liquidity_net = -liquidity_net; } current_state.liquidity = if liquidity_net < 0 { if current_state.liquidity < (-liquidity_net as u128) { return Err(AMMError::from(UniswapV3Error::LiquidityUnderflow)); } else { current_state.liquidity - (-liquidity_net as u128) } } else { current_state.liquidity + (liquidity_net as u128) }; } // Increment the current tick current_state.tick = if zero_for_one { step.tick_next.wrapping_sub(1) } else { step.tick_next } // If the current_state sqrt price is not equal to the step sqrt price, then we are not on the same tick. // Update the current_state.tick to the tick at the current_state.sqrt_price_x_96 } else if current_state.sqrt_price_x_96 != step.sqrt_price_start_x_96 { current_state.tick = uniswap_v3_math::tick_math::get_tick_at_sqrt_ratio( current_state.sqrt_price_x_96, ) .map_err(UniswapV3Error::from)?; } } // Update the pool state self.liquidity = current_state.liquidity; self.sqrt_price = current_state.sqrt_price_x_96; self.tick = current_state.tick; let amount_out = (-current_state.amount_calculated).into_raw(); tracing::trace!(?amount_out); Ok(amount_out) } fn tokens(&self) -> Vec
{ vec![self.token_a.address, self.token_b.address] } fn calculate_price(&self, base_token: Address, _quote_token: Address) -> Result { let tick = uniswap_v3_math::tick_math::get_tick_at_sqrt_ratio(self.sqrt_price) .map_err(UniswapV3Error::from)?; let shift = self.token_a.decimals as i8 - self.token_b.decimals as i8; let price = match shift.cmp(&0) { Ordering::Less => 1.0001_f64.powi(tick) / 10_f64.powi(-shift as i32), Ordering::Greater => 1.0001_f64.powi(tick) * 10_f64.powi(shift as i32), Ordering::Equal => 1.0001_f64.powi(tick), }; if base_token == self.token_a.address { Ok(price) } else { Ok(1.0 / price) } } async fn init(mut self, block_number: BlockId, provider: P) -> Result where N: Network, P: Provider + Clone, { let pool = IUniswapV3Pool::new(self.address, provider.clone()); // Get pool data self.tick_spacing = pool.tickSpacing().call().await?.as_i32(); self.fee = pool.fee().call().await?.to::(); // Get tokens self.token_a = Token::new(pool.token0().call().await?, provider.clone()).await?; self.token_b = Token::new(pool.token1().call().await?, provider.clone()).await?; let mut pool = vec![self.into()]; UniswapV3Factory::sync_slot_0(&mut pool, block_number, provider.clone()).await?; UniswapV3Factory::sync_token_decimals(&mut pool, provider.clone()).await?; UniswapV3Factory::sync_tick_bitmaps(&mut pool, block_number, provider.clone()).await?; UniswapV3Factory::sync_tick_data(&mut pool, block_number, provider.clone()).await?; let AMM::UniswapV3Pool(pool) = pool[0].to_owned() else { unreachable!() }; Ok(pool) } } impl UniswapV3Pool { // Create a new, unsynced UniswapV3 pool pub fn new(address: Address) -> Self { Self { address, ..Default::default() } } /// Modifies a positions liquidity in the pool. pub fn modify_position( &mut self, tick_lower: i32, tick_upper: i32, liquidity_delta: i128, ) -> Result<(), AMMError> { //We are only using this function when a mint or burn event is emitted, //therefore we do not need to checkTicks as that has happened before the event is emitted self.update_position(tick_lower, tick_upper, liquidity_delta)?; if liquidity_delta != 0 { //if the tick is between the tick lower and tick upper, update the liquidity between the ticks if self.tick >= tick_lower && self.tick < tick_upper { self.liquidity = if liquidity_delta < 0 { self.liquidity - ((-liquidity_delta) as u128) } else { self.liquidity + (liquidity_delta as u128) } } } Ok(()) } pub fn update_position( &mut self, tick_lower: i32, tick_upper: i32, liquidity_delta: i128, ) -> Result<(), AMMError> { let mut flipped_lower = false; let mut flipped_upper = false; if liquidity_delta != 0 { flipped_lower = self.update_tick(tick_lower, liquidity_delta, false)?; flipped_upper = self.update_tick(tick_upper, liquidity_delta, true)?; if flipped_lower { self.flip_tick(tick_lower, self.tick_spacing); } if flipped_upper { self.flip_tick(tick_upper, self.tick_spacing); } } if liquidity_delta < 0 { if flipped_lower { self.ticks.remove(&tick_lower); } if flipped_upper { self.ticks.remove(&tick_upper); } } Ok(()) } pub fn update_tick( &mut self, tick: i32, liquidity_delta: i128, upper: bool, ) -> Result { let info = self.ticks.entry(tick).or_default(); let liquidity_gross_before = info.liquidity_gross; let liquidity_gross_after = if liquidity_delta < 0 { liquidity_gross_before - ((-liquidity_delta) as u128) } else { liquidity_gross_before + (liquidity_delta as u128) }; // we do not need to check if liqudity_gross_after > maxLiquidity because we are only calling update tick on a burn or mint log. // this should already be validated when a log is let flipped = (liquidity_gross_after == 0) != (liquidity_gross_before == 0); if liquidity_gross_before == 0 { info.initialized = true; } info.liquidity_gross = liquidity_gross_after; info.liquidity_net = if upper { info.liquidity_net - liquidity_delta } else { info.liquidity_net + liquidity_delta }; Ok(flipped) } pub fn flip_tick(&mut self, tick: i32, tick_spacing: i32) { let (word_pos, bit_pos) = uniswap_v3_math::tick_bitmap::position(tick / tick_spacing); let mask = U256::from(1) << bit_pos; if let Some(word) = self.tick_bitmap.get_mut(&word_pos) { *word ^= mask; } else { self.tick_bitmap.insert(word_pos, mask); } } pub fn swap_calldata( &self, recipient: Address, zero_for_one: bool, amount_specified: I256, sqrt_price_limit_x_96: U256, calldata: Vec, ) -> Result { Ok(IUniswapV3Pool::swapCall { recipient, zeroForOne: zero_for_one, amountSpecified: amount_specified, sqrtPriceLimitX96: sqrt_price_limit_x_96.to(), data: calldata.into(), } .abi_encode() .into()) } } #[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)] pub struct UniswapV3Factory { pub address: Address, pub creation_block: u64, } impl UniswapV3Factory { pub fn new(address: Address, creation_block: u64) -> Self { UniswapV3Factory { address, creation_block, } } pub async fn get_all_pools( &self, block_number: BlockId, provider: P, ) -> Result, AMMError> where N: Network, P: Provider + Clone, { let disc_filter = Filter::new() .event_signature(FilterSet::from(vec![self.pool_creation_event()])) .address(vec![self.address()]); let sync_provider = provider.clone(); let mut futures = FuturesUnordered::new(); let sync_step = 100_000; let mut latest_block = self.creation_block; while latest_block < block_number.as_u64().unwrap_or_default() { let mut block_filter = disc_filter.clone(); let from_block = latest_block; let to_block = (from_block + sync_step).min(block_number.as_u64().unwrap_or_default()); block_filter = block_filter.from_block(from_block); block_filter = block_filter.to_block(to_block); let sync_provider = sync_provider.clone(); futures.push(async move { sync_provider.get_logs(&block_filter).await }); latest_block = to_block + 1; } let mut pools = vec![]; while let Some(res) = futures.next().await { let logs = res?; for log in logs { pools.push(self.create_pool(log)?); } } Ok(pools) } pub async fn sync_all_pools( mut pools: Vec, block_number: BlockId, provider: P, ) -> Result, AMMError> where N: Network, P: Provider + Clone, { UniswapV3Factory::sync_slot_0(&mut pools, block_number, provider.clone()).await?; UniswapV3Factory::sync_token_decimals(&mut pools, provider.clone()).await?; pools = pools .par_drain(..) .filter(|pool| match pool { AMM::UniswapV3Pool(uv3_pool) => { uv3_pool.liquidity > 0 && uv3_pool.token_a.decimals > 0 && uv3_pool.token_b.decimals > 0 } _ => true, }) .collect(); UniswapV3Factory::sync_tick_bitmaps(&mut pools, block_number, provider.clone()).await?; UniswapV3Factory::sync_tick_data(&mut pools, block_number, provider.clone()).await?; Ok(pools) } async fn sync_token_decimals( pools: &mut [AMM], provider: P, ) -> Result<(), BatchContractError> where N: Network, P: Provider + Clone, { // Get all token decimals let mut tokens = HashSet::new(); for pool in pools.iter() { for token in pool.tokens() { tokens.insert(token); } } let token_decimals = get_token_decimals(tokens.into_iter().collect(), provider).await?; // Set token decimals for pool in pools.iter_mut() { let AMM::UniswapV3Pool(uniswap_v3_pool) = pool else { unreachable!() }; if let Some(decimals) = token_decimals.get(&uniswap_v3_pool.token_a.address) { uniswap_v3_pool.token_a.decimals = *decimals; } if let Some(decimals) = token_decimals.get(&uniswap_v3_pool.token_b.address) { uniswap_v3_pool.token_b.decimals = *decimals; } } Ok(()) } async fn sync_slot_0( pools: &mut [AMM], block_number: BlockId, provider: P, ) -> Result<(), AMMError> where N: Network, P: Provider + Clone, { let step = 255; let mut futures = FuturesUnordered::new(); pools.chunks_mut(step).for_each(|group| { let provider = provider.clone(); let pool_addresses = group .iter_mut() .map(|pool| pool.address()) .collect::>(); futures.push(async move { Ok::<(&mut [AMM], Bytes), AMMError>(( group, GetUniswapV3PoolSlot0BatchRequest::deploy_builder(provider, pool_addresses) .call_raw() .block(block_number) .await?, )) }); }); while let Some(res) = futures.next().await { let (pools, return_data) = res?; let return_data = as SolValue>::abi_decode(&return_data)?; for (slot_0_data, pool) in return_data.iter().zip(pools.iter_mut()) { let AMM::UniswapV3Pool(ref mut uv3_pool) = pool else { unreachable!() }; uv3_pool.tick = slot_0_data.0; uv3_pool.liquidity = slot_0_data.1; uv3_pool.sqrt_price = slot_0_data.2; } } Ok(()) } async fn sync_tick_bitmaps( pools: &mut [AMM], block_number: BlockId, provider: P, ) -> Result<(), AMMError> where N: Network, P: Provider + Clone, { let mut futures: FuturesUnordered> = FuturesUnordered::new(); let max_range = 6900; let mut group_range = 0; let mut group = vec![]; for pool in pools.iter() { let AMM::UniswapV3Pool(uniswap_v3_pool) = pool else { unreachable!() }; let mut min_word = tick_to_word(MIN_TICK, uniswap_v3_pool.tick_spacing); let max_word = tick_to_word(MAX_TICK, uniswap_v3_pool.tick_spacing); let mut word_range = max_word - min_word; while word_range > 0 { let remaining_range = max_range - group_range; let range = word_range.min(remaining_range); group.push(TickBitmapInfo { pool: uniswap_v3_pool.address, minWord: min_word as i16, maxWord: (min_word + range) as i16, }); word_range -= range; min_word += range - 1; group_range += range; // If group is full, fire it off and reset if group_range >= max_range { // if group_range >= max_range || word_range <= 0 { let provider = provider.clone(); let pool_info = group.iter().map(|info| info.pool).collect::>(); let calldata = std::mem::take(&mut group); group_range = 0; futures.push(Box::pin(async move { Ok::<(Vec
, Bytes), AMMError>(( pool_info, GetUniswapV3PoolTickBitmapBatchRequest::deploy_builder( provider, calldata, ) .call_raw() .block(block_number) .await?, )) })); } } } // Flush group if not empty if !group.is_empty() { let provider = provider.clone(); let pool_info = group.iter().map(|info| info.pool).collect::>(); let calldata = std::mem::take(&mut group); futures.push(Box::pin(async move { Ok::<(Vec
, Bytes), AMMError>(( pool_info, GetUniswapV3PoolTickBitmapBatchRequest::deploy_builder(provider, calldata) .call_raw() .block(block_number) .await?, )) })); } let mut pool_set = pools .iter_mut() .map(|pool| (pool.address(), pool)) .collect::>(); while let Some(res) = futures.next().await { let (pools, return_data) = res?; let return_data = > as SolValue>::abi_decode(&return_data)?; for (tick_bitmaps, pool_address) in return_data.iter().zip(pools.iter()) { let pool = pool_set.get_mut(pool_address).unwrap(); let AMM::UniswapV3Pool(ref mut uv3_pool) = pool else { unreachable!() }; for chunk in tick_bitmaps.chunks_exact(2) { let word_pos = I256::from_raw(chunk[0]).as_i16(); let tick_bitmap = chunk[1]; uv3_pool.tick_bitmap.insert(word_pos, tick_bitmap); } } } Ok(()) } // TODO: Clean this function up async fn sync_tick_data( pools: &mut [AMM], block_number: BlockId, provider: P, ) -> Result<(), AMMError> where N: Network, P: Provider + Clone, { let pool_ticks = pools .par_iter() .filter_map(|pool| { if let AMM::UniswapV3Pool(uniswap_v3_pool) = pool { let min_word = tick_to_word(MIN_TICK, uniswap_v3_pool.tick_spacing); let max_word = tick_to_word(MAX_TICK, uniswap_v3_pool.tick_spacing); let initialized_ticks: Vec> = (min_word..=max_word) // Filter out empty bitmaps .filter_map(|word_pos| { uniswap_v3_pool .tick_bitmap .get(&(word_pos as i16)) .filter(|&bitmap| *bitmap != U256::ZERO) .map(|&bitmap| (word_pos, bitmap)) }) // Get tick index for non zero bitmaps .flat_map(|(word_pos, bitmap)| { (0..256) .filter(move |i| { (bitmap & (U256::from(1) << U256::from(*i))) != U256::ZERO }) .map(move |i| { let tick_index = (word_pos * 256 + i) * uniswap_v3_pool.tick_spacing; // TODO: update to use from be bytes or similar Signed::<24, 1>::from_str(&tick_index.to_string()).unwrap() }) }) .collect(); // Only return pools with non-empty initialized ticks if !initialized_ticks.is_empty() { Some((uniswap_v3_pool.address, initialized_ticks)) } else { None } } else { None } }) .collect::>)>>(); let mut futures: FuturesUnordered> = FuturesUnordered::new(); let max_ticks = 60; let mut group_ticks = 0; let mut group = vec![]; for (pool_address, mut ticks) in pool_ticks { while !ticks.is_empty() { let remaining_ticks = max_ticks - group_ticks; let selected_ticks = ticks.drain(0..remaining_ticks.min(ticks.len())); group_ticks += selected_ticks.len(); group.push(GetUniswapV3PoolTickDataBatchRequest::TickDataInfo { pool: pool_address, ticks: selected_ticks.collect(), }); if group_ticks >= max_ticks { let provider = provider.clone(); let calldata = std::mem::take(&mut group); group_ticks = 0; group.clear(); futures.push(Box::pin(async move { Ok::<(Vec, Bytes), AMMError>(( calldata.clone(), GetUniswapV3PoolTickDataBatchRequest::deploy_builder( provider, calldata, ) .call_raw() .block(block_number) .await?, )) })); } } } if !group.is_empty() { let provider = provider.clone(); let calldata = std::mem::take(&mut group); futures.push(Box::pin(async move { Ok::<(Vec, Bytes), AMMError>(( calldata.clone(), GetUniswapV3PoolTickDataBatchRequest::deploy_builder(provider, calldata) .call_raw() .block(block_number) .await?, )) })); } let mut pool_set = pools .iter_mut() .map(|pool| (pool.address(), pool)) .collect::>(); while let Some(res) = futures.next().await { let (tick_info, return_data) = res?; let return_data = > as SolValue>::abi_decode(&return_data)?; for (tick_bitmaps, tick_info) in return_data.iter().zip(tick_info.iter()) { let pool = pool_set.get_mut(&tick_info.pool).unwrap(); let AMM::UniswapV3Pool(ref mut uv3_pool) = pool else { unreachable!() }; for (tick, tick_idx) in tick_bitmaps.iter().zip(tick_info.ticks.iter()) { let info = Info { liquidity_gross: tick.1, liquidity_net: tick.2, initialized: tick.0, }; uv3_pool.ticks.insert(tick_idx.as_i32(), info); } } } Ok(()) } } fn tick_to_word(tick: i32, tick_spacing: i32) -> i32 { let mut compressed = tick / tick_spacing; if tick < 0 && tick % tick_spacing != 0 { compressed -= 1; } compressed >> 8 } impl AutomatedMarketMakerFactory for UniswapV3Factory { type PoolVariant = UniswapV3Pool; fn address(&self) -> Address { self.address } fn pool_creation_event(&self) -> B256 { IUniswapV3Factory::PoolCreated::SIGNATURE_HASH } fn create_pool(&self, log: Log) -> Result { let pool_created_event: alloy::primitives::Log = IUniswapV3Factory::PoolCreated::decode_log(&log.inner)?; Ok(AMM::UniswapV3Pool(UniswapV3Pool { address: pool_created_event.pool, token_a: pool_created_event.token0.into(), token_b: pool_created_event.token1.into(), fee: pool_created_event.fee.to::(), tick_spacing: pool_created_event.tickSpacing.unchecked_into(), ..Default::default() })) } fn creation_block(&self) -> u64 { self.creation_block } } impl DiscoverySync for UniswapV3Factory { fn discover( &self, to_block: BlockId, provider: P, ) -> impl Future, AMMError>> where N: Network, P: Provider + Clone, { info!( target = "amms::uniswap_v3::discover", address = ?self.address, "Discovering all pools" ); self.get_all_pools(to_block, provider.clone()) } fn sync( &self, amms: Vec, to_block: BlockId, provider: P, ) -> impl Future, AMMError>> where N: Network, P: Provider + Clone, { info!( target = "amms::uniswap_v3::sync", address = ?self.address, "Syncing all pools" ); UniswapV3Factory::sync_all_pools(amms, to_block, provider) } } #[cfg(test)] mod test { use super::*; use alloy::{ primitives::{address, aliases::U24, U160, U256}, providers::ProviderBuilder, rpc::client::ClientBuilder, transports::layers::{RetryBackoffLayer, ThrottleLayer}, }; sol! { /// Interface of the Quoter #[derive(Debug, PartialEq, Eq)] #[sol(rpc)] contract IQuoter { function quoteExactInputSingle(address tokenIn, address tokenOut,uint24 fee, uint256 amountIn, uint160 sqrtPriceLimitX96) external returns (uint256 amountOut); } } #[tokio::test] async fn test_simulate_swap_usdc_weth() -> eyre::Result<()> { let rpc_endpoint = std::env::var("ETHEREUM_PROVIDER")?; let client = ClientBuilder::default() .layer(ThrottleLayer::new(250)) .layer(RetryBackoffLayer::new(5, 200, 330)) .http(rpc_endpoint.parse()?); let provider = ProviderBuilder::new().connect_client(client); let pool = UniswapV3Pool::new(address!("88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640")) .init(BlockId::latest(), provider.clone()) .await?; let quoter = IQuoter::new( address!("b27308f9f90d607463bb33ea1bebb41c27ce5ab6"), provider.clone(), ); // Test swap from USDC to WETH let amount_in = U256::from(100000000); // 100 USDC let amount_out = pool.simulate_swap(pool.token_a.address, Address::default(), amount_in)?; dbg!(pool.token_a.address); dbg!(pool.token_b.address); dbg!(amount_in); dbg!(amount_out); dbg!(pool.fee); let expected_amount_out = quoter .quoteExactInputSingle( pool.token_a.address, pool.token_b.address, U24::from(pool.fee), amount_in, U160::ZERO, ) .block(BlockId::latest()) .call() .await?; assert_eq!(amount_out, expected_amount_out); let amount_in_1 = U256::from(10000000000_u64); // 10_000 USDC let amount_out_1 = pool.simulate_swap(pool.token_a.address, Address::default(), amount_in_1)?; let expected_amount_out_1 = quoter .quoteExactInputSingle( pool.token_a.address, pool.token_b.address, U24::from(pool.fee), amount_in_1, U160::ZERO, ) .block(BlockId::latest()) .call() .await?; assert_eq!(amount_out_1, expected_amount_out_1); let amount_in_2 = U256::from(10000000000000_u128); // 10_000_000 USDC let amount_out_2 = pool.simulate_swap(pool.token_a.address, Address::default(), amount_in_2)?; let expected_amount_out_2 = quoter .quoteExactInputSingle( pool.token_a.address, pool.token_b.address, U24::from(pool.fee), amount_in_2, U160::ZERO, ) .block(BlockId::latest()) .call() .await?; assert_eq!(amount_out_2, expected_amount_out_2); let amount_in_3 = U256::from(100000000000000_u128); // 100_000_000 USDC let amount_out_3 = pool.simulate_swap(pool.token_a.address, Address::default(), amount_in_3)?; let expected_amount_out_3 = quoter .quoteExactInputSingle( pool.token_a.address, pool.token_b.address, U24::from(pool.fee), amount_in_3, U160::ZERO, ) .block(BlockId::latest()) .call() .await?; assert_eq!(amount_out_3, expected_amount_out_3); // Test swap from WETH to USDC let amount_in = U256::from(1000000000000000000_u128); // 1 ETH let amount_out = pool.simulate_swap(pool.token_b.address, Address::default(), amount_in)?; let expected_amount_out = quoter .quoteExactInputSingle( pool.token_b.address, pool.token_a.address, U24::from(pool.fee), amount_in, U160::ZERO, ) .block(BlockId::latest()) .call() .await?; assert_eq!(amount_out, expected_amount_out); let amount_in_1 = U256::from(10000000000000000000_u128); // 10 ETH let amount_out_1 = pool.simulate_swap(pool.token_b.address, Address::default(), amount_in_1)?; let expected_amount_out_1 = quoter .quoteExactInputSingle( pool.token_b.address, pool.token_a.address, U24::from(pool.fee), amount_in_1, U160::ZERO, ) .block(BlockId::latest()) .call() .await?; assert_eq!(amount_out_1, expected_amount_out_1); let amount_in_2 = U256::from(100000000000000000000_u128); // 100 ETH let amount_out_2 = pool.simulate_swap(pool.token_b.address, Address::default(), amount_in_2)?; let expected_amount_out_2 = quoter .quoteExactInputSingle( pool.token_b.address, pool.token_a.address, U24::from(pool.fee), amount_in_2, U160::ZERO, ) .block(BlockId::latest()) .call() .await?; assert_eq!(amount_out_2, expected_amount_out_2); let amount_in_3 = U256::from(100000000000000000000_u128); // 100_000 ETH let amount_out_3 = pool.simulate_swap(pool.token_b.address, Address::default(), amount_in_3)?; let expected_amount_out_3 = quoter .quoteExactInputSingle( pool.token_b.address, pool.token_a.address, U24::from(pool.fee), amount_in_3, U160::ZERO, ) .block(BlockId::latest()) .call() .await?; assert_eq!(amount_out_3, expected_amount_out_3); Ok(()) } #[tokio::test] async fn test_simulate_swap_link_weth() -> eyre::Result<()> { let rpc_endpoint = std::env::var("ETHEREUM_PROVIDER")?; let client = ClientBuilder::default() .layer(ThrottleLayer::new(250)) .layer(RetryBackoffLayer::new(5, 200, 330)) .http(rpc_endpoint.parse()?); let provider = ProviderBuilder::new().connect_client(client); let current_block = BlockId::from(provider.get_block_number().await?); let pool = UniswapV3Pool::new(address!("5d4F3C6fA16908609BAC31Ff148Bd002AA6b8c83")) .init(current_block, provider.clone()) .await?; let quoter = IQuoter::new( address!("b27308f9f90d607463bb33ea1bebb41c27ce5ab6"), provider.clone(), ); // Test swap LINK to WETH let amount_in = U256::from(1000000000000000000_u128); // 1 LINK let amount_out = pool.simulate_swap(pool.token_a.address, Address::default(), amount_in)?; let expected_amount_out = quoter .quoteExactInputSingle( pool.token_a.address, pool.token_b.address, U24::from(pool.fee), amount_in, U160::ZERO, ) .block(current_block) .call() .await?; assert_eq!(amount_out, expected_amount_out); let amount_in_1 = U256::from(100000000000000000000_u128); // 100 LINK let amount_out_1 = pool .simulate_swap(pool.token_a.address, Address::default(), amount_in_1) .unwrap(); let expected_amount_out_1 = quoter .quoteExactInputSingle( pool.token_a.address, pool.token_b.address, U24::from(pool.fee), amount_in_1, U160::ZERO, ) .block(current_block) .call() .await?; assert_eq!(amount_out_1, expected_amount_out_1); let amount_in_2 = U256::from(10000000000000000000000_u128); // 10_000 LINK let amount_out_2 = pool .simulate_swap(pool.token_a.address, Address::default(), amount_in_2) .unwrap(); let expected_amount_out_2 = quoter .quoteExactInputSingle( pool.token_a.address, pool.token_b.address, U24::from(pool.fee), amount_in_2, U160::ZERO, ) .block(current_block) .call() .await?; assert_eq!(amount_out_2, expected_amount_out_2); let amount_in_3 = U256::from(10000000000000000000000_u128); // 1_000_000 LINK let amount_out_3 = pool .simulate_swap(pool.token_a.address, Address::default(), amount_in_3) .unwrap(); let expected_amount_out_3 = quoter .quoteExactInputSingle( pool.token_a.address, pool.token_b.address, U24::from(pool.fee), amount_in_3, U160::ZERO, ) .block(current_block) .call() .await?; assert_eq!(amount_out_3, expected_amount_out_3); // Test swap WETH to LINK let amount_in = U256::from(1000000000000000000_u128); // 1 ETH let amount_out = pool.simulate_swap(pool.token_b.address, Address::default(), amount_in)?; let expected_amount_out = quoter .quoteExactInputSingle( pool.token_b.address, pool.token_a.address, U24::from(pool.fee), amount_in, U160::ZERO, ) .block(current_block) .call() .await?; assert_eq!(amount_out, expected_amount_out); let amount_in_1 = U256::from(10000000000000000000_u128); // 10 ETH let amount_out_1 = pool.simulate_swap(pool.token_b.address, Address::default(), amount_in_1)?; let expected_amount_out_1 = quoter .quoteExactInputSingle( pool.token_b.address, pool.token_a.address, U24::from(pool.fee), amount_in_1, U160::ZERO, ) .block(current_block) .call() .await?; assert_eq!(amount_out_1, expected_amount_out_1); let amount_in_2 = U256::from(100000000000000000000_u128); // 100 ETH let amount_out_2 = pool.simulate_swap(pool.token_b.address, Address::default(), amount_in_2)?; let expected_amount_out_2 = quoter .quoteExactInputSingle( pool.token_b.address, pool.token_a.address, U24::from(pool.fee), amount_in_2, U160::ZERO, ) .block(current_block) .call() .await?; assert_eq!(amount_out_2, expected_amount_out_2); let amount_in_3 = U256::from(100000000000000000000_u128); // 100_000 ETH let amount_out_3 = pool.simulate_swap(pool.token_b.address, Address::default(), amount_in_3)?; let expected_amount_out_3 = quoter .quoteExactInputSingle( pool.token_b.address, pool.token_a.address, U24::from(pool.fee), amount_in_3, U160::ZERO, ) .block(current_block) .call() .await?; assert_eq!(amount_out_3, expected_amount_out_3); Ok(()) } #[tokio::test] async fn test_calculate_price() -> eyre::Result<()> { let rpc_endpoint = std::env::var("ETHEREUM_PROVIDER")?; let client = ClientBuilder::default() .layer(ThrottleLayer::new(250)) .layer(RetryBackoffLayer::new(5, 200, 330)) .http(rpc_endpoint.parse()?); let provider = ProviderBuilder::new().connect_client(client); let block_number = BlockId::from(22000114); let pool = UniswapV3Pool::new(address!("88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640")) .init(block_number, provider.clone()) .await?; let float_price_a = pool.calculate_price(pool.token_a.address, Address::default())?; let float_price_b = pool.calculate_price(pool.token_b.address, Address::default())?; assert_eq!(float_price_a, 0.00046777681145863687); assert_eq!(float_price_b, 2137.7716370372605); Ok(()) } } ================================================ FILE: src/lib.rs ================================================ #![cfg_attr(not(test), warn(unused_crate_dependencies))] pub mod amms; pub mod state_space; ================================================ FILE: src/state_space/cache.rs ================================================ use std::collections::HashMap; use crate::amms::amm::{AutomatedMarketMaker, AMM}; use arraydeque::ArrayDeque; #[derive(Debug)] pub struct StateChangeCache { oldest_block: u64, cache: ArrayDeque, } impl Default for StateChangeCache { fn default() -> Self { Self::new() } } impl StateChangeCache { pub fn new() -> Self { StateChangeCache { oldest_block: 0, cache: ArrayDeque::new(), } } pub fn is_empty(&self) -> bool { self.cache.is_empty() } pub fn push(&mut self, state_change: StateChange) { let cache = &mut self.cache; if cache.is_full() { cache.pop_back(); self.oldest_block = cache.back().unwrap().block_number; } // We can unwrap here since we check if the cache is full cache.push_front(state_change).unwrap(); } /// Unwinds the state changes up to the given block number /// Returns the state of the affected AMMs at the block number provided pub fn unwind_state_changes(&mut self, block_to_unwind: u64) -> Vec { let cache = &mut self.cache; if block_to_unwind < self.oldest_block { panic!("Block to unwind < oldest block in cache"); } // If the block to unwind is greater than the latest state change in the block, exit early if cache .front() .is_none_or(|latest| block_to_unwind > latest.block_number) { return vec![]; } let pivot_idx = cache .iter() .position(|state_change| state_change.block_number < block_to_unwind); let state_changes = if let Some(pivot_idx) = pivot_idx { cache.drain(..pivot_idx).collect() } else { cache.drain(..).collect::>() }; self.flatten_state_changes(state_changes) } fn flatten_state_changes(&self, state_changes: Vec) -> Vec { state_changes .into_iter() .rev() .fold(HashMap::new(), |mut amms, state_change| { for amm in state_change.state_change { amms.entry(amm.address()).or_insert(amm); } amms }) .into_values() .collect() } } // NOTE: we can probably make this more efficient and create a state change struct for each amm rather than // cloning each amm when caching #[derive(Debug, Clone)] pub struct StateChange { pub state_change: Vec, pub block_number: u64, } impl StateChange { pub fn new(state_change: Vec, block_number: u64) -> Self { Self { block_number, state_change, } } } // TODO: add tests ================================================ FILE: src/state_space/discovery.rs ================================================ use std::collections::{HashMap, HashSet}; use alloy::primitives::{Address, FixedBytes}; use crate::amms::factory::Factory; use super::filters::PoolFilter; #[derive(Debug, Default, Clone)] pub struct DiscoveryManager { pub factories: HashMap, pub pool_filters: Option>, pub token_decimals: HashMap, } impl DiscoveryManager { pub fn new(factories: Vec) -> Self { let factories = factories .into_iter() .map(|factory| { let address = factory.address(); (address, factory) }) .collect(); Self { factories, ..Default::default() } } pub fn with_pool_filters(self, pool_filters: Vec) -> Self { Self { pool_filters: Some(pool_filters), ..self } } pub fn disc_events(&self) -> HashSet> { self.factories .iter() .fold(HashSet::new(), |mut events_set, (_, factory)| { events_set.extend([factory.discovery_event()]); events_set }) } } ================================================ FILE: src/state_space/error.rs ================================================ use alloy::transports::TransportErrorKind; use thiserror::Error; use crate::amms::error::AMMError; #[derive(Error, Debug)] pub enum StateSpaceError { #[error(transparent)] AMMError(#[from] AMMError), #[error(transparent)] TransportError(#[from] alloy::transports::RpcError), #[error(transparent)] JoinError(#[from] tokio::task::JoinError), #[error("Block Number Does not Exist")] MissingBlockNumber, } ================================================ FILE: src/state_space/filters/blacklist.rs ================================================ use alloy::primitives::Address; use async_trait::async_trait; use crate::amms::{ amm::{AutomatedMarketMaker, AMM}, error::AMMError, }; use super::{AMMFilter, FilterStage}; #[derive(Debug, Clone)] pub struct BlacklistFilter { /// A blacklist of addresses to exclusively disallow blacklist: Vec
, } impl BlacklistFilter { pub fn new(blacklist: Vec
) -> Self { Self { blacklist } } } #[async_trait] impl AMMFilter for BlacklistFilter { /// Filter for any AMMs or tokens not in the blacklist async fn filter(&self, amms: Vec) -> Result, AMMError> { Ok(amms .into_iter() .filter(|amm| { !self.blacklist.contains(&amm.address()) && amm.tokens().iter().all(|t| !self.blacklist.contains(t)) }) .collect()) } /// Filter stage is set to after the sync stage to ensure the blacklist is applied to all /// pool and token addresses after the pools have been fully populated fn stage(&self) -> FilterStage { FilterStage::Sync } } ================================================ FILE: src/state_space/filters/mod.rs ================================================ pub mod blacklist; pub mod value; pub mod whitelist; use async_trait::async_trait; use blacklist::BlacklistFilter; use whitelist::{PoolWhitelistFilter, TokenWhitelistFilter}; use crate::amms::{amm::AMM, error::AMMError}; #[async_trait] pub trait AMMFilter { async fn filter(&self, amms: Vec) -> Result, AMMError>; fn stage(&self) -> FilterStage; } #[derive(Debug, Clone, PartialEq, Eq)] pub enum FilterStage { Discovery, Sync, } macro_rules! filter { ($($filter_type:ident),+ $(,)?) => { #[derive(Debug, Clone)] pub enum PoolFilter { $($filter_type($filter_type),)+ } #[async_trait] impl AMMFilter for PoolFilter { async fn filter(&self, amms: Vec) -> Result, AMMError> { match self { $(PoolFilter::$filter_type(filter) => filter.filter(amms).await,)+ } } fn stage(&self) -> FilterStage { match self { $(PoolFilter::$filter_type(filter) => filter.stage(),)+ } } } $( impl From<$filter_type> for PoolFilter { fn from(filter: $filter_type) -> Self { PoolFilter::$filter_type(filter) } } )+ }; } filter!( BlacklistFilter, PoolWhitelistFilter, TokenWhitelistFilter, // ValueFilter ); ================================================ FILE: src/state_space/filters/value.rs ================================================ use std::{collections::HashMap, marker::PhantomData}; use super::{AMMFilter, FilterStage}; use crate::amms::{ amm::{AutomatedMarketMaker, AMM}, error::AMMError, }; use alloy::{ network::Network, primitives::{Address, U256}, providers::Provider, sol, sol_types::SolValue, }; use async_trait::async_trait; use WethValueInPools::{PoolInfo, PoolInfoReturn}; sol! { #[sol(rpc)] WethValueInPoolsBatchRequest, "src/amms/abi/WethValueInPoolsBatchRequest.json" } pub struct ValueFilter where N: Network, P: Provider + Clone, { pub uniswap_v2_factory: Address, pub uniswap_v3_factory: Address, pub weth: Address, pub min_weth_threshold: U256, pub provider: P, phantom: PhantomData, } impl ValueFilter where N: Network, P: Provider + Clone, { pub fn new( uniswap_v2_factory: Address, uniswap_v3_factory: Address, weth: Address, min_weth_threshold: U256, provider: P, ) -> Self { Self { uniswap_v2_factory, uniswap_v3_factory, weth, min_weth_threshold, provider, phantom: PhantomData, } } pub async fn get_weth_value_in_pools( &self, pools: Vec, ) -> Result, AMMError> { let deployer = WethValueInPoolsBatchRequest::deploy_builder( self.provider.clone(), self.uniswap_v2_factory, self.uniswap_v3_factory, self.weth, pools, ); let res = deployer.call_raw().await?; let return_data = as SolValue>::abi_decode(&res)?; Ok(return_data .into_iter() .map(|pool_info| (pool_info.poolAddress, pool_info)) .collect()) } } #[async_trait] impl AMMFilter for ValueFilter where N: Network, P: Provider + Clone, { async fn filter(&self, amms: Vec) -> Result, AMMError> { let pool_infos = amms .iter() .cloned() .map(|amm| { let pool_address = amm.address(); let pool_type = match amm { AMM::BalancerPool(_) => 0, AMM::UniswapV2Pool(_) => 1, AMM::UniswapV3Pool(_) => 2, // TODO: At the moment, filters are not compatible with vaults AMM::ERC4626Vault(_) => todo!(), }; PoolInfo { poolType: pool_type, poolAddress: pool_address, } }) .collect::>(); let mut pool_info_returns = HashMap::new(); let futs = pool_infos .chunks(CHUNK_SIZE) .map(|chunk| async { self.get_weth_value_in_pools(chunk.to_vec()).await }) .collect::>(); let results = futures::future::join_all(futs).await; for result in results { pool_info_returns.extend(result?); } let filtered_amms = amms .into_iter() .filter(|amm| { let pool_address = amm.address(); pool_info_returns .get(&pool_address) .is_some_and(|pool_info_return| { pool_info_return.wethValue > self.min_weth_threshold }) }) .collect::>(); Ok(filtered_amms) } fn stage(&self) -> FilterStage { FilterStage::Sync } } ================================================ FILE: src/state_space/filters/whitelist.rs ================================================ use alloy::primitives::Address; use async_trait::async_trait; use crate::amms::{ amm::{AutomatedMarketMaker, AMM}, error::AMMError, }; use super::{AMMFilter, FilterStage}; #[derive(Debug, Clone)] pub struct PoolWhitelistFilter { pools: Vec
, } impl PoolWhitelistFilter { pub fn new(pools: Vec
) -> Self { Self { pools } } } #[async_trait] impl AMMFilter for PoolWhitelistFilter { /// Filter for any AMMs or tokens in the whitelist async fn filter(&self, amms: Vec) -> Result, AMMError> { Ok(amms .into_iter() .filter(|amm| self.pools.contains(&amm.address())) .collect()) } fn stage(&self) -> FilterStage { FilterStage::Discovery } } #[derive(Debug, Clone)] pub struct TokenWhitelistFilter { tokens: Vec
, } impl TokenWhitelistFilter { pub fn new(tokens: Vec
) -> Self { Self { tokens } } } #[async_trait] impl AMMFilter for TokenWhitelistFilter { /// Filter for any AMMs or tokens in the whitelist async fn filter(&self, amms: Vec) -> Result, AMMError> { Ok(amms .into_iter() .filter(|amm| amm.tokens().iter().any(|t| self.tokens.contains(t))) .collect()) } fn stage(&self) -> FilterStage { FilterStage::Sync } } ================================================ FILE: src/state_space/mod.rs ================================================ pub mod cache; pub mod discovery; pub mod error; pub mod filters; use crate::amms::amm::AutomatedMarketMaker; use crate::amms::amm::AMM; use crate::amms::error::AMMError; use crate::amms::factory::Factory; use alloy::consensus::BlockHeader; use alloy::eips::BlockId; use alloy::rpc::types::{Block, Filter, FilterSet, Log}; use alloy::{ network::Network, primitives::{Address, FixedBytes}, providers::Provider, }; use async_stream::stream; use cache::StateChange; use cache::StateChangeCache; use error::StateSpaceError; use filters::AMMFilter; use filters::PoolFilter; use futures::stream::FuturesUnordered; use futures::Stream; use futures::StreamExt; use std::collections::HashSet; use std::pin::Pin; use std::sync::atomic::AtomicU64; use std::sync::atomic::Ordering; use std::{collections::HashMap, marker::PhantomData, sync::Arc}; use tokio::sync::RwLock; use tracing::debug; use tracing::info; pub const CACHE_SIZE: usize = 30; #[derive(Clone)] pub struct StateSpaceManager { pub state: Arc>, pub latest_block: Arc, // discovery_manager: Option, pub block_filter: Filter, pub provider: P, phantom: PhantomData, // TODO: add support for caching } impl StateSpaceManager { pub async fn subscribe( &self, ) -> Result< Pin, StateSpaceError>> + Send>>, StateSpaceError, > where P: Provider + Clone + 'static, N: Network, { let provider = self.provider.clone(); let latest_block = self.latest_block.clone(); let state = self.state.clone(); let mut block_filter = self.block_filter.clone(); let block_stream = provider.subscribe_blocks().await?.into_stream(); Ok(Box::pin(stream! { tokio::pin!(block_stream); while let Some(block) = block_stream.next().await { let block_number = block.number(); block_filter = block_filter.select(block_number); let logs = provider.get_logs(&block_filter).await?; let affected_amms = state.write().await.sync(&logs)?; latest_block.store(block_number, Ordering::Relaxed); yield Ok(affected_amms); } })) } } // TODO: Drop impl, create a checkpoint #[derive(Debug, Default)] pub struct StateSpaceBuilder { pub provider: P, pub latest_block: u64, pub factories: Vec, pub amms: Vec, pub filters: Vec, phantom: PhantomData, // TODO: add support for caching } impl StateSpaceBuilder where N: Network, P: Provider + Clone + 'static, { pub fn new(provider: P) -> StateSpaceBuilder { Self { provider, latest_block: 0, factories: vec![], amms: vec![], filters: vec![], // discovery: false, phantom: PhantomData, } } pub fn block(self, latest_block: u64) -> StateSpaceBuilder { StateSpaceBuilder { latest_block, ..self } } pub fn with_factories(self, factories: Vec) -> StateSpaceBuilder { StateSpaceBuilder { factories, ..self } } pub fn with_amms(self, amms: Vec) -> StateSpaceBuilder { StateSpaceBuilder { amms, ..self } } pub fn with_filters(self, filters: Vec) -> StateSpaceBuilder { StateSpaceBuilder { filters, ..self } } pub async fn sync(self) -> Result, AMMError> { let chain_tip = BlockId::from(self.provider.get_block_number().await?); let factories = self.factories.clone(); let mut futures = FuturesUnordered::new(); let mut filter_set = HashSet::new(); for factory in &self.factories { for event in factory.pool_events() { filter_set.insert(event); } } for amm in self.amms.iter() { for event in amm.sync_events() { filter_set.insert(event); } } let block_filter = Filter::new().event_signature(FilterSet::from( filter_set.into_iter().collect::>>(), )); let mut amm_variants = HashMap::new(); for amm in self.amms.into_iter() { amm_variants .entry(amm.variant()) .or_insert_with(Vec::new) .push(amm); } for factory in factories { let provider = self.provider.clone(); let filters = self.filters.clone(); let extension = amm_variants.remove(&factory.variant()); futures.push(tokio::spawn(async move { let mut discovered_amms = factory.discover(chain_tip, provider.clone()).await?; if let Some(amms) = extension { discovered_amms.extend(amms); } // Apply discovery filters for filter in filters.iter() { if filter.stage() == filters::FilterStage::Discovery { let pre_filter_len = discovered_amms.len(); discovered_amms = filter.filter(discovered_amms).await?; info!( target: "state_space::sync", factory = %factory.address(), pre_filter_len, post_filter_len = discovered_amms.len(), filter = ?filter, "Discovery filter" ); } } discovered_amms = factory.sync(discovered_amms, chain_tip, provider).await?; // Apply sync filters for filter in filters.iter() { if filter.stage() == filters::FilterStage::Sync { let pre_filter_len = discovered_amms.len(); discovered_amms = filter.filter(discovered_amms).await?; info!( target: "state_space::sync", factory = %factory.address(), pre_filter_len, post_filter_len = discovered_amms.len(), filter = ?filter, "Sync filter" ); } } Ok::, AMMError>(discovered_amms) })); } let mut state_space = StateSpace::default(); while let Some(res) = futures.next().await { let synced_amms = res??; for amm in synced_amms { state_space.state.insert(amm.address(), amm); } } // Sync remaining AMM variants for (_, remaining_amms) in amm_variants.drain() { for mut amm in remaining_amms { let address = amm.address(); amm = amm.init(chain_tip, self.provider.clone()).await?; state_space.state.insert(address, amm); } } Ok(StateSpaceManager { latest_block: Arc::new(AtomicU64::new(self.latest_block)), state: Arc::new(RwLock::new(state_space)), block_filter, provider: self.provider, phantom: PhantomData, }) } } #[derive(Debug, Default)] pub struct StateSpace { pub state: HashMap, pub latest_block: Arc, cache: StateChangeCache, } impl StateSpace { pub fn get(&self, address: &Address) -> Option<&AMM> { self.state.get(address) } pub fn get_mut(&mut self, address: &Address) -> Option<&mut AMM> { self.state.get_mut(address) } pub fn sync(&mut self, logs: &[Log]) -> Result, StateSpaceError> { let latest = self.latest_block.load(Ordering::Relaxed); let Some(mut block_number) = logs .first() .map(|log| log.block_number.ok_or(StateSpaceError::MissingBlockNumber)) .transpose()? else { return Ok(vec![]); }; // Check if there is a reorg and unwind to state before block_number if latest >= block_number { info!( target: "state_space::sync", from = %latest, to = %block_number - 1, "Unwinding state changes" ); let cached_state = self.cache.unwind_state_changes(block_number); for amm in cached_state { debug!(target: "state_space::sync", ?amm, "Reverting AMM state"); self.state.insert(amm.address(), amm); } } let mut cached_amms = HashSet::new(); let mut affected_amms = HashSet::new(); for log in logs { // If the block number is updated, cache the current block state changes let log_block_number = log .block_number .ok_or(StateSpaceError::MissingBlockNumber)?; if log_block_number != block_number { let amms = cached_amms.drain().collect::>(); affected_amms.extend(amms.iter().map(|amm| amm.address())); let state_change = StateChange::new(amms, block_number); debug!( target: "state_space::sync", state_change = ?state_change, "Caching state change" ); self.cache.push(state_change); block_number = log_block_number; } // If the AMM is in the state space add the current state to cache and sync from log let address = log.address(); if let Some(amm) = self.state.get_mut(&address) { cached_amms.insert(amm.clone()); amm.sync(log)?; info!( target: "state_space::sync", ?amm, "Synced AMM" ); } } if !cached_amms.is_empty() { let amms = cached_amms.drain().collect::>(); affected_amms.extend(amms.iter().map(|amm| amm.address())); let state_change = StateChange::new(amms, block_number); debug!( target: "state_space::sync", state_change = ?state_change, "Caching state change" ); self.cache.push(state_change); } Ok(affected_amms.into_iter().collect()) } } #[macro_export] macro_rules! sync { // Sync factories with provider ($factories:expr, $provider:expr) => {{ StateSpaceBuilder::new($provider.clone()) .with_factories($factories) .sync() .await? }}; // Sync factories with filters ($factories:expr, $filters:expr, $provider:expr) => {{ StateSpaceBuilder::new($provider.clone()) .with_factories($factories) .with_filters($filters) .sync() .await? }}; ($factories:expr, $amms:expr, $filters:expr, $provider:expr) => {{ StateSpaceBuilder::new($provider.clone()) .with_factories($factories) .with_amms($amms) .with_filters($filters) .sync() .await? }}; }