diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 67e17696..a736e389 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,9 @@ name: Loom on: push: - branches: [main] + branches: [ main ] pull_request_target: - branches: [main] + branches: [ main ] env: CARGO_TERM_COLOR: always @@ -110,7 +110,7 @@ jobs: - uses: dtolnay/rust-toolchain@clippy - name: install taplo env: - version: "0.9.3" + version: "0.9.3" run: | curl -Ls "https://github.com/tamasfe/taplo/releases/download/${{ env.version }}/taplo-full-linux-x86_64.gz" | \ gzip -d > taplo && \ @@ -130,13 +130,13 @@ jobs: ref: ${{ github.event.pull_request.head.sha || github.ref }} - uses: dtolnay/rust-toolchain@clippy with: - toolchain: "1.82" + toolchain: "1.83" - uses: Swatinem/rust-cache@v2 - uses: arduino/setup-protoc@v3 - run: 'echo "pub const KEY_ENCRYPTION_PWD: [u8; 16] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];" > crates/types/entities/src/private.rs' # workaround for latest stable rust - - run: cargo +1.82 clippy --all-targets --all-features -- -D warnings + - run: cargo +1.83 clippy --all-targets --all-features -- -D warnings deny: if: github.repository == 'dexloom/loom' diff --git a/Cargo.lock b/Cargo.lock index 32efb903..108b2008 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2855,7 +2855,7 @@ dependencies = [ [[package]] name = "exex-grpc-node" -version = "0.4.0" +version = "0.5.0" dependencies = [ "eyre", "loom-node-grpc-exex-proto", @@ -2871,7 +2871,7 @@ dependencies = [ [[package]] name = "exex_grpc_loom" -version = "0.4.0" +version = "0.5.0" dependencies = [ "eyre", "loom-node-grpc-exex-proto", @@ -3144,7 +3144,7 @@ checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" [[package]] name = "gasbench" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-network", "alloy-primitives", @@ -4401,7 +4401,7 @@ dependencies = [ [[package]] name = "keys" -version = "0.4.0" +version = "0.5.0" dependencies = [ "aes", "clap", @@ -4620,7 +4620,7 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "loom" -version = "0.4.0" +version = "0.5.0" dependencies = [ "loom-broadcast-accounts", "loom-broadcast-broadcaster", @@ -4666,7 +4666,7 @@ dependencies = [ [[package]] name = "loom-broadcast-accounts" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-consensus", "alloy-eips", @@ -4692,7 +4692,7 @@ dependencies = [ [[package]] name = "loom-broadcast-broadcaster" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-eips", "alloy-network", @@ -4715,7 +4715,7 @@ dependencies = [ [[package]] name = "loom-broadcast-flashbots" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-consensus", "alloy-json-rpc", @@ -4745,7 +4745,7 @@ dependencies = [ [[package]] name = "loom-core-actors" -version = "0.4.0" +version = "0.5.0" dependencies = [ "async-trait", "eyre", @@ -4757,7 +4757,7 @@ dependencies = [ [[package]] name = "loom-core-actors-macros" -version = "0.4.0" +version = "0.5.0" dependencies = [ "proc-macro2", "quote", @@ -4767,7 +4767,7 @@ dependencies = [ [[package]] name = "loom-core-block-history" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-eips", "alloy-network", @@ -4795,7 +4795,7 @@ dependencies = [ [[package]] name = "loom-core-blockchain" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy", "influxdb", @@ -4811,7 +4811,7 @@ dependencies = [ [[package]] name = "loom-core-blockchain-actors" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-network", "alloy-primitives", @@ -4855,7 +4855,7 @@ dependencies = [ [[package]] name = "loom-core-mempool" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -4874,7 +4874,7 @@ dependencies = [ [[package]] name = "loom-core-router" -version = "0.4.0" +version = "0.5.0" dependencies = [ "eyre", "loom-core-actors", @@ -4889,7 +4889,7 @@ dependencies = [ [[package]] name = "loom-core-topology" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-primitives", "alloy-provider", @@ -4938,7 +4938,7 @@ dependencies = [ [[package]] name = "loom-defi-abi" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-contract", "alloy-primitives", @@ -4948,14 +4948,14 @@ dependencies = [ [[package]] name = "loom-defi-address-book" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-primitives", ] [[package]] name = "loom-defi-health-monitor" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-consensus", "alloy-eips", @@ -4980,13 +4980,14 @@ dependencies = [ [[package]] name = "loom-defi-market" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-network", "alloy-primitives", "alloy-provider", "alloy-rpc-types", "alloy-transport", + "async-stream", "eyre", "loom-core-actors", "loom-core-actors-macros", @@ -4998,23 +4999,21 @@ dependencies = [ "loom-types-events", "revm", "tokio", + "tokio-stream", "tracing", ] [[package]] name = "loom-defi-pools" -version = "0.4.0" +version = "0.5.0" dependencies = [ - "alloy-primitives", - "alloy-provider", + "alloy", "alloy-rpc-client", - "alloy-rpc-types", - "alloy-rpc-types-trace", - "alloy-sol-macro", - "alloy-sol-types", "alloy-transport", + "async-stream", "env_logger", "eyre", + "futures", "lazy_static", "loom-defi-abi", "loom-defi-address-book", @@ -5029,13 +5028,14 @@ dependencies = [ "revm", "strum", "tokio", + "tokio-stream", "tracing", "url", ] [[package]] name = "loom-defi-preloader" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-eips", "alloy-network", @@ -5058,7 +5058,7 @@ dependencies = [ [[package]] name = "loom-defi-price" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-network", "alloy-primitives", @@ -5077,7 +5077,7 @@ dependencies = [ [[package]] name = "loom-defi-uniswap-v3-math" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy", "eyre", @@ -5086,7 +5086,7 @@ dependencies = [ [[package]] name = "loom-evm-db" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy", "chrono", @@ -5105,7 +5105,7 @@ dependencies = [ [[package]] name = "loom-evm-utils" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy", "axum", @@ -5128,7 +5128,7 @@ dependencies = [ [[package]] name = "loom-execution-estimator" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-consensus", "alloy-eips", @@ -5156,7 +5156,7 @@ dependencies = [ [[package]] name = "loom-execution-multicaller" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-eips", "alloy-network", @@ -5185,7 +5185,7 @@ dependencies = [ [[package]] name = "loom-metrics" -version = "0.4.0" +version = "0.5.0" dependencies = [ "async-trait", "chrono", @@ -5202,11 +5202,11 @@ dependencies = [ [[package]] name = "loom-node-actor-config" -version = "0.4.0" +version = "0.5.0" [[package]] name = "loom-node-db-access" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-eips", "alloy-network", @@ -5241,7 +5241,7 @@ dependencies = [ [[package]] name = "loom-node-debug-provider" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy", "alloy-provider", @@ -5264,7 +5264,7 @@ dependencies = [ [[package]] name = "loom-node-exex" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-eips", "alloy-network", @@ -5292,7 +5292,7 @@ dependencies = [ [[package]] name = "loom-node-grpc" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-consensus", "alloy-eips", @@ -5321,7 +5321,7 @@ dependencies = [ [[package]] name = "loom-node-grpc-exex-proto" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-consensus", "alloy-eips", @@ -5350,7 +5350,7 @@ dependencies = [ [[package]] name = "loom-node-json-rpc" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-network", "alloy-primitives", @@ -5375,7 +5375,7 @@ dependencies = [ [[package]] name = "loom-node-player" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-eips", "alloy-network", @@ -5400,7 +5400,7 @@ dependencies = [ [[package]] name = "loom-rpc-handler" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-primitives", "axum", @@ -5431,7 +5431,7 @@ dependencies = [ [[package]] name = "loom-rpc-state" -version = "0.4.0" +version = "0.5.0" dependencies = [ "loom-core-blockchain", "loom-evm-utils", @@ -5441,7 +5441,7 @@ dependencies = [ [[package]] name = "loom-storage-db" -version = "0.4.0" +version = "0.5.0" dependencies = [ "bb8", "diesel", @@ -5451,7 +5451,7 @@ dependencies = [ [[package]] name = "loom-strategy-backrun" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-consensus", "alloy-eips", @@ -5484,7 +5484,7 @@ dependencies = [ [[package]] name = "loom-strategy-merger" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-eips", "alloy-network", @@ -5513,7 +5513,7 @@ dependencies = [ [[package]] name = "loom-types-blockchain" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-consensus", "alloy-eips", @@ -5541,7 +5541,7 @@ dependencies = [ [[package]] name = "loom-types-entities" -version = "0.4.0" +version = "0.5.0" dependencies = [ "aes", "alloy-consensus", @@ -5556,6 +5556,7 @@ dependencies = [ "alloy-signer", "alloy-signer-local", "alloy-transport", + "async-stream", "chrono", "criterion", "eyre", @@ -5584,13 +5585,14 @@ dependencies = [ "strum_macros", "thiserror 1.0.69", "tokio", + "tokio-stream", "toml", "tracing", ] [[package]] name = "loom-types-events" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-consensus", "alloy-eips", @@ -5607,7 +5609,7 @@ dependencies = [ [[package]] name = "loom_anvil" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy-consensus", "alloy-node-bindings", @@ -5654,7 +5656,7 @@ dependencies = [ [[package]] name = "loom_exex" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy", "axum", @@ -5994,7 +5996,7 @@ dependencies = [ [[package]] name = "nodebench" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy", "chrono", @@ -7118,7 +7120,7 @@ dependencies = [ [[package]] name = "replayer" -version = "0.4.0" +version = "0.5.0" dependencies = [ "alloy", "clap", diff --git a/Cargo.toml b/Cargo.toml index e6934c17..c818f2c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,8 +67,8 @@ exclude = [".github/"] homepage = "https://github.com/dexloom/loom" license = "MIT OR Apache-2.0" repository = "https://github.com/dexloom/loom" -rust-version = "1.82" -version = "0.4.0" +rust-version = "1.83" +version = "0.5.0" [workspace.dependencies] # broadcast diff --git a/bin/gasbench/src/cli.rs b/bin/gasbench/src/cli.rs index 739a1d64..01b30a05 100644 --- a/bin/gasbench/src/cli.rs +++ b/bin/gasbench/src/cli.rs @@ -8,6 +8,9 @@ pub struct Cli { #[arg(short, long)] pub anvil: bool, + #[arg(short, long)] + pub filter: Option, + #[arg(value_name = "File", help = "File name")] pub file: Option, } diff --git a/bin/gasbench/src/main.rs b/bin/gasbench/src/main.rs index 9fe7e486..c7bcc258 100644 --- a/bin/gasbench/src/main.rs +++ b/bin/gasbench/src/main.rs @@ -110,7 +110,9 @@ async fn main() -> Result<()> { btree_map.insert(pool.clone(), swap_directions); - let swap_paths = market.build_swap_path_vec(&btree_map)?; + //let swap_paths = market.build_swap_path_vec(&btree_map)?; + + let swap_paths = market.swap_paths(); let db = market_state_instance.read().await.state_db.clone(); @@ -132,14 +134,22 @@ async fn main() -> Result<()> { if !swap_path.tokens[0].is_weth() { continue; } + let sp = swap_path.clone(); let sp_dto: SwapLineDTO = (&sp).into(); + println!("Checking {}", sp_dto); + if let Some(filter) = &cli.filter.clone() { + if !format!("{}", sp_dto).contains(filter) { + println!("Skipping {}", sp_dto); + continue; + } + } let mut swapline = SwapLine { path: sp, amount_in: SwapAmountType::Set(in_amount), ..SwapLine::default() }; match swapline.calculate_with_in_amount(&db, env.clone(), in_amount) { Ok((out_amount, gas_used, _)) => { - info!("{} gas: {} amount {} -> {}", sp_dto, gas_used, in_amount_f64, NWETH::to_float(out_amount)); + println!("{} gas: {} amount {} -> {}", sp_dto, gas_used, in_amount_f64, NWETH::to_float(out_amount)); swapline.amount_out = SwapAmountType::Set(out_amount) } Err(e) => { @@ -203,15 +213,24 @@ async fn main() -> Result<()> { let change_i: i64 = *gas as i64 - *stored_gas as i64; let change = format!("{change_i}"); - let change = match change_i { - i if i > 0 => change.red(), - i if i < 0 => change.green(), - _ => change.normal(), + let change = if *gas < 40000 { + change.red() + } else { + match change_i { + i if i > 0 => change.red(), + i if i < 0 => change.green(), + _ => change.normal(), + } }; + println!("{} : {} {} - {} ", change, current_entry, gas, stored_gas,); } None => { - println!("{} : {} {}", "NO_DATA".green(), current_entry, gas,); + if *gas < 40000 { + println!("{} : {} {}", "FAILED".red(), current_entry, gas,); + } else { + println!("{} : {} {}", "NO_DATA".green(), current_entry, gas,); + } } } } diff --git a/bin/gasbench/src/soltest.rs b/bin/gasbench/src/soltest.rs index 131cff06..d3489140 100644 --- a/bin/gasbench/src/soltest.rs +++ b/bin/gasbench/src/soltest.rs @@ -6,7 +6,14 @@ fn format_test_file(test_names: String, call_data: String, test_size: usize) -> // SPDX-License-Identifier: Unlicense pragma solidity ^0.8.15; -contract MulticallerCallData {{ +import "forge-std/Test.sol"; +import "forge-std/console.sol"; + +import {{ERC20}} from "./mocks/ERC20.sol"; +import {{MultiCaller}} from "./Interface.sol"; +import {{TestHelper, SwapTest}} from "./Helper.sol"; + +contract MulticallerGasBench is Test, TestHelper, SwapTest {{ string[{}] testname = [ {} @@ -17,14 +24,37 @@ contract MulticallerCallData {{ ]; - function get_call_data(uint256 i ) internal returns (bytes memory) {{ + function get_call_data(uint256 i) internal override returns (bytes memory) {{ return callsdata[i]; }} - function get_test_name(uint256 i ) internal returns (string memory) {{ + function get_test_name(uint256 i) internal override returns (string memory) {{ return testname[i]; }} + function get_count() internal override returns (uint256) {{ + return callsdata.length; + }} + + function get_swap_token() internal override returns (address) {{ + return address(weth); + }} + + function get_multicaller() internal override returns (address) {{ + return address(TestHelper.multicaller); + }} + + function test_combo() public {{ + run_test_all(); + }} + + function test_single() public {{ + run_test_one(0); + }} + + + + }} "#, test_size, test_names, test_size, call_data diff --git a/crates/core/blockchain-actors/src/actor.rs b/crates/core/blockchain-actors/src/actor.rs index 148732e4..979b984f 100644 --- a/crates/core/blockchain-actors/src/actor.rs +++ b/crates/core/blockchain-actors/src/actor.rs @@ -16,7 +16,7 @@ use loom_core_router::SwapRouterActor; use loom_defi_address_book::TokenAddressEth; use loom_defi_health_monitor::{PoolHealthMonitorActor, StuffingTxMonitorActor}; use loom_defi_market::{ - CurvePoolLoaderOneShotActor, HistoryPoolLoaderOneShotActor, NewPoolLoaderActor, PoolLoaderActor, RequiredPoolLoaderActor, + HistoryPoolLoaderOneShotActor, NewPoolLoaderActor, PoolLoaderActor, ProtocolPoolLoaderOneShotActor, RequiredPoolLoaderActor, }; use loom_defi_pools::{PoolLoadersBuilder, PoolsConfig}; use loom_defi_preloader::MarketStatePreloadedOneShotActor; @@ -276,7 +276,6 @@ where } /// Starts mempool actor collecting pending txes from all mempools and pulling new tx hashes in mempool_events channel - pub fn mempool(&mut self) -> Result<&mut Self> { if !self.has_mempool { self.has_mempool = true; @@ -324,9 +323,11 @@ where self.actor_manager.start(PoolHealthMonitorActor::new().on_bc(&self.bc))?; Ok(self) } - /// Starts state health monitor + //TODO : Move out of Blockchain - /*pub fn with_health_monitor_state(&mut self) -> Result<&mut Self> { + /* + /// Starts state health monitor + pub fn with_health_monitor_state(&mut self) -> Result<&mut Self> { self.actor_manager.start(StateHealthMonitorActor::new(self.provider.clone()).on_bc(&self.bc))?; Ok(self) } @@ -361,8 +362,9 @@ where } /// Start pool loader for curve + steth + wsteth - pub fn with_curve_pool_protocol_loader(&mut self) -> Result<&mut Self> { - self.actor_manager.start(CurvePoolLoaderOneShotActor::new(self.provider.clone()).on_bc(&self.bc, &self.state))?; + pub fn with_curve_pool_protocol_loader(&mut self, pools_config: PoolsConfig) -> Result<&mut Self> { + let pool_loaders = Arc::new(PoolLoadersBuilder::default_pool_loaders(self.provider.clone(), pools_config)); + self.actor_manager.start(ProtocolPoolLoaderOneShotActor::new(self.provider.clone(), pool_loaders).on_bc(&self.bc))?; Ok(self) } @@ -371,7 +373,7 @@ where if pools_config.is_enabled(PoolClass::Curve) { self.with_new_pool_loader(pools_config.clone())? .with_pool_history_loader(pools_config.clone())? - .with_curve_pool_protocol_loader()? + .with_curve_pool_protocol_loader(pools_config.clone())? .with_pool_loader(pools_config) } else { self.with_new_pool_loader(pools_config.clone())?.with_pool_history_loader(pools_config.clone())?.with_pool_loader(pools_config) @@ -402,8 +404,6 @@ where Ok(self) } - /// Strategy Part - /// Starts EVM gas estimator and tips filler pub fn with_evm_estimator(&mut self) -> Result<&mut Self> { self.actor_manager.start( diff --git a/crates/core/blockchain/src/blockchain.rs b/crates/core/blockchain/src/blockchain.rs index 1e534a0d..ba8c8a44 100644 --- a/crates/core/blockchain/src/blockchain.rs +++ b/crates/core/blockchain/src/blockchain.rs @@ -7,8 +7,8 @@ use loom_types_blockchain::{ChainParameters, Mempool}; use loom_types_blockchain::{LoomDataTypes, LoomDataTypesEthereum}; use loom_types_entities::{AccountNonceAndBalanceState, LatestBlock, Market, Token}; use loom_types_events::{ - MarketEvents, MempoolEvents, MessageBlock, MessageBlockHeader, MessageBlockLogs, MessageBlockStateUpdate, MessageHealthEvent, - MessageMempoolDataUpdate, MessageTxCompose, Task, + LoomTask, MarketEvents, MempoolEvents, MessageBlock, MessageBlockHeader, MessageBlockLogs, MessageBlockStateUpdate, MessageHealthEvent, + MessageMempoolDataUpdate, MessageTxCompose, }; #[derive(Clone)] @@ -31,7 +31,7 @@ pub struct Blockchain { pool_health_monitor_channel: Broadcaster>, influxdb_write_channel: Broadcaster, - tasks_channel: Broadcaster, + tasks_channel: Broadcaster, } impl Blockchain { @@ -49,7 +49,7 @@ impl Blockchain { let pool_health_monitor_channel: Broadcaster = Broadcaster::new(1000); let influx_write_channel: Broadcaster = Broadcaster::new(1000); - let tasks_channel: Broadcaster = Broadcaster::new(1000); + let tasks_channel: Broadcaster = Broadcaster::new(1000); let mut market_instance = Market::default(); @@ -154,7 +154,7 @@ impl Blockchain { self.influxdb_write_channel.clone() } - pub fn tasks_channel(&self) -> Broadcaster { + pub fn tasks_channel(&self) -> Broadcaster { self.tasks_channel.clone() } } diff --git a/crates/core/topology/src/topology.rs b/crates/core/topology/src/topology.rs index ee5b449f..f7953d32 100644 --- a/crates/core/topology/src/topology.rs +++ b/crates/core/topology/src/topology.rs @@ -18,7 +18,7 @@ use loom_core_block_history::BlockHistoryActor; use loom_core_blockchain::{Blockchain, BlockchainState, Strategy}; use loom_core_mempool::MempoolActor; use loom_defi_health_monitor::PoolHealthMonitorActor; -use loom_defi_market::{CurvePoolLoaderOneShotActor, HistoryPoolLoaderOneShotActor, NewPoolLoaderActor, PoolLoaderActor}; +use loom_defi_market::{HistoryPoolLoaderOneShotActor, NewPoolLoaderActor, PoolLoaderActor, ProtocolPoolLoaderOneShotActor}; use loom_defi_pools::{PoolLoadersBuilder, PoolsConfig}; use loom_defi_preloader::MarketStatePreloadedOneShotActor; use loom_defi_price::PriceActor; @@ -449,8 +449,8 @@ impl< if params.protocol { info!("Starting curve pools loader {name}"); - let mut curve_pools_loader_actor = CurvePoolLoaderOneShotActor::new(client.clone()); - match curve_pools_loader_actor.access(blockchain.market()).access(blockchain_state.market_state()).start() { + let mut curve_pools_loader_actor = ProtocolPoolLoaderOneShotActor::new(client.clone(), pool_loaders.clone()); + match curve_pools_loader_actor.produce(blockchain.tasks_channel()).start() { Err(e) => { panic!("CurvePoolLoaderOneShotActor : {}", e) } diff --git a/crates/defi/address-book/src/lib.rs b/crates/defi/address-book/src/lib.rs index 5729406e..785e0b31 100644 --- a/crates/defi/address-book/src/lib.rs +++ b/crates/defi/address-book/src/lib.rs @@ -94,6 +94,8 @@ impl CurvePoolAddress { pub const ETH_BTC_USD: Address = address!("7f86bf177dd4f3494b841a37e810a34dd56c829b"); pub const FRXETH_WETH: Address = address!("9c3b46c0ceb5b9e304fcd6d88fc50f7dd24b31bc"); pub const ETH: Address = address!("a1f8a6807c402e4a15ef4eba36528a3fed24e577"); + pub const STETH_ETH: Address = address!("dc24316b9ae028f1497c275eb9192a3ea0f67022"); + pub const STETH_WETH: Address = address!("828b154032950c8ff7cf8085d841723db2696056"); } #[non_exhaustive] diff --git a/crates/defi/market/Cargo.toml b/crates/defi/market/Cargo.toml index c32f5067..2c4818b7 100644 --- a/crates/defi/market/Cargo.toml +++ b/crates/defi/market/Cargo.toml @@ -18,8 +18,10 @@ loom-types-blockchain.workspace = true loom-types-entities.workspace = true loom-types-events.workspace = true +async-stream.workspace = true eyre.workspace = true tokio.workspace = true +tokio-stream.workspace = true tracing.workspace = true diff --git a/crates/defi/market/src/curve_protocol_pool_actor.rs b/crates/defi/market/src/curve_protocol_pool_actor.rs deleted file mode 100644 index 94e5b1a5..00000000 --- a/crates/defi/market/src/curve_protocol_pool_actor.rs +++ /dev/null @@ -1,141 +0,0 @@ -use revm::{Database, DatabaseCommit}; -use std::marker::PhantomData; -use std::sync::Arc; - -use alloy_network::Network; -use alloy_provider::Provider; -use alloy_transport::Transport; -use tracing::{debug, error}; - -use crate::pool_loader_actor::fetch_state_and_add_pool; -use loom_core_actors::{Accessor, Actor, ActorResult, SharedState, WorkerResult}; -use loom_core_actors_macros::{Accessor, Consumer}; -use loom_core_blockchain::{Blockchain, BlockchainState}; -use loom_defi_pools::protocols::CurveProtocol; -use loom_defi_pools::{CurvePool, CurvePoolAbiEncoder}; -use loom_node_debug_provider::DebugProviderExt; -use loom_types_entities::{Market, MarketState, PoolId, PoolWrapper}; -use revm::DatabaseRef; - -async fn curve_pool_loader_worker( - client: P, - market: SharedState, - market_state: SharedState>, -) -> WorkerResult -where - T: Transport + Clone, - N: Network, - P: Provider + DebugProviderExt + Send + Sync + Clone + 'static, - DB: Database + DatabaseRef + DatabaseCommit + Send + Sync + Clone + 'static, -{ - let curve_contracts = CurveProtocol::get_contracts_vec(client.clone()); - for curve_contract in curve_contracts.into_iter() { - if let Ok(curve_pool) = - CurvePool::>::fetch_pool_data_with_default_encoder(client.clone(), curve_contract).await - { - let pool_wrapped = PoolWrapper::new(Arc::new(curve_pool)); - match fetch_state_and_add_pool(client.clone(), market.clone(), market_state.clone(), pool_wrapped.clone()).await { - Err(e) => { - error!("Curve pool loading error : {}", e) - } - Ok(_) => { - debug!("Curve pool loaded {:#20x}", pool_wrapped.get_address()); - } - } - } - } - - for factory_idx in 0..10 { - if let Ok(factory_address) = CurveProtocol::get_factory_address(client.clone(), factory_idx).await { - if let Ok(pool_count) = CurveProtocol::get_pool_count(client.clone(), factory_address).await { - for pool_id in 0..pool_count { - if let Ok(addr) = CurveProtocol::get_pool_address(client.clone(), factory_address, pool_id).await { - if market.read().await.get_pool(&PoolId::Address(addr)).is_some() { - continue; - } - - match CurveProtocol::get_contract_from_code(client.clone(), addr).await { - Ok(curve_contract) => { - if let Ok(curve_pool) = - CurvePool::::fetch_pool_data_with_default_encoder(client.clone(), curve_contract).await - { - let pool_wrapped = PoolWrapper::new(Arc::new(curve_pool)); - - match fetch_state_and_add_pool( - client.clone(), - market.clone(), - market_state.clone(), - pool_wrapped.clone(), - ) - .await - { - Err(e) => { - error!("Curve pool loading error {:?} : {}", pool_wrapped.get_address(), e); - } - Ok(_) => { - debug!("Curve pool loaded {:#20x}", pool_wrapped.get_address()); - } - } - } - } - Err(e) => { - error!("Contract from code error {:#20x} : {}", addr, e) - } - } - } - } - } - } - } - - Ok("curve_protocol_loader_worker".to_string()) -} - -#[derive(Accessor, Consumer)] -pub struct CurvePoolLoaderOneShotActor { - client: P, - #[accessor] - market: Option>, - #[accessor] - market_state: Option>>, - _t: PhantomData, - _n: PhantomData, -} - -impl CurvePoolLoaderOneShotActor -where - N: Network, - T: Transport + Clone, - P: Provider + DebugProviderExt + Send + Sync + Clone + 'static, - DB: Database + DatabaseRef + DatabaseCommit + Send + Sync + Clone + 'static, -{ - pub fn new(client: P) -> Self { - Self { client, market: None, market_state: None, _n: PhantomData, _t: PhantomData } - } - - pub fn on_bc(self, bc: &Blockchain, state: &BlockchainState) -> Self { - Self { market: Some(bc.market()), market_state: Some(state.market_state_commit()), ..self } - } -} - -impl Actor for CurvePoolLoaderOneShotActor -where - T: Transport + Clone, - N: Network, - P: Provider + DebugProviderExt + Send + Sync + Clone + 'static, - DB: Database + DatabaseRef + DatabaseCommit + Send + Sync + Clone + 'static, -{ - fn start(&self) -> ActorResult { - let task = tokio::task::spawn(curve_pool_loader_worker( - self.client.clone(), - self.market.clone().unwrap(), - self.market_state.clone().unwrap(), - )); - - Ok(vec![task]) - } - - fn name(&self) -> &'static str { - "CurvePoolLoaderOneShotActor" - } -} diff --git a/crates/defi/market/src/history_pool_actor.rs b/crates/defi/market/src/history_pool_loader_actor.rs similarity index 96% rename from crates/defi/market/src/history_pool_actor.rs rename to crates/defi/market/src/history_pool_loader_actor.rs index 4907ff01..70bd766c 100644 --- a/crates/defi/market/src/history_pool_actor.rs +++ b/crates/defi/market/src/history_pool_loader_actor.rs @@ -13,12 +13,12 @@ use loom_core_blockchain::Blockchain; use loom_node_debug_provider::DebugProviderExt; use loom_types_blockchain::LoomDataTypesEthereum; use loom_types_entities::PoolLoaders; -use loom_types_events::Task; +use loom_types_events::LoomTask; async fn history_pool_loader_one_shot_worker( client: P, pool_loaders: Arc>, - tasks_tx: Broadcaster, + tasks_tx: Broadcaster, ) -> WorkerResult where N: Network, @@ -60,7 +60,7 @@ where client: P, pool_loaders: Arc>, #[producer] - tasks_tx: Option>, + tasks_tx: Option>, _t: PhantomData, _n: PhantomData, } diff --git a/crates/defi/market/src/lib.rs b/crates/defi/market/src/lib.rs index e653809f..1dc5ebcc 100644 --- a/crates/defi/market/src/lib.rs +++ b/crates/defi/market/src/lib.rs @@ -1,12 +1,12 @@ -pub use curve_protocol_pool_actor::CurvePoolLoaderOneShotActor; -pub use history_pool_actor::HistoryPoolLoaderOneShotActor; +pub use history_pool_loader_actor::HistoryPoolLoaderOneShotActor; pub use new_pool_actor::NewPoolLoaderActor; pub use pool_loader_actor::{fetch_and_add_pool_by_pool_id, fetch_state_and_add_pool, PoolLoaderActor}; +pub use protocol_pool_loader_actor::ProtocolPoolLoaderOneShotActor; pub use required_pools_actor::RequiredPoolLoaderActor; -mod curve_protocol_pool_actor; -mod history_pool_actor; +mod history_pool_loader_actor; mod logs_parser; mod new_pool_actor; mod pool_loader_actor; +mod protocol_pool_loader_actor; mod required_pools_actor; diff --git a/crates/defi/market/src/logs_parser.rs b/crates/defi/market/src/logs_parser.rs index 3bf04852..93fd8243 100644 --- a/crates/defi/market/src/logs_parser.rs +++ b/crates/defi/market/src/logs_parser.rs @@ -8,12 +8,12 @@ use tracing::error; use loom_core_actors::{run_async, Broadcaster}; use loom_types_entities::PoolLoaders; -use loom_types_events::Task; +use loom_types_events::LoomTask; pub async fn process_log_entries( log_entries: Vec, pool_loaders: &PoolLoaders, - tasks_tx: Broadcaster, + tasks_tx: Broadcaster, ) -> Result<()> where T: Transport + Clone, @@ -34,6 +34,6 @@ where } } - run_async!(tasks_tx.send(Task::FetchAndAddPools(pool_to_fetch))); + run_async!(tasks_tx.send(LoomTask::FetchAndAddPools(pool_to_fetch))); Ok(()) } diff --git a/crates/defi/market/src/new_pool_actor.rs b/crates/defi/market/src/new_pool_actor.rs index fd62cc8b..11008269 100644 --- a/crates/defi/market/src/new_pool_actor.rs +++ b/crates/defi/market/src/new_pool_actor.rs @@ -10,14 +10,14 @@ use loom_core_actors::{subscribe, Actor, ActorResult, Broadcaster, Consumer, Pro use loom_core_actors_macros::{Consumer, Producer}; use loom_core_blockchain::Blockchain; use loom_types_entities::PoolLoaders; -use loom_types_events::{MessageBlockLogs, Task}; +use loom_types_events::{LoomTask, MessageBlockLogs}; use crate::logs_parser::process_log_entries; pub async fn new_pool_worker( log_update_rx: Broadcaster, pools_loaders: Arc>, - tasks_tx: Broadcaster, + tasks_tx: Broadcaster, ) -> WorkerResult where T: Transport + Clone, @@ -61,7 +61,7 @@ where #[consumer] log_update_rx: Option>, #[producer] - tasks_tx: Option>, + tasks_tx: Option>, } impl NewPoolLoaderActor diff --git a/crates/defi/market/src/pool_loader_actor.rs b/crates/defi/market/src/pool_loader_actor.rs index 6577e7c4..abe8f9d4 100644 --- a/crates/defi/market/src/pool_loader_actor.rs +++ b/crates/defi/market/src/pool_loader_actor.rs @@ -16,7 +16,7 @@ use loom_core_blockchain::{Blockchain, BlockchainState}; use loom_node_debug_provider::DebugProviderExt; use loom_types_entities::required_state::RequiredStateReader; use loom_types_entities::{Market, MarketState, PoolClass, PoolId, PoolLoaders, PoolWrapper}; -use loom_types_events::Task; +use loom_types_events::LoomTask; use revm::{Database, DatabaseCommit, DatabaseRef}; use tokio::sync::Semaphore; @@ -28,7 +28,7 @@ pub async fn pool_loader_worker( pool_loaders: Arc>, market: SharedState, market_state: SharedState>, - tasks_rx: Broadcaster, + tasks_rx: Broadcaster, ) -> WorkerResult where T: Transport + Clone, @@ -43,7 +43,7 @@ where loop { if let Ok(task) = tasks_rx.recv().await { let pools = match task { - Task::FetchAndAddPools(pools) => pools, + LoomTask::FetchAndAddPools(pools) => pools, _ => continue, }; @@ -103,7 +103,7 @@ where P: Provider + DebugProviderExt + Send + Sync + Clone + 'static, DB: DatabaseRef + Database + DatabaseCommit + Send + Sync + Clone + 'static, { - debug!("Fetching pool {}", pool_id); + debug!(%pool_id, %pool_class, "Fetching pool"); let pool = pool_loaders.load_pool_with_provider(client.clone(), pool_id, &pool_class).await?; fetch_state_and_add_pool(client, market.clone(), market_state.clone(), pool).await?; @@ -184,7 +184,7 @@ where #[accessor] market_state: Option>>, #[consumer] - tasks_rx: Option>, + tasks_rx: Option>, _t: PhantomData, _n: PhantomData, } diff --git a/crates/defi/market/src/protocol_pool_loader_actor.rs b/crates/defi/market/src/protocol_pool_loader_actor.rs new file mode 100644 index 00000000..f0183446 --- /dev/null +++ b/crates/defi/market/src/protocol_pool_loader_actor.rs @@ -0,0 +1,91 @@ +use std::marker::PhantomData; +use std::sync::Arc; + +use alloy_network::Network; +use alloy_provider::Provider; +use alloy_transport::Transport; +use tracing::error; + +use loom_core_actors::{Actor, ActorResult, Broadcaster, Producer, WorkerResult}; +use loom_core_actors_macros::Producer; +use loom_core_blockchain::Blockchain; +use loom_node_debug_provider::DebugProviderExt; +use loom_types_entities::PoolLoaders; +use loom_types_events::LoomTask; +use tokio_stream::StreamExt; + +async fn protocol_pool_loader_worker( + _client: P, + pool_loaders: Arc>, + tasks_tx: Broadcaster, +) -> WorkerResult +where + T: Transport + Clone, + N: Network, + P: Provider + DebugProviderExt + Send + Sync + Clone + 'static, +{ + for (pool_class, pool_loader) in pool_loaders.map.iter() { + let tasks_tx_clone = tasks_tx.clone(); + if let Ok(mut proto_loader) = pool_loader.clone().protocol_loader() { + tokio::task::spawn(async move { + while let Some((pool_id, pool_class)) = proto_loader.next().await { + if let Err(error) = tasks_tx_clone.send(LoomTask::FetchAndAddPools(vec![(pool_id, pool_class)])).await { + error!(%error, "tasks_tx.send"); + } + } + }); + } else { + error!("Protocol loader unavailable for {}", pool_class); + } + } + + Ok("curve_protocol_loader_worker".to_string()) +} + +#[derive(Producer)] +pub struct ProtocolPoolLoaderOneShotActor +where + N: Network, + T: Transport + Clone, + P: Provider + DebugProviderExt + Send + Sync + Clone + 'static, +{ + client: P, + pool_loaders: Arc>, + #[producer] + tasks_tx: Option>, + _t: PhantomData, + _n: PhantomData, +} + +impl ProtocolPoolLoaderOneShotActor +where + N: Network, + T: Transport + Clone, + P: Provider + DebugProviderExt + Send + Sync + Clone + 'static, +{ + pub fn new(client: P, pool_loaders: Arc>) -> Self { + Self { client, pool_loaders, tasks_tx: None, _n: PhantomData, _t: PhantomData } + } + + pub fn on_bc(self, bc: &Blockchain) -> Self { + Self { tasks_tx: Some(bc.tasks_channel()), ..self } + } +} + +impl Actor for ProtocolPoolLoaderOneShotActor +where + T: Transport + Clone, + N: Network, + P: Provider + DebugProviderExt + Send + Sync + Clone + 'static, +{ + fn start(&self) -> ActorResult { + let task = + tokio::task::spawn(protocol_pool_loader_worker(self.client.clone(), self.pool_loaders.clone(), self.tasks_tx.clone().unwrap())); + + Ok(vec![task]) + } + + fn name(&self) -> &'static str { + "CurvePoolLoaderOneShotActor" + } +} diff --git a/crates/defi/pools/Cargo.toml b/crates/defi/pools/Cargo.toml index e3c8509a..14e4e52e 100644 --- a/crates/defi/pools/Cargo.toml +++ b/crates/defi/pools/Cargo.toml @@ -16,22 +16,19 @@ loom-evm-utils.workspace = true loom-types-blockchain.workspace = true loom-types-entities.workspace = true +async-stream.workspace = true eyre.workspace = true +futures.workspace = true lazy_static.workspace = true reth-storage-api.workspace = true revm.workspace = true strum.workspace = true +tokio-stream.workspace = true tracing.workspace = true # alloy -alloy-primitives.workspace = true -alloy-provider.workspace = true -alloy-rpc-types.workspace = true -alloy-rpc-types-trace.workspace = true -alloy-sol-macro.workspace = true -alloy-sol-types.workspace = true -alloy-transport.workspace = true +alloy.workspace = true [features] debug-calculation = [] diff --git a/crates/defi/pools/src/curvepool.rs b/crates/defi/pools/src/curvepool.rs index 3ae67874..bc4003fc 100644 --- a/crates/defi/pools/src/curvepool.rs +++ b/crates/defi/pools/src/curvepool.rs @@ -1,9 +1,9 @@ use std::sync::Arc; -use alloy_primitives::{address, Address, Bytes, U256}; -use alloy_provider::{Network, Provider}; -use alloy_sol_types::SolCall; -use alloy_transport::Transport; +use alloy::primitives::{address, Address, Bytes, U256}; +use alloy::providers::{Network, Provider}; +use alloy::sol_types::SolCall; +use alloy::transports::Transport; use eyre::{eyre, ErrReport, Result}; use loom_defi_abi::IERC20; use loom_defi_address_book::TokenAddressEth; @@ -595,10 +595,10 @@ where mod tests { use eyre::Result; - use alloy_primitives::U256; - use alloy_provider::network::primitives::BlockTransactionsKind; - use alloy_provider::Provider; - use alloy_rpc_types::BlockNumberOrTag; + use alloy::primitives::U256; + use alloy::providers::network::primitives::BlockTransactionsKind; + use alloy::providers::Provider; + use alloy::rpc::types::BlockNumberOrTag; use env_logger::Env as EnvLog; use loom_evm_db::{DatabaseLoomExt, LoomDBType}; use loom_node_debug_provider::AnvilDebugProviderFactory; diff --git a/crates/defi/pools/src/db_reader/uniswapv3.rs b/crates/defi/pools/src/db_reader/uniswapv3.rs index ef5388e7..ae3982ea 100644 --- a/crates/defi/pools/src/db_reader/uniswapv3.rs +++ b/crates/defi/pools/src/db_reader/uniswapv3.rs @@ -1,7 +1,7 @@ use std::ops::{BitAnd, Shl, Shr}; -use alloy_primitives::{Address, Signed, Uint, B256, I256}; -use alloy_primitives::{U160, U256}; +use alloy::primitives::{Address, Signed, Uint, B256, I256}; +use alloy::primitives::{U160, U256}; use eyre::Result; use lazy_static::lazy_static; use revm::DatabaseRef; @@ -96,7 +96,7 @@ impl UniswapV3DBReader { #[cfg(test)] mod test { - use alloy_primitives::Address; + use alloy::primitives::Address; use eyre::Result; use revm::primitives::Env; use std::env; diff --git a/crates/defi/pools/src/loaders/curve.rs b/crates/defi/pools/src/loaders/curve.rs index 186e336b..794d90e6 100644 --- a/crates/defi/pools/src/loaders/curve.rs +++ b/crates/defi/pools/src/loaders/curve.rs @@ -1,18 +1,15 @@ use crate::protocols::CurveProtocol; use crate::{pool_loader, CurvePool}; -use alloy_primitives::Bytes; -use alloy_provider::network::Ethereum; -use alloy_provider::Network; -use alloy_provider::Provider; -use alloy_transport::Transport; +use alloy::primitives::Bytes; +use alloy::providers::network::Ethereum; +use async_stream::stream; use eyre::{eyre, ErrReport}; -use loom_types_blockchain::LoomDataTypes; -use loom_types_blockchain::LoomDataTypesEthereum; +use futures::Stream; +use loom_types_blockchain::{LoomDataTypes, LoomDataTypesEthereum}; use loom_types_entities::{PoolClass, PoolId, PoolLoader, PoolWrapper}; use revm::primitives::Env; use revm::DatabaseRef; use std::future::Future; -use std::marker::PhantomData; use std::pin::Pin; use std::sync::Arc; use tracing::error; @@ -78,4 +75,31 @@ where fn is_code(&self, _code: &Bytes) -> bool { false } + + fn protocol_loader(&self) -> eyre::Result + Send>>> { + let provider_clone = self.provider.clone(); + + if let Some(client) = provider_clone { + Ok(Box::pin(stream! { + let curve_contracts = CurveProtocol::get_contracts_vec(client.clone()); + for curve_contract in curve_contracts.iter() { + yield (PoolId::Address(curve_contract.get_address()), PoolClass::Curve) + } + + for factory_idx in 0..10 { + if let Ok(factory_address) = CurveProtocol::get_factory_address(client.clone(), factory_idx).await { + if let Ok(pool_count) = CurveProtocol::get_pool_count(client.clone(), factory_address).await { + for pool_id in 0..pool_count { + if let Ok(addr) = CurveProtocol::get_pool_address(client.clone(), factory_address, pool_id).await { + yield (PoolId::Address(addr), PoolClass::Curve) + } + } + } + } + } + })) + } else { + Err(eyre!("NO_PROVIDER")) + } + } } diff --git a/crates/defi/pools/src/loaders/maverick.rs b/crates/defi/pools/src/loaders/maverick.rs index 098635d5..b0394603 100644 --- a/crates/defi/pools/src/loaders/maverick.rs +++ b/crates/defi/pools/src/loaders/maverick.rs @@ -1,10 +1,8 @@ use crate::{pool_loader, MaverickPool}; -use alloy_primitives::Bytes; -use alloy_primitives::Log as EVMLog; -use alloy_provider::network::Ethereum; -use alloy_provider::{Network, Provider}; -use alloy_sol_types::SolEventInterface; -use alloy_transport::Transport; +use alloy::primitives::Bytes; +use alloy::primitives::Log as EVMLog; +use alloy::providers::network::Ethereum; +use alloy::sol_types::SolEventInterface; use eyre::{eyre, ErrReport, Result}; use loom_defi_abi::maverick::IMaverickPool::IMaverickPoolEvents; use loom_types_blockchain::{LoomDataTypes, LoomDataTypesEthereum}; @@ -12,9 +10,9 @@ use loom_types_entities::{PoolClass, PoolId, PoolLoader, PoolWrapper}; use revm::primitives::Env; use revm::DatabaseRef; use std::future::Future; -use std::marker::PhantomData; use std::pin::Pin; use std::sync::Arc; +use tokio_stream::Stream; pool_loader!(MaverickPoolLoader); @@ -75,4 +73,8 @@ where fn is_code(&self, _code: &Bytes) -> bool { false } + + fn protocol_loader(&self) -> Result + Send>>> { + Err(eyre!("NOT_IMPLEMENTED")) + } } diff --git a/crates/defi/pools/src/loaders/mod.rs b/crates/defi/pools/src/loaders/mod.rs index fe103a06..63827899 100644 --- a/crates/defi/pools/src/loaders/mod.rs +++ b/crates/defi/pools/src/loaders/mod.rs @@ -4,9 +4,9 @@ mod uniswap2; mod uniswap3; use crate::loaders::curve::CurvePoolLoader; -use alloy_provider::network::Ethereum; -use alloy_provider::{Network, Provider}; -use alloy_transport::Transport; +use alloy::providers::network::Ethereum; +use alloy::providers::{Network, Provider}; +use alloy::transports::Transport; use loom_types_blockchain::{LoomDataTypes, LoomDataTypesEthereum}; use loom_types_entities::pool_config::PoolsConfig; use loom_types_entities::{PoolClass, PoolLoader, PoolLoaders}; @@ -15,11 +15,17 @@ use std::sync::Arc; pub use uniswap2::UniswapV2PoolLoader; pub use uniswap3::UniswapV3PoolLoader; +/// creates pool loader and imports necessary crates #[macro_export] macro_rules! pool_loader { // This will match the input like MaverickPoolLoader ($name:ident) => { + use alloy::providers::{Network, Provider}; + use alloy::transports::Transport; + use std::marker::PhantomData; + #[derive(Clone)] + pub struct $name where T: Transport + Clone, @@ -31,6 +37,7 @@ macro_rules! pool_loader { phantom_data: PhantomData<(P, T, N, LDT)>, } + #[allow(dead_code)] impl $name where T: Transport + Clone, @@ -41,6 +48,10 @@ macro_rules! pool_loader { pub fn new() -> Self { Self::default() } + + pub fn with_provider(provder: P) -> Self { + Self { provider: Some(provder), phantom_data: PhantomData } + } } impl Default for $name diff --git a/crates/defi/pools/src/loaders/uniswap2.rs b/crates/defi/pools/src/loaders/uniswap2.rs index 29f0f5f0..f0e9ad4e 100644 --- a/crates/defi/pools/src/loaders/uniswap2.rs +++ b/crates/defi/pools/src/loaders/uniswap2.rs @@ -1,19 +1,17 @@ use crate::protocols::{fetch_uni2_factory, UniswapV2Protocol}; use crate::{pool_loader, UniswapV2Pool}; -use alloy_primitives::Bytes; -use alloy_primitives::Log as EVMLog; -use alloy_provider::network::Ethereum; -use alloy_provider::{Network, Provider}; -use alloy_sol_types::SolEventInterface; -use alloy_transport::Transport; +use alloy::primitives::Bytes; +use alloy::primitives::Log as EVMLog; +use alloy::providers::network::Ethereum; +use alloy::sol_types::SolEventInterface; use eyre::{eyre, ErrReport}; +use futures::Stream; use loom_defi_abi::uniswap2::IUniswapV2Pair::IUniswapV2PairEvents; use loom_types_blockchain::{LoomDataTypes, LoomDataTypesEthereum}; use loom_types_entities::{get_protocol_by_factory, PoolClass, PoolId, PoolLoader, PoolProtocol, PoolWrapper}; use revm::primitives::Env; use revm::DatabaseRef; use std::future::Future; -use std::marker::PhantomData; use std::pin::Pin; use std::sync::Arc; @@ -86,4 +84,8 @@ where fn is_code(&self, code: &Bytes) -> bool { UniswapV2Protocol::is_code(code) } + + fn protocol_loader(&self) -> eyre::Result + Send>>> { + Err(eyre!("NOT_IMPLEMENTED")) + } } diff --git a/crates/defi/pools/src/loaders/uniswap3.rs b/crates/defi/pools/src/loaders/uniswap3.rs index 10fe638a..131996a5 100644 --- a/crates/defi/pools/src/loaders/uniswap3.rs +++ b/crates/defi/pools/src/loaders/uniswap3.rs @@ -1,20 +1,17 @@ use crate::protocols::{fetch_uni3_factory, UniswapV3Protocol}; use crate::{pool_loader, MaverickPool, PancakeV3Pool, UniswapV3Pool}; -use alloy_primitives::Bytes; -use alloy_primitives::Log as EVMLog; -use alloy_provider::network::Ethereum; -use alloy_provider::Network; -use alloy_provider::Provider; -use alloy_sol_types::SolEventInterface; -use alloy_transport::Transport; +use alloy::primitives::Bytes; +use alloy::primitives::Log as EVMLog; +use alloy::providers::network::Ethereum; +use alloy::sol_types::SolEventInterface; use eyre::{eyre, ErrReport}; +use futures::Stream; use loom_defi_abi::uniswap3::IUniswapV3Pool::IUniswapV3PoolEvents; use loom_types_blockchain::{LoomDataTypes, LoomDataTypesEthereum}; use loom_types_entities::{get_protocol_by_factory, PoolClass, PoolId, PoolLoader, PoolProtocol, PoolWrapper}; use revm::primitives::Env; use revm::DatabaseRef; use std::future::Future; -use std::marker::PhantomData; use std::pin::Pin; use std::sync::Arc; use tracing::error; @@ -98,4 +95,8 @@ where fn is_code(&self, code: &Bytes) -> bool { UniswapV3Protocol::is_code(code) } + + fn protocol_loader(&self) -> eyre::Result + Send>>> { + Err(eyre!("NOT_IMPLEMENTED")) + } } diff --git a/crates/defi/pools/src/maverickpool.rs b/crates/defi/pools/src/maverickpool.rs index f92b9581..e213eefc 100644 --- a/crates/defi/pools/src/maverickpool.rs +++ b/crates/defi/pools/src/maverickpool.rs @@ -1,7 +1,7 @@ -use alloy_primitives::{Address, Bytes, U128, U256}; -use alloy_provider::{Network, Provider}; -use alloy_sol_types::{SolCall, SolInterface}; -use alloy_transport::Transport; +use alloy::primitives::{Address, Bytes, U128, U256}; +use alloy::providers::{Network, Provider}; +use alloy::sol_types::{SolCall, SolInterface}; +use alloy::transports::Transport; use eyre::{eyre, ErrReport, OptionExt, Result}; use loom_defi_abi::maverick::IMaverickPool::{getStateCall, IMaverickPoolCalls, IMaverickPoolInstance}; use loom_defi_abi::maverick::IMaverickQuoter::{calculateSwapCall, IMaverickQuoterCalls}; @@ -425,8 +425,8 @@ impl PoolAbiEncoder for MaverickAbiSwapEncoder { #[cfg(test)] mod tests { use super::*; - use alloy_provider::network::primitives::BlockTransactionsKind; - use alloy_rpc_types::BlockNumberOrTag; + use alloy::providers::network::primitives::BlockTransactionsKind; + use alloy::rpc::types::BlockNumberOrTag; use loom_defi_abi::maverick::IMaverickQuoter::IMaverickQuoterInstance; use loom_evm_db::LoomDBType; use loom_evm_utils::evm_env::env_for_block; diff --git a/crates/defi/pools/src/pancakev3pool.rs b/crates/defi/pools/src/pancakev3pool.rs index feb1270c..f9c4ebdf 100644 --- a/crates/defi/pools/src/pancakev3pool.rs +++ b/crates/defi/pools/src/pancakev3pool.rs @@ -2,11 +2,11 @@ use std::fmt::Debug; use std::ops::Sub; use crate::state_readers::UniswapV3StateReader; -use alloy_primitives::aliases::{I24, U24}; -use alloy_primitives::{Address, Bytes, I256, U160, U256}; -use alloy_provider::{Network, Provider}; -use alloy_sol_types::{SolCall, SolInterface}; -use alloy_transport::Transport; +use alloy::primitives::aliases::{I24, U24}; +use alloy::primitives::{Address, Bytes, I256, U160, U256}; +use alloy::providers::{Network, Provider}; +use alloy::sol_types::{SolCall, SolInterface}; +use alloy::transports::Transport; use eyre::{eyre, ErrReport, OptionExt, Result}; use loom_defi_abi::pancake::IPancakeQuoterV2::IPancakeQuoterV2Calls; use loom_defi_abi::pancake::IPancakeV3Pool::slot0Return; diff --git a/crates/defi/pools/src/protocols/curve.rs b/crates/defi/pools/src/protocols/curve.rs index d94b153a..4ea367bb 100644 --- a/crates/defi/pools/src/protocols/curve.rs +++ b/crates/defi/pools/src/protocols/curve.rs @@ -1,11 +1,11 @@ use std::fmt::{Display, Formatter}; use std::marker::PhantomData; -use alloy_primitives::{address, Address, Bytes, U256}; -use alloy_provider::{Network, Provider}; -use alloy_rpc_types::{BlockId, BlockNumberOrTag}; -use alloy_sol_types::SolInterface; -use alloy_transport::Transport; +use alloy::primitives::{address, Address, Bytes, U256}; +use alloy::providers::{Network, Provider}; +use alloy::rpc::types::{BlockId, BlockNumberOrTag}; +use alloy::sol_types::SolInterface; +use alloy::transports::Transport; use eyre::{eyre, Report, Result}; use tracing::{debug, error, trace}; diff --git a/crates/defi/pools/src/protocols/helper.rs b/crates/defi/pools/src/protocols/helper.rs index 6f3ea35d..0f38affd 100644 --- a/crates/defi/pools/src/protocols/helper.rs +++ b/crates/defi/pools/src/protocols/helper.rs @@ -1,6 +1,6 @@ -use alloy_primitives::{keccak256, Address, Bytes, B256}; -use alloy_provider::{Network, Provider}; -use alloy_transport::Transport; +use alloy::primitives::{keccak256, Address, Bytes, B256}; +use alloy::providers::{Network, Provider}; +use alloy::transports::Transport; use eyre::Result; use loom_defi_abi::uniswap2::IUniswapV2Pair; diff --git a/crates/defi/pools/src/protocols/protocol.rs b/crates/defi/pools/src/protocols/protocol.rs index 9e5c48a0..4540857d 100644 --- a/crates/defi/pools/src/protocols/protocol.rs +++ b/crates/defi/pools/src/protocols/protocol.rs @@ -1,4 +1,4 @@ -use alloy_primitives::Address; +use alloy::primitives::Address; #[allow(dead_code)] pub trait Protocol { diff --git a/crates/defi/pools/src/protocols/sushiswap.rs b/crates/defi/pools/src/protocols/sushiswap.rs index 30f773c2..8bddb890 100644 --- a/crates/defi/pools/src/protocols/sushiswap.rs +++ b/crates/defi/pools/src/protocols/sushiswap.rs @@ -1,6 +1,6 @@ use crate::protocols::helper::get_uniswap2pool_address; use crate::protocols::protocol::Protocol; -use alloy_primitives::{Address, B256}; +use alloy::primitives::{Address, B256}; use loom_defi_address_book::FactoryAddress; pub struct SushiswapProtocol {} diff --git a/crates/defi/pools/src/protocols/uniswapv2.rs b/crates/defi/pools/src/protocols/uniswapv2.rs index 36ac1009..95e35402 100644 --- a/crates/defi/pools/src/protocols/uniswapv2.rs +++ b/crates/defi/pools/src/protocols/uniswapv2.rs @@ -1,5 +1,5 @@ -use alloy_primitives::{b256, Address, Bytes, B256}; -use alloy_sol_types::SolCall; +use alloy::primitives::{b256, Address, Bytes, B256}; +use alloy::sol_types::SolCall; use loom_defi_abi::uniswap2::IUniswapV2Pair; use loom_defi_address_book::FactoryAddress; diff --git a/crates/defi/pools/src/protocols/uniswapv3.rs b/crates/defi/pools/src/protocols/uniswapv3.rs index c0d657a8..4757cd25 100644 --- a/crates/defi/pools/src/protocols/uniswapv3.rs +++ b/crates/defi/pools/src/protocols/uniswapv3.rs @@ -1,5 +1,5 @@ -use alloy_primitives::{b256, Address, Bytes, B256}; -use alloy_sol_types::SolCall; +use alloy::primitives::{b256, Address, Bytes, B256}; +use alloy::sol_types::SolCall; use loom_defi_abi::uniswap3::IUniswapV3Pool; use loom_defi_address_book::FactoryAddress; diff --git a/crates/defi/pools/src/state_readers/erc20.rs b/crates/defi/pools/src/state_readers/erc20.rs index f7d2f37f..475f90b4 100644 --- a/crates/defi/pools/src/state_readers/erc20.rs +++ b/crates/defi/pools/src/state_readers/erc20.rs @@ -1,6 +1,5 @@ -use alloy_primitives::{Address, U256}; -use alloy_sol_types::SolCall; -use alloy_sol_types::SolInterface; +use alloy::primitives::{Address, U256}; +use alloy::sol_types::{SolCall, SolInterface}; use eyre::Result; use loom_defi_abi::IERC20; use loom_evm_utils::evm::evm_call; diff --git a/crates/defi/pools/src/state_readers/uniswapv2.rs b/crates/defi/pools/src/state_readers/uniswapv2.rs index 847c5dc9..320e7511 100644 --- a/crates/defi/pools/src/state_readers/uniswapv2.rs +++ b/crates/defi/pools/src/state_readers/uniswapv2.rs @@ -1,5 +1,5 @@ -use alloy_primitives::{Address, U256}; -use alloy_sol_types::{SolCall, SolInterface}; +use alloy::primitives::{Address, U256}; +use alloy::sol_types::{SolCall, SolInterface}; use eyre::Result; use revm::primitives::Env; use revm::DatabaseRef; diff --git a/crates/defi/pools/src/state_readers/uniswapv3.rs b/crates/defi/pools/src/state_readers/uniswapv3.rs index c06ae13b..52b178f1 100644 --- a/crates/defi/pools/src/state_readers/uniswapv3.rs +++ b/crates/defi/pools/src/state_readers/uniswapv3.rs @@ -1,6 +1,6 @@ -use alloy_primitives::aliases::U24; -use alloy_primitives::Address; -use alloy_sol_types::{SolCall, SolInterface}; +use alloy::primitives::aliases::U24; +use alloy::primitives::Address; +use alloy::sol_types::{SolCall, SolInterface}; use revm::primitives::Env; use revm::DatabaseRef; diff --git a/crates/defi/pools/src/state_readers/uniswapv3_quoter.rs b/crates/defi/pools/src/state_readers/uniswapv3_quoter.rs index cd4ba475..fc9548af 100644 --- a/crates/defi/pools/src/state_readers/uniswapv3_quoter.rs +++ b/crates/defi/pools/src/state_readers/uniswapv3_quoter.rs @@ -1,6 +1,6 @@ -use alloy_primitives::aliases::U24; -use alloy_primitives::{Address, U160, U256}; -use alloy_sol_types::SolCall; +use alloy::primitives::aliases::U24; +use alloy::primitives::{Address, U160, U256}; +use alloy::sol_types::SolCall; use eyre::{eyre, Result}; use loom_defi_abi::uniswap_periphery::IQuoterV2; use loom_evm_utils::evm::evm_call; diff --git a/crates/defi/pools/src/uniswapv2pool.rs b/crates/defi/pools/src/uniswapv2pool.rs index 6f11483f..0727834b 100644 --- a/crates/defi/pools/src/uniswapv2pool.rs +++ b/crates/defi/pools/src/uniswapv2pool.rs @@ -1,8 +1,8 @@ -use alloy_primitives::{Address, Bytes, U256}; -use alloy_provider::{Network, Provider}; -use alloy_rpc_types::BlockNumberOrTag; -use alloy_sol_types::SolInterface; -use alloy_transport::Transport; +use alloy::primitives::{Address, Bytes, U256}; +use alloy::providers::{Network, Provider}; +use alloy::rpc::types::BlockNumberOrTag; +use alloy::sol_types::SolInterface; +use alloy::transports::Transport; use eyre::{eyre, ErrReport, Result}; use lazy_static::lazy_static; use loom_defi_abi::uniswap2::IUniswapV2Pair; @@ -374,8 +374,8 @@ impl PoolAbiEncoder for UniswapV2PoolAbiEncoder { #[cfg(test)] mod test { use super::*; - use alloy_primitives::{address, BlockNumber}; - use alloy_rpc_types::BlockId; + use alloy::primitives::{address, BlockNumber}; + use alloy::rpc::types::BlockId; use loom_defi_abi::uniswap2::IUniswapV2Router; use loom_defi_address_book::PeripheryAddress; use loom_evm_db::LoomDBType; diff --git a/crates/defi/pools/src/uniswapv3pool.rs b/crates/defi/pools/src/uniswapv3pool.rs index f0330c45..efcef9cc 100644 --- a/crates/defi/pools/src/uniswapv3pool.rs +++ b/crates/defi/pools/src/uniswapv3pool.rs @@ -3,10 +3,10 @@ use std::ops::Sub; use crate::state_readers::UniswapV3QuoterV2StateReader; use crate::state_readers::{UniswapV3QuoterV2Encoder, UniswapV3StateReader}; -use alloy_primitives::{Address, Bytes, I256, U160, U256}; -use alloy_provider::{Network, Provider}; -use alloy_sol_types::{SolCall, SolInterface}; -use alloy_transport::Transport; +use alloy::primitives::{Address, Bytes, I256, U160, U256}; +use alloy::providers::{Network, Provider}; +use alloy::sol_types::{SolCall, SolInterface}; +use alloy::transports::Transport; use eyre::{eyre, ErrReport, OptionExt, Result}; use loom_defi_abi::uniswap3::IUniswapV3Pool; use loom_defi_abi::uniswap3::IUniswapV3Pool::slot0Return; @@ -503,8 +503,8 @@ impl PoolAbiEncoder for UniswapV3AbiSwapEncoder { #[cfg(test)] mod test { use super::*; - use alloy_primitives::{address, BlockNumber}; - use alloy_rpc_types::{BlockId, BlockNumberOrTag}; + use alloy::primitives::{address, BlockNumber}; + use alloy::rpc::types::{BlockId, BlockNumberOrTag}; use loom_defi_abi::uniswap_periphery::IQuoterV2; use loom_defi_abi::uniswap_periphery::IQuoterV2::{QuoteExactInputSingleParams, QuoteExactOutputSingleParams}; use loom_defi_address_book::{PeripheryAddress, UniswapV3PoolAddress}; diff --git a/crates/defi/pools/src/virtual_impl/tick_provider.rs b/crates/defi/pools/src/virtual_impl/tick_provider.rs index d54abd15..ee1cb9eb 100644 --- a/crates/defi/pools/src/virtual_impl/tick_provider.rs +++ b/crates/defi/pools/src/virtual_impl/tick_provider.rs @@ -1,27 +1,27 @@ use crate::db_reader::UniswapV3DBReader; -use alloy_primitives::{Address, U256}; +use alloy::primitives::{Address, U256}; use loom_defi_uniswap_v3_math::tick_provider::TickProvider; use revm::DatabaseRef; -pub struct TickProviderEVMDB<'a, DB> { - pub db: &'a DB, +pub struct TickProviderEVMDB { + pub db: DB, pub pool_address: Address, } -impl<'a, DB> TickProviderEVMDB<'a, DB> +impl TickProviderEVMDB where DB: DatabaseRef, { - pub fn new(db: &'a DB, pool_address: Address) -> Self { + pub fn new(db: DB, pool_address: Address) -> Self { TickProviderEVMDB { db, pool_address } } } -impl<'a, DB> TickProvider for TickProviderEVMDB<'a, DB> +impl TickProvider for TickProviderEVMDB where DB: DatabaseRef, { fn get_tick(&self, tick: i16) -> eyre::Result { - UniswapV3DBReader::tick_bitmap(self.db, self.pool_address, tick) + UniswapV3DBReader::tick_bitmap(&self.db, self.pool_address, tick) } } diff --git a/crates/defi/pools/src/virtual_impl/uniswapv3.rs b/crates/defi/pools/src/virtual_impl/uniswapv3.rs index d7c931cd..631813aa 100644 --- a/crates/defi/pools/src/virtual_impl/uniswapv3.rs +++ b/crates/defi/pools/src/virtual_impl/uniswapv3.rs @@ -1,4 +1,4 @@ -use alloy_primitives::{Address, I256, U256}; +use alloy::primitives::{Address, I256, U256}; use eyre::eyre; use loom_defi_uniswap_v3_math::tick_math::{MAX_SQRT_RATIO, MAX_TICK, MIN_SQRT_RATIO, MIN_TICK}; use revm::DatabaseRef; @@ -337,7 +337,7 @@ impl UniswapV3PoolVirtual { #[cfg(test)] mod test { - use alloy_primitives::U256; + use alloy::primitives::U256; use loom_defi_uniswap_v3_math::full_math::mul_div_rounding_up; #[test] diff --git a/crates/execution/estimator/src/evm.rs b/crates/execution/estimator/src/evm.rs index f9812caa..e34d94f6 100644 --- a/crates/execution/estimator/src/evm.rs +++ b/crates/execution/estimator/src/evm.rs @@ -99,6 +99,8 @@ where estimate_request.swap ); // simulation has failed but this could be caused by a token / pool with unsupported fee issue + trace!("evm_access_list error calldata : {} {}", to, call_data); + return Ok(()); } }; diff --git a/crates/execution/multicaller/src/helpers.rs b/crates/execution/multicaller/src/abi_helpers.rs similarity index 97% rename from crates/execution/multicaller/src/helpers.rs rename to crates/execution/multicaller/src/abi_helpers.rs index 7f5042c4..07951555 100644 --- a/crates/execution/multicaller/src/helpers.rs +++ b/crates/execution/multicaller/src/abi_helpers.rs @@ -93,11 +93,11 @@ impl AbiEncoderHelper { IMultiCaller::revertArgCall { value }.abi_encode().into() } - pub fn encode_multicaller_revert_stack() -> Bytes { + pub fn encode_multicaller_log_stack() -> Bytes { IMultiCaller::logStackCall {}.abi_encode().into() } - pub fn encode_multicaller_revert_stack_offset(offset: U256) -> Bytes { + pub fn encode_multicaller_log_stack_offset(offset: U256) -> Bytes { IMultiCaller::logStackOffsetCall { offset }.abi_encode().into() } diff --git a/crates/execution/multicaller/src/deploy.rs b/crates/execution/multicaller/src/deploy.rs index eeb65fd1..09d443c2 100644 --- a/crates/execution/multicaller/src/deploy.rs +++ b/crates/execution/multicaller/src/deploy.rs @@ -18,9 +18,9 @@ use tracing::{debug, error, info}; lazy_static! { //static ref NO_OWNER_CODE : Vec = hex::decode("3615612c16575f3560e01c806328472417146115b2578063fa461e33146115e357806323a69e75146115e35780638b418713146115aa57806320c13b0b14612ae75780631626ba7e14612af7578063f04f2707146100e9578063ab6291fe146115ba578063923b8a2a146115c25750606435806080146100b75750604435806060146115e35750600435806020146100af5750602435806040146100af57506084358060a0146100af5750612c16565b600401611665565b8035601414612b07575060243580156100d2576020526100da565b506044356020525b60205f52606435600401611665565b5060643560040180358091602001610120375961010052610120016101205b8080518060f01c806180001615156101fd57828260b01c62ffffff1680156101b9578062ffffff146101b9579081610fff160181600c1c60ff1680156101b757908260141c60071660051b6020018362800000161561016957602090035f51035b905b8215156101795750506101b1565b826020116101985781518152602001906020019160209003919061016b565b905160018360031b1b6001900380199116908251161790525b506101bb565b505b505b5061ffff1680156115575780617ffc146102b55780617ffe14610dc65780617ffb146104325780617fff14610e5f5780617ffd14610ef85780617ffa1461035e575b508060b01c697fffffffffffffffffff1691908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612c1a579491505015156102ab578060c81c62ffffff1680156102a9578062ffffff146102a95780610fff1681600c1c60ff16908260141c60071660051b836280000016156102a4575f510380830160051c60051b83601f16156102a1576020015f81525b5f525b6020013e5b505b505060200161155d565b505f91908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612c1a57949150501515610354578060c81c62ffffff168015610352578062ffffff146103525780610fff1681600c1c60ff16908260141c60071660051b8362800000161561034d575f510380830160051c60051b83601f161561034a576020015f81525b5f525b6020013e5b505b505060200161155d565b508060b01c62ffffff168060141c60071660051b6020018162800000161561038857602090035f51035b51905091908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612c1a57949150501515610428578060c81c62ffffff168015610426578062ffffff146104265780610fff1681600c1c60ff16908260141c60071660051b83628000001615610421575f510380830160051c60051b83601f161561041e576020015f81525b5f525b6020013e5b505b505060200161155d565b5060a01c61ffff16600c0190600c015b805160f81c8015610db5576010811161056157806001146104cb57806002146104d657806003146104e157806004146104ec57806005146104f75780600614610502578060071461050d57806008146105185780600a1461052b5780600b146105345780600c1461053d5780600d146105465780600e1461054f5780600f146105585750610db5565b506020516001610dad565b506040516001610dad565b506060516001610dad565b506080516001610dad565b5060a0516001610dad565b5060c0516001610dad565b5060e0516001610dad565b505f51805190602090035f526001610dad565b50476001610dad565b50416001610dad565b50426001610dad565b50436001610dad565b50486001610dad565b503a6001610dad565b60208110156106a057806011146105e857806012146105f357806013146105fe57806014146106095780601514610614578060161461061f578060171461062a578060181461063557806019146106405780601a1461064a5780601b1461065e5780601c146106725780601d1461067f5780601e1461068c5780601f146106965750610db5565b509190016001610dad565b509190036001610dad565b509190026001610dad565b509190046001610dad565b509190056001610dad565b509190166001610dad565b509190176001610dad565b509190186001610dad565b5090196001610dad565b50806001015160f81c9091901b6002610dad565b50806001015160f81c9091901c6002610dad565b5090600190016001610dad565b5090600190036001610dad565b5091036001610dad565b5091046001610dad565b60308110156107d657806020146106ef578060211461070057806022146107105780602314610734578060241461074b578060251461076857806026146107875780602a146107aa5750610db5565b5080600101516021610dad56610db5565b50806001015160ff166002610dad565b50806001015161ffff166003610dad565b50806001015163ffffffff166005610dad565b50806001015167ffffffffffffffff166009610dad565b5080600101516dffffffffffffffffffffffffffff166007610dad565b5080600101516fffffffffffffffffffffffffffffffff166009610dad565b50806001015173ffffffffffffffffffffffffffffffffffffffff16600d610dad565b50907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90026001610dad565b6030811015610894578060311461080d578060321461081857806033146108325780603414610844578060351461085c5750610db5565b5060ff166001610dad565b5061ffff166001610dad565b5063ffffffff166001610dad565b5067ffffffffffffffff166001610dad565b506dffffffffffffffffffffffffffff166001610dad565b506fffffffffffffffffffffffffffffffff166001610dad565b5073ffffffffffffffffffffffffffffffffffffffff166001610dad565b6050811015610d275780604014610923578060411461098b57806042146109f25780604314610a5a5780604414610ac15780604514610b295780604614610b905780604714610bf55780604814610c5b5780604914610c755780604a14610c8e5780604b14610ca85780604c14610cc15780604d14610cdb5780604e14610cf45780604f14610d0b5750610db5565b50919014156109355760016001610dad565b7f455100000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901461099c5760016001610dad565b7f4e4551000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901015610a045760016001610dad565b7f4c5400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919010610a6b5760016001610dad565b7f475445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901115610ad35760016001610dad565b7f475400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919011610b3a5760016001610dad565b7f4c5445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5090610b9f5760016001610dad565b7f5a5200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509015610c055760016001610dad565b7f4e5a52000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901415610c6d5760016001610dad565b5f5f5260205ff35b50919014610c865760016001610dad565b5f5f5260205ff35b5091901015610ca05760016001610dad565b5f5f5260205ff35b50919010610cb95760016001610dad565b5f5f5260205ff35b5091901115610cd35760016001610dad565b5f5f5260205ff35b50919011610cec5760016001610dad565b5f5f5260205ff35b5090610d035760016001610dad565b5f5f5260205ff35b509015610d1b5760016001610dad565b5f5f5260205ff3610db5565b6060811015610da75780605014610d465780605114610d7a5750610db5565b50806001015160f81c8060051b5f5103805f525f5b9060200190815101916001900391821515610d5b579150506002610dad565b50806001015160f81c5f515f5b815101906020900390916001900391821515610d87579150506002610dad565b50610db5565b909101610442565b50505f516020019081525f5261155d565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855afa15612c1a5792505060c81c62ffffff168015610e56578062ffffff14610e565780610fff1681600c1c60ff16908260141c60071660051b83628000001615610e51575f510380830160051c60051b83601f1615610e4e576020015f81525b5f525b6020013e5b5060200161155d565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855af415612c1a5792505060c81c62ffffff168015610eef578062ffffff14610eef5780610fff1681600c1c60ff16908260141c60071660051b83628000001615610eea575f510380830160051c60051b83601f1615610ee7576020015f81525b5f525b6020013e5b5060200161155d565b508060a01c61ffff1682600c015160e01c8063a85f1d24146113895780634df86adf146112a457806305ec9cad146114445780639b81788b14610f8c5780638bceaa1814610fef57806384f16ca01461105157806395b66162146110b45780639a23842e146111165780634fae2f231461117a578063a9f2812f146111dd578063f93a171614611241576199995f5260205ffd5b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa15610fc957905080602001519051610fce565b50505f5f5b9082026127100291900390910290046001015f516020019081525f5261154c565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa1561102c57905080602001519051611031565b50505f5f5b82026127100291900390910290046001015f516020019081525f5261154c565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa1561108e57905080602001519051611093565b50505f5f5b9090919092029182029190612710020190045f516020019081525f5261154c565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156110f1579050806020015190516110f6565b50505f5f5b90919092029182029190612710020190045f516020019081525f5261154c565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561115457905080602001519051611159565b50505f5f5b9082026127100291900390910290046001015f516020019081525f5261154c565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156111b8579050806020015190516111bd565b50505f5f5b82026127100291900390910290046001015f516020019081525f5261154c565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561121b57905080602001519051611220565b50505f5f5b9090919092029182029190612710020190045f516020019081525f5261154c565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561127f57905080602001519051611284565b50505f5f5b90919092029182029190612710020190045f516020019081525f5261154c565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa15612c1a575180156112e757600190035b80841115611345577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b85606401516101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050508015611380575f5f5f5f84415af1505b5050505061154c565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa15612c1a575180156113cc57600190035b8084111561142a577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5050801561143c575f5f5f5f84415af1505b50505061154c565b5083600c0173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160040151826024015182610100516370a082318152308160200152602081602483601c01855afa15612c1a5751801561149757600190035b808411156114f5577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b61010051632e1a7d4d81529081602001525f5f602483601c015f73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25af150508115611538575f5f5f5f85415af1505b84604401515f5f5f475f945af15050505050505b915050600c0161155d565b5061ffff015b01818110610108575b505060043560240135602435602401356044356024013501336101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af1505050612c22565b506084611665565b506024611665565b506004611665565b6044356004018035601414612bcf575060043560405260243560205261165a565b506044356004018035601414612bcf57506004355f811261162e576040526024357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0260205261165a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff026020526024356040525b60405f526044356004015b80358091602001610120375961010052610120016101205b8080518060f01c8061800016151561177257828260b01c62ffffff16801561172e578062ffffff1461172e579081610fff160181600c1c60ff16801561172c57908260141c60071660051b602001836280000016156116de57602090035f51035b905b8215156116ee575050611726565b8260201161170d578151815260200190602001916020900391906116e0565b905160018360031b1b6001900380199116908251161790525b50611730565b505b505b5061ffff168015612acc5780617ffc1461182a5780617ffe1461233b5780617ffb146119a75780617fff146123d45780617ffd1461246d5780617ffa146118d3575b508060b01c697fffffffffffffffffff1691908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612c1a57949150501515611820578060c81c62ffffff16801561181e578062ffffff1461181e5780610fff1681600c1c60ff16908260141c60071660051b83628000001615611819575f510380830160051c60051b83601f1615611816576020015f81525b5f525b6020013e5b505b5050602001612ad2565b505f91908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612c1a579491505015156118c9578060c81c62ffffff1680156118c7578062ffffff146118c75780610fff1681600c1c60ff16908260141c60071660051b836280000016156118c2575f510380830160051c60051b83601f16156118bf576020015f81525b5f525b6020013e5b505b5050602001612ad2565b508060b01c62ffffff168060141c60071660051b602001816280000016156118fd57602090035f51035b51905091908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612c1a5794915050151561199d578060c81c62ffffff16801561199b578062ffffff1461199b5780610fff1681600c1c60ff16908260141c60071660051b83628000001615611996575f510380830160051c60051b83601f1615611993576020015f81525b5f525b6020013e5b505b5050602001612ad2565b5060a01c61ffff16600c0190600c015b805160f81c801561232a5760108111611ad65780600114611a405780600214611a4b5780600314611a565780600414611a615780600514611a6c5780600614611a775780600714611a825780600814611a8d5780600a14611aa05780600b14611aa95780600c14611ab25780600d14611abb5780600e14611ac45780600f14611acd575061232a565b506020516001612322565b506040516001612322565b506060516001612322565b506080516001612322565b5060a0516001612322565b5060c0516001612322565b5060e0516001612322565b505f51805190602090035f526001612322565b50476001612322565b50416001612322565b50426001612322565b50436001612322565b50486001612322565b503a6001612322565b6020811015611c155780601114611b5d5780601214611b685780601314611b735780601414611b7e5780601514611b895780601614611b945780601714611b9f5780601814611baa5780601914611bb55780601a14611bbf5780601b14611bd35780601c14611be75780601d14611bf45780601e14611c015780601f14611c0b575061232a565b509190016001612322565b509190036001612322565b509190026001612322565b509190046001612322565b509190056001612322565b509190166001612322565b509190176001612322565b509190186001612322565b5090196001612322565b50806001015160f81c9091901b6002612322565b50806001015160f81c9091901c6002612322565b5090600190016001612322565b5090600190036001612322565b5091036001612322565b5091046001612322565b6030811015611d4b5780602014611c645780602114611c755780602214611c855780602314611ca95780602414611cc05780602514611cdd5780602614611cfc5780602a14611d1f575061232a565b50806001015160216123225661232a565b50806001015160ff166002612322565b50806001015161ffff166003612322565b50806001015163ffffffff166005612322565b50806001015167ffffffffffffffff166009612322565b5080600101516dffffffffffffffffffffffffffff166007612322565b5080600101516fffffffffffffffffffffffffffffffff166009612322565b50806001015173ffffffffffffffffffffffffffffffffffffffff16600d612322565b50907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90026001612322565b6030811015611e095780603114611d825780603214611d8d5780603314611da75780603414611db95780603514611dd1575061232a565b5060ff166001612322565b5061ffff166001612322565b5063ffffffff166001612322565b5067ffffffffffffffff166001612322565b506dffffffffffffffffffffffffffff166001612322565b506fffffffffffffffffffffffffffffffff166001612322565b5073ffffffffffffffffffffffffffffffffffffffff166001612322565b605081101561229c5780604014611e985780604114611f005780604214611f675780604314611fcf5780604414612036578060451461209e5780604614612105578060471461216a57806048146121d057806049146121ea5780604a146122035780604b1461221d5780604c146122365780604d146122505780604e146122695780604f14612280575061232a565b5091901415611eaa5760016001612322565b7f455100000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919014611f115760016001612322565b7f4e4551000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901015611f795760016001612322565b7f4c5400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919010611fe05760016001612322565b7f475445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919011156120485760016001612322565b7f475400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190116120af5760016001612322565b7f4c5445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50906121145760016001612322565b7f5a5200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50901561217a5760016001612322565b7f4e5a52000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919014156121e25760016001612322565b5f5f5260205ff35b509190146121fb5760016001612322565b5f5f5260205ff35b50919010156122155760016001612322565b5f5f5260205ff35b5091901061222e5760016001612322565b5f5f5260205ff35b50919011156122485760016001612322565b5f5f5260205ff35b509190116122615760016001612322565b5f5f5260205ff35b50906122785760016001612322565b5f5f5260205ff35b5090156122905760016001612322565b5f5f5260205ff361232a565b606081101561231c57806050146122bb57806051146122ef575061232a565b50806001015160f81c8060051b5f5103805f525f5b90602001908151019160019003918215156122d0579150506002612322565b50806001015160f81c5f515f5b8151019060209003909160019003918215156122fc579150506002612322565b5061232a565b9091016119b7565b50505f516020019081525f52612ad2565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855afa15612c1a5792505060c81c62ffffff1680156123cb578062ffffff146123cb5780610fff1681600c1c60ff16908260141c60071660051b836280000016156123c6575f510380830160051c60051b83601f16156123c3576020015f81525b5f525b6020013e5b50602001612ad2565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855af415612c1a5792505060c81c62ffffff168015612464578062ffffff146124645780610fff1681600c1c60ff16908260141c60071660051b8362800000161561245f575f510380830160051c60051b83601f161561245c576020015f81525b5f525b6020013e5b50602001612ad2565b508060a01c61ffff1682600c015160e01c8063a85f1d24146128fe5780634df86adf1461281957806305ec9cad146129b95780639b81788b146125015780638bceaa181461256457806384f16ca0146125c657806395b66162146126295780639a23842e1461268b5780634fae2f23146126ef578063a9f2812f14612752578063f93a1716146127b6576199995f5260205ffd5b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa1561253e57905080602001519051612543565b50505f5f5b9082026127100291900390910290046001015f516020019081525f52612ac1565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156125a1579050806020015190516125a6565b50505f5f5b82026127100291900390910290046001015f516020019081525f52612ac1565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa1561260357905080602001519051612608565b50505f5f5b9090919092029182029190612710020190045f516020019081525f52612ac1565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156126665790508060200151905161266b565b50505f5f5b90919092029182029190612710020190045f516020019081525f52612ac1565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156126c9579050806020015190516126ce565b50505f5f5b9082026127100291900390910290046001015f516020019081525f52612ac1565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561272d57905080602001519051612732565b50505f5f5b82026127100291900390910290046001015f516020019081525f52612ac1565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561279057905080602001519051612795565b50505f5f5b9090919092029182029190612710020190045f516020019081525f52612ac1565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156127f4579050806020015190516127f9565b50505f5f5b90919092029182029190612710020190045f516020019081525f52612ac1565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa15612c1a5751801561285c57600190035b808411156128ba577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b85606401516101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af150505080156128f5575f5f5f5f84415af1505b50505050612ac1565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa15612c1a5751801561294157600190035b8084111561299f577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b505080156129b1575f5f5f5f84415af1505b505050612ac1565b5083600c0173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160040151826024015182610100516370a082318152308160200152602081602483601c01855afa15612c1a57518015612a0c57600190035b80841115612a6a577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b61010051632e1a7d4d81529081602001525f5f602483601c015f73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25af150508115612aad575f5f5f5f85415af1505b84604401515f5f5f475f945af15050505050505b915050600c01612ad2565b5061ffff015b0181811061167d575b505060205f51f3612c22565b506320c13b0b60e01b5f5260205ff35b50631626ba7e60e01b5f5260205ff35b6020013560601c6024358015612b5e573361010051630902f1ac8152606081600483601c01855afa15612b4257905080602001519051612b47565b50505f5f5b908202612710029190039091029004600101612ba4565b506044353361010051630902f1ac8152606081600483601c01855afa15612b8d57905080602001519051612b92565b50505f5f5b82026127100291900390910290046001015b336101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050505f5ff35b6020013560601c600435805f9012612be657612beb565b506024355b336101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050505f5ff35b5f5ff35b3d5f5f3e3d5ffd5b").unwrap(); - static ref NO_OWNER_CODE : Vec = hex::decode("3615612d38575f3560e01c80632847241714611643578063fa461e331461167457806323a69e75146116745780638b4187131461163b57806320c13b0b14612c065780631626ba7e14612c16578063f04f2707146100ec57806391dd73461461164b578063923b8a2a146116535750606435806080146100b75750604435806060146116745750600435806020146100af5750602435806040146100af57506084358060a0146100af5750612d38565b6004016116f6565b8060040135601414612c26575060243580156100d5576020526100dd565b506044356020525b60205f526064356004016116f6565b5060643560040180358091602001610120375961010052610120016101205b8080518060f01c8061800016151561020057828260b01c62ffffff1680156101bc578062ffffff146101bc579081610fff160181600c1c60ff1680156101ba57908260141c60071660051b6020018362800000161561016c57602090035f51035b905b82151561017c5750506101b4565b8260201161019b5781518152602001906020019160209003919061016e565b905160018360031b1b6001900380199116908251161790525b506101be565b505b505b5061ffff1680156115e85780617ffc146102b85780617ffe14610dc95780617ffb146104355780617fff14610e625780617ffd14610efb5780617ffa14610361575b508060b01c697fffffffffffffffffff1691908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612d3c579491505015156102ae578060c81c62ffffff1680156102ac578062ffffff146102ac5780610fff1681600c1c60ff16908260141c60071660051b836280000016156102a7575f510380830160051c60051b83601f16156102a4576020015f81525b5f525b6020013e5b505b50506020016115ee565b505f91908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612d3c57949150501515610357578060c81c62ffffff168015610355578062ffffff146103555780610fff1681600c1c60ff16908260141c60071660051b83628000001615610350575f510380830160051c60051b83601f161561034d576020015f81525b5f525b6020013e5b505b50506020016115ee565b508060b01c62ffffff168060141c60071660051b6020018162800000161561038b57602090035f51035b51905091908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612d3c5794915050151561042b578060c81c62ffffff168015610429578062ffffff146104295780610fff1681600c1c60ff16908260141c60071660051b83628000001615610424575f510380830160051c60051b83601f1615610421576020015f81525b5f525b6020013e5b505b50506020016115ee565b5060a01c61ffff16600c0190600c015b805160f81c8015610db8576010811161056457806001146104ce57806002146104d957806003146104e457806004146104ef57806005146104fa57806006146105055780600714610510578060081461051b5780600a1461052e5780600b146105375780600c146105405780600d146105495780600e146105525780600f1461055b5750610db8565b506020516001610db0565b506040516001610db0565b506060516001610db0565b506080516001610db0565b5060a0516001610db0565b5060c0516001610db0565b5060e0516001610db0565b505f51805190602090035f526001610db0565b50476001610db0565b50416001610db0565b50426001610db0565b50436001610db0565b50486001610db0565b503a6001610db0565b60208110156106a357806011146105eb57806012146105f65780601314610601578060141461060c57806015146106175780601614610622578060171461062d578060181461063857806019146106435780601a1461064d5780601b146106615780601c146106755780601d146106825780601e1461068f5780601f146106995750610db8565b509190016001610db0565b509190036001610db0565b509190026001610db0565b509190046001610db0565b509190056001610db0565b509190166001610db0565b509190176001610db0565b509190186001610db0565b5090196001610db0565b50806001015160f81c9091901b6002610db0565b50806001015160f81c9091901c6002610db0565b5090600190016001610db0565b5090600190036001610db0565b5091036001610db0565b5091046001610db0565b60308110156107d957806020146106f2578060211461070357806022146107135780602314610737578060241461074e578060251461076b578060261461078a5780602a146107ad5750610db8565b5080600101516021610db056610db8565b50806001015160ff166002610db0565b50806001015161ffff166003610db0565b50806001015163ffffffff166005610db0565b50806001015167ffffffffffffffff166009610db0565b5080600101516dffffffffffffffffffffffffffff166007610db0565b5080600101516fffffffffffffffffffffffffffffffff166009610db0565b50806001015173ffffffffffffffffffffffffffffffffffffffff16600d610db0565b50907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90026001610db0565b60308110156108975780603114610810578060321461081b57806033146108355780603414610847578060351461085f5750610db8565b5060ff166001610db0565b5061ffff166001610db0565b5063ffffffff166001610db0565b5067ffffffffffffffff166001610db0565b506dffffffffffffffffffffffffffff166001610db0565b506fffffffffffffffffffffffffffffffff166001610db0565b5073ffffffffffffffffffffffffffffffffffffffff166001610db0565b6050811015610d2a5780604014610926578060411461098e57806042146109f55780604314610a5d5780604414610ac45780604514610b2c5780604614610b935780604714610bf85780604814610c5e5780604914610c785780604a14610c915780604b14610cab5780604c14610cc45780604d14610cde5780604e14610cf75780604f14610d0e5750610db8565b50919014156109385760016001610db0565b7f455100000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901461099f5760016001610db0565b7f4e4551000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901015610a075760016001610db0565b7f4c5400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919010610a6e5760016001610db0565b7f475445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901115610ad65760016001610db0565b7f475400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919011610b3d5760016001610db0565b7f4c5445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5090610ba25760016001610db0565b7f5a5200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509015610c085760016001610db0565b7f4e5a52000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901415610c705760016001610db0565b5f5f5260205ff35b50919014610c895760016001610db0565b5f5f5260205ff35b5091901015610ca35760016001610db0565b5f5f5260205ff35b50919010610cbc5760016001610db0565b5f5f5260205ff35b5091901115610cd65760016001610db0565b5f5f5260205ff35b50919011610cef5760016001610db0565b5f5f5260205ff35b5090610d065760016001610db0565b5f5f5260205ff35b509015610d1e5760016001610db0565b5f5f5260205ff3610db8565b6060811015610daa5780605014610d495780605114610d7d5750610db8565b50806001015160f81c8060051b5f5103805f525f5b9060200190815101916001900391821515610d5e579150506002610db0565b50806001015160f81c5f515f5b815101906020900390916001900391821515610d8a579150506002610db0565b50610db8565b909101610445565b50505f516020019081525f526115ee565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855afa15612d3c5792505060c81c62ffffff168015610e59578062ffffff14610e595780610fff1681600c1c60ff16908260141c60071660051b83628000001615610e54575f510380830160051c60051b83601f1615610e51576020015f81525b5f525b6020013e5b506020016115ee565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855af415612d3c5792505060c81c62ffffff168015610ef2578062ffffff14610ef25780610fff1681600c1c60ff16908260141c60071660051b83628000001615610eed575f510380830160051c60051b83601f1615610eea576020015f81525b5f525b6020013e5b506020016115ee565b508060a01c61ffff1682600c015160e01c8063a85f1d24146113a25780634df86adf146112bd57806305ec9cad1461145d5780639b81788b14610fa55780638bceaa181461100857806384f16ca01461106a57806395b66162146110cd5780639a23842e1461112f5780634fae2f2314611193578063a9f2812f146111f6578063f93a17161461125a578063fcccdd98146115695780631e00cebd1461159e576199995f5260205ffd5b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa15610fe257905080602001519051610fe7565b50505f5f5b9082026127100291900390910290046001015f516020019081525f526115dd565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156110455790508060200151905161104a565b50505f5f5b82026127100291900390910290046001015f516020019081525f526115dd565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156110a7579050806020015190516110ac565b50505f5f5b9090919092029182029190612710020190045f516020019081525f526115dd565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa1561110a5790508060200151905161110f565b50505f5f5b90919092029182029190612710020190045f516020019081525f526115dd565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561116d57905080602001519051611172565b50505f5f5b9082026127100291900390910290046001015f516020019081525f526115dd565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156111d1579050806020015190516111d6565b50505f5f5b82026127100291900390910290046001015f516020019081525f526115dd565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561123457905080602001519051611239565b50505f5f5b9090919092029182029190612710020190045f516020019081525f526115dd565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156112985790508060200151905161129d565b50505f5f5b90919092029182029190612710020190045f516020019081525f526115dd565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa15612d3c5751801561130057600190035b8084111561135e577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b85606401516101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050508015611399575f5f5f5f84415af1505b505050506115dd565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa15612d3c575180156113e557600190035b80841115611443577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50508015611455575f5f5f5f84415af1505b5050506115dd565b5083600c0173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160040151826024015182610100516370a082318152308160200152602081602483601c01855afa15612d3c575180156114b057600190035b8084111561150e577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b61010051632e1a7d4d81529081602001525f5f602483601c015f73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25af150508115611551575f5f5f5f85415af1505b84604401515f5f5f475f945af15050505050506115dd565b5083600c015f51805f01517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa3506115dd565b5083600c018060240151906004015160051b5f5180919003517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa3505b915050600c016115ee565b5061ffff015b0181811061010b575b505060043560240135602435602401356044356024013501336101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af1505050612d44565b5060846116f6565b5060246116f6565b5060046116f6565b6044356004018035601414612cf157506004356040526024356020526116eb565b506044356004018035601414612cf157506004355f81126116bf576040526024357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff026020526116eb565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff026020526024356040525b60405f526044356004015b80358091602001610120375961010052610120016101205b8080518060f01c8061800016151561180357828260b01c62ffffff1680156117bf578062ffffff146117bf579081610fff160181600c1c60ff1680156117bd57908260141c60071660051b6020018362800000161561176f57602090035f51035b905b82151561177f5750506117b7565b8260201161179e57815181526020019060200191602090039190611771565b905160018360031b1b6001900380199116908251161790525b506117c1565b505b505b5061ffff168015612beb5780617ffc146118bb5780617ffe146123cc5780617ffb14611a385780617fff146124655780617ffd146124fe5780617ffa14611964575b508060b01c697fffffffffffffffffff1691908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612d3c579491505015156118b1578060c81c62ffffff1680156118af578062ffffff146118af5780610fff1681600c1c60ff16908260141c60071660051b836280000016156118aa575f510380830160051c60051b83601f16156118a7576020015f81525b5f525b6020013e5b505b5050602001612bf1565b505f91908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612d3c5794915050151561195a578060c81c62ffffff168015611958578062ffffff146119585780610fff1681600c1c60ff16908260141c60071660051b83628000001615611953575f510380830160051c60051b83601f1615611950576020015f81525b5f525b6020013e5b505b5050602001612bf1565b508060b01c62ffffff168060141c60071660051b6020018162800000161561198e57602090035f51035b51905091908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612d3c57949150501515611a2e578060c81c62ffffff168015611a2c578062ffffff14611a2c5780610fff1681600c1c60ff16908260141c60071660051b83628000001615611a27575f510380830160051c60051b83601f1615611a24576020015f81525b5f525b6020013e5b505b5050602001612bf1565b5060a01c61ffff16600c0190600c015b805160f81c80156123bb5760108111611b675780600114611ad15780600214611adc5780600314611ae75780600414611af25780600514611afd5780600614611b085780600714611b135780600814611b1e5780600a14611b315780600b14611b3a5780600c14611b435780600d14611b4c5780600e14611b555780600f14611b5e57506123bb565b5060205160016123b3565b5060405160016123b3565b5060605160016123b3565b5060805160016123b3565b5060a05160016123b3565b5060c05160016123b3565b5060e05160016123b3565b505f51805190602090035f5260016123b3565b504760016123b3565b504160016123b3565b504260016123b3565b504360016123b3565b504860016123b3565b503a60016123b3565b6020811015611ca65780601114611bee5780601214611bf95780601314611c045780601414611c0f5780601514611c1a5780601614611c255780601714611c305780601814611c3b5780601914611c465780601a14611c505780601b14611c645780601c14611c785780601d14611c855780601e14611c925780601f14611c9c57506123bb565b5091900160016123b3565b5091900360016123b3565b5091900260016123b3565b5091900460016123b3565b5091900560016123b3565b5091901660016123b3565b5091901760016123b3565b5091901860016123b3565b50901960016123b3565b50806001015160f81c9091901b60026123b3565b50806001015160f81c9091901c60026123b3565b50906001900160016123b3565b50906001900360016123b3565b50910360016123b3565b50910460016123b3565b6030811015611ddc5780602014611cf55780602114611d065780602214611d165780602314611d3a5780602414611d515780602514611d6e5780602614611d8d5780602a14611db057506123bb565b50806001015160216123b3566123bb565b50806001015160ff1660026123b3565b50806001015161ffff1660036123b3565b50806001015163ffffffff1660056123b3565b50806001015167ffffffffffffffff1660096123b3565b5080600101516dffffffffffffffffffffffffffff1660076123b3565b5080600101516fffffffffffffffffffffffffffffffff1660096123b3565b50806001015173ffffffffffffffffffffffffffffffffffffffff16600d6123b3565b50907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff900260016123b3565b6030811015611e9a5780603114611e135780603214611e1e5780603314611e385780603414611e4a5780603514611e6257506123bb565b5060ff1660016123b3565b5061ffff1660016123b3565b5063ffffffff1660016123b3565b5067ffffffffffffffff1660016123b3565b506dffffffffffffffffffffffffffff1660016123b3565b506fffffffffffffffffffffffffffffffff1660016123b3565b5073ffffffffffffffffffffffffffffffffffffffff1660016123b3565b605081101561232d5780604014611f295780604114611f915780604214611ff8578060431461206057806044146120c7578060451461212f578060461461219657806047146121fb5780604814612261578060491461227b5780604a146122945780604b146122ae5780604c146122c75780604d146122e15780604e146122fa5780604f1461231157506123bb565b5091901415611f3b57600160016123b3565b7f455100000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919014611fa257600160016123b3565b7f4e4551000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190101561200a57600160016123b3565b7f4c5400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901061207157600160016123b3565b7f475445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919011156120d957600160016123b3565b7f475400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901161214057600160016123b3565b7f4c5445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50906121a557600160016123b3565b7f5a5200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50901561220b57600160016123b3565b7f4e5a52000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190141561227357600160016123b3565b5f5f5260205ff35b5091901461228c57600160016123b3565b5f5f5260205ff35b50919010156122a657600160016123b3565b5f5f5260205ff35b509190106122bf57600160016123b3565b5f5f5260205ff35b50919011156122d957600160016123b3565b5f5f5260205ff35b509190116122f257600160016123b3565b5f5f5260205ff35b509061230957600160016123b3565b5f5f5260205ff35b50901561232157600160016123b3565b5f5f5260205ff36123bb565b60608110156123ad578060501461234c578060511461238057506123bb565b50806001015160f81c8060051b5f5103805f525f5b90602001908151019160019003918215156123615791505060026123b3565b50806001015160f81c5f515f5b81510190602090039091600190039182151561238d5791505060026123b3565b506123bb565b909101611a48565b50505f516020019081525f52612bf1565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855afa15612d3c5792505060c81c62ffffff16801561245c578062ffffff1461245c5780610fff1681600c1c60ff16908260141c60071660051b83628000001615612457575f510380830160051c60051b83601f1615612454576020015f81525b5f525b6020013e5b50602001612bf1565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855af415612d3c5792505060c81c62ffffff1680156124f5578062ffffff146124f55780610fff1681600c1c60ff16908260141c60071660051b836280000016156124f0575f510380830160051c60051b83601f16156124ed576020015f81525b5f525b6020013e5b50602001612bf1565b508060a01c61ffff1682600c015160e01c8063a85f1d24146129a55780634df86adf146128c057806305ec9cad14612a605780639b81788b146125a85780638bceaa181461260b57806384f16ca01461266d57806395b66162146126d05780639a23842e146127325780634fae2f2314612796578063a9f2812f146127f9578063f93a17161461285d578063fcccdd9814612b6c5780631e00cebd14612ba1576199995f5260205ffd5b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156125e5579050806020015190516125ea565b50505f5f5b9082026127100291900390910290046001015f516020019081525f52612be0565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156126485790508060200151905161264d565b50505f5f5b82026127100291900390910290046001015f516020019081525f52612be0565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156126aa579050806020015190516126af565b50505f5f5b9090919092029182029190612710020190045f516020019081525f52612be0565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa1561270d57905080602001519051612712565b50505f5f5b90919092029182029190612710020190045f516020019081525f52612be0565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561277057905080602001519051612775565b50505f5f5b9082026127100291900390910290046001015f516020019081525f52612be0565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156127d4579050806020015190516127d9565b50505f5f5b82026127100291900390910290046001015f516020019081525f52612be0565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156128375790508060200151905161283c565b50505f5f5b9090919092029182029190612710020190045f516020019081525f52612be0565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561289b579050806020015190516128a0565b50505f5f5b90919092029182029190612710020190045f516020019081525f52612be0565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa15612d3c5751801561290357600190035b80841115612961577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b85606401516101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af1505050801561299c575f5f5f5f84415af1505b50505050612be0565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa15612d3c575180156129e857600190035b80841115612a46577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50508015612a58575f5f5f5f84415af1505b505050612be0565b5083600c0173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160040151826024015182610100516370a082318152308160200152602081602483601c01855afa15612d3c57518015612ab357600190035b80841115612b11577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b61010051632e1a7d4d81529081602001525f5f602483601c015f73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25af150508115612b54575f5f5f5f85415af1505b84604401515f5f5f475f945af1505050505050612be0565b5083600c015f51805f01517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa350612be0565b5083600c018060240151906004015160051b5f5180919003517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa3505b915050600c01612bf1565b5061ffff015b0181811061170e575b505060205f51f3612d44565b506320c13b0b60e01b5f5260205ff35b50631626ba7e60e01b5f5260205ff35b6084356020013560601c6024358015612c80573361010051630902f1ac8152606081600483601c01855afa15612c6457905080602001519051612c69565b50505f5f5b908202612710029190039091029004600101612cc6565b506044353361010051630902f1ac8152606081600483601c01855afa15612caf57905080602001519051612cb4565b50505f5f5b82026127100291900390910290046001015b336101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050505f5ff35b6020013560601c600435805f9012612d0857612d0d565b506024355b336101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050505f5ff35b5f5ff35b3d5f5f3e3d5ffd5b").unwrap(); + //static ref NO_OWNER_CODE : Vec = hex::decode("3615612d38575f3560e01c80632847241714611643578063fa461e331461167457806323a69e75146116745780638b4187131461163b57806320c13b0b14612c065780631626ba7e14612c16578063f04f2707146100ec57806391dd73461461164b578063923b8a2a146116535750606435806080146100b75750604435806060146116745750600435806020146100af5750602435806040146100af57506084358060a0146100af5750612d38565b6004016116f6565b8060040135601414612c26575060243580156100d5576020526100dd565b506044356020525b60205f526064356004016116f6565b5060643560040180358091602001610120375961010052610120016101205b8080518060f01c8061800016151561020057828260b01c62ffffff1680156101bc578062ffffff146101bc579081610fff160181600c1c60ff1680156101ba57908260141c60071660051b6020018362800000161561016c57602090035f51035b905b82151561017c5750506101b4565b8260201161019b5781518152602001906020019160209003919061016e565b905160018360031b1b6001900380199116908251161790525b506101be565b505b505b5061ffff1680156115e85780617ffc146102b85780617ffe14610dc95780617ffb146104355780617fff14610e625780617ffd14610efb5780617ffa14610361575b508060b01c697fffffffffffffffffff1691908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612d3c579491505015156102ae578060c81c62ffffff1680156102ac578062ffffff146102ac5780610fff1681600c1c60ff16908260141c60071660051b836280000016156102a7575f510380830160051c60051b83601f16156102a4576020015f81525b5f525b6020013e5b505b50506020016115ee565b505f91908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612d3c57949150501515610357578060c81c62ffffff168015610355578062ffffff146103555780610fff1681600c1c60ff16908260141c60071660051b83628000001615610350575f510380830160051c60051b83601f161561034d576020015f81525b5f525b6020013e5b505b50506020016115ee565b508060b01c62ffffff168060141c60071660051b6020018162800000161561038b57602090035f51035b51905091908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612d3c5794915050151561042b578060c81c62ffffff168015610429578062ffffff146104295780610fff1681600c1c60ff16908260141c60071660051b83628000001615610424575f510380830160051c60051b83601f1615610421576020015f81525b5f525b6020013e5b505b50506020016115ee565b5060a01c61ffff16600c0190600c015b805160f81c8015610db8576010811161056457806001146104ce57806002146104d957806003146104e457806004146104ef57806005146104fa57806006146105055780600714610510578060081461051b5780600a1461052e5780600b146105375780600c146105405780600d146105495780600e146105525780600f1461055b5750610db8565b506020516001610db0565b506040516001610db0565b506060516001610db0565b506080516001610db0565b5060a0516001610db0565b5060c0516001610db0565b5060e0516001610db0565b505f51805190602090035f526001610db0565b50476001610db0565b50416001610db0565b50426001610db0565b50436001610db0565b50486001610db0565b503a6001610db0565b60208110156106a357806011146105eb57806012146105f65780601314610601578060141461060c57806015146106175780601614610622578060171461062d578060181461063857806019146106435780601a1461064d5780601b146106615780601c146106755780601d146106825780601e1461068f5780601f146106995750610db8565b509190016001610db0565b509190036001610db0565b509190026001610db0565b509190046001610db0565b509190056001610db0565b509190166001610db0565b509190176001610db0565b509190186001610db0565b5090196001610db0565b50806001015160f81c9091901b6002610db0565b50806001015160f81c9091901c6002610db0565b5090600190016001610db0565b5090600190036001610db0565b5091036001610db0565b5091046001610db0565b60308110156107d957806020146106f2578060211461070357806022146107135780602314610737578060241461074e578060251461076b578060261461078a5780602a146107ad5750610db8565b5080600101516021610db056610db8565b50806001015160ff166002610db0565b50806001015161ffff166003610db0565b50806001015163ffffffff166005610db0565b50806001015167ffffffffffffffff166009610db0565b5080600101516dffffffffffffffffffffffffffff166007610db0565b5080600101516fffffffffffffffffffffffffffffffff166009610db0565b50806001015173ffffffffffffffffffffffffffffffffffffffff16600d610db0565b50907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90026001610db0565b60308110156108975780603114610810578060321461081b57806033146108355780603414610847578060351461085f5750610db8565b5060ff166001610db0565b5061ffff166001610db0565b5063ffffffff166001610db0565b5067ffffffffffffffff166001610db0565b506dffffffffffffffffffffffffffff166001610db0565b506fffffffffffffffffffffffffffffffff166001610db0565b5073ffffffffffffffffffffffffffffffffffffffff166001610db0565b6050811015610d2a5780604014610926578060411461098e57806042146109f55780604314610a5d5780604414610ac45780604514610b2c5780604614610b935780604714610bf85780604814610c5e5780604914610c785780604a14610c915780604b14610cab5780604c14610cc45780604d14610cde5780604e14610cf75780604f14610d0e5750610db8565b50919014156109385760016001610db0565b7f455100000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901461099f5760016001610db0565b7f4e4551000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901015610a075760016001610db0565b7f4c5400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919010610a6e5760016001610db0565b7f475445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901115610ad65760016001610db0565b7f475400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919011610b3d5760016001610db0565b7f4c5445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5090610ba25760016001610db0565b7f5a5200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509015610c085760016001610db0565b7f4e5a52000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901415610c705760016001610db0565b5f5f5260205ff35b50919014610c895760016001610db0565b5f5f5260205ff35b5091901015610ca35760016001610db0565b5f5f5260205ff35b50919010610cbc5760016001610db0565b5f5f5260205ff35b5091901115610cd65760016001610db0565b5f5f5260205ff35b50919011610cef5760016001610db0565b5f5f5260205ff35b5090610d065760016001610db0565b5f5f5260205ff35b509015610d1e5760016001610db0565b5f5f5260205ff3610db8565b6060811015610daa5780605014610d495780605114610d7d5750610db8565b50806001015160f81c8060051b5f5103805f525f5b9060200190815101916001900391821515610d5e579150506002610db0565b50806001015160f81c5f515f5b815101906020900390916001900391821515610d8a579150506002610db0565b50610db8565b909101610445565b50505f516020019081525f526115ee565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855afa15612d3c5792505060c81c62ffffff168015610e59578062ffffff14610e595780610fff1681600c1c60ff16908260141c60071660051b83628000001615610e54575f510380830160051c60051b83601f1615610e51576020015f81525b5f525b6020013e5b506020016115ee565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855af415612d3c5792505060c81c62ffffff168015610ef2578062ffffff14610ef25780610fff1681600c1c60ff16908260141c60071660051b83628000001615610eed575f510380830160051c60051b83601f1615610eea576020015f81525b5f525b6020013e5b506020016115ee565b508060a01c61ffff1682600c015160e01c8063a85f1d24146113a25780634df86adf146112bd57806305ec9cad1461145d5780639b81788b14610fa55780638bceaa181461100857806384f16ca01461106a57806395b66162146110cd5780639a23842e1461112f5780634fae2f2314611193578063a9f2812f146111f6578063f93a17161461125a578063fcccdd98146115695780631e00cebd1461159e576199995f5260205ffd5b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa15610fe257905080602001519051610fe7565b50505f5f5b9082026127100291900390910290046001015f516020019081525f526115dd565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156110455790508060200151905161104a565b50505f5f5b82026127100291900390910290046001015f516020019081525f526115dd565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156110a7579050806020015190516110ac565b50505f5f5b9090919092029182029190612710020190045f516020019081525f526115dd565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa1561110a5790508060200151905161110f565b50505f5f5b90919092029182029190612710020190045f516020019081525f526115dd565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561116d57905080602001519051611172565b50505f5f5b9082026127100291900390910290046001015f516020019081525f526115dd565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156111d1579050806020015190516111d6565b50505f5f5b82026127100291900390910290046001015f516020019081525f526115dd565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561123457905080602001519051611239565b50505f5f5b9090919092029182029190612710020190045f516020019081525f526115dd565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156112985790508060200151905161129d565b50505f5f5b90919092029182029190612710020190045f516020019081525f526115dd565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa15612d3c5751801561130057600190035b8084111561135e577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b85606401516101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050508015611399575f5f5f5f84415af1505b505050506115dd565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa15612d3c575180156113e557600190035b80841115611443577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50508015611455575f5f5f5f84415af1505b5050506115dd565b5083600c0173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160040151826024015182610100516370a082318152308160200152602081602483601c01855afa15612d3c575180156114b057600190035b8084111561150e577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b61010051632e1a7d4d81529081602001525f5f602483601c015f73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25af150508115611551575f5f5f5f85415af1505b84604401515f5f5f475f945af15050505050506115dd565b5083600c015f51805f01517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa3506115dd565b5083600c018060240151906004015160051b5f5180919003517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa3505b915050600c016115ee565b5061ffff015b0181811061010b575b505060043560240135602435602401356044356024013501336101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af1505050612d44565b5060846116f6565b5060246116f6565b5060046116f6565b6044356004018035601414612cf157506004356040526024356020526116eb565b506044356004018035601414612cf157506004355f81126116bf576040526024357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff026020526116eb565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff026020526024356040525b60405f526044356004015b80358091602001610120375961010052610120016101205b8080518060f01c8061800016151561180357828260b01c62ffffff1680156117bf578062ffffff146117bf579081610fff160181600c1c60ff1680156117bd57908260141c60071660051b6020018362800000161561176f57602090035f51035b905b82151561177f5750506117b7565b8260201161179e57815181526020019060200191602090039190611771565b905160018360031b1b6001900380199116908251161790525b506117c1565b505b505b5061ffff168015612beb5780617ffc146118bb5780617ffe146123cc5780617ffb14611a385780617fff146124655780617ffd146124fe5780617ffa14611964575b508060b01c697fffffffffffffffffff1691908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612d3c579491505015156118b1578060c81c62ffffff1680156118af578062ffffff146118af5780610fff1681600c1c60ff16908260141c60071660051b836280000016156118aa575f510380830160051c60051b83601f16156118a7576020015f81525b5f525b6020013e5b505b5050602001612bf1565b505f91908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612d3c5794915050151561195a578060c81c62ffffff168015611958578062ffffff146119585780610fff1681600c1c60ff16908260141c60071660051b83628000001615611953575f510380830160051c60051b83601f1615611950576020015f81525b5f525b6020013e5b505b5050602001612bf1565b508060b01c62ffffff168060141c60071660051b6020018162800000161561198e57602090035f51035b51905091908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612d3c57949150501515611a2e578060c81c62ffffff168015611a2c578062ffffff14611a2c5780610fff1681600c1c60ff16908260141c60071660051b83628000001615611a27575f510380830160051c60051b83601f1615611a24576020015f81525b5f525b6020013e5b505b5050602001612bf1565b5060a01c61ffff16600c0190600c015b805160f81c80156123bb5760108111611b675780600114611ad15780600214611adc5780600314611ae75780600414611af25780600514611afd5780600614611b085780600714611b135780600814611b1e5780600a14611b315780600b14611b3a5780600c14611b435780600d14611b4c5780600e14611b555780600f14611b5e57506123bb565b5060205160016123b3565b5060405160016123b3565b5060605160016123b3565b5060805160016123b3565b5060a05160016123b3565b5060c05160016123b3565b5060e05160016123b3565b505f51805190602090035f5260016123b3565b504760016123b3565b504160016123b3565b504260016123b3565b504360016123b3565b504860016123b3565b503a60016123b3565b6020811015611ca65780601114611bee5780601214611bf95780601314611c045780601414611c0f5780601514611c1a5780601614611c255780601714611c305780601814611c3b5780601914611c465780601a14611c505780601b14611c645780601c14611c785780601d14611c855780601e14611c925780601f14611c9c57506123bb565b5091900160016123b3565b5091900360016123b3565b5091900260016123b3565b5091900460016123b3565b5091900560016123b3565b5091901660016123b3565b5091901760016123b3565b5091901860016123b3565b50901960016123b3565b50806001015160f81c9091901b60026123b3565b50806001015160f81c9091901c60026123b3565b50906001900160016123b3565b50906001900360016123b3565b50910360016123b3565b50910460016123b3565b6030811015611ddc5780602014611cf55780602114611d065780602214611d165780602314611d3a5780602414611d515780602514611d6e5780602614611d8d5780602a14611db057506123bb565b50806001015160216123b3566123bb565b50806001015160ff1660026123b3565b50806001015161ffff1660036123b3565b50806001015163ffffffff1660056123b3565b50806001015167ffffffffffffffff1660096123b3565b5080600101516dffffffffffffffffffffffffffff1660076123b3565b5080600101516fffffffffffffffffffffffffffffffff1660096123b3565b50806001015173ffffffffffffffffffffffffffffffffffffffff16600d6123b3565b50907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff900260016123b3565b6030811015611e9a5780603114611e135780603214611e1e5780603314611e385780603414611e4a5780603514611e6257506123bb565b5060ff1660016123b3565b5061ffff1660016123b3565b5063ffffffff1660016123b3565b5067ffffffffffffffff1660016123b3565b506dffffffffffffffffffffffffffff1660016123b3565b506fffffffffffffffffffffffffffffffff1660016123b3565b5073ffffffffffffffffffffffffffffffffffffffff1660016123b3565b605081101561232d5780604014611f295780604114611f915780604214611ff8578060431461206057806044146120c7578060451461212f578060461461219657806047146121fb5780604814612261578060491461227b5780604a146122945780604b146122ae5780604c146122c75780604d146122e15780604e146122fa5780604f1461231157506123bb565b5091901415611f3b57600160016123b3565b7f455100000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919014611fa257600160016123b3565b7f4e4551000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190101561200a57600160016123b3565b7f4c5400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901061207157600160016123b3565b7f475445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919011156120d957600160016123b3565b7f475400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901161214057600160016123b3565b7f4c5445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50906121a557600160016123b3565b7f5a5200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50901561220b57600160016123b3565b7f4e5a52000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190141561227357600160016123b3565b5f5f5260205ff35b5091901461228c57600160016123b3565b5f5f5260205ff35b50919010156122a657600160016123b3565b5f5f5260205ff35b509190106122bf57600160016123b3565b5f5f5260205ff35b50919011156122d957600160016123b3565b5f5f5260205ff35b509190116122f257600160016123b3565b5f5f5260205ff35b509061230957600160016123b3565b5f5f5260205ff35b50901561232157600160016123b3565b5f5f5260205ff36123bb565b60608110156123ad578060501461234c578060511461238057506123bb565b50806001015160f81c8060051b5f5103805f525f5b90602001908151019160019003918215156123615791505060026123b3565b50806001015160f81c5f515f5b81510190602090039091600190039182151561238d5791505060026123b3565b506123bb565b909101611a48565b50505f516020019081525f52612bf1565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855afa15612d3c5792505060c81c62ffffff16801561245c578062ffffff1461245c5780610fff1681600c1c60ff16908260141c60071660051b83628000001615612457575f510380830160051c60051b83601f1615612454576020015f81525b5f525b6020013e5b50602001612bf1565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855af415612d3c5792505060c81c62ffffff1680156124f5578062ffffff146124f55780610fff1681600c1c60ff16908260141c60071660051b836280000016156124f0575f510380830160051c60051b83601f16156124ed576020015f81525b5f525b6020013e5b50602001612bf1565b508060a01c61ffff1682600c015160e01c8063a85f1d24146129a55780634df86adf146128c057806305ec9cad14612a605780639b81788b146125a85780638bceaa181461260b57806384f16ca01461266d57806395b66162146126d05780639a23842e146127325780634fae2f2314612796578063a9f2812f146127f9578063f93a17161461285d578063fcccdd9814612b6c5780631e00cebd14612ba1576199995f5260205ffd5b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156125e5579050806020015190516125ea565b50505f5f5b9082026127100291900390910290046001015f516020019081525f52612be0565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156126485790508060200151905161264d565b50505f5f5b82026127100291900390910290046001015f516020019081525f52612be0565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156126aa579050806020015190516126af565b50505f5f5b9090919092029182029190612710020190045f516020019081525f52612be0565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa1561270d57905080602001519051612712565b50505f5f5b90919092029182029190612710020190045f516020019081525f52612be0565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561277057905080602001519051612775565b50505f5f5b9082026127100291900390910290046001015f516020019081525f52612be0565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156127d4579050806020015190516127d9565b50505f5f5b82026127100291900390910290046001015f516020019081525f52612be0565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156128375790508060200151905161283c565b50505f5f5b9090919092029182029190612710020190045f516020019081525f52612be0565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561289b579050806020015190516128a0565b50505f5f5b90919092029182029190612710020190045f516020019081525f52612be0565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa15612d3c5751801561290357600190035b80841115612961577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b85606401516101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af1505050801561299c575f5f5f5f84415af1505b50505050612be0565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa15612d3c575180156129e857600190035b80841115612a46577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50508015612a58575f5f5f5f84415af1505b505050612be0565b5083600c0173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160040151826024015182610100516370a082318152308160200152602081602483601c01855afa15612d3c57518015612ab357600190035b80841115612b11577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b61010051632e1a7d4d81529081602001525f5f602483601c015f73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25af150508115612b54575f5f5f5f85415af1505b84604401515f5f5f475f945af1505050505050612be0565b5083600c015f51805f01517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa350612be0565b5083600c018060240151906004015160051b5f5180919003517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa3505b915050600c01612bf1565b5061ffff015b0181811061170e575b505060205f51f3612d44565b506320c13b0b60e01b5f5260205ff35b50631626ba7e60e01b5f5260205ff35b6084356020013560601c6024358015612c80573361010051630902f1ac8152606081600483601c01855afa15612c6457905080602001519051612c69565b50505f5f5b908202612710029190039091029004600101612cc6565b506044353361010051630902f1ac8152606081600483601c01855afa15612caf57905080602001519051612cb4565b50505f5f5b82026127100291900390910290046001015b336101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050505f5ff35b6020013560601c600435805f9012612d0857612d0d565b506024355b336101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050505f5ff35b5f5ff35b3d5f5f3e3d5ffd5b").unwrap(); //static ref NO_OWNER_CODE : Vec = hex::decode("3615612d38575f3560e01c80632847241714611643578063fa461e331461167457806323a69e75146116745780638b4187131461163b57806320c13b0b14612c065780631626ba7e14612c16578063f04f2707146100ec57806391dd73461461164b578063923b8a2a146116535750606435806080146100b75750604435806060146116745750600435806020146100af5750602435806040146100af57506084358060a0146100af5750612d38565b6004016116f6565b8060040135601414612c26575060243580156100d5576020526100dd565b506044356020525b60205f526064356004016116f6565b5060643560040180358091602001610120375961010052610120016101205b8080518060f01c8061800016151561020057828260b01c62ffffff1680156101bc578062ffffff146101bc579081610fff160181600c1c60ff1680156101ba57908260141c60071660051b6020018362800000161561016c57602090035f51035b905b82151561017c5750506101b4565b8260201161019b5781518152602001906020019160209003919061016e565b905160018360031b1b6001900380199116908251161790525b506101be565b505b505b5061ffff1680156115e85780617ffc146102b85780617ffe14610dc95780617ffb146104355780617fff14610e625780617ffd14610efb5780617ffa14610361575b508060b01c697fffffffffffffffffff1691908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612d3c579491505015156102ae578060c81c62ffffff1680156102ac578062ffffff146102ac5780610fff1681600c1c60ff16908260141c60071660051b836280000016156102a7575f510380830160051c60051b83601f16156102a4576020015f81525b5f525b6020013e5b505b50506020016115ee565b505f91908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612d3c57949150501515610357578060c81c62ffffff168015610355578062ffffff146103555780610fff1681600c1c60ff16908260141c60071660051b83628000001615610350575f510380830160051c60051b83601f161561034d576020015f81525b5f525b6020013e5b505b50506020016115ee565b508060b01c62ffffff168060141c60071660051b6020018162800000161561038b57602090035f51035b51905091908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612d3c5794915050151561042b578060c81c62ffffff168015610429578062ffffff146104295780610fff1681600c1c60ff16908260141c60071660051b83628000001615610424575f510380830160051c60051b83601f1615610421576020015f81525b5f525b6020013e5b505b50506020016115ee565b5060a01c61ffff16600c0190600c015b805160f81c8015610db8576010811161056457806001146104ce57806002146104d957806003146104e457806004146104ef57806005146104fa57806006146105055780600714610510578060081461051b5780600a1461052e5780600b146105375780600c146105405780600d146105495780600e146105525780600f1461055b5750610db8565b506020516001610db0565b506040516001610db0565b506060516001610db0565b506080516001610db0565b5060a0516001610db0565b5060c0516001610db0565b5060e0516001610db0565b505f51805190602090035f526001610db0565b50476001610db0565b50416001610db0565b50426001610db0565b50436001610db0565b50486001610db0565b503a6001610db0565b60208110156106a357806011146105eb57806012146105f65780601314610601578060141461060c57806015146106175780601614610622578060171461062d578060181461063857806019146106435780601a1461064d5780601b146106615780601c146106755780601d146106825780601e1461068f5780601f146106995750610db8565b509190016001610db0565b509190036001610db0565b509190026001610db0565b509190046001610db0565b509190056001610db0565b509190166001610db0565b509190176001610db0565b509190186001610db0565b5090196001610db0565b50806001015160f81c9091901b6002610db0565b50806001015160f81c9091901c6002610db0565b5090600190016001610db0565b5090600190036001610db0565b5091036001610db0565b5091046001610db0565b60308110156107d957806020146106f2578060211461070357806022146107135780602314610737578060241461074e578060251461076b578060261461078a5780602a146107ad5750610db8565b5080600101516021610db056610db8565b50806001015160ff166002610db0565b50806001015161ffff166003610db0565b50806001015163ffffffff166005610db0565b50806001015167ffffffffffffffff166009610db0565b5080600101516dffffffffffffffffffffffffffff166007610db0565b5080600101516fffffffffffffffffffffffffffffffff166009610db0565b50806001015173ffffffffffffffffffffffffffffffffffffffff16600d610db0565b50907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90026001610db0565b60308110156108975780603114610810578060321461081b57806033146108355780603414610847578060351461085f5750610db8565b5060ff166001610db0565b5061ffff166001610db0565b5063ffffffff166001610db0565b5067ffffffffffffffff166001610db0565b506dffffffffffffffffffffffffffff166001610db0565b506fffffffffffffffffffffffffffffffff166001610db0565b5073ffffffffffffffffffffffffffffffffffffffff166001610db0565b6050811015610d2a5780604014610926578060411461098e57806042146109f55780604314610a5d5780604414610ac45780604514610b2c5780604614610b935780604714610bf85780604814610c5e5780604914610c785780604a14610c915780604b14610cab5780604c14610cc45780604d14610cde5780604e14610cf75780604f14610d0e5750610db8565b50919014156109385760016001610db0565b7f455100000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901461099f5760016001610db0565b7f4e4551000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901015610a075760016001610db0565b7f4c5400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919010610a6e5760016001610db0565b7f475445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901115610ad65760016001610db0565b7f475400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919011610b3d5760016001610db0565b7f4c5445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5090610ba25760016001610db0565b7f5a5200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509015610c085760016001610db0565b7f4e5a52000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901415610c705760016001610db0565b5f5f5260205ff35b50919014610c895760016001610db0565b5f5f5260205ff35b5091901015610ca35760016001610db0565b5f5f5260205ff35b50919010610cbc5760016001610db0565b5f5f5260205ff35b5091901115610cd65760016001610db0565b5f5f5260205ff35b50919011610cef5760016001610db0565b5f5f5260205ff35b5090610d065760016001610db0565b5f5f5260205ff35b509015610d1e5760016001610db0565b5f5f5260205ff3610db8565b6060811015610daa5780605014610d495780605114610d7d5750610db8565b50806001015160f81c8060051b5f5103805f525f5b9060200190815101916001900391821515610d5e579150506002610db0565b50806001015160f81c5f515f5b815101906020900390916001900391821515610d8a579150506002610db0565b50610db8565b909101610445565b50505f516020019081525f526115ee565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855afa15612d3c5792505060c81c62ffffff168015610e59578062ffffff14610e595780610fff1681600c1c60ff16908260141c60071660051b83628000001615610e54575f510380830160051c60051b83601f1615610e51576020015f81525b5f525b6020013e5b506020016115ee565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855af415612d3c5792505060c81c62ffffff168015610ef2578062ffffff14610ef25780610fff1681600c1c60ff16908260141c60071660051b83628000001615610eed575f510380830160051c60051b83601f1615610eea576020015f81525b5f525b6020013e5b506020016115ee565b508060a01c61ffff1682600c015160e01c8063a85f1d24146113a25780634df86adf146112bd57806305ec9cad1461145d5780639b81788b14610fa55780638bceaa181461100857806384f16ca01461106a57806395b66162146110cd5780639a23842e1461112f5780634fae2f2314611193578063a9f2812f146111f6578063f93a17161461125a578063fcccdd98146115695780631e00cebd1461159e576199995f5260205ffd5b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa15610fe257905080602001519051610fe7565b50505f5f5b9082026127100291900390910290046001015f516020019081525f526115dd565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156110455790508060200151905161104a565b50505f5f5b82026127100291900390910290046001015f516020019081525f526115dd565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156110a7579050806020015190516110ac565b50505f5f5b9090919092029182029190612710020190045f516020019081525f526115dd565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa1561110a5790508060200151905161110f565b50505f5f5b90919092029182029190612710020190045f516020019081525f526115dd565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561116d57905080602001519051611172565b50505f5f5b9082026127100291900390910290046001015f516020019081525f526115dd565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156111d1579050806020015190516111d6565b50505f5f5b82026127100291900390910290046001015f516020019081525f526115dd565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561123457905080602001519051611239565b50505f5f5b9090919092029182029190612710020190045f516020019081525f526115dd565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156112985790508060200151905161129d565b50505f5f5b90919092029182029190612710020190045f516020019081525f526115dd565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa15612d3c5751801561130057600190035b8084111561135e577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b85606401516101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050508015611399575f5f5f5f84415af1505b505050506115dd565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa15612d3c575180156113e557600190035b80841115611443577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50508015611455575f5f5f5f84415af1505b5050506115dd565b5083600c0173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160040151826024015182610100516370a082318152308160200152602081602483601c01855afa15612d3c575180156114b057600190035b8084111561150e577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b61010051632e1a7d4d81529081602001525f5f602483601c015f73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25af150508115611551575f5f5f5f85415af1505b84604401515f5f5f475f945af15050505050506115dd565b5083600c015f51805f01517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa3506115dd565b5083600c018060240151906004015160051b5f5180919003517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa3505b915050600c016115ee565b5061ffff015b0181811061010b575b505060043560240135602435602401356044356024013501336101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af1505050612d44565b5060846116f6565b5060246116f6565b5060246116f6565b6044356004018035601414612cf157506004356040526024356020526116eb565b506044356004018035601414612cf157506004355f81126116bf576040526024357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff026020526116eb565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff026020526024356040525b60405f526044356004015b80358091602001610120375961010052610120016101205b8080518060f01c8061800016151561180357828260b01c62ffffff1680156117bf578062ffffff146117bf579081610fff160181600c1c60ff1680156117bd57908260141c60071660051b6020018362800000161561176f57602090035f51035b905b82151561177f5750506117b7565b8260201161179e57815181526020019060200191602090039190611771565b905160018360031b1b6001900380199116908251161790525b506117c1565b505b505b5061ffff168015612beb5780617ffc146118bb5780617ffe146123cc5780617ffb14611a385780617fff146124655780617ffd146124fe5780617ffa14611964575b508060b01c697fffffffffffffffffff1691908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612d3c579491505015156118b1578060c81c62ffffff1680156118af578062ffffff146118af5780610fff1681600c1c60ff16908260141c60071660051b836280000016156118aa575f510380830160051c60051b83601f16156118a7576020015f81525b5f525b6020013e5b505b5050602001612bf1565b505f91908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612d3c5794915050151561195a578060c81c62ffffff168015611958578062ffffff146119585780610fff1681600c1c60ff16908260141c60071660051b83628000001615611953575f510380830160051c60051b83601f1615611950576020015f81525b5f525b6020013e5b505b5050602001612bf1565b508060b01c62ffffff168060141c60071660051b6020018162800000161561198e57602090035f51035b51905091908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af115612d3c57949150501515611a2e578060c81c62ffffff168015611a2c578062ffffff14611a2c5780610fff1681600c1c60ff16908260141c60071660051b83628000001615611a27575f510380830160051c60051b83601f1615611a24576020015f81525b5f525b6020013e5b505b5050602001612bf1565b5060a01c61ffff16600c0190600c015b805160f81c80156123bb5760108111611b675780600114611ad15780600214611adc5780600314611ae75780600414611af25780600514611afd5780600614611b085780600714611b135780600814611b1e5780600a14611b315780600b14611b3a5780600c14611b435780600d14611b4c5780600e14611b555780600f14611b5e57506123bb565b5060205160016123b3565b5060405160016123b3565b5060605160016123b3565b5060805160016123b3565b5060a05160016123b3565b5060c05160016123b3565b5060e05160016123b3565b505f51805190602090035f5260016123b3565b504760016123b3565b504160016123b3565b504260016123b3565b504360016123b3565b504860016123b3565b503a60016123b3565b6020811015611ca65780601114611bee5780601214611bf95780601314611c045780601414611c0f5780601514611c1a5780601614611c255780601714611c305780601814611c3b5780601914611c465780601a14611c505780601b14611c645780601c14611c785780601d14611c855780601e14611c925780601f14611c9c57506123bb565b5091900160016123b3565b5091900360016123b3565b5091900260016123b3565b5091900460016123b3565b5091900560016123b3565b5091901660016123b3565b5091901760016123b3565b5091901860016123b3565b50901960016123b3565b50806001015160f81c9091901b60026123b3565b50806001015160f81c9091901c60026123b3565b50906001900160016123b3565b50906001900360016123b3565b50910360016123b3565b50910460016123b3565b6030811015611ddc5780602014611cf55780602114611d065780602214611d165780602314611d3a5780602414611d515780602514611d6e5780602614611d8d5780602a14611db057506123bb565b50806001015160216123b3566123bb565b50806001015160ff1660026123b3565b50806001015161ffff1660036123b3565b50806001015163ffffffff1660056123b3565b50806001015167ffffffffffffffff1660096123b3565b5080600101516dffffffffffffffffffffffffffff1660076123b3565b5080600101516fffffffffffffffffffffffffffffffff1660096123b3565b50806001015173ffffffffffffffffffffffffffffffffffffffff16600d6123b3565b50907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff900260016123b3565b6030811015611e9a5780603114611e135780603214611e1e5780603314611e385780603414611e4a5780603514611e6257506123bb565b5060ff1660016123b3565b5061ffff1660016123b3565b5063ffffffff1660016123b3565b5067ffffffffffffffff1660016123b3565b506dffffffffffffffffffffffffffff1660016123b3565b506fffffffffffffffffffffffffffffffff1660016123b3565b5073ffffffffffffffffffffffffffffffffffffffff1660016123b3565b605081101561232d5780604014611f295780604114611f915780604214611ff8578060431461206057806044146120c7578060451461212f578060461461219657806047146121fb5780604814612261578060491461227b5780604a146122945780604b146122ae5780604c146122c75780604d146122e15780604e146122fa5780604f1461231157506123bb565b5091901415611f3b57600160016123b3565b7f455100000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919014611fa257600160016123b3565b7f4e4551000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190101561200a57600160016123b3565b7f4c5400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901061207157600160016123b3565b7f475445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919011156120d957600160016123b3565b7f475400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901161214057600160016123b3565b7f4c5445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50906121a557600160016123b3565b7f5a5200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50901561220b57600160016123b3565b7f4e5a52000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190141561227357600160016123b3565b5f5f5260205ff35b5091901461228c57600160016123b3565b5f5f5260205ff35b50919010156122a657600160016123b3565b5f5f5260205ff35b509190106122bf57600160016123b3565b5f5f5260205ff35b50919011156122d957600160016123b3565b5f5f5260205ff35b509190116122f257600160016123b3565b5f5f5260205ff35b509061230957600160016123b3565b5f5f5260205ff35b50901561232157600160016123b3565b5f5f5260205ff36123bb565b60608110156123ad578060501461234c578060511461238057506123bb565b50806001015160f81c8060051b5f5103805f525f5b90602001908151019160019003918215156123615791505060026123b3565b50806001015160f81c5f515f5b81510190602090039091600190039182151561238d5791505060026123b3565b506123bb565b909101611a48565b50505f516020019081525f52612bf1565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855afa15612d3c5792505060c81c62ffffff16801561245c578062ffffff1461245c5780610fff1681600c1c60ff16908260141c60071660051b83628000001615612457575f510380830160051c60051b83601f1615612454576020015f81525b5f525b6020013e5b50602001612bf1565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855af415612d3c5792505060c81c62ffffff1680156124f5578062ffffff146124f55780610fff1681600c1c60ff16908260141c60071660051b836280000016156124f0575f510380830160051c60051b83601f16156124ed576020015f81525b5f525b6020013e5b50602001612bf1565b508060a01c61ffff1682600c015160e01c8063a85f1d24146129a55780634df86adf146128c057806305ec9cad14612a605780639b81788b146125a85780638bceaa181461260b57806384f16ca01461266d57806395b66162146126d05780639a23842e146127325780634fae2f2314612796578063a9f2812f146127f9578063f93a17161461285d578063fcccdd9814612b6c5780631e00cebd14612ba1576199995f5260205ffd5b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156125e5579050806020015190516125ea565b50505f5f5b9082026127100291900390910290046001015f516020019081525f52612be0565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156126485790508060200151905161264d565b50505f5f5b82026127100291900390910290046001015f516020019081525f52612be0565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156126aa579050806020015190516126af565b50505f5f5b9090919092029182029190612710020190045f516020019081525f52612be0565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa1561270d57905080602001519051612712565b50505f5f5b90919092029182029190612710020190045f516020019081525f52612be0565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561277057905080602001519051612775565b50505f5f5b9082026127100291900390910290046001015f516020019081525f52612be0565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156127d4579050806020015190516127d9565b50505f5f5b82026127100291900390910290046001015f516020019081525f52612be0565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156128375790508060200151905161283c565b50505f5f5b9090919092029182029190612710020190045f516020019081525f52612be0565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561289b579050806020015190516128a0565b50505f5f5b90919092029182029190612710020190045f516020019081525f52612be0565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa15612d3c5751801561290357600190035b80841115612961577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b85606401516101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af1505050801561299c575f5f5f5f84415af1505b50505050612be0565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa15612d3c575180156129e857600190035b80841115612a46577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50508015612a58575f5f5f5f84415af1505b505050612be0565b5083600c0173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160040151826024015182610100516370a082318152308160200152602081602483601c01855afa15612d3c57518015612ab357600190035b80841115612b11577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b61010051632e1a7d4d81529081602001525f5f602483601c015f73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25af150508115612b54575f5f5f5f85415af1505b84604401515f5f5f475f945af1505050505050612be0565b5083600c015f51805f01517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa350612be0565b5083600c018060240151906004015160051b5f5180919003517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa3505b915050600c01612bf1565b5061ffff015b0181811061170e575b505060205f51f3612d44565b506320c13b0b60e01b5f5260205ff35b50631626ba7e60e01b5f5260205ff35b6084356020013560601c6024358015612c80573361010051630902f1ac8152606081600483601c01855afa15612c6457905080602001519051612c69565b50505f5f5b908202612710029190039091029004600101612cc6565b506044353361010051630902f1ac8152606081600483601c01855afa15612caf57905080602001519051612cb4565b50505f5f5b82026127100291900390910290046001015b336101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050505f5ff35b6020013560601c600435805f9012612d0857612d0d565b506024355b336101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050505f5ff35b5f5ff35b3d5f5f3e3d5ffd5b").unwrap(); - //static ref NO_OWNER_CODE : Vec = hex::decode("36156142b8575f3560e01c80632847241714611668578063fa461e3314612bd357806323a69e7514612bd35780638b4187131461166057806320c13b0b146141865780631626ba7e14614196578063f04f2707146100ec57806391dd734614611670578063923b8a2a14612bb25750606435806080146100b7575060443580606014612bd35750600435806020146100af5750602435806040146100af57506084358060a0146100af57506142b8565b600401612c55565b80600401356014146141a6575060243580156100d5576020526100dd565b506044356020525b60205f52606435600401612c55565b5060643560040180358091602001610120375961010052610120016101205b8080518060f01c8061800016151561020057828260b01c62ffffff1680156101bc578062ffffff146101bc579081610fff160181600c1c60ff1680156101ba57908260141c60071660051b6020018362800000161561016c57602090035f51035b905b82151561017c5750506101b4565b8260201161019b5781518152602001906020019160209003919061016e565b905160018360031b1b6001900380199116908251161790525b506101be565b505b505b5061ffff16801561160d5780617ffc146102ab5780617ffe14610da25780617ffb1461040e5780617fff14610e2e5780617ffd14610eba5780617ffa14610347575b508060b01c697fffffffffffffffffff1691908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af1156142bc579491505015156102a1578060c81c62ffffff16801561029f578062ffffff1461029f5780610fff1681600c1c60ff169082628000001615610285575f51610290565b8260141c60071660051b5b602083068381015f52016020013e5b505b5050602001611613565b505f91908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af1156142bc5794915050151561033d578060c81c62ffffff16801561033b578062ffffff1461033b5780610fff1681600c1c60ff169082628000001615610321575f5161032c565b8260141c60071660051b5b602083068381015f52016020013e5b505b5050602001611613565b508060b01c62ffffff168060141c60071660051b6020018162800000161561037157602090035f51035b51905091908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af1156142bc57949150501515610404578060c81c62ffffff168015610402578062ffffff146104025780610fff1681600c1c60ff1690826280000016156103e8575f516103f3565b8260141c60071660051b5b602083068381015f52016020013e5b505b5050602001611613565b5060a01c61ffff16600c0190600c015b805160f81c8015610d91576010811161053d57806001146104a757806002146104b257806003146104bd57806004146104c857806005146104d357806006146104de57806007146104e957806008146104f45780600a146105075780600b146105105780600c146105195780600d146105225780600e1461052b5780600f146105345750610d91565b506020516001610d89565b506040516001610d89565b506060516001610d89565b506080516001610d89565b5060a0516001610d89565b5060c0516001610d89565b5060e0516001610d89565b505f51805190602090035f526001610d89565b50476001610d89565b50416001610d89565b50426001610d89565b50436001610d89565b50486001610d89565b503a6001610d89565b602081101561067c57806011146105c457806012146105cf57806013146105da57806014146105e557806015146105f057806016146105fb57806017146106065780601814610611578060191461061c5780601a146106265780601b1461063a5780601c1461064e5780601d1461065b5780601e146106685780601f146106725750610d91565b509190016001610d89565b509190036001610d89565b509190026001610d89565b509190046001610d89565b509190056001610d89565b509190166001610d89565b509190176001610d89565b509190186001610d89565b5090196001610d89565b50806001015160f81c9091901b6002610d89565b50806001015160f81c9091901c6002610d89565b5090600190016001610d89565b5090600190036001610d89565b5091036001610d89565b5091046001610d89565b60308110156107b257806020146106cb57806021146106dc57806022146106ec57806023146107105780602414610727578060251461074457806026146107635780602a146107865750610d91565b5080600101516021610d8956610d91565b50806001015160ff166002610d89565b50806001015161ffff166003610d89565b50806001015163ffffffff166005610d89565b50806001015167ffffffffffffffff166009610d89565b5080600101516dffffffffffffffffffffffffffff166007610d89565b5080600101516fffffffffffffffffffffffffffffffff166009610d89565b50806001015173ffffffffffffffffffffffffffffffffffffffff16600d610d89565b50907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90026001610d89565b603081101561087057806031146107e957806032146107f4578060331461080e578060341461082057806035146108385750610d91565b5060ff166001610d89565b5061ffff166001610d89565b5063ffffffff166001610d89565b5067ffffffffffffffff166001610d89565b506dffffffffffffffffffffffffffff166001610d89565b506fffffffffffffffffffffffffffffffff166001610d89565b5073ffffffffffffffffffffffffffffffffffffffff166001610d89565b6050811015610d0357806040146108ff578060411461096757806042146109ce5780604314610a365780604414610a9d5780604514610b055780604614610b6c5780604714610bd15780604814610c375780604914610c515780604a14610c6a5780604b14610c845780604c14610c9d5780604d14610cb75780604e14610cd05780604f14610ce75750610d91565b50919014156109115760016001610d89565b7f455100000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190146109785760016001610d89565b7f4e4551000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919010156109e05760016001610d89565b7f4c5400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919010610a475760016001610d89565b7f475445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901115610aaf5760016001610d89565b7f475400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919011610b165760016001610d89565b7f4c5445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5090610b7b5760016001610d89565b7f5a5200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509015610be15760016001610d89565b7f4e5a52000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901415610c495760016001610d89565b5f5f5260205ff35b50919014610c625760016001610d89565b5f5f5260205ff35b5091901015610c7c5760016001610d89565b5f5f5260205ff35b50919010610c955760016001610d89565b5f5f5260205ff35b5091901115610caf5760016001610d89565b5f5f5260205ff35b50919011610cc85760016001610d89565b5f5f5260205ff35b5090610cdf5760016001610d89565b5f5f5260205ff35b509015610cf75760016001610d89565b5f5f5260205ff3610d91565b6060811015610d835780605014610d225780605114610d565750610d91565b50806001015160f81c8060051b5f5103805f525f5b9060200190815101916001900391821515610d37579150506002610d89565b50806001015160f81c5f515f5b815101906020900390916001900391821515610d63579150506002610d89565b50610d91565b90910161041e565b50505f516020019081525f52611613565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855afa156142bc5792505060c81c62ffffff168015610e25578062ffffff14610e255780610fff1681600c1c60ff169082628000001615610e0b575f51610e16565b8260141c60071660051b5b602083068381015f52016020013e5b50602001611613565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855af4156142bc5792505060c81c62ffffff168015610eb1578062ffffff14610eb15780610fff1681600c1c60ff169082628000001615610e97575f51610ea2565b8260141c60071660051b5b602083068381015f52016020013e5b50602001611613565b508060a01c61ffff1682600c015160e01c8063a85f1d24146113775780634df86adf1461129257806305ec9cad146114325780639b81788b14610f7a5780638bceaa1814610fdd57806384f16ca01461103f57806395b66162146110a25780639a23842e146111045780634fae2f2314611168578063a9f2812f146111cb578063f93a17161461122f578063fe9bf13d1461153e578063fcccdd98146115725780631e00cebd146115a75780630a6c13bf146115ea576199995f5260205ffd5b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa15610fb757905080602001519051610fbc565b50505f5f5b9082026127100291900390910290046001015f516020019081525f52611602565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa1561101a5790508060200151905161101f565b50505f5f5b82026127100291900390910290046001015f516020019081525f52611602565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa1561107c57905080602001519051611081565b50505f5f5b9090919092029182029190612710020190045f516020019081525f52611602565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156110df579050806020015190516110e4565b50505f5f5b90919092029182029190612710020190045f516020019081525f52611602565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561114257905080602001519051611147565b50505f5f5b9082026127100291900390910290046001015f516020019081525f52611602565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156111a6579050806020015190516111ab565b50505f5f5b82026127100291900390910290046001015f516020019081525f52611602565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156112095790508060200151905161120e565b50505f5f5b9090919092029182029190612710020190045f516020019081525f52611602565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561126d57905080602001519051611272565b50505f5f5b90919092029182029190612710020190045f516020019081525f52611602565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa156142bc575180156112d557600190035b80841115611333577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b85606401516101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af1505050801561136e575f5f5f5f84415af1505b50505050611602565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa156142bc575180156113ba57600190035b80841115611418577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5050801561142a575f5f5f5f84415af1505b505050611602565b5083600c0173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160040151826024015182610100516370a082318152308160200152602081602483601c01855afa156142bc5751801561148557600190035b808411156114e3577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b61010051632e1a7d4d81529081602001525f5f602483601c015f73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25af150508115611526575f5f5f5f85415af1505b84604401515f5f5f475f945af1505050505050611602565b5083600c0180600401517f4bc761c3621ed10674d0b96fcf93f708ec089e64acf91cec204e8e5e6bc415685f5fa250611602565b5083600c015f51805f01517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa350611602565b5083600c018060240151906004015160051b5f5180919003517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa350611602565b5083600c018060040151600160ff1b1760045260245ffd5b915050600c01611613565b5061ffff015b0181811061010b575b505060043560240135602435602401356044356024013501336101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050506142c4565b506084612c55565b506024612c55565b50602480358091602001610120375961010052610120016101205b8080518060f01c8061800016151561178057828260b01c62ffffff16801561173c578062ffffff1461173c579081610fff160181600c1c60ff16801561173a57908260141c60071660051b602001836280000016156116ec57602090035f51035b905b8215156116fc575050611734565b8260201161171b578151815260200190602001916020900391906116ee565b905160018360031b1b6001900380199116908251161790525b5061173e565b505b505b5061ffff168015612b8d5780617ffc1461182b5780617ffe146123225780617ffb1461198e5780617fff146123ae5780617ffd1461243a5780617ffa146118c7575b508060b01c697fffffffffffffffffff1691908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af1156142bc57949150501515611821578060c81c62ffffff16801561181f578062ffffff1461181f5780610fff1681600c1c60ff169082628000001615611805575f51611810565b8260141c60071660051b5b602083068381015f52016020013e5b505b5050602001612b93565b505f91908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af1156142bc579491505015156118bd578060c81c62ffffff1680156118bb578062ffffff146118bb5780610fff1681600c1c60ff1690826280000016156118a1575f516118ac565b8260141c60071660051b5b602083068381015f52016020013e5b505b5050602001612b93565b508060b01c62ffffff168060141c60071660051b602001816280000016156118f157602090035f51035b51905091908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af1156142bc57949150501515611984578060c81c62ffffff168015611982578062ffffff146119825780610fff1681600c1c60ff169082628000001615611968575f51611973565b8260141c60071660051b5b602083068381015f52016020013e5b505b5050602001612b93565b5060a01c61ffff16600c0190600c015b805160f81c80156123115760108111611abd5780600114611a275780600214611a325780600314611a3d5780600414611a485780600514611a535780600614611a5e5780600714611a695780600814611a745780600a14611a875780600b14611a905780600c14611a995780600d14611aa25780600e14611aab5780600f14611ab45750612311565b506020516001612309565b506040516001612309565b506060516001612309565b506080516001612309565b5060a0516001612309565b5060c0516001612309565b5060e0516001612309565b505f51805190602090035f526001612309565b50476001612309565b50416001612309565b50426001612309565b50436001612309565b50486001612309565b503a6001612309565b6020811015611bfc5780601114611b445780601214611b4f5780601314611b5a5780601414611b655780601514611b705780601614611b7b5780601714611b865780601814611b915780601914611b9c5780601a14611ba65780601b14611bba5780601c14611bce5780601d14611bdb5780601e14611be85780601f14611bf25750612311565b509190016001612309565b509190036001612309565b509190026001612309565b509190046001612309565b509190056001612309565b509190166001612309565b509190176001612309565b509190186001612309565b5090196001612309565b50806001015160f81c9091901b6002612309565b50806001015160f81c9091901c6002612309565b5090600190016001612309565b5090600190036001612309565b5091036001612309565b5091046001612309565b6030811015611d325780602014611c4b5780602114611c5c5780602214611c6c5780602314611c905780602414611ca75780602514611cc45780602614611ce35780602a14611d065750612311565b508060010151602161230956612311565b50806001015160ff166002612309565b50806001015161ffff166003612309565b50806001015163ffffffff166005612309565b50806001015167ffffffffffffffff166009612309565b5080600101516dffffffffffffffffffffffffffff166007612309565b5080600101516fffffffffffffffffffffffffffffffff166009612309565b50806001015173ffffffffffffffffffffffffffffffffffffffff16600d612309565b50907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90026001612309565b6030811015611df05780603114611d695780603214611d745780603314611d8e5780603414611da05780603514611db85750612311565b5060ff166001612309565b5061ffff166001612309565b5063ffffffff166001612309565b5067ffffffffffffffff166001612309565b506dffffffffffffffffffffffffffff166001612309565b506fffffffffffffffffffffffffffffffff166001612309565b5073ffffffffffffffffffffffffffffffffffffffff166001612309565b60508110156122835780604014611e7f5780604114611ee75780604214611f4e5780604314611fb6578060441461201d578060451461208557806046146120ec578060471461215157806048146121b757806049146121d15780604a146121ea5780604b146122045780604c1461221d5780604d146122375780604e146122505780604f146122675750612311565b5091901415611e915760016001612309565b7f455100000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919014611ef85760016001612309565b7f4e4551000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901015611f605760016001612309565b7f4c5400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919010611fc75760016001612309565b7f475445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190111561202f5760016001612309565b7f475400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190116120965760016001612309565b7f4c5445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50906120fb5760016001612309565b7f5a5200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5090156121615760016001612309565b7f4e5a52000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919014156121c95760016001612309565b5f5f5260205ff35b509190146121e25760016001612309565b5f5f5260205ff35b50919010156121fc5760016001612309565b5f5f5260205ff35b509190106122155760016001612309565b5f5f5260205ff35b509190111561222f5760016001612309565b5f5f5260205ff35b509190116122485760016001612309565b5f5f5260205ff35b509061225f5760016001612309565b5f5f5260205ff35b5090156122775760016001612309565b5f5f5260205ff3612311565b606081101561230357806050146122a257806051146122d65750612311565b50806001015160f81c8060051b5f5103805f525f5b90602001908151019160019003918215156122b7579150506002612309565b50806001015160f81c5f515f5b8151019060209003909160019003918215156122e3579150506002612309565b50612311565b90910161199e565b50505f516020019081525f52612b93565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855afa156142bc5792505060c81c62ffffff1680156123a5578062ffffff146123a55780610fff1681600c1c60ff16908262800000161561238b575f51612396565b8260141c60071660051b5b602083068381015f52016020013e5b50602001612b93565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855af4156142bc5792505060c81c62ffffff168015612431578062ffffff146124315780610fff1681600c1c60ff169082628000001615612417575f51612422565b8260141c60071660051b5b602083068381015f52016020013e5b50602001612b93565b508060a01c61ffff1682600c015160e01c8063a85f1d24146128f75780634df86adf1461281257806305ec9cad146129b25780639b81788b146124fa5780638bceaa181461255d57806384f16ca0146125bf57806395b66162146126225780639a23842e146126845780634fae2f23146126e8578063a9f2812f1461274b578063f93a1716146127af578063fe9bf13d14612abe578063fcccdd9814612af25780631e00cebd14612b275780630a6c13bf14612b6a576199995f5260205ffd5b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156125375790508060200151905161253c565b50505f5f5b9082026127100291900390910290046001015f516020019081525f52612b82565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa1561259a5790508060200151905161259f565b50505f5f5b82026127100291900390910290046001015f516020019081525f52612b82565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156125fc57905080602001519051612601565b50505f5f5b9090919092029182029190612710020190045f516020019081525f52612b82565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa1561265f57905080602001519051612664565b50505f5f5b90919092029182029190612710020190045f516020019081525f52612b82565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156126c2579050806020015190516126c7565b50505f5f5b9082026127100291900390910290046001015f516020019081525f52612b82565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156127265790508060200151905161272b565b50505f5f5b82026127100291900390910290046001015f516020019081525f52612b82565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156127895790508060200151905161278e565b50505f5f5b9090919092029182029190612710020190045f516020019081525f52612b82565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156127ed579050806020015190516127f2565b50505f5f5b90919092029182029190612710020190045f516020019081525f52612b82565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa156142bc5751801561285557600190035b808411156128b3577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b85606401516101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af150505080156128ee575f5f5f5f84415af1505b50505050612b82565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa156142bc5751801561293a57600190035b80841115612998577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b505080156129aa575f5f5f5f84415af1505b505050612b82565b5083600c0173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160040151826024015182610100516370a082318152308160200152602081602483601c01855afa156142bc57518015612a0557600190035b80841115612a63577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b61010051632e1a7d4d81529081602001525f5f602483601c015f73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25af150508115612aa6575f5f5f5f85415af1505b84604401515f5f5f475f945af1505050505050612b82565b5083600c0180600401517f4bc761c3621ed10674d0b96fcf93f708ec089e64acf91cec204e8e5e6bc415685f5fa250612b82565b5083600c015f51805f01517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa350612b82565b5083600c018060240151906004015160051b5f5180919003517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa350612b82565b5083600c018060040151600160ff1b1760045260245ffd5b915050600c01612b93565b5061ffff015b0181811061168b575b50505f515160205f52602060205260405260605ff35b60443560040180356014146142715750600435604052602435602052612c4a565b50604435600401803560141461427157506004355f8112612c1e576040526024357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff02602052612c4a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff026020526024356040525b60405f526044356004015b80358091602001610120375961010052610120016101205b8080518060f01c80618000161515612d6257828260b01c62ffffff168015612d1e578062ffffff14612d1e579081610fff160181600c1c60ff168015612d1c57908260141c60071660051b60200183628000001615612cce57602090035f51035b905b821515612cde575050612d16565b82602011612cfd57815181526020019060200191602090039190612cd0565b905160018360031b1b6001900380199116908251161790525b50612d20565b505b505b5061ffff16801561416f5780617ffc14612e0d5780617ffe146139045780617ffb14612f705780617fff146139905780617ffd14613a1c5780617ffa14612ea9575b508060b01c697fffffffffffffffffff1691908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af1156142bc57949150501515612e03578060c81c62ffffff168015612e01578062ffffff14612e015780610fff1681600c1c60ff169082628000001615612de7575f51612df2565b8260141c60071660051b5b602083068381015f52016020013e5b505b5050602001614175565b505f91908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af1156142bc57949150501515612e9f578060c81c62ffffff168015612e9d578062ffffff14612e9d5780610fff1681600c1c60ff169082628000001615612e83575f51612e8e565b8260141c60071660051b5b602083068381015f52016020013e5b505b5050602001614175565b508060b01c62ffffff168060141c60071660051b60200181628000001615612ed357602090035f51035b51905091908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af1156142bc57949150501515612f66578060c81c62ffffff168015612f64578062ffffff14612f645780610fff1681600c1c60ff169082628000001615612f4a575f51612f55565b8260141c60071660051b5b602083068381015f52016020013e5b505b5050602001614175565b5060a01c61ffff16600c0190600c015b805160f81c80156138f3576010811161309f57806001146130095780600214613014578060031461301f578060041461302a57806005146130355780600614613040578060071461304b57806008146130565780600a146130695780600b146130725780600c1461307b5780600d146130845780600e1461308d5780600f1461309657506138f3565b5060205160016138eb565b5060405160016138eb565b5060605160016138eb565b5060805160016138eb565b5060a05160016138eb565b5060c05160016138eb565b5060e05160016138eb565b505f51805190602090035f5260016138eb565b504760016138eb565b504160016138eb565b504260016138eb565b504360016138eb565b504860016138eb565b503a60016138eb565b60208110156131de57806011146131265780601214613131578060131461313c57806014146131475780601514613152578060161461315d57806017146131685780601814613173578060191461317e5780601a146131885780601b1461319c5780601c146131b05780601d146131bd5780601e146131ca5780601f146131d457506138f3565b5091900160016138eb565b5091900360016138eb565b5091900260016138eb565b5091900460016138eb565b5091900560016138eb565b5091901660016138eb565b5091901760016138eb565b5091901860016138eb565b50901960016138eb565b50806001015160f81c9091901b60026138eb565b50806001015160f81c9091901c60026138eb565b50906001900160016138eb565b50906001900360016138eb565b50910360016138eb565b50910460016138eb565b6030811015613314578060201461322d578060211461323e578060221461324e5780602314613272578060241461328957806025146132a657806026146132c55780602a146132e857506138f3565b50806001015160216138eb566138f3565b50806001015160ff1660026138eb565b50806001015161ffff1660036138eb565b50806001015163ffffffff1660056138eb565b50806001015167ffffffffffffffff1660096138eb565b5080600101516dffffffffffffffffffffffffffff1660076138eb565b5080600101516fffffffffffffffffffffffffffffffff1660096138eb565b50806001015173ffffffffffffffffffffffffffffffffffffffff16600d6138eb565b50907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff900260016138eb565b60308110156133d2578060311461334b578060321461335657806033146133705780603414613382578060351461339a57506138f3565b5060ff1660016138eb565b5061ffff1660016138eb565b5063ffffffff1660016138eb565b5067ffffffffffffffff1660016138eb565b506dffffffffffffffffffffffffffff1660016138eb565b506fffffffffffffffffffffffffffffffff1660016138eb565b5073ffffffffffffffffffffffffffffffffffffffff1660016138eb565b6050811015613865578060401461346157806041146134c95780604214613530578060431461359857806044146135ff578060451461366757806046146136ce5780604714613733578060481461379957806049146137b35780604a146137cc5780604b146137e65780604c146137ff5780604d146138195780604e146138325780604f1461384957506138f3565b509190141561347357600160016138eb565b7f455100000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190146134da57600160016138eb565b7f4e4551000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190101561354257600160016138eb565b7f4c5400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190106135a957600160016138eb565b7f475445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190111561361157600160016138eb565b7f475400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901161367857600160016138eb565b7f4c5445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50906136dd57600160016138eb565b7f5a5200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50901561374357600160016138eb565b7f4e5a52000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919014156137ab57600160016138eb565b5f5f5260205ff35b509190146137c457600160016138eb565b5f5f5260205ff35b50919010156137de57600160016138eb565b5f5f5260205ff35b509190106137f757600160016138eb565b5f5f5260205ff35b509190111561381157600160016138eb565b5f5f5260205ff35b5091901161382a57600160016138eb565b5f5f5260205ff35b509061384157600160016138eb565b5f5f5260205ff35b50901561385957600160016138eb565b5f5f5260205ff36138f3565b60608110156138e5578060501461388457806051146138b857506138f3565b50806001015160f81c8060051b5f5103805f525f5b90602001908151019160019003918215156138995791505060026138eb565b50806001015160f81c5f515f5b8151019060209003909160019003918215156138c55791505060026138eb565b506138f3565b909101612f80565b50505f516020019081525f52614175565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855afa156142bc5792505060c81c62ffffff168015613987578062ffffff146139875780610fff1681600c1c60ff16908262800000161561396d575f51613978565b8260141c60071660051b5b602083068381015f52016020013e5b50602001614175565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855af4156142bc5792505060c81c62ffffff168015613a13578062ffffff14613a135780610fff1681600c1c60ff1690826280000016156139f9575f51613a04565b8260141c60071660051b5b602083068381015f52016020013e5b50602001614175565b508060a01c61ffff1682600c015160e01c8063a85f1d2414613ed95780634df86adf14613df457806305ec9cad14613f945780639b81788b14613adc5780638bceaa1814613b3f57806384f16ca014613ba157806395b6616214613c045780639a23842e14613c665780634fae2f2314613cca578063a9f2812f14613d2d578063f93a171614613d91578063fe9bf13d146140a0578063fcccdd98146140d45780631e00cebd146141095780630a6c13bf1461414c576199995f5260205ffd5b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa15613b1957905080602001519051613b1e565b50505f5f5b9082026127100291900390910290046001015f516020019081525f52614164565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa15613b7c57905080602001519051613b81565b50505f5f5b82026127100291900390910290046001015f516020019081525f52614164565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa15613bde57905080602001519051613be3565b50505f5f5b9090919092029182029190612710020190045f516020019081525f52614164565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa15613c4157905080602001519051613c46565b50505f5f5b90919092029182029190612710020190045f516020019081525f52614164565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa15613ca457905080602001519051613ca9565b50505f5f5b9082026127100291900390910290046001015f516020019081525f52614164565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa15613d0857905080602001519051613d0d565b50505f5f5b82026127100291900390910290046001015f516020019081525f52614164565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa15613d6b57905080602001519051613d70565b50505f5f5b9090919092029182029190612710020190045f516020019081525f52614164565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa15613dcf57905080602001519051613dd4565b50505f5f5b90919092029182029190612710020190045f516020019081525f52614164565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa156142bc57518015613e3757600190035b80841115613e95577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b85606401516101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050508015613ed0575f5f5f5f84415af1505b50505050614164565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa156142bc57518015613f1c57600190035b80841115613f7a577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50508015613f8c575f5f5f5f84415af1505b505050614164565b5083600c0173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160040151826024015182610100516370a082318152308160200152602081602483601c01855afa156142bc57518015613fe757600190035b80841115614045577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b61010051632e1a7d4d81529081602001525f5f602483601c015f73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25af150508115614088575f5f5f5f85415af1505b84604401515f5f5f475f945af1505050505050614164565b5083600c0180600401517f4bc761c3621ed10674d0b96fcf93f708ec089e64acf91cec204e8e5e6bc415685f5fa250614164565b5083600c015f51805f01517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa350614164565b5083600c018060240151906004015160051b5f5180919003517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa350614164565b5083600c018060040151600160ff1b1760045260245ffd5b915050600c01614175565b5061ffff015b01818110612c6d575b505060205f51f35b506320c13b0b60e01b5f5260205ff35b50631626ba7e60e01b5f5260205ff35b6084356020013560601c6024358015614200573361010051630902f1ac8152606081600483601c01855afa156141e4579050806020015190516141e9565b50505f5f5b908202612710029190039091029004600101614246565b506044353361010051630902f1ac8152606081600483601c01855afa1561422f57905080602001519051614234565b50505f5f5b82026127100291900390910290046001015b336101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050505f5ff35b6020013560601c600435805f90126142885761428d565b506024355b336101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050505f5ff35b5f5ff35b3d5f5f3e3d5ffd5b").unwrap(); + static ref NO_OWNER_CODE : Vec = hex::decode("36156142d6575f3560e01c80632847241714611672578063fa461e3314612be757806323a69e7514612be75780638b4187131461166a57806320c13b0b146141a45780631626ba7e146141b4578063f04f2707146100ec57806391dd73461461167a578063923b8a2a14612bc65750606435806080146100b7575060443580606014612be75750600435806020146100af5750602435806040146100af57506084358060a0146100af57506142d6565b600401612c69565b80600401356014146141c4575060243580156100d5576020526100dd565b506044356020525b60205f52606435600401612c69565b5060643560040180358091602001610120375961010052610120016101205b8080518060f01c8061800016151561020057828260b01c62ffffff1680156101bc578062ffffff146101bc579081610fff160181600c1c60ff1680156101ba57908260141c60071660051b6020018362800000161561016c57602090035f51035b905b82151561017c5750506101b4565b8260201161019b5781518152602001906020019160209003919061016e565b905160018360031b1b6001900380199116908251161790525b506101be565b505b505b5061ffff1680156116175780617ffc146102ad5780617ffe14610da85780617ffb146104145780617fff14610e365780617ffd14610ec45780617ffa1461034b575b508060b01c697fffffffffffffffffff1691908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af1156142da579491505015156102a3578060c81c62ffffff1680156102a1578062ffffff146102a15780610fff1681600c1c60ff169082628000001615610285575f51610290565b8260141c60071660051b5b6020830683810182015f52016020013e5b505b505060200161161d565b505f91908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af1156142da57949150501515610341578060c81c62ffffff16801561033f578062ffffff1461033f5780610fff1681600c1c60ff169082628000001615610323575f5161032e565b8260141c60071660051b5b6020830683810182015f52016020013e5b505b505060200161161d565b508060b01c62ffffff168060141c60071660051b6020018162800000161561037557602090035f51035b51905091908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af1156142da5794915050151561040a578060c81c62ffffff168015610408578062ffffff146104085780610fff1681600c1c60ff1690826280000016156103ec575f516103f7565b8260141c60071660051b5b6020830683810182015f52016020013e5b505b505060200161161d565b5060a01c61ffff16600c0190600c015b805160f81c8015610d97576010811161054357806001146104ad57806002146104b857806003146104c357806004146104ce57806005146104d957806006146104e457806007146104ef57806008146104fa5780600a1461050d5780600b146105165780600c1461051f5780600d146105285780600e146105315780600f1461053a5750610d97565b506020516001610d8f565b506040516001610d8f565b506060516001610d8f565b506080516001610d8f565b5060a0516001610d8f565b5060c0516001610d8f565b5060e0516001610d8f565b505f51805190602090035f526001610d8f565b50476001610d8f565b50416001610d8f565b50426001610d8f565b50436001610d8f565b50486001610d8f565b503a6001610d8f565b602081101561068257806011146105ca57806012146105d557806013146105e057806014146105eb57806015146105f65780601614610601578060171461060c578060181461061757806019146106225780601a1461062c5780601b146106405780601c146106545780601d146106615780601e1461066e5780601f146106785750610d97565b509190016001610d8f565b509190036001610d8f565b509190026001610d8f565b509190046001610d8f565b509190056001610d8f565b509190166001610d8f565b509190176001610d8f565b509190186001610d8f565b5090196001610d8f565b50806001015160f81c9091901b6002610d8f565b50806001015160f81c9091901c6002610d8f565b5090600190016001610d8f565b5090600190036001610d8f565b5091036001610d8f565b5091046001610d8f565b60308110156107b857806020146106d157806021146106e257806022146106f25780602314610716578060241461072d578060251461074a57806026146107695780602a1461078c5750610d97565b5080600101516021610d8f56610d97565b50806001015160ff166002610d8f565b50806001015161ffff166003610d8f565b50806001015163ffffffff166005610d8f565b50806001015167ffffffffffffffff166009610d8f565b5080600101516dffffffffffffffffffffffffffff166007610d8f565b5080600101516fffffffffffffffffffffffffffffffff166009610d8f565b50806001015173ffffffffffffffffffffffffffffffffffffffff16600d610d8f565b50907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90026001610d8f565b603081101561087657806031146107ef57806032146107fa57806033146108145780603414610826578060351461083e5750610d97565b5060ff166001610d8f565b5061ffff166001610d8f565b5063ffffffff166001610d8f565b5067ffffffffffffffff166001610d8f565b506dffffffffffffffffffffffffffff166001610d8f565b506fffffffffffffffffffffffffffffffff166001610d8f565b5073ffffffffffffffffffffffffffffffffffffffff166001610d8f565b6050811015610d095780604014610905578060411461096d57806042146109d45780604314610a3c5780604414610aa35780604514610b0b5780604614610b725780604714610bd75780604814610c3d5780604914610c575780604a14610c705780604b14610c8a5780604c14610ca35780604d14610cbd5780604e14610cd65780604f14610ced5750610d97565b50919014156109175760016001610d8f565b7f455100000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901461097e5760016001610d8f565b7f4e4551000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919010156109e65760016001610d8f565b7f4c5400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919010610a4d5760016001610d8f565b7f475445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901115610ab55760016001610d8f565b7f475400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919011610b1c5760016001610d8f565b7f4c5445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5090610b815760016001610d8f565b7f5a5200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509015610be75760016001610d8f565b7f4e5a52000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901415610c4f5760016001610d8f565b5f5f5260205ff35b50919014610c685760016001610d8f565b5f5f5260205ff35b5091901015610c825760016001610d8f565b5f5f5260205ff35b50919010610c9b5760016001610d8f565b5f5f5260205ff35b5091901115610cb55760016001610d8f565b5f5f5260205ff35b50919011610cce5760016001610d8f565b5f5f5260205ff35b5090610ce55760016001610d8f565b5f5f5260205ff35b509015610cfd5760016001610d8f565b5f5f5260205ff3610d97565b6060811015610d895780605014610d285780605114610d5c5750610d97565b50806001015160f81c8060051b5f5103805f525f5b9060200190815101916001900391821515610d3d579150506002610d8f565b50806001015160f81c5f515f5b815101906020900390916001900391821515610d69579150506002610d8f565b50610d97565b909101610424565b50505f516020019081525f5261161d565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855afa156142da5792505060c81c62ffffff168015610e2d578062ffffff14610e2d5780610fff1681600c1c60ff169082628000001615610e11575f51610e1c565b8260141c60071660051b5b6020830683810182015f52016020013e5b5060200161161d565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855af4156142da5792505060c81c62ffffff168015610ebb578062ffffff14610ebb5780610fff1681600c1c60ff169082628000001615610e9f575f51610eaa565b8260141c60071660051b5b6020830683810182015f52016020013e5b5060200161161d565b508060a01c61ffff1682600c015160e01c8063a85f1d24146113815780634df86adf1461129c57806305ec9cad1461143c5780639b81788b14610f845780638bceaa1814610fe757806384f16ca01461104957806395b66162146110ac5780639a23842e1461110e5780634fae2f2314611172578063a9f2812f146111d5578063f93a171614611239578063fe9bf13d14611548578063fcccdd981461157c5780631e00cebd146115b15780630a6c13bf146115f4576199995f5260205ffd5b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa15610fc157905080602001519051610fc6565b50505f5f5b9082026127100291900390910290046001015f516020019081525f5261160c565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa1561102457905080602001519051611029565b50505f5f5b82026127100291900390910290046001015f516020019081525f5261160c565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156110865790508060200151905161108b565b50505f5f5b9090919092029182029190612710020190045f516020019081525f5261160c565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156110e9579050806020015190516110ee565b50505f5f5b90919092029182029190612710020190045f516020019081525f5261160c565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561114c57905080602001519051611151565b50505f5f5b9082026127100291900390910290046001015f516020019081525f5261160c565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156111b0579050806020015190516111b5565b50505f5f5b82026127100291900390910290046001015f516020019081525f5261160c565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561121357905080602001519051611218565b50505f5f5b9090919092029182029190612710020190045f516020019081525f5261160c565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156112775790508060200151905161127c565b50505f5f5b90919092029182029190612710020190045f516020019081525f5261160c565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa156142da575180156112df57600190035b8084111561133d577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b85606401516101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050508015611378575f5f5f5f84415af1505b5050505061160c565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa156142da575180156113c457600190035b80841115611422577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50508015611434575f5f5f5f84415af1505b50505061160c565b5083600c0173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160040151826024015182610100516370a082318152308160200152602081602483601c01855afa156142da5751801561148f57600190035b808411156114ed577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b61010051632e1a7d4d81529081602001525f5f602483601c015f73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25af150508115611530575f5f5f5f85415af1505b84604401515f5f5f475f945af150505050505061160c565b5083600c0180600401517f4bc761c3621ed10674d0b96fcf93f708ec089e64acf91cec204e8e5e6bc415685f5fa25061160c565b5083600c015f51805f01517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa35061160c565b5083600c018060240151906004015160051b5f5180919003517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa35061160c565b5083600c018060040151600160ff1b1760045260245ffd5b915050600c0161161d565b5061ffff015b0181811061010b575b505060043560240135602435602401356044356024013501336101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050506142e2565b506084612c69565b506024612c69565b50602480358091602001610120375961010052610120016101205b8080518060f01c8061800016151561178a57828260b01c62ffffff168015611746578062ffffff14611746579081610fff160181600c1c60ff16801561174457908260141c60071660051b602001836280000016156116f657602090035f51035b905b82151561170657505061173e565b82602011611725578151815260200190602001916020900391906116f8565b905160018360031b1b6001900380199116908251161790525b50611748565b505b505b5061ffff168015612ba15780617ffc146118375780617ffe146123325780617ffb1461199e5780617fff146123c05780617ffd1461244e5780617ffa146118d5575b508060b01c697fffffffffffffffffff1691908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af1156142da5794915050151561182d578060c81c62ffffff16801561182b578062ffffff1461182b5780610fff1681600c1c60ff16908262800000161561180f575f5161181a565b8260141c60071660051b5b6020830683810182015f52016020013e5b505b5050602001612ba7565b505f91908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af1156142da579491505015156118cb578060c81c62ffffff1680156118c9578062ffffff146118c95780610fff1681600c1c60ff1690826280000016156118ad575f516118b8565b8260141c60071660051b5b6020830683810182015f52016020013e5b505b5050602001612ba7565b508060b01c62ffffff168060141c60071660051b602001816280000016156118ff57602090035f51035b51905091908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af1156142da57949150501515611994578060c81c62ffffff168015611992578062ffffff146119925780610fff1681600c1c60ff169082628000001615611976575f51611981565b8260141c60071660051b5b6020830683810182015f52016020013e5b505b5050602001612ba7565b5060a01c61ffff16600c0190600c015b805160f81c80156123215760108111611acd5780600114611a375780600214611a425780600314611a4d5780600414611a585780600514611a635780600614611a6e5780600714611a795780600814611a845780600a14611a975780600b14611aa05780600c14611aa95780600d14611ab25780600e14611abb5780600f14611ac45750612321565b506020516001612319565b506040516001612319565b506060516001612319565b506080516001612319565b5060a0516001612319565b5060c0516001612319565b5060e0516001612319565b505f51805190602090035f526001612319565b50476001612319565b50416001612319565b50426001612319565b50436001612319565b50486001612319565b503a6001612319565b6020811015611c0c5780601114611b545780601214611b5f5780601314611b6a5780601414611b755780601514611b805780601614611b8b5780601714611b965780601814611ba15780601914611bac5780601a14611bb65780601b14611bca5780601c14611bde5780601d14611beb5780601e14611bf85780601f14611c025750612321565b509190016001612319565b509190036001612319565b509190026001612319565b509190046001612319565b509190056001612319565b509190166001612319565b509190176001612319565b509190186001612319565b5090196001612319565b50806001015160f81c9091901b6002612319565b50806001015160f81c9091901c6002612319565b5090600190016001612319565b5090600190036001612319565b5091036001612319565b5091046001612319565b6030811015611d425780602014611c5b5780602114611c6c5780602214611c7c5780602314611ca05780602414611cb75780602514611cd45780602614611cf35780602a14611d165750612321565b508060010151602161231956612321565b50806001015160ff166002612319565b50806001015161ffff166003612319565b50806001015163ffffffff166005612319565b50806001015167ffffffffffffffff166009612319565b5080600101516dffffffffffffffffffffffffffff166007612319565b5080600101516fffffffffffffffffffffffffffffffff166009612319565b50806001015173ffffffffffffffffffffffffffffffffffffffff16600d612319565b50907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90026001612319565b6030811015611e005780603114611d795780603214611d845780603314611d9e5780603414611db05780603514611dc85750612321565b5060ff166001612319565b5061ffff166001612319565b5063ffffffff166001612319565b5067ffffffffffffffff166001612319565b506dffffffffffffffffffffffffffff166001612319565b506fffffffffffffffffffffffffffffffff166001612319565b5073ffffffffffffffffffffffffffffffffffffffff166001612319565b60508110156122935780604014611e8f5780604114611ef75780604214611f5e5780604314611fc6578060441461202d578060451461209557806046146120fc578060471461216157806048146121c757806049146121e15780604a146121fa5780604b146122145780604c1461222d5780604d146122475780604e146122605780604f146122775750612321565b5091901415611ea15760016001612319565b7f455100000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919014611f085760016001612319565b7f4e4551000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5091901015611f705760016001612319565b7f4c5400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919010611fd75760016001612319565b7f475445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190111561203f5760016001612319565b7f475400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190116120a65760016001612319565b7f4c5445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509061210b5760016001612319565b7f5a5200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b5090156121715760016001612319565b7f4e5a52000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919014156121d95760016001612319565b5f5f5260205ff35b509190146121f25760016001612319565b5f5f5260205ff35b509190101561220c5760016001612319565b5f5f5260205ff35b509190106122255760016001612319565b5f5f5260205ff35b509190111561223f5760016001612319565b5f5f5260205ff35b509190116122585760016001612319565b5f5f5260205ff35b509061226f5760016001612319565b5f5f5260205ff35b5090156122875760016001612319565b5f5f5260205ff3612321565b606081101561231357806050146122b257806051146122e65750612321565b50806001015160f81c8060051b5f5103805f525f5b90602001908151019160019003918215156122c7579150506002612319565b50806001015160f81c5f515f5b8151019060209003909160019003918215156122f3579150506002612319565b50612321565b9091016119ae565b50505f516020019081525f52612ba7565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855afa156142da5792505060c81c62ffffff1680156123b7578062ffffff146123b75780610fff1681600c1c60ff16908262800000161561239b575f516123a6565b8260141c60071660051b5b6020830683810182015f52016020013e5b50602001612ba7565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855af4156142da5792505060c81c62ffffff168015612445578062ffffff146124455780610fff1681600c1c60ff169082628000001615612429575f51612434565b8260141c60071660051b5b6020830683810182015f52016020013e5b50602001612ba7565b508060a01c61ffff1682600c015160e01c8063a85f1d241461290b5780634df86adf1461282657806305ec9cad146129c65780639b81788b1461250e5780638bceaa181461257157806384f16ca0146125d357806395b66162146126365780639a23842e146126985780634fae2f23146126fc578063a9f2812f1461275f578063f93a1716146127c3578063fe9bf13d14612ad2578063fcccdd9814612b065780631e00cebd14612b3b5780630a6c13bf14612b7e576199995f5260205ffd5b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa1561254b57905080602001519051612550565b50505f5f5b9082026127100291900390910290046001015f516020019081525f52612b96565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa156125ae579050806020015190516125b3565b50505f5f5b82026127100291900390910290046001015f516020019081525f52612b96565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa1561261057905080602001519051612615565b50505f5f5b9090919092029182029190612710020190045f516020019081525f52612b96565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa1561267357905080602001519051612678565b50505f5f5b90919092029182029190612710020190045f516020019081525f52612b96565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa156126d6579050806020015190516126db565b50505f5f5b9082026127100291900390910290046001015f516020019081525f52612b96565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561273a5790508060200151905161273f565b50505f5f5b82026127100291900390910290046001015f516020019081525f52612b96565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561279d579050806020015190516127a2565b50505f5f5b9090919092029182029190612710020190045f516020019081525f52612b96565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa1561280157905080602001519051612806565b50505f5f5b90919092029182029190612710020190045f516020019081525f52612b96565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa156142da5751801561286957600190035b808411156128c7577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b85606401516101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050508015612902575f5f5f5f84415af1505b50505050612b96565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa156142da5751801561294e57600190035b808411156129ac577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b505080156129be575f5f5f5f84415af1505b505050612b96565b5083600c0173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160040151826024015182610100516370a082318152308160200152602081602483601c01855afa156142da57518015612a1957600190035b80841115612a77577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b61010051632e1a7d4d81529081602001525f5f602483601c015f73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25af150508115612aba575f5f5f5f85415af1505b84604401515f5f5f475f945af1505050505050612b96565b5083600c0180600401517f4bc761c3621ed10674d0b96fcf93f708ec089e64acf91cec204e8e5e6bc415685f5fa250612b96565b5083600c015f51805f01517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa350612b96565b5083600c018060240151906004015160051b5f5180919003517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa350612b96565b5083600c018060040151600160ff1b1760045260245ffd5b915050600c01612ba7565b5061ffff015b01818110611695575b50505f515160205f52602060205260405260605ff35b604435600401803560141461428f5750600435604052602435602052612c5e565b50604435600401803560141461428f57506004355f8112612c32576040526024357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff02602052612c5e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff026020526024356040525b60405f526044356004015b80358091602001610120375961010052610120016101205b8080518060f01c80618000161515612d7657828260b01c62ffffff168015612d32578062ffffff14612d32579081610fff160181600c1c60ff168015612d3057908260141c60071660051b60200183628000001615612ce257602090035f51035b905b821515612cf2575050612d2a565b82602011612d1157815181526020019060200191602090039190612ce4565b905160018360031b1b6001900380199116908251161790525b50612d34565b505b505b5061ffff16801561418d5780617ffc14612e235780617ffe1461391e5780617ffb14612f8a5780617fff146139ac5780617ffd14613a3a5780617ffa14612ec1575b508060b01c697fffffffffffffffffff1691908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af1156142da57949150501515612e19578060c81c62ffffff168015612e17578062ffffff14612e175780610fff1681600c1c60ff169082628000001615612dfb575f51612e06565b8260141c60071660051b5b6020830683810182015f52016020013e5b505b5050602001614193565b505f91908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af1156142da57949150501515612eb7578060c81c62ffffff168015612eb5578062ffffff14612eb55780610fff1681600c1c60ff169082628000001615612e99575f51612ea4565b8260141c60071660051b5b6020830683810182015f52016020013e5b505b5050602001614193565b508060b01c62ffffff168060141c60071660051b60200181628000001615612eeb57602090035f51035b51905091908073ffffffffffffffffffffffffffffffffffffffff16818060a01c61ffff165f5f826020880189875af1156142da57949150501515612f80578060c81c62ffffff168015612f7e578062ffffff14612f7e5780610fff1681600c1c60ff169082628000001615612f62575f51612f6d565b8260141c60071660051b5b6020830683810182015f52016020013e5b505b5050602001614193565b5060a01c61ffff16600c0190600c015b805160f81c801561390d57601081116130b95780600114613023578060021461302e57806003146130395780600414613044578060051461304f578060061461305a578060071461306557806008146130705780600a146130835780600b1461308c5780600c146130955780600d1461309e5780600e146130a75780600f146130b0575061390d565b506020516001613905565b506040516001613905565b506060516001613905565b506080516001613905565b5060a0516001613905565b5060c0516001613905565b5060e0516001613905565b505f51805190602090035f526001613905565b50476001613905565b50416001613905565b50426001613905565b50436001613905565b50486001613905565b503a6001613905565b60208110156131f85780601114613140578060121461314b57806013146131565780601414613161578060151461316c57806016146131775780601714613182578060181461318d57806019146131985780601a146131a25780601b146131b65780601c146131ca5780601d146131d75780601e146131e45780601f146131ee575061390d565b509190016001613905565b509190036001613905565b509190026001613905565b509190046001613905565b509190056001613905565b509190166001613905565b509190176001613905565b509190186001613905565b5090196001613905565b50806001015160f81c9091901b6002613905565b50806001015160f81c9091901c6002613905565b5090600190016001613905565b5090600190036001613905565b5091036001613905565b5091046001613905565b603081101561332e578060201461324757806021146132585780602214613268578060231461328c57806024146132a357806025146132c057806026146132df5780602a14613302575061390d565b50806001015160216139055661390d565b50806001015160ff166002613905565b50806001015161ffff166003613905565b50806001015163ffffffff166005613905565b50806001015167ffffffffffffffff166009613905565b5080600101516dffffffffffffffffffffffffffff166007613905565b5080600101516fffffffffffffffffffffffffffffffff166009613905565b50806001015173ffffffffffffffffffffffffffffffffffffffff16600d613905565b50907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90026001613905565b60308110156133ec57806031146133655780603214613370578060331461338a578060341461339c57806035146133b4575061390d565b5060ff166001613905565b5061ffff166001613905565b5063ffffffff166001613905565b5067ffffffffffffffff166001613905565b506dffffffffffffffffffffffffffff166001613905565b506fffffffffffffffffffffffffffffffff166001613905565b5073ffffffffffffffffffffffffffffffffffffffff166001613905565b605081101561387f578060401461347b57806041146134e3578060421461354a57806043146135b25780604414613619578060451461368157806046146136e8578060471461374d57806048146137b357806049146137cd5780604a146137e65780604b146138005780604c146138195780604d146138335780604e1461384c5780604f14613863575061390d565b509190141561348d5760016001613905565b7f455100000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190146134f45760016001613905565b7f4e4551000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190101561355c5760016001613905565b7f4c5400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190106135c35760016001613905565b7f475445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190111561362b5760016001613905565b7f475400000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b509190116136925760016001613905565b7f4c5445000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50906136f75760016001613905565b7f5a5200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50901561375d5760016001613905565b7f4e5a52000000000000000000000000000000000000000000000000000000000060037f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50919014156137c55760016001613905565b5f5f5260205ff35b509190146137de5760016001613905565b5f5f5260205ff35b50919010156137f85760016001613905565b5f5f5260205ff35b509190106138115760016001613905565b5f5f5260205ff35b509190111561382b5760016001613905565b5f5f5260205ff35b509190116138445760016001613905565b5f5f5260205ff35b509061385b5760016001613905565b5f5f5260205ff35b5090156138735760016001613905565b5f5f5260205ff361390d565b60608110156138ff578060501461389e57806051146138d2575061390d565b50806001015160f81c8060051b5f5103805f525f5b90602001908151019160019003918215156138b3579150506002613905565b50806001015160f81c5f515f5b8151019060209003909160019003918215156138df579150506002613905565b5061390d565b909101612f9a565b50505f516020019081525f52614193565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855afa156142da5792505060c81c62ffffff1680156139a3578062ffffff146139a35780610fff1681600c1c60ff169082628000001615613987575f51613992565b8260141c60071660051b5b6020830683810182015f52016020013e5b50602001614193565b508073ffffffffffffffffffffffffffffffffffffffff168160a01c61ffff165f5f8260208701855af4156142da5792505060c81c62ffffff168015613a31578062ffffff14613a315780610fff1681600c1c60ff169082628000001615613a15575f51613a20565b8260141c60071660051b5b6020830683810182015f52016020013e5b50602001614193565b508060a01c61ffff1682600c015160e01c8063a85f1d2414613ef75780634df86adf14613e1257806305ec9cad14613fb25780639b81788b14613afa5780638bceaa1814613b5d57806384f16ca014613bbf57806395b6616214613c225780639a23842e14613c845780634fae2f2314613ce8578063a9f2812f14613d4b578063f93a171614613daf578063fe9bf13d146140be578063fcccdd98146140f25780631e00cebd146141275780630a6c13bf1461416a576199995f5260205ffd5b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa15613b3757905080602001519051613b3c565b50505f5f5b9082026127100291900390910290046001015f516020019081525f52614182565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa15613b9a57905080602001519051613b9f565b50505f5f5b82026127100291900390910290046001015f516020019081525f52614182565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa15613bfc57905080602001519051613c01565b50505f5f5b9090919092029182029190612710020190045f516020019081525f52614182565b5083600c016126f2908060240151906004015161010051630902f1ac8152606081600483601c01855afa15613c5f57905080602001519051613c64565b50505f5f5b90919092029182029190612710020190045f516020019081525f52614182565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa15613cc257905080602001519051613cc7565b50505f5f5b9082026127100291900390910290046001015f516020019081525f52614182565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa15613d2657905080602001519051613d2b565b50505f5f5b82026127100291900390910290046001015f516020019081525f52614182565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa15613d8957905080602001519051613d8e565b50505f5f5b9090919092029182029190612710020190045f516020019081525f52614182565b5083600c0180602401518160440151916004015161010051630902f1ac8152606081600483601c01855afa15613ded57905080602001519051613df2565b50505f5f5b90919092029182029190612710020190045f516020019081525f52614182565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa156142da57518015613e5557600190035b80841115613eb3577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b85606401516101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050508015613eee575f5f5f5f84415af1505b50505050614182565b5083600c0180600401518160240151826044015182610100516370a082318152308160200152602081602483601c01855afa156142da57518015613f3a57600190035b80841115613f98577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b50508015613faa575f5f5f5f84415af1505b505050614182565b5083600c0173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160040151826024015182610100516370a082318152308160200152602081602483601c01855afa156142da5751801561400557600190035b80841115614063577f424200000000000000000000000000000000000000000000000000000000000060027f08c379a0000000000000000000000000000000000000000000000000000000005f52602060045260245260445260645ffd5b61010051632e1a7d4d81529081602001525f5f602483601c015f73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25af1505081156140a6575f5f5f5f85415af1505b84604401515f5f5f475f945af1505050505050614182565b5083600c0180600401517f4bc761c3621ed10674d0b96fcf93f708ec089e64acf91cec204e8e5e6bc415685f5fa250614182565b5083600c015f51805f01517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa350614182565b5083600c018060240151906004015160051b5f5180919003517f89af0fd11b64392b3a1ab47eb65ae5e5f01335c6fc2ac518b0fc21aa0f7ff8c65f5fa350614182565b5083600c018060040151600160ff1b1760045260245ffd5b915050600c01614193565b5061ffff015b01818110612c81575b505060205f51f35b506320c13b0b60e01b5f5260205ff35b50631626ba7e60e01b5f5260205ff35b6084356020013560601c602435801561421e573361010051630902f1ac8152606081600483601c01855afa1561420257905080602001519051614207565b50505f5f5b908202612710029190039091029004600101614264565b506044353361010051630902f1ac8152606081600483601c01855afa1561424d57905080602001519051614252565b50505f5f5b82026127100291900390910290046001015b336101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050505f5ff35b6020013560601c600435805f90126142a6576142ab565b506024355b336101005163a9059cbb81529081602001529081604001525f5f604483601c015f865af15050505f5ff35b5f5ff35b3d5f5f3e3d5ffd5b").unwrap(); static ref NO_OWNER_DEPLOY_PREFIX : Vec = hex::decode("612c2380600a3d393df3").unwrap(); } pub const DEFAULT_VIRTUAL_ADDRESS: Address = Address::repeat_byte(0x78); diff --git a/crates/execution/multicaller/src/lib.rs b/crates/execution/multicaller/src/lib.rs index fd4b5bd1..457efa23 100644 --- a/crates/execution/multicaller/src/lib.rs +++ b/crates/execution/multicaller/src/lib.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] +pub use abi_helpers::AbiEncoderHelper; pub use deploy::{MulticallerDeployer, DEFAULT_VIRTUAL_ADDRESS}; -pub use helpers::AbiEncoderHelper; pub use multicaller_encoder::MulticallerEncoder; pub use multicaller_encoder::MulticallerSwapEncoder; pub use opcodes_encoder::{OpcodesEncoder, OpcodesEncoderV2}; @@ -8,10 +8,11 @@ pub use pool_abi_encoder::ProtocolABIEncoderV2; pub use swapline_encoder::SwapLineEncoder; pub use swapstep_encoder::SwapStepEncoder; +mod abi_helpers; mod deploy; -mod helpers; mod multicaller_encoder; mod opcodes_encoder; +mod opcodes_helpers; pub mod pool_abi_encoder; pub mod pool_opcodes_encoder; mod swap_encoder; diff --git a/crates/execution/multicaller/src/opcodes_helpers.rs b/crates/execution/multicaller/src/opcodes_helpers.rs new file mode 100644 index 00000000..c593c17e --- /dev/null +++ b/crates/execution/multicaller/src/opcodes_helpers.rs @@ -0,0 +1,93 @@ +use crate::AbiEncoderHelper; +use alloy_primitives::{Address, U256}; +use eyre::Result; +use loom_types_blockchain::{MulticallerCall, MulticallerCalls}; +use loom_types_entities::SwapAmountType; + +pub struct OpcodesHelpers {} + +impl OpcodesHelpers { + pub fn build_log_stack(size: usize) -> Result { + let mut calls = MulticallerCalls::new(); + + for i in 0..size { + calls.add(MulticallerCall::new_internal_call(&AbiEncoderHelper::encode_multicaller_log_stack_offset(U256::from(i)))); + } + + Ok(calls) + } + + pub fn build_call_stack( + amount: SwapAmountType, + call: MulticallerCall, + offset: u32, + len: usize, + balance_of_token: Option
, + ) -> Result { + let mut calls = MulticallerCalls::new(); + let mut call = call; + + match amount { + SwapAmountType::Set(_value) => {} + SwapAmountType::Balance(balance_of_owner) => { + let mut balance_opcode = MulticallerCall::new_static_call( + balance_of_token.unwrap(), + &AbiEncoderHelper::encode_erc20_balance_of(balance_of_owner), + ); + balance_opcode.set_return_stack(true, 0, 0x0, 0x20); + calls.add(balance_opcode); + + call.set_call_stack(true, 0, offset, len); + } + SwapAmountType::RelativeStack(stack_offset) => { + call.set_call_stack(true, stack_offset, offset, len); + } + SwapAmountType::NotSet => { + call.set_call_stack(true, 0, offset, len); + } + SwapAmountType::Stack0 => { + call.set_call_stack(false, 0, offset, len); + } + } + calls.add(call); + + Ok(calls) + } + + pub fn build_multiple_stack( + amount: SwapAmountType, + calls: Vec<(MulticallerCall, u32, usize)>, + balance_of_token: Option
, + ) -> Result { + let mut multicaller_calls = MulticallerCalls::new(); + + if let SwapAmountType::Balance(balance_of_owner) = amount { + let mut balance_opcode = + MulticallerCall::new_static_call(balance_of_token.unwrap(), &AbiEncoderHelper::encode_erc20_balance_of(balance_of_owner)); + balance_opcode.set_return_stack(true, 0, 0x0, 0x20); + multicaller_calls.add(balance_opcode); + } + + for (call, offset, len) in calls { + let mut call = call; + match amount { + SwapAmountType::Set(_value) => {} + SwapAmountType::Balance(_balance_of_owner) => { + call.set_call_stack(true, 0, offset, len); + } + SwapAmountType::RelativeStack(stack_offset) => { + call.set_call_stack(true, stack_offset, offset, len); + } + SwapAmountType::NotSet => { + call.set_call_stack(true, 0, offset, len); + } + SwapAmountType::Stack0 => { + call.set_call_stack(false, 0, offset, len); + } + } + multicaller_calls.add(call); + } + + Ok(multicaller_calls) + } +} diff --git a/crates/execution/multicaller/src/pool_opcodes_encoder/curve.rs b/crates/execution/multicaller/src/pool_opcodes_encoder/curve.rs index 4f1a9f27..5c11461b 100644 --- a/crates/execution/multicaller/src/pool_opcodes_encoder/curve.rs +++ b/crates/execution/multicaller/src/pool_opcodes_encoder/curve.rs @@ -1,11 +1,13 @@ -use alloy_primitives::{Address, Bytes, U256}; -use eyre::Result; +use alloy_primitives::{Address, U256}; +use eyre::{eyre, Result}; use lazy_static::lazy_static; use std::collections::HashMap; -use tracing::error; +use tracing::trace; -use crate::helpers::AbiEncoderHelper; +use crate::abi_helpers::AbiEncoderHelper; +use crate::opcodes_helpers::OpcodesHelpers; use crate::pool_abi_encoder::ProtocolAbiSwapEncoderTrait; +use crate::pool_opcodes_encoder::swap_opcodes_encoders::MulticallerOpcodesPayload; use crate::pool_opcodes_encoder::SwapOpcodesEncoderTrait; use loom_types_blockchain::{MulticallerCall, MulticallerCalls}; use loom_types_entities::Pool; @@ -40,6 +42,7 @@ impl SwapOpcodesEncoderTrait for CurveSwapOpcodesEncoder { amount_in: SwapAmountType, cur_pool: &dyn Pool, next_pool: Option<&dyn Pool>, + payload: MulticallerOpcodesPayload, multicaller: Address, ) -> Result<()> { //let pool_encoder = abi_encoder.cur_pool.get_encoder().ok_or_eyre("NO_POOL_ENCODER")?; @@ -48,238 +51,75 @@ impl SwapOpcodesEncoderTrait for CurveSwapOpcodesEncoder { let in_native = if abi_encoder.is_native(cur_pool) { AbiEncoderHelper::is_weth(token_from_address) } else { false }; let out_native = if abi_encoder.is_native(cur_pool) { AbiEncoderHelper::is_weth(token_to_address) } else { false }; - match amount_in { - SwapAmountType::Set(amount) => { - if in_native { - let weth_withdraw_opcode = - MulticallerCall::new_call(token_from_address, &AbiEncoderHelper::encode_weth_withdraw(amount)); - let mut swap_opcode = MulticallerCall::new_call_with_value( - pool_address, - &abi_encoder.encode_swap_in_amount_provided( - cur_pool, - token_from_address, - token_to_address, - amount, - multicaller, - Bytes::new(), - )?, - amount, - ); - if !Self::need_balance(cur_pool.get_address()) { - swap_opcode.set_return_stack(true, 0, 0x0, 0x20); - } - swap_opcodes.add(weth_withdraw_opcode).add(swap_opcode); - } else { - let approve_opcode = MulticallerCall::new_call( - token_from_address, - &AbiEncoderHelper::encode_erc20_approve(cur_pool.get_address(), amount), - ); - let mut swap_opcode = MulticallerCall::new_call( - pool_address, - &abi_encoder.encode_swap_in_amount_provided( - cur_pool, - token_from_address, - token_to_address, - amount, - multicaller, - Bytes::new(), - )?, - ); - - if !Self::need_balance(cur_pool.get_address()) { - swap_opcode.set_return_stack(true, 0, 0x0, 0x20); - } - - swap_opcodes.add(approve_opcode).add(swap_opcode); - } - } - SwapAmountType::Stack0 => { - if in_native { - let mut weth_withdraw_opcode = - MulticallerCall::new_call(token_from_address, &AbiEncoderHelper::encode_weth_withdraw(U256::ZERO)); - weth_withdraw_opcode.set_call_stack(false, 0, 0x4, 0x20); - - let mut swap_opcode = MulticallerCall::new_call_with_value( - pool_address, - &abi_encoder.encode_swap_in_amount_provided( - cur_pool, - token_from_address, - token_to_address, - U256::ZERO, - multicaller, - Bytes::new(), - )?, - U256::ZERO, - ); - swap_opcode.set_call_stack( - false, - 0, - abi_encoder.swap_in_amount_offset(cur_pool, token_from_address, token_to_address).unwrap(), - 0x20, - ); - if !Self::need_balance(cur_pool.get_address()) { - swap_opcode.set_return_stack(true, 0, 0x0, 0x20); - } - swap_opcodes.add(weth_withdraw_opcode).add(swap_opcode); - } else { - let mut approve_opcode = MulticallerCall::new_call( - token_from_address, - &AbiEncoderHelper::encode_erc20_approve(cur_pool.get_address(), U256::ZERO), - ); - approve_opcode.set_call_stack(false, 0, 0x24, 0x20); - - let mut swap_opcode = MulticallerCall::new_call( - pool_address, - &abi_encoder.encode_swap_in_amount_provided( - cur_pool, - token_from_address, - token_to_address, - U256::ZERO, - multicaller, - Bytes::new(), - )?, - ); - swap_opcode.set_call_stack( - false, - 0, - abi_encoder.swap_in_amount_offset(cur_pool, token_from_address, token_to_address).unwrap(), - 0x20, - ); - if !Self::need_balance(cur_pool.get_address()) { - swap_opcode.set_return_stack(true, 0, 0x0, 0x20); - } - - swap_opcodes.add(approve_opcode).add(swap_opcode); - } + trace!( + "curve swap for pool={:?} native={} amount={:?} from {} to {}", + cur_pool.get_address(), + cur_pool.is_native(), + amount_in, + token_from_address, + token_to_address + ); + + let mut opcodes: Vec<(MulticallerCall, u32, usize)> = Vec::new(); + + if in_native { + // Swap opcode + let mut swap_opcode = MulticallerCall::new_call_with_value( + pool_address, + &abi_encoder.encode_swap_in_amount_provided( + cur_pool, + token_from_address, + token_to_address, + amount_in.unwrap_or_default(), + multicaller, + payload.encode()?, + )?, + amount_in.unwrap_or_default(), + ); + + if !Self::need_balance(cur_pool.get_address()) { + swap_opcode.set_return_stack(true, 0, 0x0, 0x20); } - SwapAmountType::RelativeStack(stack_offset) => { - if in_native { - let mut weth_withdraw_opcode = - MulticallerCall::new_call(token_from_address, &AbiEncoderHelper::encode_weth_withdraw(U256::ZERO)); - weth_withdraw_opcode.set_call_stack(true, stack_offset, 0x4, 0x20); - let mut swap_opcode = MulticallerCall::new_call_with_value( - pool_address, - &abi_encoder.encode_swap_in_amount_provided( - cur_pool, - token_from_address, - token_to_address, - U256::ZERO, - multicaller, - Bytes::new(), - )?, - U256::ZERO, - ); - swap_opcode.set_call_stack( - true, - stack_offset, - abi_encoder.swap_in_amount_offset(cur_pool, token_from_address, token_to_address).unwrap(), - 0x20, - ); - if !Self::need_balance(cur_pool.get_address()) { - swap_opcode.set_return_stack(true, 0, 0x0, 0x20); - } - swap_opcodes.add(weth_withdraw_opcode).add(swap_opcode); - } else { - let mut approve_opcode = MulticallerCall::new_call( - token_from_address, - &AbiEncoderHelper::encode_erc20_approve(cur_pool.get_address(), U256::ZERO), - ); - approve_opcode.set_call_stack(true, stack_offset, 0x24, 0x20); - - let mut swap_opcode = MulticallerCall::new_call( - pool_address, - &abi_encoder.encode_swap_in_amount_provided( - cur_pool, - token_from_address, - token_to_address, - U256::ZERO, - multicaller, - Bytes::new(), - )?, - ); - swap_opcode.set_call_stack( - true, - stack_offset, - abi_encoder.swap_in_amount_offset(cur_pool, token_from_address, token_to_address).unwrap(), - 0x20, - ); - if !Self::need_balance(cur_pool.get_address()) { - swap_opcode.set_return_stack(true, 0, 0x0, 0x20); - } - - swap_opcodes.add(approve_opcode).add(swap_opcode); - } - } - SwapAmountType::Balance(addr) => { - let mut balance_opcode = - MulticallerCall::new_static_call(token_from_address, &AbiEncoderHelper::encode_erc20_balance_of(addr)); - balance_opcode.set_return_stack(true, 0, 0x0, 0x20); - - if in_native { - let mut weth_withdraw_opcode = - MulticallerCall::new_call(token_from_address, &AbiEncoderHelper::encode_weth_withdraw(U256::ZERO)); - weth_withdraw_opcode.set_call_stack(true, 0, 0x4, 0x20); - - let mut swap_opcode = MulticallerCall::new_call_with_value( - pool_address, - &abi_encoder.encode_swap_in_amount_provided( - cur_pool, - token_from_address, - token_to_address, - U256::ZERO, - multicaller, - Bytes::new(), - )?, - U256::ZERO, - ); - swap_opcode.set_call_stack( - true, - 0, - abi_encoder.swap_in_amount_offset(cur_pool, token_from_address, token_to_address).unwrap(), - 0x20, - ); - if !Self::need_balance(cur_pool.get_address()) { - swap_opcode.set_return_stack(true, 0, 0x0, 0x20); - } - swap_opcodes.add(balance_opcode).add(weth_withdraw_opcode).add(swap_opcode); - } else { - let mut approve_opcode = MulticallerCall::new_call( - token_from_address, - &AbiEncoderHelper::encode_erc20_approve(cur_pool.get_address(), U256::ZERO), - ); - approve_opcode.set_call_stack(true, 0, 0x24, 0x20); - - let mut swap_opcode = MulticallerCall::new_call( - pool_address, - &abi_encoder.encode_swap_in_amount_provided( - cur_pool, - token_from_address, - token_to_address, - U256::ZERO, - multicaller, - Bytes::new(), - )?, - ); - swap_opcode.set_call_stack( - true, - 0, - abi_encoder.swap_in_amount_offset(cur_pool, token_from_address, token_to_address).unwrap(), - 0x20, - ); - - if !Self::need_balance(cur_pool.get_address()) { - swap_opcode.set_return_stack(true, 0, 0x0, 0x20); - } - - swap_opcodes.add(balance_opcode).add(approve_opcode).add(swap_opcode); - } - } - _ => { - error!("Curve amount not handled") + // Withdraw WETH + opcodes.push(( + MulticallerCall::new_call(token_from_address, &AbiEncoderHelper::encode_weth_withdraw(amount_in.unwrap_or_default())), + 0x4, + 0x20, + )); + opcodes.push((swap_opcode, abi_encoder.swap_in_amount_offset(cur_pool, token_from_address, token_to_address).unwrap(), 0x20)); + } else { + //Approve + opcodes.push(( + MulticallerCall::new_call( + token_from_address, + &AbiEncoderHelper::encode_erc20_approve(cur_pool.get_address(), amount_in.unwrap_or_default()), + ), + 0x24, + 0x20, + )); + + // SWAP + let mut swap_opcode = MulticallerCall::new_call( + pool_address, + &abi_encoder.encode_swap_in_amount_provided( + cur_pool, + token_from_address, + token_to_address, + amount_in.unwrap_or_default(), + multicaller, + payload.encode()?, + )?, + ); + + if !Self::need_balance(cur_pool.get_address()) { + swap_opcode.set_return_stack(true, 0, 0x0, 0x20); } + opcodes.push((swap_opcode, abi_encoder.swap_in_amount_offset(cur_pool, token_from_address, token_to_address).unwrap(), 0x20)); } + swap_opcodes.merge(OpcodesHelpers::build_multiple_stack(amount_in, opcodes, Some(token_from_address))?); + if out_native { let mut weth_deposit_opcode = MulticallerCall::new_call_with_value(token_to_address, &AbiEncoderHelper::encode_weth_deposit(), U256::ZERO); @@ -296,6 +136,8 @@ impl SwapOpcodesEncoderTrait for CurveSwapOpcodesEncoder { } if let PreswapRequirement::Transfer(addr) = abi_encoder.preswap_requirement(next_pool) { + trace!("transfer token={:?}, to={:?}, amount=stack_rel_0", token_to_address, addr); + let mut transfer_opcode = MulticallerCall::new_call(token_to_address, &AbiEncoderHelper::encode_erc20_transfer(addr, U256::ZERO)); transfer_opcode.set_call_stack(true, 0, 0x24, 0x20); @@ -304,4 +146,19 @@ impl SwapOpcodesEncoderTrait for CurveSwapOpcodesEncoder { } Ok(()) } + + fn encode_swap_out_amount_provided( + &self, + _swap_opcodes: &mut MulticallerCalls, + _abi_encoder: &dyn ProtocolAbiSwapEncoderTrait, + _token_from_address: Address, + _token_to_address: Address, + _amount_out: SwapAmountType, + _cur_pool: &dyn Pool, + _next_pool: Option<&dyn Pool>, + _payload: MulticallerOpcodesPayload, + _multicaller_address: Address, + ) -> Result<()> { + Err(eyre!("NOT_IMPLEMENTED")) + } } diff --git a/crates/execution/multicaller/src/pool_opcodes_encoder/mod.rs b/crates/execution/multicaller/src/pool_opcodes_encoder/mod.rs index 106eff1b..8a689741 100644 --- a/crates/execution/multicaller/src/pool_opcodes_encoder/mod.rs +++ b/crates/execution/multicaller/src/pool_opcodes_encoder/mod.rs @@ -1,7 +1,8 @@ use crate::pool_abi_encoder::ProtocolAbiSwapEncoderTrait; +pub use crate::pool_opcodes_encoder::swap_opcodes_encoders::MulticallerOpcodesPayload; use alloy_primitives::Address; pub use curve::CurveSwapOpcodesEncoder; -use eyre::Result; +use eyre::{eyre, Result}; use loom_types_blockchain::MulticallerCalls; use loom_types_entities::{Pool, SwapAmountType}; pub use steth::StEthSwapEncoder; @@ -29,6 +30,53 @@ pub trait SwapOpcodesEncoderTrait: Send + Sync + 'static { amount_in: SwapAmountType, cur_pool: &dyn Pool, next_pool: Option<&dyn Pool>, - multicaller: Address, + payload: MulticallerOpcodesPayload, + multicaller_address: Address, ) -> Result<()>; + + #[allow(clippy::too_many_arguments)] + fn encode_swap_out_amount_provided( + &self, + swap_opcodes: &mut MulticallerCalls, + abi_encoder: &dyn ProtocolAbiSwapEncoderTrait, + token_from_address: Address, + token_to_address: Address, + amount_out: SwapAmountType, + cur_pool: &dyn Pool, + next_pool: Option<&dyn Pool>, + payload: MulticallerOpcodesPayload, + multicaller_address: Address, + ) -> Result<()>; + + #[allow(clippy::too_many_arguments)] + fn encode_flash_swap_in_amount_provided( + &self, + _swap_opcodes: &mut MulticallerCalls, + _abi_encoder: &dyn ProtocolAbiSwapEncoderTrait, + _token_from_address: Address, + _token_to_address: Address, + _amount_in: SwapAmountType, + _flash_pool: &dyn Pool, + _prev_pool: Option<&dyn Pool>, + _payload: MulticallerOpcodesPayload, + _multicaller_address: Address, + ) -> Result<()> { + Err(eyre!("NOT_IMPLEMENTED")) + } + + #[allow(clippy::too_many_arguments)] + fn encode_flash_swap_out_amount_provided( + &self, + _swap_opcodes: &mut MulticallerCalls, + _abi_encoder: &dyn ProtocolAbiSwapEncoderTrait, + _token_from_address: Address, + _token_to_address: Address, + _amount_out: SwapAmountType, + _flash_pool: &dyn Pool, + _next_pool: Option<&dyn Pool>, + _payload: MulticallerOpcodesPayload, + _multicaller_address: Address, + ) -> Result<()> { + Err(eyre!("NOT_IMPLEMENTED")) + } } diff --git a/crates/execution/multicaller/src/pool_opcodes_encoder/steth.rs b/crates/execution/multicaller/src/pool_opcodes_encoder/steth.rs index b39ea094..fa7f36d6 100644 --- a/crates/execution/multicaller/src/pool_opcodes_encoder/steth.rs +++ b/crates/execution/multicaller/src/pool_opcodes_encoder/steth.rs @@ -1,7 +1,9 @@ -use crate::helpers::AbiEncoderHelper; +use crate::abi_helpers::AbiEncoderHelper; +use crate::opcodes_helpers::OpcodesHelpers; use crate::pool_abi_encoder::ProtocolAbiSwapEncoderTrait; +use crate::pool_opcodes_encoder::swap_opcodes_encoders::MulticallerOpcodesPayload; use crate::pool_opcodes_encoder::SwapOpcodesEncoderTrait; -use alloy_primitives::{Address, Bytes, U256}; +use alloy_primitives::{Address, Bytes}; use eyre::{eyre, Result}; use loom_defi_address_book::TokenAddressEth; use loom_types_blockchain::{MulticallerCall, MulticallerCalls}; @@ -20,72 +22,30 @@ impl SwapOpcodesEncoderTrait for StEthSwapEncoder { amount_in: SwapAmountType, cur_pool: &dyn Pool, next_pool: Option<&dyn Pool>, + _payload: MulticallerOpcodesPayload, multicaller: Address, ) -> Result<()> { let pool_address = cur_pool.get_address(); if token_from_address == TokenAddressEth::WETH && token_to_address == TokenAddressEth::STETH { - match amount_in { - SwapAmountType::Set(amount) => { - let weth_withdraw_opcode = - MulticallerCall::new_call(token_from_address, &AbiEncoderHelper::encode_weth_withdraw(amount)); - let swap_opcode = MulticallerCall::new_call_with_value( - pool_address, - &abi_encoder.encode_swap_in_amount_provided( - cur_pool, - token_from_address, - token_to_address, - amount, - multicaller, - Bytes::new(), - )?, - amount, - ); - - //let steth_balance_opcode = Opcode::new_static_call( token_to_address, &EncoderHelper::encode_erc20_balance_of(multicaller) ); - - swap_opcodes.add(weth_withdraw_opcode).add(swap_opcode); - //.add(steth_balance_opcode); - } - SwapAmountType::Stack0 => { - let mut weth_withdraw_opcode = - MulticallerCall::new_call(token_from_address, &AbiEncoderHelper::encode_weth_withdraw(U256::ZERO)); - weth_withdraw_opcode.set_call_stack(false, 0, 0x4, 0x20); - - let mut swap_opcode = MulticallerCall::new_call_with_value(pool_address, &Bytes::new(), U256::ZERO); - swap_opcode.set_call_stack(false, 0, 0x4, 0x0); - - swap_opcodes.add(weth_withdraw_opcode).add(swap_opcode); - } - - SwapAmountType::RelativeStack(stack_offset) => { - let mut weth_withdraw_opcode = - MulticallerCall::new_call(token_from_address, &AbiEncoderHelper::encode_weth_withdraw(U256::ZERO)); - weth_withdraw_opcode.set_call_stack(true, stack_offset, 0x4, 0x20); - - let mut swap_opcode = MulticallerCall::new_call_with_value(pool_address, &Bytes::new(), U256::ZERO); - swap_opcode.set_call_stack(true, stack_offset, 0, 0); - - swap_opcodes.add(weth_withdraw_opcode).add(swap_opcode); - } - SwapAmountType::Balance(addr) => { - let mut weth_balance_opcode = - MulticallerCall::new_static_call(token_from_address, &AbiEncoderHelper::encode_erc20_balance_of(addr)); - weth_balance_opcode.set_return_stack(true, 0, 0, 0x20); - - let mut weth_withdraw_opcode = - MulticallerCall::new_call(token_from_address, &AbiEncoderHelper::encode_weth_withdraw(U256::ZERO)); - weth_withdraw_opcode.set_call_stack(true, 0, 0x4, 0x20); - - let mut swap_opcode = MulticallerCall::new_call_with_value(pool_address, &Bytes::new(), U256::ZERO); - swap_opcode.set_call_stack(true, 0, 0, 0); - - swap_opcodes.add(weth_balance_opcode).add(weth_withdraw_opcode).add(swap_opcode); - } - _ => { - return Err(eyre!("CANNOT_ENCODE_STETH_SWAP")); - } - } + let weth_withdraw_opcode = + MulticallerCall::new_call(token_from_address, &AbiEncoderHelper::encode_weth_withdraw(amount_in.unwrap_or_default())); + let swap_opcode = MulticallerCall::new_call_with_value( + pool_address, + &abi_encoder.encode_swap_in_amount_provided( + cur_pool, + token_from_address, + token_to_address, + amount_in.unwrap_or_default(), + multicaller, + Bytes::new(), + )?, + amount_in.unwrap_or_default(), + ); + + let opcodes_vec = vec![(weth_withdraw_opcode, 0x4, 0x20), (swap_opcode, 0x0, 0)]; + + swap_opcodes.merge(OpcodesHelpers::build_multiple_stack(amount_in, opcodes_vec, Some(token_from_address))?); if next_pool.is_some() { let mut steth_balance_opcode = @@ -99,4 +59,19 @@ impl SwapOpcodesEncoderTrait for StEthSwapEncoder { Err(eyre!("CANNOT_ENCODE_STETH_SWAP")) } + + fn encode_swap_out_amount_provided( + &self, + _swap_opcodes: &mut MulticallerCalls, + _abi_encoder: &dyn ProtocolAbiSwapEncoderTrait, + _token_from_address: Address, + _token_to_address: Address, + _amount_out: SwapAmountType, + _cur_pool: &dyn Pool, + _next_pool: Option<&dyn Pool>, + _payload: MulticallerOpcodesPayload, + _multicaller_address: Address, + ) -> Result<()> { + Err(eyre!("NOT_IMPLEMENTED")) + } } diff --git a/crates/execution/multicaller/src/pool_opcodes_encoder/swap_opcodes_encoders.rs b/crates/execution/multicaller/src/pool_opcodes_encoder/swap_opcodes_encoders.rs index 86852c20..40c4d5f0 100644 --- a/crates/execution/multicaller/src/pool_opcodes_encoder/swap_opcodes_encoders.rs +++ b/crates/execution/multicaller/src/pool_opcodes_encoder/swap_opcodes_encoders.rs @@ -2,13 +2,46 @@ use crate::pool_abi_encoder::ProtocolAbiSwapEncoderTrait; use crate::pool_opcodes_encoder::{ CurveSwapOpcodesEncoder, SwapOpcodesEncoderTrait, UniswapV2SwapOpcodesEncoder, UniswapV3SwapOpcodesEncoder, }; -use alloy_primitives::Address; +use crate::{OpcodesEncoder, OpcodesEncoderV2}; +use alloy_primitives::{Address, Bytes}; use eyre::OptionExt; +use eyre::Result; use loom_types_blockchain::MulticallerCalls; use loom_types_entities::{Pool, PoolClass, SwapAmountType}; use std::collections::HashMap; use std::sync::Arc; +#[derive(Clone, Default)] +pub enum MulticallerOpcodesPayload { + #[default] + Empty, + Opcodes(MulticallerCalls), + Bytes(Bytes), + Address(Address), +} + +impl MulticallerOpcodesPayload { + pub fn is_empty(&self) -> bool { + match self { + Self::Empty => true, + Self::Bytes(b) => b.is_empty(), + Self::Address(_) => false, + Self::Opcodes(o) => o.is_empty(), + } + } +} + +impl MulticallerOpcodesPayload { + pub fn encode(&self) -> Result { + match self { + Self::Empty => Ok(Bytes::default()), + Self::Opcodes(opcodes) => OpcodesEncoderV2::pack_do_calls_data(opcodes), + Self::Bytes(bytes) => Ok(bytes.clone()), + Self::Address(address) => Ok(Bytes::from(address.to_vec())), + } + } +} + #[derive(Clone)] pub struct ProtocolSwapOpcodesEncoderV2 { pool_classes: HashMap>, @@ -42,7 +75,8 @@ impl SwapOpcodesEncoderTrait for ProtocolSwapOpcodesEncoderV2 { amount_in: SwapAmountType, cur_pool: &dyn Pool, next_pool: Option<&dyn Pool>, - multicaller: Address, + payload: MulticallerOpcodesPayload, + multicaller_address: Address, ) -> eyre::Result<()> { let opcodes_encoder = self.pool_classes.get(&cur_pool.get_class()).ok_or_eyre("OPCODES_ENCODER_NOT_FOUND")?; opcodes_encoder.encode_swap_in_amount_provided( @@ -53,7 +87,86 @@ impl SwapOpcodesEncoderTrait for ProtocolSwapOpcodesEncoderV2 { amount_in, cur_pool, next_pool, - multicaller, + payload, + multicaller_address, + ) + } + + fn encode_swap_out_amount_provided( + &self, + swap_opcodes: &mut MulticallerCalls, + abi_encoder: &dyn ProtocolAbiSwapEncoderTrait, + token_from_address: Address, + token_to_address: Address, + amount_out: SwapAmountType, + cur_pool: &dyn Pool, + next_pool: Option<&dyn Pool>, + payload: MulticallerOpcodesPayload, + multicaller_address: Address, + ) -> eyre::Result<()> { + let opcodes_encoder = self.pool_classes.get(&cur_pool.get_class()).ok_or_eyre("OPCODES_ENCODER_NOT_FOUND")?; + opcodes_encoder.encode_swap_out_amount_provided( + swap_opcodes, + abi_encoder, + token_from_address, + token_to_address, + amount_out, + cur_pool, + next_pool, + payload, + multicaller_address, + ) + } + + fn encode_flash_swap_in_amount_provided( + &self, + swap_opcodes: &mut MulticallerCalls, + abi_encoder: &dyn ProtocolAbiSwapEncoderTrait, + token_from_address: Address, + token_to_address: Address, + amount_in: SwapAmountType, + flash_pool: &dyn Pool, + prev_pool: Option<&dyn Pool>, + payload: MulticallerOpcodesPayload, + multicaller_address: Address, + ) -> Result<()> { + let opcodes_encoder = self.pool_classes.get(&flash_pool.get_class()).ok_or_eyre("OPCODES_ENCODER_NOT_FOUND")?; + opcodes_encoder.encode_flash_swap_in_amount_provided( + swap_opcodes, + abi_encoder, + token_from_address, + token_to_address, + amount_in, + flash_pool, + prev_pool, + payload, + multicaller_address, + ) + } + + fn encode_flash_swap_out_amount_provided( + &self, + swap_opcodes: &mut MulticallerCalls, + abi_encoder: &dyn ProtocolAbiSwapEncoderTrait, + token_from_address: Address, + token_to_address: Address, + amount_out: SwapAmountType, + flash_pool: &dyn Pool, + next_pool: Option<&dyn Pool>, + payload: MulticallerOpcodesPayload, + multicaller_address: Address, + ) -> Result<()> { + let opcodes_encoder = self.pool_classes.get(&flash_pool.get_class()).ok_or_eyre("OPCODES_ENCODER_NOT_FOUND")?; + opcodes_encoder.encode_flash_swap_out_amount_provided( + swap_opcodes, + abi_encoder, + token_from_address, + token_to_address, + amount_out, + flash_pool, + next_pool, + payload, + multicaller_address, ) } } diff --git a/crates/execution/multicaller/src/pool_opcodes_encoder/uniswap2.rs b/crates/execution/multicaller/src/pool_opcodes_encoder/uniswap2.rs index d830aab9..034760e8 100644 --- a/crates/execution/multicaller/src/pool_opcodes_encoder/uniswap2.rs +++ b/crates/execution/multicaller/src/pool_opcodes_encoder/uniswap2.rs @@ -1,10 +1,13 @@ +use crate::opcodes_helpers::OpcodesHelpers; use crate::pool_abi_encoder::ProtocolAbiSwapEncoderTrait; +use crate::pool_opcodes_encoder::swap_opcodes_encoders::MulticallerOpcodesPayload; use crate::pool_opcodes_encoder::SwapOpcodesEncoderTrait; use crate::AbiEncoderHelper; use alloy_primitives::{Address, Bytes, U256}; +use eyre::eyre; use loom_types_blockchain::{MulticallerCall, MulticallerCalls}; use loom_types_entities::{Pool, PreswapRequirement, SwapAmountType}; -use tracing::trace; +use tracing::{trace, warn}; pub struct UniswapV2SwapOpcodesEncoder; @@ -18,65 +21,33 @@ impl SwapOpcodesEncoderTrait for UniswapV2SwapOpcodesEncoder { amount_in: SwapAmountType, cur_pool: &dyn Pool, next_pool: Option<&dyn Pool>, + _payload: MulticallerOpcodesPayload, multicaller_address: Address, ) -> eyre::Result<()> { - let swap_to: Address = if let Some(next_pool) = next_pool { - match abi_encoder.preswap_requirement(next_pool) { - PreswapRequirement::Transfer(next_funds_to) => next_funds_to, - _ => multicaller_address, - } - } else { - multicaller_address - }; + // Getting destination address + let swap_to = next_pool.and_then(|next_pool| abi_encoder.preswap_requirement(next_pool).address()).unwrap_or(multicaller_address); - match amount_in { - SwapAmountType::Set(value) => { - trace!("uniswap v2 i == 0 set amount in {}", value); - - let get_out_amount_opcode = MulticallerCall::new_internal_call(&AbiEncoderHelper::encode_multicaller_uni2_get_out_amount( - token_from_address, - token_to_address, - cur_pool.get_address(), - value, - cur_pool.get_fee(), - )); - swap_opcodes.add(get_out_amount_opcode); - } - SwapAmountType::Balance(addr) => { - trace!("uniswap v2 i == 0 balance of addr={:?}", addr); - let mut balance_opcode = - MulticallerCall::new_static_call(token_from_address, &AbiEncoderHelper::encode_erc20_balance_of(addr)); - balance_opcode.set_return_stack(true, 0, 0x0, 0x20); - swap_opcodes.add(balance_opcode); - - trace!("uni2 get out amount from={:?}, to={:?}, pool={:?}", token_from_address, token_to_address, cur_pool.get_address()); - let mut get_out_amount_opcode = - MulticallerCall::new_internal_call(&AbiEncoderHelper::encode_multicaller_uni2_get_out_amount( - token_from_address, - token_to_address, - cur_pool.get_address(), - U256::ZERO, - cur_pool.get_fee(), - )); - get_out_amount_opcode.set_call_stack(true, 0, 0x24, 0x20); - swap_opcodes.add(get_out_amount_opcode); - } - _ => { - trace!("uniswap v2"); + trace!( + "uniswap v2 get out amount for pool={:?}, amount={:?} from {} to {}", + cur_pool.get_address(), + amount_in, + token_from_address, + token_to_address + ); - let mut get_out_amount_opcode = - MulticallerCall::new_internal_call(&AbiEncoderHelper::encode_multicaller_uni2_get_out_amount( - token_from_address, - token_to_address, - cur_pool.get_address(), - U256::ZERO, - cur_pool.get_fee(), - )); - get_out_amount_opcode.set_call_stack(true, 0, 0x24, 0x20); - swap_opcodes.add(get_out_amount_opcode); - } - } + // calculating out amount for in amount provided + let get_out_amount_opcode = MulticallerCall::new_internal_call(&AbiEncoderHelper::encode_multicaller_uni2_get_out_amount( + token_from_address, + token_to_address, + cur_pool.get_address(), + amount_in.unwrap_or_default(), + cur_pool.get_fee(), + )); + + // setting argument from stack if it is required + swap_opcodes.merge(OpcodesHelpers::build_call_stack(amount_in, get_out_amount_opcode, 0x24, 0x20, Some(token_from_address))?); + // abi encode and add uniswap swap opcode let mut swap_opcode = MulticallerCall::new_call( cur_pool.get_address(), &abi_encoder.encode_swap_out_amount_provided( @@ -88,6 +59,8 @@ impl SwapOpcodesEncoderTrait for UniswapV2SwapOpcodesEncoder { Bytes::new(), )?, ); + + // setting stack swap argument based on calculated out amount swap_opcode.set_call_stack( true, 0, @@ -95,6 +68,200 @@ impl SwapOpcodesEncoderTrait for UniswapV2SwapOpcodesEncoder { 0x20, ); + swap_opcodes.add(swap_opcode); + + Ok(()) + } + + fn encode_swap_out_amount_provided( + &self, + _swap_opcodes: &mut MulticallerCalls, + _abi_encoder: &dyn ProtocolAbiSwapEncoderTrait, + _token_from_address: Address, + _token_to_address: Address, + _amount_out: SwapAmountType, + _cur_pool: &dyn Pool, + _next_pool: Option<&dyn Pool>, + _payload: MulticallerOpcodesPayload, + _multicaller_address: Address, + ) -> eyre::Result<()> { + Err(eyre!("NOT_IMPLEMENTED")) + } + + fn encode_flash_swap_in_amount_provided( + &self, + swap_opcodes: &mut MulticallerCalls, + abi_encoder: &dyn ProtocolAbiSwapEncoderTrait, + token_from_address: Address, + token_to_address: Address, + amount_in: SwapAmountType, + flash_pool: &dyn Pool, + prev_pool: Option<&dyn Pool>, + payload: MulticallerOpcodesPayload, + multicaller_address: Address, + ) -> eyre::Result<()> { + let payload = if let MulticallerOpcodesPayload::Opcodes(inside_opcodes) = &payload { + let mut inside_opcodes = inside_opcodes.clone(); + + match amount_in { + SwapAmountType::Set(amount) => { + // first swap, need to return token_from to this pool, otherwise tokens should be already on the contract + trace!("uniswap v2 transfer token={:?}, to={:?}, amount={}", token_from_address, flash_pool.get_address(), amount); + + inside_opcodes.add(MulticallerCall::new_call( + token_from_address, + &AbiEncoderHelper::encode_erc20_transfer(flash_pool.get_address(), amount), + )); + } + _ => { + warn!("InAmountTypeNotSet"); + } + } + + // if there is a prev_pool transfer funds in case it is uniswap2. + if let Some(prev_pool) = prev_pool { + if let PreswapRequirement::Transfer(swap_to) = abi_encoder.preswap_requirement(prev_pool) { + trace!("uniswap v2 transfer token_to_address={:?}, funds_to={:?} amount=stack_norel_0", token_to_address, swap_to); + let mut transfer_opcode = + MulticallerCall::new_call(token_to_address, &AbiEncoderHelper::encode_erc20_transfer(swap_to, U256::ZERO)); + transfer_opcode.set_call_stack(false, 0, 0x24, 0x20); + inside_opcodes.insert(transfer_opcode); + } + } + MulticallerOpcodesPayload::Opcodes(inside_opcodes) + } else { + payload + }; + + let inside_call_bytes = payload.encode()?; + + // getting out amount for in amount provided + + trace!("uniswap v2 get out amount for pool={:?}, amount={:?}", flash_pool.get_address(), amount_in); + let mut get_out_amount_opcode = MulticallerCall::new_internal_call(&AbiEncoderHelper::encode_multicaller_uni2_get_out_amount( + token_from_address, + token_to_address, + flash_pool.get_address(), + amount_in.unwrap_or_default(), + flash_pool.get_fee(), + )); + + // setting up stack, in amount is out amount for previous swap and is located in stack0 + if amount_in.is_not_set() { + get_out_amount_opcode.set_call_stack(false, 0, 0x24, 0x20); + } + + // abi encode uniswap2 out amount provided swap. + let mut swap_opcode = MulticallerCall::new_call( + flash_pool.get_address(), + &abi_encoder.encode_swap_out_amount_provided( + flash_pool, + token_from_address, + token_to_address, + U256::ZERO, + multicaller_address, + inside_call_bytes, + )?, + ); + + // setting call stack to calculated out amount. + swap_opcode.set_call_stack( + true, + 0, + abi_encoder.swap_out_amount_offset(flash_pool, token_from_address, token_to_address).unwrap(), + 0x20, + ); + + swap_opcodes.add(get_out_amount_opcode).add(swap_opcode); + + Ok(()) + } + + fn encode_flash_swap_out_amount_provided( + &self, + swap_opcodes: &mut MulticallerCalls, + abi_encoder: &dyn ProtocolAbiSwapEncoderTrait, + token_from_address: Address, + token_to_address: Address, + amount_out: SwapAmountType, + flash_pool: &dyn Pool, + next_pool: Option<&dyn Pool>, + payload: MulticallerOpcodesPayload, + multicaller_address: Address, + ) -> eyre::Result<()> { + // getting address for token_to + let swap_to = next_pool.and_then(|next_pool| abi_encoder.preswap_requirement(next_pool).address()).unwrap_or(multicaller_address); + + // add get_in amount to keep amount we should return in stack. + let payload = if let MulticallerOpcodesPayload::Opcodes(inside_opcodes) = &payload { + let mut inside_opcodes = inside_opcodes.clone(); + + let mut get_in_amount_opcode = MulticallerCall::new_internal_call(&AbiEncoderHelper::encode_multicaller_uni2_get_in_amount( + token_from_address, + token_to_address, + flash_pool.get_address(), + amount_out.unwrap_or_default(), + flash_pool.get_fee(), + )); + + // is not set, will use stack0 + if amount_out.is_not_set() { + get_in_amount_opcode.set_call_stack(false, 0, 0x24, 0x20); + } + + inside_opcodes.insert(get_in_amount_opcode); + + // if we need funds somewhere else, we transfer it because cannot set destination in uniswap2 with parameters + if swap_to != multicaller_address { + trace!("retflash transfer token={:?}, to={:?}, amount=stack_norel_0", token_to_address, swap_to); + + let mut transfer_opcode = + MulticallerCall::new_call(token_to_address, &AbiEncoderHelper::encode_erc20_transfer(swap_to, U256::ZERO)); + transfer_opcode.set_call_stack(false, 0, 0x24, 0x20); + inside_opcodes.add(transfer_opcode); + } + + MulticallerOpcodesPayload::Opcodes(inside_opcodes) + } else { + payload + }; + + // encode inside bytes + let inside_call_bytes = payload.encode()?; + + // flash swap without amount + trace!( + "uniswap v2 swap out amount provided for pool={:?}, from={} to={} amount_out={:?} receiver={} inside_opcodes_len={}", + flash_pool.get_address(), + token_from_address, + token_to_address, + amount_out, + swap_to, + inside_call_bytes.len() + ); + let mut swap_opcode = MulticallerCall::new_call( + flash_pool.get_address(), + &abi_encoder.encode_swap_out_amount_provided( + flash_pool, + token_from_address, + token_to_address, + amount_out.unwrap_or_default(), + multicaller_address, + inside_call_bytes, + )?, + ); + + // set rel_stack(0) is amount is not set + if amount_out.is_not_set() { + trace!("uniswap v2 amount not set"); + swap_opcode.set_call_stack( + true, + 0, + abi_encoder.swap_out_amount_offset(flash_pool, token_from_address, token_to_address).unwrap(), + 0x20, + ); + } + swap_opcodes.add(swap_opcode); Ok(()) } diff --git a/crates/execution/multicaller/src/pool_opcodes_encoder/uniswap3.rs b/crates/execution/multicaller/src/pool_opcodes_encoder/uniswap3.rs index b77e960a..d54d04f9 100644 --- a/crates/execution/multicaller/src/pool_opcodes_encoder/uniswap3.rs +++ b/crates/execution/multicaller/src/pool_opcodes_encoder/uniswap3.rs @@ -1,7 +1,10 @@ +use crate::opcodes_helpers::OpcodesHelpers; use crate::pool_abi_encoder::ProtocolAbiSwapEncoderTrait; +use crate::pool_opcodes_encoder::swap_opcodes_encoders::MulticallerOpcodesPayload; use crate::pool_opcodes_encoder::SwapOpcodesEncoderTrait; use crate::AbiEncoderHelper; use alloy_primitives::{Address, Bytes, U256}; +use eyre::{eyre, OptionExt}; use loom_types_blockchain::{MulticallerCall, MulticallerCalls}; use loom_types_entities::{Pool, PreswapRequirement, SwapAmountType}; use tracing::trace; @@ -18,9 +21,10 @@ impl SwapOpcodesEncoderTrait for UniswapV3SwapOpcodesEncoder { amount_in: SwapAmountType, cur_pool: &dyn Pool, next_pool: Option<&dyn Pool>, + payload: MulticallerOpcodesPayload, multicaller_address: Address, ) -> eyre::Result<()> { - let inside_call_payload = Bytes::from(token_from_address.to_vec()); + let inside_call_payload = if payload.is_empty() { Bytes::from(token_from_address.to_vec()) } else { payload.encode()? }; let swap_to: Address = if let Some(next_pool) = next_pool { match abi_encoder.preswap_requirement(next_pool) { @@ -31,72 +35,17 @@ impl SwapOpcodesEncoderTrait for UniswapV3SwapOpcodesEncoder { multicaller_address }; - let mut swap_opcode = match amount_in { - SwapAmountType::Set(amount) => { - trace!("uniswap v3 i == 0 set amount in for pool={:?}, amount={}", cur_pool.get_address(), amount); - MulticallerCall::new_call( - cur_pool.get_address(), - &abi_encoder.encode_swap_in_amount_provided( - cur_pool, - token_from_address, - token_to_address, - amount, - swap_to, - inside_call_payload, - )?, - ) - } - SwapAmountType::Balance(addr) => { - trace!("uniswap v3 i == 0 balance of for pool={:?}, addr={}", cur_pool.get_address(), addr); - let mut balance_opcode = - MulticallerCall::new_static_call(token_from_address, &AbiEncoderHelper::encode_erc20_balance_of(addr)); - balance_opcode.set_return_stack(true, 0, 0x0, 0x20); - - swap_opcodes.add(balance_opcode); - - let mut swap_opcode = MulticallerCall::new_call( - cur_pool.get_address(), - &abi_encoder.encode_swap_in_amount_provided( - cur_pool, - token_from_address, - token_to_address, - U256::ZERO, - swap_to, - inside_call_payload, - )?, - ); - - swap_opcode.set_call_stack( - true, - 0, - abi_encoder.swap_in_amount_offset(cur_pool, token_from_address, token_to_address).unwrap(), - 0x20, - ); - swap_opcode - } - _ => { - trace!("uniswap v3 i == 0 else for pool={:?}", cur_pool.get_address()); - let mut swap_opcode = MulticallerCall::new_call( - cur_pool.get_address(), - &abi_encoder.encode_swap_in_amount_provided( - cur_pool, - token_from_address, - token_to_address, - U256::ZERO, - swap_to, - inside_call_payload, - )?, - ); - - swap_opcode.set_call_stack( - true, - 0, - abi_encoder.swap_in_amount_offset(cur_pool, token_from_address, token_to_address).unwrap(), - 0x20, - ); - swap_opcode - } - }; + let mut swap_opcode = MulticallerCall::new_call( + cur_pool.get_address(), + &abi_encoder.encode_swap_in_amount_provided( + cur_pool, + token_from_address, + token_to_address, + amount_in.unwrap_or_default(), + swap_to, + inside_call_payload, + )?, + ); swap_opcode.set_return_stack( true, @@ -105,7 +54,13 @@ impl SwapOpcodesEncoderTrait for UniswapV3SwapOpcodesEncoder { 0x20, ); - swap_opcodes.add(swap_opcode); + swap_opcodes.merge(OpcodesHelpers::build_call_stack( + amount_in, + swap_opcode, + abi_encoder.swap_in_amount_offset(cur_pool, token_from_address, token_to_address).ok_or_eyre("NO_OFFSET")?, + 0x20, + Some(token_from_address), + )?); if next_pool.is_some() { trace!("has next pool"); @@ -116,4 +71,173 @@ impl SwapOpcodesEncoderTrait for UniswapV3SwapOpcodesEncoder { } Ok(()) } + + fn encode_swap_out_amount_provided( + &self, + _swap_opcodes: &mut MulticallerCalls, + _abi_encoder: &dyn ProtocolAbiSwapEncoderTrait, + _token_from_address: Address, + _token_to_address: Address, + _amount_out: SwapAmountType, + _cur_pool: &dyn Pool, + _next_pool: Option<&dyn Pool>, + _payload: MulticallerOpcodesPayload, + _multicaller_address: Address, + ) -> eyre::Result<()> { + Err(eyre!("NOT_IMPLEMENTED")) + } + + fn encode_flash_swap_in_amount_provided( + &self, + swap_opcodes: &mut MulticallerCalls, + abi_encoder: &dyn ProtocolAbiSwapEncoderTrait, + token_from_address: Address, + token_to_address: Address, + amount_in: SwapAmountType, + flash_pool: &dyn Pool, + prev_pool: Option<&dyn Pool>, + payload: MulticallerOpcodesPayload, + multicaller_address: Address, + ) -> eyre::Result<()> { + let swap_to = match prev_pool { + Some(prev_pool) => match abi_encoder.preswap_requirement(prev_pool) { + PreswapRequirement::Transfer(funds_to) => { + trace!("other transfer to previous pool: funds_to={:?}, prev_pool={:?}", funds_to, prev_pool.get_address()); + funds_to + } + _ => { + trace!("other swap to multicaller, prev_pool={:?}", prev_pool.get_address()); + multicaller_address + } + }, + None => multicaller_address, + }; + + let payload = match payload { + MulticallerOpcodesPayload::Opcodes(payload) => { + trace!("uniswap v3 transfer token={:?}, to={:?}, amount={:?}", token_from_address, flash_pool.get_address(), amount_in); + let mut payload = payload; + let mut transfer_opcode = MulticallerCall::new_call( + token_from_address, + &AbiEncoderHelper::encode_erc20_transfer(flash_pool.get_address(), amount_in.unwrap_or_default()), + ); + + if amount_in.is_not_set() { + transfer_opcode.set_call_stack(false, 1, 0x24, 0x20); + } + + payload.add(transfer_opcode); + + MulticallerOpcodesPayload::Opcodes(payload) + } + _ => payload, + }; + + let inside_call_bytes = payload.encode()?; + + trace!( + "uniswap v3 flash swap in amount for pool={:?} from {} to {} amount={:?}", + flash_pool.get_address(), + token_from_address, + token_to_address, + amount_in, + ); + let mut swap_opcode = MulticallerCall::new_call( + flash_pool.get_address(), + &abi_encoder.encode_swap_in_amount_provided( + flash_pool, + token_from_address, + token_to_address, + amount_in.unwrap_or_default(), + swap_to, + inside_call_bytes, + )?, + ); + + if amount_in.is_not_set() { + swap_opcode.set_call_stack( + false, + 0, + abi_encoder.swap_in_amount_offset(flash_pool, token_from_address, token_to_address).unwrap(), + 0x20, + ); + } + + swap_opcodes.add(swap_opcode); + + Ok(()) + } + + fn encode_flash_swap_out_amount_provided( + &self, + swap_opcodes: &mut MulticallerCalls, + abi_encoder: &dyn ProtocolAbiSwapEncoderTrait, + token_from_address: Address, + token_to_address: Address, + amount_out: SwapAmountType, + flash_pool: &dyn Pool, + next_pool: Option<&dyn Pool>, + payload: MulticallerOpcodesPayload, + multicaller_address: Address, + ) -> eyre::Result<()> { + let swap_to = next_pool.and_then(|next_pool| abi_encoder.preswap_requirement(next_pool).address()).unwrap_or(multicaller_address); + + let payload = if let MulticallerOpcodesPayload::Opcodes(inside_opcodes) = payload { + let mut inside_opcodes = inside_opcodes; + //if next_pool.is_none() { + trace!("retflash transfer token={:?}, to={:?}, amount=stack_norel_1", token_from_address, flash_pool.get_address()); + let mut transfer_opcode = MulticallerCall::new_call( + token_from_address, + &AbiEncoderHelper::encode_erc20_transfer(flash_pool.get_address(), U256::ZERO), + ); + transfer_opcode.set_call_stack(false, 1, 0x24, 0x20); + + inside_opcodes.add(transfer_opcode); + + MulticallerOpcodesPayload::Opcodes(inside_opcodes) + } else { + payload + }; + + let inside_call_bytes = payload.encode()?; + + trace!( + "uniswap v3 swap out amount provided for pool={:?}, from={} to={} amount_out={:?} receiver={} inside_opcodes_len={}", + flash_pool.get_address(), + token_from_address, + token_to_address, + amount_out, + swap_to, + inside_call_bytes.len() + ); + + let mut swap_opcode = MulticallerCall::new_call( + flash_pool.get_address(), + &abi_encoder.encode_swap_out_amount_provided( + flash_pool, + token_from_address, + token_to_address, + amount_out.unwrap_or_default(), + swap_to, + inside_call_bytes, + )?, + ); + + if amount_out.is_not_set() { + trace!("uniswap v3 swap out amount is not set"); + + swap_opcode.set_call_stack( + true, + 0, + abi_encoder.swap_out_amount_offset(flash_pool, token_from_address, token_to_address).unwrap(), + 0x20, + ); + + swap_opcodes.add(MulticallerCall::new_calculation_call(&Bytes::from(vec![0x2, 0x2A, 0x00]))); + }; + + swap_opcodes.add(swap_opcode); + + Ok(()) + } } diff --git a/crates/execution/multicaller/src/pool_opcodes_encoder/wsteth.rs b/crates/execution/multicaller/src/pool_opcodes_encoder/wsteth.rs index 7d60a09f..2121108c 100644 --- a/crates/execution/multicaller/src/pool_opcodes_encoder/wsteth.rs +++ b/crates/execution/multicaller/src/pool_opcodes_encoder/wsteth.rs @@ -1,7 +1,9 @@ -use crate::helpers::AbiEncoderHelper; +use crate::abi_helpers::AbiEncoderHelper; +use crate::opcodes_helpers::OpcodesHelpers; use crate::pool_abi_encoder::ProtocolAbiSwapEncoderTrait; +use crate::pool_opcodes_encoder::swap_opcodes_encoders::MulticallerOpcodesPayload; use crate::pool_opcodes_encoder::SwapOpcodesEncoderTrait; -use alloy_primitives::{Address, Bytes, U256}; +use alloy_primitives::{Address, Bytes}; use eyre::{eyre, Result}; use loom_defi_address_book::TokenAddressEth; use loom_types_blockchain::{MulticallerCall, MulticallerCalls}; @@ -20,201 +22,82 @@ impl SwapOpcodesEncoderTrait for WstEthSwapEncoder { amount_in: SwapAmountType, cur_pool: &dyn Pool, next_pool: Option<&dyn Pool>, + _payload: MulticallerOpcodesPayload, multicaller: Address, ) -> Result<()> { let pool_address = cur_pool.get_address(); if token_from_address == TokenAddressEth::WETH && token_to_address == TokenAddressEth::WSTETH { - match amount_in { - SwapAmountType::Set(amount) => { - let weth_withdraw_opcode = - MulticallerCall::new_call(token_from_address, &AbiEncoderHelper::encode_weth_withdraw(amount)); - let mut swap_opcode = MulticallerCall::new_call_with_value( - pool_address, - &abi_encoder.encode_swap_in_amount_provided( - cur_pool, - token_from_address, - token_to_address, - amount, - multicaller, - Bytes::new(), - )?, - amount, - ); - if next_pool.is_some() { - swap_opcode.set_return_stack(true, 0, 0, 0x20); - } - - swap_opcodes.add(weth_withdraw_opcode).add(swap_opcode); - } - SwapAmountType::Stack0 => { - let mut weth_withdraw_opcode = - MulticallerCall::new_call(token_from_address, &AbiEncoderHelper::encode_weth_withdraw(U256::ZERO)); - weth_withdraw_opcode.set_call_stack(false, 0, 0x4, 0x20); - - let mut swap_opcode = MulticallerCall::new_call_with_value(pool_address, &Bytes::new(), U256::ZERO); - swap_opcode.set_call_stack(false, 0, 0, 0x20); - - if next_pool.is_some() { - swap_opcode.set_return_stack(true, 0, 0, 0x20); - } - - swap_opcodes.add(weth_withdraw_opcode).add(swap_opcode); - } - - SwapAmountType::RelativeStack(stack_offset) => { - let mut weth_withdraw_opcode = - MulticallerCall::new_call(token_from_address, &AbiEncoderHelper::encode_weth_withdraw(U256::ZERO)); - weth_withdraw_opcode.set_call_stack(true, stack_offset, 0x4, 0x20); - - let mut swap_opcode = MulticallerCall::new_call_with_value(pool_address, &Bytes::new(), U256::ZERO); - swap_opcode.set_call_stack(true, stack_offset, 0, 0); - - if next_pool.is_some() { - swap_opcode.set_return_stack(true, 0, 0, 0x20); - } - - swap_opcodes.add(weth_withdraw_opcode).add(swap_opcode); - } - SwapAmountType::Balance(addr) => { - let weth_balance_opcode = - MulticallerCall::new_static_call(token_from_address, &AbiEncoderHelper::encode_erc20_balance_of(addr)); - - let mut weth_withdraw_opcode = - MulticallerCall::new_call(token_from_address, &AbiEncoderHelper::encode_weth_withdraw(U256::ZERO)); - weth_withdraw_opcode.set_call_stack(true, 0, 0x4, 0x20); + let weth_withdraw_opcode = + MulticallerCall::new_call(token_from_address, &AbiEncoderHelper::encode_weth_withdraw(amount_in.unwrap_or_default())); + let mut swap_opcode = MulticallerCall::new_call_with_value( + pool_address, + &abi_encoder.encode_swap_in_amount_provided( + cur_pool, + token_from_address, + token_to_address, + amount_in.unwrap_or_default(), + multicaller, + Bytes::new(), + )?, + amount_in.unwrap_or_default(), + ); + + if next_pool.is_some() { + swap_opcode.set_return_stack(true, 0, 0, 0x20); + } - let mut swap_opcode = MulticallerCall::new_call_with_value(pool_address, &Bytes::new(), U256::ZERO); - swap_opcode.set_call_stack(true, 0, 0, 0); + let opcodes_vec = vec![(weth_withdraw_opcode, 0x4, 0x20), (swap_opcode, 0x0, 0x20)]; - if next_pool.is_some() { - swap_opcode.set_return_stack(true, 0, 0, 0x20); - } + swap_opcodes.merge(OpcodesHelpers::build_multiple_stack(amount_in, opcodes_vec, Some(token_from_address))?); - swap_opcodes.add(weth_balance_opcode).add(weth_withdraw_opcode).add(swap_opcode); - } - _ => { - return Err(eyre!("CANNOT_ENCODE_WSTETH_SWAP")); - } - } return Ok(()); } if token_from_address == TokenAddressEth::STETH && token_to_address == TokenAddressEth::WSTETH || token_from_address == TokenAddressEth::WSTETH && token_to_address == TokenAddressEth::STETH { - match amount_in { - SwapAmountType::Set(amount) => { - let steth_approve_opcode = - MulticallerCall::new_call(token_from_address, &AbiEncoderHelper::encode_erc20_approve(token_to_address, amount)); - let mut swap_opcode = MulticallerCall::new_call( - pool_address, - &abi_encoder.encode_swap_in_amount_provided( - cur_pool, - token_from_address, - token_to_address, - amount, - multicaller, - Bytes::new(), - )?, - ); - - if next_pool.is_some() { - swap_opcode.set_return_stack(true, 0, 0, 0x20); - } - - swap_opcodes.add(steth_approve_opcode).add(swap_opcode); - } - SwapAmountType::Stack0 => { - let mut steth_approve_opcode = MulticallerCall::new_call( - token_from_address, - &AbiEncoderHelper::encode_erc20_approve(token_to_address, U256::ZERO), - ); - steth_approve_opcode.set_call_stack(false, 0, 0x24, 0x20); - - let mut swap_opcode = MulticallerCall::new_call( - pool_address, - &abi_encoder.encode_swap_in_amount_provided( - cur_pool, - token_from_address, - token_to_address, - U256::ZERO, - multicaller, - Bytes::new(), - )?, - ); - swap_opcode.set_call_stack(false, 0, 0x4, 0x20); - - if next_pool.is_some() { - swap_opcode.set_return_stack(true, 0, 0, 0x20); - } - - swap_opcodes.add(steth_approve_opcode).add(swap_opcode); - } - - SwapAmountType::RelativeStack(stack_offset) => { - let mut steth_approve_opcode = MulticallerCall::new_call( - token_from_address, - &AbiEncoderHelper::encode_erc20_approve(token_to_address, U256::ZERO), - ); - steth_approve_opcode.set_call_stack(true, stack_offset, 0x24, 0x20); - - let mut swap_opcode = MulticallerCall::new_call( - pool_address, - &abi_encoder.encode_swap_in_amount_provided( - cur_pool, - token_from_address, - token_to_address, - U256::ZERO, - multicaller, - Bytes::new(), - )?, - ); - swap_opcode.set_call_stack(true, stack_offset, 0x4, 0x20); - - if next_pool.is_some() { - swap_opcode.set_return_stack(true, 0, 0, 0x20); - } - - swap_opcodes.add(steth_approve_opcode).add(swap_opcode); - } - SwapAmountType::Balance(addr) => { - let mut steth_balance_opcode = - MulticallerCall::new_static_call(token_from_address, &AbiEncoderHelper::encode_erc20_balance_of(addr)); - steth_balance_opcode.set_return_stack(true, 0, 0, 0x20); - - let mut steth_approve_opcode = MulticallerCall::new_call( - token_from_address, - &AbiEncoderHelper::encode_erc20_approve(token_to_address, U256::ZERO), - ); - steth_approve_opcode.set_call_stack(true, 0, 0x24, 0x20); - - let mut swap_opcode = MulticallerCall::new_call( - pool_address, - &abi_encoder.encode_swap_in_amount_provided( - cur_pool, - token_from_address, - token_to_address, - U256::ZERO, - multicaller, - Bytes::new(), - )?, - ); - swap_opcode.set_call_stack(true, 0, 0x4, 0x20); + let steth_approve_opcode = MulticallerCall::new_call( + token_from_address, + &AbiEncoderHelper::encode_erc20_approve(token_to_address, amount_in.unwrap_or_default()), + ); + + let mut swap_opcode = MulticallerCall::new_call( + pool_address, + &abi_encoder.encode_swap_in_amount_provided( + cur_pool, + token_from_address, + token_to_address, + amount_in.unwrap_or_default(), + multicaller, + Bytes::new(), + )?, + ); + if next_pool.is_some() { + swap_opcode.set_return_stack(true, 0, 0, 0x20); + } + let opcodes_vec = vec![(steth_approve_opcode, 0x24, 0x20), (swap_opcode, 0x04, 0x20)]; - if next_pool.is_some() { - swap_opcode.set_return_stack(true, 0, 0, 0x20); - } + swap_opcodes.merge(OpcodesHelpers::build_multiple_stack(amount_in, opcodes_vec, Some(token_from_address))?); - swap_opcodes.add(steth_balance_opcode).add(steth_approve_opcode).add(swap_opcode); - } - _ => { - return Err(eyre!("CANNOT_ENCODE_WSTETH_SWAP")); - } - } return Ok(()); } Err(eyre!("CANNOT_ENCODE_WSTETH_SWAP")) } + + fn encode_swap_out_amount_provided( + &self, + _swap_opcodes: &mut MulticallerCalls, + _abi_encoder: &dyn ProtocolAbiSwapEncoderTrait, + _token_from_address: Address, + _token_to_address: Address, + _amount_out: SwapAmountType, + _cur_pool: &dyn Pool, + _next_pool: Option<&dyn Pool>, + _payload: MulticallerOpcodesPayload, + _multicaller_address: Address, + ) -> Result<()> { + Err(eyre!("NOT_IMPLEMENTED")) + } } diff --git a/crates/execution/multicaller/src/swap_encoder.rs b/crates/execution/multicaller/src/swap_encoder.rs index 08aa855d..419a7337 100644 --- a/crates/execution/multicaller/src/swap_encoder.rs +++ b/crates/execution/multicaller/src/swap_encoder.rs @@ -45,11 +45,7 @@ impl SwapEncoder for MulticallerSwapEncoder { match &swap { Swap::ExchangeSwapLine(swap_line) => { trace!("START: exchange swap line"); - match self.swap_step_encoder.swap_line_encoder.encode_swap_line_in_amount( - swap_line, - self.swap_step_encoder.get_contract_address(), - self.swap_step_encoder.get_contract_address(), - ) { + match self.swap_step_encoder.swap_line_encoder.encode_swap_line_in_amount(swap_line, None) { Ok(calls) => calls, Err(e) => { error!("swap_line_encoder.encode_swap_line_in_amount : {}", e); diff --git a/crates/execution/multicaller/src/swapline_encoder.rs b/crates/execution/multicaller/src/swapline_encoder.rs index a2240348..6d8c306a 100644 --- a/crates/execution/multicaller/src/swapline_encoder.rs +++ b/crates/execution/multicaller/src/swapline_encoder.rs @@ -1,18 +1,18 @@ use std::sync::Arc; -use alloy_primitives::{Address, Bytes, U256}; -use eyre::{eyre, OptionExt, Result}; -use tracing::{trace, warn}; +use alloy_primitives::{Address, U256}; +use eyre::{eyre, Result}; +use tracing::trace; -use crate::helpers::AbiEncoderHelper; -use crate::opcodes_encoder::{OpcodesEncoder, OpcodesEncoderV2}; +use crate::abi_helpers::AbiEncoderHelper; use crate::pool_abi_encoder::ProtocolAbiSwapEncoderTrait; -use crate::pool_opcodes_encoder::{ProtocolSwapOpcodesEncoderV2, SwapOpcodesEncoderTrait}; +use crate::pool_opcodes_encoder::{MulticallerOpcodesPayload, ProtocolSwapOpcodesEncoderV2, SwapOpcodesEncoderTrait}; use crate::ProtocolABIEncoderV2; use loom_defi_address_book::TokenAddressEth; use loom_types_blockchain::LoomDataTypesEthereum; use loom_types_blockchain::{MulticallerCall, MulticallerCalls}; -use loom_types_entities::{PoolClass, PoolWrapper, PreswapRequirement, SwapAmountType, SwapLine, Token}; +use loom_types_entities::SwapAmountType::RelativeStack; +use loom_types_entities::{PoolWrapper, SwapAmountType, SwapLine, Token}; #[derive(Clone)] pub struct SwapLineEncoder { @@ -27,20 +27,6 @@ impl SwapLineEncoder { abi_encoder: Arc, opcodes_encoder: Arc, ) -> SwapLineEncoder { - /*let mut opcodes_encoders_map: HashMap> = Default::default(); - - let uni2_opcodes_encoder = Rc::new(UniswapV2SwapOpcodesEncoder {}); - let uni3_opcodes_encoder = Rc::new(UniswapV3SwapOpcodesEncoder {}); - let curve_opcodes_encoder = Rc::new(CurveSwapOpcodesEncoder {}); - - opcodes_encoders_map.insert(PoolClass::UniswapV2, uni2_opcodes_encoder.clone()); - opcodes_encoders_map.insert(PoolClass::Maverick, uni3_opcodes_encoder.clone()); - opcodes_encoders_map.insert(PoolClass::UniswapV3, uni3_opcodes_encoder.clone()); - opcodes_encoders_map.insert(PoolClass::PancakeV3, uni3_opcodes_encoder.clone()); - opcodes_encoders_map.insert(PoolClass::Curve, curve_opcodes_encoder.clone()); - - */ - SwapLineEncoder { multicaller_address, abi_encoder, opcodes_encoder } } @@ -55,9 +41,9 @@ impl SwapLineEncoder { &self, swap_path: &SwapLine, inside_swap_opcodes: MulticallerCalls, - funds_to: Address, + funds_to: Option<&PoolWrapper>, ) -> Result { - trace!("encode_flash_swap_line_in_amount funds_to={}", funds_to); + trace!("encode_flash_swap_line_in_amount funds_to={:?}", funds_to); let mut flash_swap_opcodes = MulticallerCalls::new(); let mut inside_opcodes = inside_swap_opcodes.clone(); @@ -66,215 +52,28 @@ impl SwapLineEncoder { let mut reverse_tokens: Vec> = swap_path.tokens().clone(); reverse_tokens.reverse(); - let mut prev_pool: Option<&PoolWrapper> = None; + let mut prev_pool: Option<&PoolWrapper> = funds_to; for (pool_idx, flash_pool) in reverse_pools.iter().enumerate() { let token_from_address = reverse_tokens[pool_idx + 1].get_address(); let token_to_address = reverse_tokens[pool_idx].get_address(); - let amount_in = if pool_idx == swap_path.pools().len() - 1 { swap_path.amount_in } else { SwapAmountType::Stack0 }; - - let swap_to = match prev_pool { - Some(prev_pool) => match flash_pool.get_class() { - PoolClass::UniswapV2 => match self.abi_encoder.preswap_requirement(prev_pool.as_ref()) { - PreswapRequirement::Transfer(transfer_to) => { - trace!( - "uniswap v2 transfer to previous pool: token={:?}, to={:?}, prev_pool={:?}", - token_to_address, - transfer_to, - prev_pool.get_address() - ); - let mut transfer_opcode = MulticallerCall::new_call( - token_to_address, - &AbiEncoderHelper::encode_erc20_transfer(transfer_to, U256::ZERO), - ); - transfer_opcode.set_call_stack(false, 0, 0x24, 0x20); - inside_opcodes.insert(transfer_opcode); - transfer_to - } - _ => self.multicaller_address, - }, - _ => match self.abi_encoder.preswap_requirement(prev_pool.as_ref()) { - PreswapRequirement::Transfer(funds_to) => { - trace!("other transfer to previous pool: funds_to={:?}, prev_pool={:?}", funds_to, prev_pool); - funds_to - } - _ => { - trace!("other swap to multicaller, prev_pool={:?}", prev_pool); - self.multicaller_address - } - }, - }, - None => funds_to, - }; + let amount_in = if pool_idx == swap_path.pools().len() - 1 { swap_path.amount_in } else { SwapAmountType::RelativeStack(0) }; - match flash_pool.get_class() { - PoolClass::UniswapV2 => { - match amount_in { - SwapAmountType::Set(amount) => { - trace!( - "uniswap v2 transfer token={:?}, to={:?}, amount={}", - token_from_address, - flash_pool.get_address(), - amount - ); - inside_opcodes.add(MulticallerCall::new_call( - token_from_address, - &AbiEncoderHelper::encode_erc20_transfer(flash_pool.get_address(), amount), - )); - } - _ => { - warn!("InAmountTypeNotSet") - } - } - - if pool_idx == 0 && funds_to != self.multicaller_address { - trace!("uniswap v2 transfer to token_to_address={:?}, funds_to={:?}", token_to_address, funds_to); - let mut transfer_opcode = - MulticallerCall::new_call(token_to_address, &AbiEncoderHelper::encode_erc20_transfer(funds_to, U256::ZERO)); - transfer_opcode.set_call_stack(false, 0, 0x24, 0x20); - inside_opcodes.insert(transfer_opcode); - } - } - PoolClass::UniswapV3 | PoolClass::Maverick | PoolClass::PancakeV3 => { - let transfer_opcode = match amount_in { - SwapAmountType::Set(amount) => { - trace!( - "uniswap v3 transfer token={:?}, to={:?}, amount={:?}", - token_to_address, - flash_pool.get_address(), - amount - ); - - MulticallerCall::new_call( - token_from_address, - &AbiEncoderHelper::encode_erc20_transfer(flash_pool.get_address(), amount), - ) - } - _ => { - trace!("other transfer token={:?}, to={:?}", token_to_address, flash_pool.get_address()); - MulticallerCall::new_call( - token_from_address, - &AbiEncoderHelper::encode_erc20_transfer(flash_pool.get_address(), U256::ZERO), - ) - .set_call_stack(false, 1, 0x24, 0x20) - .clone() - } - }; - - inside_opcodes.add(transfer_opcode); - } - - _ => { - return Err(eyre!("CANNOT_ENCODE_FLASH_CALL")); - } - } - - let inside_call_bytes = OpcodesEncoderV2::pack_do_calls_data(&inside_opcodes)?; - flash_swap_opcodes = MulticallerCalls::new(); - - trace!("flash swap_to {:?}", swap_to); - - match flash_pool.get_class() { - PoolClass::UniswapV2 => { - let get_out_amount_opcode = match amount_in { - SwapAmountType::Set(amount) => { - trace!("uniswap v2 get out amount for pool={:?}, amount={}", flash_pool.get_address(), amount); - MulticallerCall::new_internal_call(&AbiEncoderHelper::encode_multicaller_uni2_get_out_amount( - token_from_address, - token_to_address, - flash_pool.get_address(), - amount, - flash_pool.get_fee(), - )) - } - _ => { - trace!("uniswap v2 get out amount, pool={:?}", flash_pool.get_address()); - MulticallerCall::new_internal_call(&AbiEncoderHelper::encode_multicaller_uni2_get_out_amount( - token_from_address, - token_to_address, - flash_pool.get_address(), - U256::ZERO, - flash_pool.get_fee(), - )) - .set_call_stack(false, 0, 0x24, 0x20) - .clone() - } - }; - - let mut swap_opcode = MulticallerCall::new_call( - flash_pool.get_address(), - &self.abi_encoder.encode_swap_out_amount_provided( - flash_pool.as_ref(), - token_from_address, - token_to_address, - U256::ZERO, - self.multicaller_address, - inside_call_bytes, - )?, - ); - swap_opcode.set_call_stack( - true, - 0, - self.abi_encoder.swap_out_amount_offset(flash_pool.as_ref(), token_from_address, token_to_address).unwrap(), - 0x20, - ); - - flash_swap_opcodes.add(get_out_amount_opcode).add(swap_opcode); - - prev_pool = Some(flash_pool); - inside_opcodes = flash_swap_opcodes.clone(); - } - PoolClass::UniswapV3 | PoolClass::Maverick | PoolClass::PancakeV3 => { - let swap_opcode = match amount_in { - SwapAmountType::Set(amount) => { - trace!("uniswap v3 swap in amount for pool={:?}, amount={}", flash_pool.get_address(), amount); - MulticallerCall::new_call( - flash_pool.get_address(), - &self.abi_encoder.encode_swap_in_amount_provided( - flash_pool.as_ref(), - token_from_address, - token_to_address, - amount, - swap_to, - inside_call_bytes, - )?, - ) - } - _ => { - trace!("uniswap v3 swap in amount for pool={:?}", flash_pool.get_address()); - MulticallerCall::new_call( - flash_pool.get_address(), - &self.abi_encoder.encode_swap_in_amount_provided( - flash_pool.as_ref(), - token_from_address, - token_to_address, - U256::ZERO, - swap_to, - inside_call_bytes, - )?, - ) - .set_call_stack( - false, - 0, - self.abi_encoder - .swap_in_amount_offset(flash_pool.as_ref(), token_from_address, token_to_address) - .ok_or_eyre("NO_OFFSET")?, - 0x20, - ) - .clone() - } - }; - - flash_swap_opcodes.add(swap_opcode); + self.opcodes_encoder.encode_flash_swap_in_amount_provided( + &mut flash_swap_opcodes, + self.abi_encoder.as_ref(), + token_from_address, + token_to_address, + amount_in, + flash_pool.as_ref(), + prev_pool.map(|v| v.as_ref()), + MulticallerOpcodesPayload::Opcodes(inside_opcodes), + self.multicaller_address, + )?; - prev_pool = Some(flash_pool); - inside_opcodes = flash_swap_opcodes.clone(); - } - _ => { - return Err(eyre!("CANNOT_ENCODE_FLASH_CALL")); - } - } + prev_pool = Some(flash_pool); + inside_opcodes = flash_swap_opcodes.clone(); } Ok(flash_swap_opcodes) @@ -284,9 +83,8 @@ impl SwapLineEncoder { &self, swap_path: &SwapLine, inside_swap_opcodes: MulticallerCalls, - _funds_from: Address, ) -> Result { - trace!("encode_flash_swap_line_out_amount"); + trace!("encode_flash_swap_line_out_amount inside_opcodes={}", inside_swap_opcodes.len()); let mut flash_swap_opcodes = MulticallerCalls::new(); let mut inside_opcodes = inside_swap_opcodes.clone(); @@ -295,14 +93,30 @@ impl SwapLineEncoder { let tokens: Vec> = swap_path.tokens().clone(); for (pool_idx, flash_pool) in pools.iter().enumerate() { + flash_swap_opcodes = MulticallerCalls::new(); + let token_from_address = tokens[pool_idx].get_address(); let token_to_address = tokens[pool_idx + 1].get_address(); let next_pool = if pool_idx < pools.len() - 1 { Some(&pools[pool_idx + 1]) } else { None }; - let amount_out = if pool_idx == pools.len() - 1 { swap_path.amount_out } else { SwapAmountType::Stack0 }; + let amount_out = if pool_idx == pools.len() - 1 { swap_path.amount_out } else { SwapAmountType::RelativeStack(0) }; - let swap_to = match next_pool { + self.opcodes_encoder.encode_flash_swap_out_amount_provided( + &mut flash_swap_opcodes, + self.abi_encoder.as_ref(), + token_from_address, + token_to_address, + amount_out, + flash_pool.as_ref(), + next_pool.map(|v| v.as_ref()), + MulticallerOpcodesPayload::Opcodes(inside_opcodes), + self.multicaller_address, + )?; + + inside_opcodes = flash_swap_opcodes.clone(); + + /*let swap_to = match next_pool { Some(next_pool) => next_pool.get_address(), None => self.multicaller_address, }; @@ -314,29 +128,34 @@ impl SwapLineEncoder { token_from_address, token_to_address, flash_pool.get_address(), - amount_out.unwrap_or_zero(), + amount_out.unwrap_or_default(), flash_pool.get_fee(), )); - match amount_out { - SwapAmountType::Set(_) => {} - _ => { - get_in_amount_opcode.set_call_stack(false, 0, 0x24, 0x20); - } + if amount_out.is_not_set() { + get_in_amount_opcode.set_call_stack(false, 0, 0x24, 0x20); } + inside_opcodes.insert(get_in_amount_opcode); if pool_idx == 0 && swap_to != flash_pool.get_address() { + trace!( + "retflash transfer token={:?}, to={:?}, amount=stack_no_rel_1", + token_from_address, + flash_pool.get_address() + ); + let mut transfer_opcode = MulticallerCall::new_call( token_from_address, &AbiEncoderHelper::encode_erc20_transfer(flash_pool.get_address(), U256::ZERO), ); transfer_opcode.set_call_stack(false, 1, 0x24, 0x20); - inside_opcodes.add(transfer_opcode); }; if swap_to != self.multicaller_address { + trace!("retflash transfer token={:?}, to={:?}, amount=stack_norel_0", token_to_address, swap_to); + let mut transfer_opcode = MulticallerCall::new_call(token_to_address, &AbiEncoderHelper::encode_erc20_transfer(swap_to, U256::ZERO)); transfer_opcode.set_call_stack(false, 0, 0x24, 0x20); @@ -345,6 +164,7 @@ impl SwapLineEncoder { } PoolClass::UniswapV3 | PoolClass::Maverick | PoolClass::PancakeV3 => { if pool_idx == 0 { + trace!("retflash transfer token={:?}, to={:?}, amount=stack_norel_1", token_from_address, flash_pool.get_address()); let mut transfer_opcode = MulticallerCall::new_call( token_from_address, &AbiEncoderHelper::encode_erc20_transfer(flash_pool.get_address(), U256::ZERO), @@ -365,83 +185,74 @@ impl SwapLineEncoder { trace!("flash swap_to {:?}", swap_to); - match flash_pool.get_class() { + + */ + /*match flash_pool.get_class() { PoolClass::UniswapV2 => { - trace!("uniswap v2 swap out amount provided for pool={:?}, amount_out={:?}", flash_pool.get_address(), amount_out); + trace!( + "uniswap v2 swap out amount provided for pool={:?}, amount_out={:?} receiver={} inside_opcodes_len={}", + flash_pool.get_address(), + amount_out, + self.multicaller_address, + inside_opcodes.len() + ); let mut swap_opcode = MulticallerCall::new_call( flash_pool.get_address(), &self.abi_encoder.encode_swap_out_amount_provided( flash_pool.as_ref(), token_from_address, token_to_address, - amount_out.unwrap_or_zero(), + amount_out.unwrap_or_default(), self.multicaller_address, inside_call_bytes, )?, ); - match amount_out { - SwapAmountType::Set(_) => { - trace!("uniswap v2 amount out set amount"); - } - _ => { - trace!("uniswap v2 amount out else"); - swap_opcode.set_call_stack( - true, - 0, - self.abi_encoder.swap_out_amount_offset(flash_pool.as_ref(), token_from_address, token_to_address).unwrap(), - 0x20, - ); - } - }; + if amount_out.is_not_set() { + trace!("uniswap v2 amount not set"); + swap_opcode.set_call_stack( + true, + 0, + self.abi_encoder.swap_out_amount_offset(flash_pool.as_ref(), token_from_address, token_to_address).unwrap(), + 0x20, + ); + } flash_swap_opcodes.add(swap_opcode); inside_opcodes = flash_swap_opcodes.clone(); } PoolClass::UniswapV3 | PoolClass::PancakeV3 | PoolClass::Maverick => { - let swap_opcode = match amount_out { - SwapAmountType::Set(amount) => { - trace!( - "uniswap v3 swap out amount provided for pool={:?}, amount_out={:?}", - flash_pool.get_address(), - amount_out - ); - MulticallerCall::new_call( - flash_pool.get_address(), - &self.abi_encoder.encode_swap_out_amount_provided( - flash_pool.as_ref(), - token_from_address, - token_to_address, - amount, - swap_to, - inside_call_bytes, - )?, - ) - } - _ => { - trace!("uniswap v3 else swap out amount for pool={:?}", flash_pool.get_address()); - flash_swap_opcodes.add(MulticallerCall::new_calculation_call(&Bytes::from(vec![0x8, 0x2A, 0x00]))); - - MulticallerCall::new_call( - flash_pool.get_address(), - &self.abi_encoder.encode_swap_out_amount_provided( - flash_pool.as_ref(), - token_from_address, - token_to_address, - U256::ZERO, - swap_to, - inside_call_bytes, - )?, - ) - .set_call_stack( - true, - 0, - self.abi_encoder.swap_out_amount_offset(flash_pool.as_ref(), token_from_address, token_to_address).unwrap(), - 0x20, - ) - .clone() - } + trace!( + "uniswap v3 swap out amount provided for pool={:?}, amount_out={:?} receiver={} inside_opcodes_len={}", + flash_pool.get_address(), + amount_out, + swap_to, + inside_opcodes.len() + ); + let mut swap_opcode = MulticallerCall::new_call( + flash_pool.get_address(), + &self.abi_encoder.encode_swap_out_amount_provided( + flash_pool.as_ref(), + token_from_address, + token_to_address, + amount_out.unwrap_or_default(), + swap_to, + inside_call_bytes, + )?, + ); + + if amount_out.is_not_set() { + trace!("uniswap v3 swap out amount is not set"); + + flash_swap_opcodes.add(MulticallerCall::new_calculation_call(&Bytes::from(vec![0x8, 0x2A, 0x00]))); + + swap_opcode.set_call_stack( + true, + 0, + self.abi_encoder.swap_out_amount_offset(flash_pool.as_ref(), token_from_address, token_to_address).unwrap(), + 0x20, + ); }; flash_swap_opcodes.add(swap_opcode); @@ -452,6 +263,8 @@ impl SwapLineEncoder { return Err(eyre!("CANNOT_ENCODE_FLASH_CALL")); } } + + */ } Ok(flash_swap_opcodes) @@ -464,33 +277,39 @@ impl SwapLineEncoder { pub fn encode_swap_line_in_amount( &self, swap_path: &SwapLine, - funds_from: Address, - funds_to: Address, + funds_to: Option<&PoolWrapper>, ) -> Result { let mut swap_opcodes = MulticallerCalls::new(); + let mut amount_in = swap_path.amount_in; + for i in 0..swap_path.pools().len() { let token_from_address = swap_path.tokens()[i].get_address(); let token_to_address = swap_path.tokens()[i + 1].get_address(); let cur_pool = &swap_path.pools()[i].clone(); - let next_pool: Option<&PoolWrapper> = if i < swap_path.pools().len() - 1 { Some(&swap_path.pools()[i + 1]) } else { None }; + let next_pool: Option<&PoolWrapper> = if i < swap_path.pools().len() - 1 { Some(&swap_path.pools()[i + 1]) } else { funds_to }; trace!( - "encode_swap_line_in_amount for from={} to={} pool={}, next_pool={:?}", + "encode_swap_line_in_amount for from={} to={} pool={}, next_pool={:?} funds_to {:?}", token_from_address, token_to_address, cur_pool.get_address(), - next_pool.map(|next_pool| next_pool.get_address()) + next_pool.map(|next_pool| next_pool.get_address()), + funds_to ); - let amount_in = if i == 0 { - if let PreswapRequirement::Transfer(funds_needed_at) = self.abi_encoder.preswap_requirement(cur_pool.as_ref()) { + /*let amount_in = if i == 0 { + /*if let PreswapRequirement::Transfer(funds_needed_at) = self.abi_encoder.preswap_requirement(cur_pool.as_ref()) { if funds_needed_at != funds_from { + trace!( + "encode_swap_line_in_amount i == 0 amount in {:?} funds {}->{}", + swap_path.amount_in, + funds_from, + funds_needed_at + ); match swap_path.amount_in { SwapAmountType::Set(value) => { - trace!("encode_swap_line_in_amount i == 0 set amount in {}", value); - trace!("transfer token={:?}, to={:?}, amount={}", token_from_address, funds_needed_at, value); let transfer_opcode = MulticallerCall::new_call( token_from_address, @@ -533,18 +352,25 @@ impl SwapLineEncoder { } else { swap_path.amount_in } + + */ + swap_path.amount_in } else { SwapAmountType::RelativeStack(0) }; - let swap_to: Address = if let Some(next_pool) = next_pool { + */ + + /*let swap_to: Address = if let Some(next_pool) = next_pool { match &self.abi_encoder.preswap_requirement(next_pool.as_ref()) { PreswapRequirement::Transfer(next_funds_to) => *next_funds_to, _ => self.multicaller_address, } } else { funds_to - }; + };*/ + + let swap_to = next_pool.map(|x| x.get_address()).unwrap_or(self.multicaller_address); trace!("swap_to {:?}", swap_to); @@ -556,75 +382,11 @@ impl SwapLineEncoder { amount_in, cur_pool.as_ref(), next_pool.map(|next_pool| next_pool.as_ref()), + MulticallerOpcodesPayload::Empty, self.multicaller_address, )?; - /* - match cur_pool.get_class() { - PoolClass::UniswapV2 => UniswapV2SwapOpcodesEncoder {}.encode_swap_in_amount_provided( - &mut swap_opcodes, - self.abi_encoder.as_ref(), - token_from_address, - token_to_address, - amount_in, - cur_pool, - next_pool, - self.multicaller_address, - )?, - PoolClass::UniswapV3 | PoolClass::PancakeV3 | PoolClass::Maverick => UniswapV3SwapOpcodesEncoder {} - .encode_swap_in_amount_provided( - &mut swap_opcodes, - self.abi_encoder.as_ref(), - token_from_address, - token_to_address, - amount_in, - cur_pool, - next_pool, - self.multicaller_address, - )?, - PoolClass::Curve => { - CurveSwapOpcodesEncoder {}.encode_swap_in_amount_provided( - &mut swap_opcodes, - self.abi_encoder.as_ref(), - token_from_address, - token_to_address, - amount_in, - cur_pool, - next_pool, - self.multicaller_address, - )?; - } - PoolClass::LidoWstEth => { - WstEthSwapEncoder {}.encode_swap_in_amount_provided( - &mut swap_opcodes, - self.abi_encoder.as_ref(), - token_from_address, - token_to_address, - amount_in, - cur_pool, - next_pool, - self.multicaller_address, - )?; - } - - PoolClass::LidoStEth => { - StEthSwapEncoder {}.encode_swap_in_amount_provided( - &mut swap_opcodes, - self.abi_encoder.as_ref(), - token_from_address, - token_to_address, - amount_in, - cur_pool, - next_pool, - self.multicaller_address, - )?; - } - _ => { - return Err(eyre!("POOL_TYPE_NOT_SUPPORTED")); - } - } - - */ + amount_in = RelativeStack(0); } Ok(swap_opcodes) } diff --git a/crates/execution/multicaller/src/swapstep_encoder.rs b/crates/execution/multicaller/src/swapstep_encoder.rs index e280db03..9a926398 100644 --- a/crates/execution/multicaller/src/swapstep_encoder.rs +++ b/crates/execution/multicaller/src/swapstep_encoder.rs @@ -1,9 +1,9 @@ use alloy_primitives::{Address, Bytes, U256}; use eyre::Result; use lazy_static::lazy_static; -use tracing::{debug, trace}; +use tracing::trace; -use crate::helpers::AbiEncoderHelper; +use crate::abi_helpers::AbiEncoderHelper; use crate::opcodes_encoder::{OpcodesEncoder, OpcodesEncoderV2}; use crate::SwapLineEncoder; use loom_types_blockchain::LoomDataTypesEthereum; @@ -70,14 +70,10 @@ impl SwapStepEncoder { } if swap.swap_line_vec().len() == 1 { - swap_opcodes.merge(self.swap_line_encoder.encode_swap_line_in_amount( - swap.swap_line_vec().first().unwrap(), - flash_funds_to, - self.multicaller_address, - )?); + swap_opcodes.merge(self.swap_line_encoder.encode_swap_line_in_amount(swap.swap_line_vec().first().unwrap(), None)?); } else { for swap_path in swap.swap_line_vec().iter() { - let opcodes = self.swap_line_encoder.encode_swap_line_in_amount(swap_path, flash_funds_to, self.multicaller_address)?; + let opcodes = self.swap_line_encoder.encode_swap_line_in_amount(swap_path, None)?; let call_bytes = OpcodesEncoderV2::pack_do_calls(&opcodes)?; swap_opcodes.add(MulticallerCall::new_call(self.multicaller_address, &call_bytes)); } @@ -98,33 +94,26 @@ impl SwapStepEncoder { pub fn encode_in_amount( &self, - step0: SwapStep, - step1: SwapStep, + flash_step: SwapStep, + swap_step: SwapStep, ) -> Result { - let flash = step0.clone(); - let mut swap = step1.clone(); + let mut swap_step = swap_step; - let flash_funds_to = self.multicaller_address; + //let flash_funds_to = self.multicaller_address; - if flash.len() > 1 || swap.len() > 1 { - swap.get_mut_swap_line_by_index(swap.len() - 1).amount_in = SwapAmountType::Balance(flash_funds_to); + if flash_step.len() > 1 || swap_step.len() > 1 { + swap_step.get_mut_swap_line_by_index(swap_step.len() - 1).amount_in = SwapAmountType::Balance(self.multicaller_address); } - trace!("funds_to {:?}", flash_funds_to); - let mut swap_opcodes = MulticallerCalls::new(); - if swap.swap_line_vec().len() == 1 { + if swap_step.swap_line_vec().len() == 1 { trace!("swap.swap_line_vec().len() == 1"); - swap_opcodes.merge(self.swap_line_encoder.encode_swap_line_in_amount( - swap.swap_line_vec().first().unwrap(), - flash_funds_to, - self.multicaller_address, - )?); + swap_opcodes.merge(self.swap_line_encoder.encode_swap_line_in_amount(swap_step.swap_line_vec().first().unwrap(), None)?); } else { trace!("swap.swap_line_vec().len() != 1"); - for swap_path in swap.swap_line_vec().iter() { - let opcodes = self.swap_line_encoder.encode_swap_line_in_amount(swap_path, flash_funds_to, self.multicaller_address)?; + for swap_path in swap_step.swap_line_vec().iter() { + let opcodes = self.swap_line_encoder.encode_swap_line_in_amount(swap_path, None)?; let call_bytes = OpcodesEncoderV2::pack_do_calls(&opcodes)?; swap_opcodes.add(MulticallerCall::new_call(self.multicaller_address, &call_bytes)); @@ -134,7 +123,9 @@ impl SwapStepEncoder { } } - let mut flash_swaps = flash.swap_line_vec().clone(); + let flash_funds_to = swap_step.get_first_pool(); + + let mut flash_swaps = flash_step.swap_line_vec().clone(); flash_swaps.reverse(); for flash_swap_path in flash_swaps.iter() { @@ -146,27 +137,19 @@ impl SwapStepEncoder { pub fn encode_out_amount( &self, - step0: SwapStep, - step1: SwapStep, + swap_step: SwapStep, + flash_step: SwapStep, ) -> Result { - let flash = step1.clone(); - let swap = step0.clone(); - - let flash_funds_to = self.multicaller_address; - - debug!("funds_to {:?}", flash_funds_to); - let mut swap_opcodes = MulticallerCalls::new(); - if swap.swap_line_vec().len() == 1 { - swap_opcodes.merge(self.swap_line_encoder.encode_swap_line_in_amount( - swap.swap_line_vec().first().unwrap(), - flash_funds_to, - self.multicaller_address, - )?); + if swap_step.swap_line_vec().len() == 1 { + swap_opcodes.merge( + self.swap_line_encoder + .encode_swap_line_in_amount(swap_step.swap_line_vec().first().unwrap(), flash_step.get_first_pool())?, + ); } else { - for swap_path in swap.swap_line_vec().iter() { - let opcodes = self.swap_line_encoder.encode_swap_line_in_amount(swap_path, flash_funds_to, self.multicaller_address)?; + for swap_path in swap_step.swap_line_vec().iter() { + let opcodes = self.swap_line_encoder.encode_swap_line_in_amount(swap_path, None)?; let call_bytes = OpcodesEncoderV2::pack_do_calls(&opcodes)?; swap_opcodes.add(MulticallerCall::new_call(self.multicaller_address, &call_bytes)); @@ -176,11 +159,11 @@ impl SwapStepEncoder { } } - let mut flash_swaps = flash.swap_line_vec().clone(); + let mut flash_swaps = flash_step.swap_line_vec().clone(); flash_swaps.reverse(); for flash_swap_path in flash_swaps.iter() { - swap_opcodes = self.swap_line_encoder.encode_flash_swap_line_out_amount(flash_swap_path, swap_opcodes, flash_funds_to)?; + swap_opcodes = self.swap_line_encoder.encode_flash_swap_line_out_amount(flash_swap_path, swap_opcodes)?; } Ok(swap_opcodes) diff --git a/crates/node/debug-provider/src/anvilprovider.rs b/crates/node/debug-provider/src/anvilprovider.rs index 3dbe163b..e49f59c9 100644 --- a/crates/node/debug-provider/src/anvilprovider.rs +++ b/crates/node/debug-provider/src/anvilprovider.rs @@ -106,14 +106,10 @@ mod test { use alloy::node_bindings::Anvil; use alloy::primitives::{B256, U256}; use alloy::rpc::types::BlockNumberOrTag; - use alloy::transports::http::Http; - use alloy_provider::ext::AnvilApi; use alloy_provider::ProviderBuilder; use alloy_rpc_client::ClientBuilder; use env_logger::Env as EnvLog; use eyre::Result; - use reqwest::Client; - use std::ops::Deref; use std::sync::Arc; use super::*; diff --git a/crates/types/blockchain/src/opcodes.rs b/crates/types/blockchain/src/opcodes.rs index 0d5e161f..ac9d734a 100644 --- a/crates/types/blockchain/src/opcodes.rs +++ b/crates/types/blockchain/src/opcodes.rs @@ -106,12 +106,25 @@ impl MulticallerCalls { Self::default() } + pub fn len(&self) -> usize { + self.opcodes_vec.len() + } + + pub fn is_empty(&self) -> bool { + self.opcodes_vec.is_empty() + } + pub fn log(&self) { for (i, o) in self.opcodes_vec.iter().enumerate() { debug!("{} {:?}", i, o); } } + pub fn clean(&mut self) -> &mut Self { + self.opcodes_vec = Vec::new(); + self + } + pub fn add(&mut self, opcode: MulticallerCall) -> &mut Self { self.opcodes_vec.push(opcode); self diff --git a/crates/types/entities/Cargo.toml b/crates/types/entities/Cargo.toml index a95760bd..584a8311 100644 --- a/crates/types/entities/Cargo.toml +++ b/crates/types/entities/Cargo.toml @@ -15,7 +15,9 @@ loom-node-debug-provider.workspace = true loom-types-blockchain.workspace = true aes.workspace = true +async-stream.workspace = true eyre.workspace = true +futures.workspace = true hex.workspace = true indexmap.workspace = true lazy_static.workspace = true @@ -26,6 +28,7 @@ strum.workspace = true strum_macros.workspace = true thiserror.workspace = true tokio.workspace = true +tokio-stream.workspace = true toml.workspace = true tracing.workspace = true diff --git a/crates/types/entities/src/market.rs b/crates/types/entities/src/market.rs index 76cafdab..a468f01c 100644 --- a/crates/types/entities/src/market.rs +++ b/crates/types/entities/src/market.rs @@ -110,6 +110,12 @@ impl Market { self.swap_paths.get_pool_paths_vec(pool_address) } + /// Get all swap paths from the market by the pool address. + #[inline] + pub fn swap_paths(&self) -> Vec> { + self.swap_paths.paths.clone().into_iter().collect::>() + } + /// Get a pool reference by the pool address. If the pool exists but the class is unknown it returns None. #[inline] pub fn get_pool(&self, address: &PoolId) -> Option<&PoolWrapper> { @@ -154,7 +160,6 @@ impl Market { } /// Get all pool addresses that allow to swap from `token_from_address` to `token_to_address`. - #[inline] pub fn get_token_token_pools(&self, token_from_address: &LDT::Address, token_to_address: &LDT::Address) -> Option>> { self.token_token_pools.get(token_from_address)?.get(token_to_address).cloned() diff --git a/crates/types/entities/src/pool.rs b/crates/types/entities/src/pool.rs index f08e6301..9e2ee43e 100644 --- a/crates/types/entities/src/pool.rs +++ b/crates/types/entities/src/pool.rs @@ -287,15 +287,46 @@ pub struct DefaultAbiSwapEncoder {} impl PoolAbiEncoder for DefaultAbiSwapEncoder {} -#[derive(Clone, Debug, PartialEq)] -pub enum PreswapRequirement { +#[derive(Clone, Debug)] +pub enum PreswapRequirement { Unknown, - Transfer(Address), + Transfer(LDT::Address), Allowance, Callback, Base, } +impl PartialEq for PreswapRequirement +where + LDT: LoomDataTypes, +{ + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (PreswapRequirement::Unknown, PreswapRequirement::Unknown) => true, + (PreswapRequirement::Transfer(addr1), PreswapRequirement::Transfer(addr2)) => addr1 == addr2, + (PreswapRequirement::Allowance, PreswapRequirement::Allowance) => true, + (PreswapRequirement::Callback, PreswapRequirement::Callback) => true, + (PreswapRequirement::Base, PreswapRequirement::Base) => true, + _ => false, + } + } +} + +impl PreswapRequirement { + pub fn address_or(&self, default_address: LDT::Address) -> LDT::Address { + match self { + PreswapRequirement::Transfer(address) => *address, + _ => default_address, + } + } + pub fn address(&self) -> Option { + match self { + PreswapRequirement::Transfer(address) => Some(*address), + _ => None, + } + } +} + pub trait PoolAbiEncoder: Send + Sync { fn encode_swap_in_amount_provided( &self, diff --git a/crates/types/entities/src/pool_loader.rs b/crates/types/entities/src/pool_loader.rs index 98ec60fc..6d73dc57 100644 --- a/crates/types/entities/src/pool_loader.rs +++ b/crates/types/entities/src/pool_loader.rs @@ -12,7 +12,9 @@ use std::collections::HashMap; use std::future::Future; use std::pin::Pin; use std::sync::Arc; +use tokio_stream::Stream; +#[allow(clippy::type_complexity)] pub trait PoolLoader: Send + Sync + 'static where N: Network, @@ -34,6 +36,7 @@ where env: Env, ) -> Result>; fn is_code(&self, code: &Bytes) -> bool; + fn protocol_loader(&self) -> Result + Send>>>; } pub struct PoolLoaders @@ -45,7 +48,7 @@ where { provider: Option

, config: Option, - map: HashMap>>, + pub map: HashMap>>, } impl PoolLoaders diff --git a/crates/types/entities/src/swap.rs b/crates/types/entities/src/swap.rs index 983f26e4..58330dd8 100644 --- a/crates/types/entities/src/swap.rs +++ b/crates/types/entities/src/swap.rs @@ -1,7 +1,7 @@ use std::fmt::{Display, Formatter}; use std::sync::Arc; -use crate::{PoolId, SwapAmountType, SwapLine, SwapStep, Token}; +use crate::{PoolId, SwapLine, SwapStep, Token}; use alloy_primitives::U256; use loom_types_blockchain::{LoomDataTypes, LoomDataTypesEthereum}; @@ -29,35 +29,7 @@ impl Display for Swap { impl Swap { pub fn to_swap_steps(self: &Swap, multicaller: LDT::Address) -> Option<(SwapStep, SwapStep)> { match self { - Swap::BackrunSwapLine(swap_line) => { - let mut sp0: Option> = None; - let mut sp1: Option> = None; - - for i in 1..swap_line.path.pool_count() { - let (flash_path, inside_path) = swap_line.split(i).unwrap(); - if flash_path.can_flash_swap() || inside_path.can_flash_swap() { - sp0 = Some(flash_path); - sp1 = Some(inside_path); - break; - } - } - - if sp0.is_none() || sp1.is_none() { - let (flash_path, inside_path) = swap_line.split(1).unwrap(); - sp0 = Some(flash_path); - sp1 = Some(inside_path); - } - - let mut step_0 = SwapStep::new(multicaller); - step_0.add(sp0.unwrap()); - - let mut step_1 = SwapStep::new(multicaller); - let mut sp1 = sp1.unwrap(); - sp1.amount_in = SwapAmountType::Balance(multicaller); - step_1.add(sp1); - - Some((step_0, step_1)) - } + Swap::BackrunSwapLine(swap_line) => swap_line.to_swap_steps(multicaller), Swap::BackrunSwapSteps((sp0, sp1)) => Some((sp0.clone(), sp1.clone())), _ => None, } diff --git a/crates/types/entities/src/swap_encoder.rs b/crates/types/entities/src/swap_encoder.rs index 7663c33b..6c8b961f 100644 --- a/crates/types/entities/src/swap_encoder.rs +++ b/crates/types/entities/src/swap_encoder.rs @@ -15,7 +15,6 @@ pub trait SwapEncoder { /// - sender_eth_balance - balance of EOA /// /// returns (to. value, call_data) for transaction - #[allow(clippy::too_many_arguments)] fn encode( &self, diff --git a/crates/types/entities/src/swapline.rs b/crates/types/entities/src/swapline.rs index 9d7e8a42..96f7d1cb 100644 --- a/crates/types/entities/src/swapline.rs +++ b/crates/types/entities/src/swapline.rs @@ -25,18 +25,29 @@ pub enum SwapAmountType { impl Copy for SwapAmountType {} impl SwapAmountType { + #[inline] pub fn unwrap(&self) -> U256 { match &self { Self::Set(x) => *x, _ => panic!("called `InAmountType::unwrap()` on a unknown value"), } } - pub fn unwrap_or_zero(&self) -> U256 { + #[inline] + pub fn unwrap_or_default(&self) -> U256 { match &self { Self::Set(x) => *x, _ => U256::ZERO, } } + + #[inline] + pub fn is_set(&self) -> bool { + matches!(self, Self::Set(_)) + } + #[inline] + pub fn is_not_set(&self) -> bool { + !matches!(self, Self::Set(_)) + } } #[derive(Clone, Debug)] @@ -141,7 +152,7 @@ impl SwapLine { token_from: self.get_first_token().map_or(LDT::Address::default(), |x| x.get_address()), token_to: self.get_last_token().map_or(LDT::Address::default(), |x| x.get_address()), is_in_amount: true, - amount: self.amount_in.unwrap_or_zero(), + amount: self.amount_in.unwrap_or_default(), } } @@ -190,26 +201,28 @@ impl SwapLine { let mut sp1: Option> = None; for i in 1..self.path.pool_count() { - let (flash_path, inside_path) = self.split(i).unwrap(); - if flash_path.can_flash_swap() || inside_path.can_flash_swap() { - sp0 = Some(flash_path); - sp1 = Some(inside_path); + let (head_path, mut tail_path) = self.split(i).unwrap(); + if head_path.can_flash_swap() || tail_path.can_flash_swap() { + if head_path.can_flash_swap() { + tail_path.amount_in = SwapAmountType::::Stack0; + } + sp0 = Some(head_path); + sp1 = Some(tail_path); break; } } if sp0.is_none() || sp1.is_none() { - let (flash_path, inside_path) = self.split(1).unwrap(); - sp0 = Some(flash_path); - sp1 = Some(inside_path); + let (head_path, tail_path) = self.split(1).unwrap(); + sp0 = Some(head_path); + sp1 = Some(tail_path); } let mut step_0 = SwapStep::::new(multicaller); step_0.add(sp0.unwrap()); let mut step_1 = SwapStep::::new(multicaller); - let mut sp1 = sp1.unwrap(); - sp1.amount_in = SwapAmountType::::Balance(multicaller); + let sp1 = sp1.unwrap(); step_1.add(sp1); Some((step_0, step_1)) diff --git a/crates/types/entities/src/swappath.rs b/crates/types/entities/src/swappath.rs index 8d78b99b..fb2a6d14 100644 --- a/crates/types/entities/src/swappath.rs +++ b/crates/types/entities/src/swappath.rs @@ -115,8 +115,8 @@ impl SwapPath { #[derive(Clone, Debug, Default)] pub struct SwapPaths { - paths: HashSet>, - pool_paths: HashMap, HashSet>>, + pub paths: HashSet>, + pub pool_paths: HashMap, HashSet>>, } impl SwapPaths { diff --git a/crates/types/entities/src/swapstep.rs b/crates/types/entities/src/swapstep.rs index f79811f0..a5067880 100644 --- a/crates/types/entities/src/swapstep.rs +++ b/crates/types/entities/src/swapstep.rs @@ -293,6 +293,22 @@ impl SwapStep { ret } + pub fn get_first_pool(&self) -> Option<&PoolWrapper> { + if self.swap_line_vec.len() == 1 { + self.swap_line_vec.first().and_then(|x| x.path.pools.first()) + } else { + None + } + } + + pub fn get_last_pool(&self) -> Option<&PoolWrapper> { + if self.swap_line_vec.len() == 1 { + self.swap_line_vec.first().and_then(|x| x.path.pools.last()) + } else { + None + } + } + pub fn get_first_token(&self) -> Option<&Arc>> { let mut ret: Option<&Arc>> = None; for sp in self.swap_line_vec.iter() { diff --git a/crates/types/events/src/lib.rs b/crates/types/events/src/lib.rs index 6564b68f..0853ffa5 100644 --- a/crates/types/events/src/lib.rs +++ b/crates/types/events/src/lib.rs @@ -5,7 +5,7 @@ pub use message::Message; pub use node::*; pub use state_update_event::*; pub use swap_compose::*; -pub use tasks::Task; +pub use tasks::LoomTask; pub use tx_compose::*; mod best_tx_compose; diff --git a/crates/types/events/src/tasks.rs b/crates/types/events/src/tasks.rs index 61e8f6c0..b5f8a508 100644 --- a/crates/types/events/src/tasks.rs +++ b/crates/types/events/src/tasks.rs @@ -2,7 +2,7 @@ use loom_types_blockchain::{LoomDataTypes, LoomDataTypesEthereum}; use loom_types_entities::{PoolClass, PoolId}; #[derive(Clone, Debug)] -pub enum Task { +pub enum LoomTask { FetchAndAddPools(Vec<(PoolId, PoolClass)>), FetchStateAndAddPools(Vec<(PoolId, PoolClass)>), }