diff --git a/noir/noir-repo/Cargo.lock b/noir/noir-repo/Cargo.lock index d5ce8a105099..3b7c1b6e56ed 100644 --- a/noir/noir-repo/Cargo.lock +++ b/noir/noir-repo/Cargo.lock @@ -411,7 +411,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138985dd8aefbefeaa66b01b7f5b2b6b4c333fcef1cc5f32c63a2aabe37d6de3" dependencies = [ - "futures 0.3.30", + "futures 0.3.28", "lsp-types 0.94.1", "pin-project-lite", "rustix", @@ -967,14 +967,14 @@ checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" [[package]] name = "console" -version = "0.15.8" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" dependencies = [ "encode_unicode 0.3.6", "lazy_static", "libc", - "windows-sys 0.52.0", + "windows-sys 0.45.0", ] [[package]] @@ -1675,6 +1675,15 @@ dependencies = [ "rayon", ] +[[package]] +name = "file-id" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6584280525fb2059cba3db2c04abf947a1a29a45ddae89f3870f8281704fafc9" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "filetime" version = "0.2.22" @@ -1749,6 +1758,15 @@ dependencies = [ "percent-encoding 2.3.0", ] +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + [[package]] name = "funty" version = "2.0.0" @@ -1763,9 +1781,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" dependencies = [ "futures-channel", "futures-core", @@ -1778,9 +1796,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", "futures-sink", @@ -1788,15 +1806,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" dependencies = [ "futures-core", "futures-task", @@ -1806,15 +1824,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", @@ -1823,21 +1841,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ "futures 0.1.31", "futures-channel", @@ -2096,9 +2114,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ "bytes", "futures-channel", @@ -2111,7 +2129,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.4.9", "tokio", "tower-service", "tracing", @@ -2120,9 +2138,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.2" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" dependencies = [ "futures-util", "http", @@ -2290,6 +2308,26 @@ dependencies = [ "str_stack", ] +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags 1.3.2", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + [[package]] name = "instant" version = "0.1.12" @@ -2363,7 +2401,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a" dependencies = [ "derive_more", - "futures 0.3.30", + "futures 0.3.28", "jsonrpc-core", "jsonrpc-pubsub", "log", @@ -2378,7 +2416,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" dependencies = [ - "futures 0.3.30", + "futures 0.3.28", "futures-executor", "futures-util", "log", @@ -2393,7 +2431,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b51da17abecbdab3e3d4f26b01c5ec075e88d3abe3ab3b05dc9aa69392764ec0" dependencies = [ - "futures 0.3.30", + "futures 0.3.28", "jsonrpc-client-transports", ] @@ -2415,7 +2453,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff" dependencies = [ - "futures 0.3.30", + "futures 0.3.28", "hyper", "jsonrpc-core", "jsonrpc-server-utils", @@ -2431,7 +2469,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240f87695e6c6f62fb37f05c02c04953cf68d6408b8c1c89de85c7a0125b1011" dependencies = [ - "futures 0.3.30", + "futures 0.3.28", "jsonrpc-core", "lazy_static", "log", @@ -2447,7 +2485,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" dependencies = [ "bytes", - "futures 0.3.30", + "futures 0.3.28", "globset", "jsonrpc-core", "lazy_static", @@ -2479,6 +2517,26 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "kqueue" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -2503,6 +2561,17 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +[[package]] +name = "libredox" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" +dependencies = [ + "bitflags 2.4.2", + "libc", + "redox_syscall 0.4.1", +] + [[package]] name = "linux-raw-sys" version = "0.4.13" @@ -2659,6 +2728,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", + "log", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.48.0", ] @@ -2727,6 +2797,8 @@ dependencies = [ "noirc_driver", "noirc_errors", "noirc_frontend", + "notify", + "notify-debouncer-full", "paste", "pprof", "predicates 2.1.5", @@ -2738,6 +2810,7 @@ dependencies = [ "similar-asserts", "tempfile", "termcolor", + "termion", "test-binary", "thiserror", "tokio", @@ -3050,6 +3123,39 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" +[[package]] +name = "notify" +version = "6.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" +dependencies = [ + "bitflags 2.4.2", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "log", + "mio", + "walkdir", + "windows-sys 0.48.0", +] + +[[package]] +name = "notify-debouncer-full" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f5dab59c348b9b50cf7f261960a20e389feb2713636399cd9082cd4b536154" +dependencies = [ + "crossbeam-channel", + "file-id", + "log", + "notify", + "parking_lot 0.12.1", + "walkdir", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -3111,6 +3217,12 @@ dependencies = [ "libc", ] +[[package]] +name = "numtoa" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" + [[package]] name = "object" version = "0.31.1" @@ -3670,6 +3782,21 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_termios" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20145670ba436b55d91fc92d25e71160fbfbdd57831631c8d7d36377a476f1cb" + [[package]] name = "redox_users" version = "0.4.3" @@ -4432,6 +4559,16 @@ dependencies = [ "serde", ] +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "socket2" version = "0.5.5" @@ -4608,6 +4745,18 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "termion" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "417813675a504dfbbf21bfde32c03e5bf9f2413999962b479023c02848c1c7a5" +dependencies = [ + "libc", + "libredox", + "numtoa", + "redox_termios", +] + [[package]] name = "termtree" version = "0.4.1" @@ -4743,7 +4892,7 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", - "socket2", + "socket2 0.5.5", "tokio-macros", "windows-sys 0.48.0", ] @@ -5490,6 +5639,15 @@ dependencies = [ "windows_x86_64_msvc 0.33.0", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -5508,6 +5666,21 @@ dependencies = [ "windows-targets 0.52.4", ] +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-targets" version = "0.48.1" @@ -5538,6 +5711,12 @@ dependencies = [ "windows_x86_64_msvc 0.52.4", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" @@ -5556,6 +5735,12 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd761fd3eb9ab8cc1ed81e56e567f02dd82c4c837e48ac3b2181b9ffc5060807" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.48.0" @@ -5574,6 +5759,12 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cab0cf703a96bab2dc0c02c0fa748491294bf9b7feb27e1f4f96340f208ada0e" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.48.0" @@ -5592,6 +5783,12 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cfdbe89cc9ad7ce618ba34abc34bbb6c36d99e96cae2245b7943cd75ee773d0" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.48.0" @@ -5610,6 +5807,12 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4dd9b0c0e9ece7bb22e84d70d01b71c6d6248b81a3c60d11869451b4cb24784" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.48.0" @@ -5622,6 +5825,12 @@ version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" @@ -5640,6 +5849,12 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff1e4aa646495048ec7f3ffddc411e1d829c026a2ec62b39da15c1055e406eaa" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.48.0" diff --git a/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs b/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs index 4f8f3f19ab8e..fd538dc578bc 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs @@ -7,7 +7,7 @@ use noirc_frontend::{ }, macros_api::{FileId, HirContext, MacroError}, node_interner::FuncId, - parse_program, FunctionReturnType, NoirFunction, UnresolvedTypeData, + parse_program, FunctionReturnType, ItemVisibility, NoirFunction, UnresolvedTypeData, }; use crate::utils::hir_utils::fetch_struct_trait_impls; @@ -113,7 +113,7 @@ pub fn inject_compute_note_hash_and_nullifier( context.def_map_mut(crate_id).unwrap() .modules_mut()[module_id.0] .declare_function( - func.name_ident().clone(), func_id + func.name_ident().clone(), ItemVisibility::Public, func_id ).expect( "Failed to declare the autogenerated compute_note_hash_and_nullifier function, likely due to a duplicate definition. See https://github.com/AztecProtocol/aztec-packages/issues/4647." ); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index ef52533b5239..5b6610df7b47 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -227,9 +227,7 @@ impl<'block> BrilligBlock<'block> { dfg, ); } - _ => { - todo!("ICE: Param type not supported") - } + Type::Function => todo!("ICE: Type::Function Param not supported"), } } } @@ -658,7 +656,7 @@ impl<'block> BrilligBlock<'block> { let rc_register = match self.convert_ssa_value(*value, dfg) { BrilligVariable::BrilligArray(BrilligArray { rc, .. }) | BrilligVariable::BrilligVector(BrilligVector { rc, .. }) => rc, - _ => unreachable!("ICE: increment rc on non-array"), + other => unreachable!("ICE: increment rc on non-array: {other:?}"), }; self.brillig_context.codegen_usize_op_in_place( rc_register, @@ -666,7 +664,21 @@ impl<'block> BrilligBlock<'block> { 1, ); } - _ => todo!("ICE: Instruction not supported {instruction:?}"), + Instruction::DecrementRc { value } => { + let rc_register = match self.convert_ssa_value(*value, dfg) { + BrilligVariable::BrilligArray(BrilligArray { rc, .. }) + | BrilligVariable::BrilligVector(BrilligVector { rc, .. }) => rc, + other => unreachable!("ICE: decrement rc on non-array: {other:?}"), + }; + self.brillig_context.codegen_usize_op_in_place( + rc_register, + BrilligBinaryOp::Sub, + 1, + ); + } + Instruction::EnableSideEffects { .. } => { + todo!("enable_side_effects not supported by brillig") + } }; let dead_variables = self diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 140ed0b53ff5..4442efe286a5 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -503,7 +503,7 @@ impl Context { Instruction::Load { .. } => { unreachable!("Expected all load instructions to be removed before acir_gen") } - Instruction::IncrementRc { .. } => { + Instruction::IncrementRc { .. } | Instruction::DecrementRc { .. } => { // Do nothing. Only Brillig needs to worry about reference counted arrays } Instruction::RangeCheck { value, max_bit_size, assert_message } => { diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs index bf34a47485bb..2c39c83b3422 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs @@ -384,6 +384,20 @@ impl FunctionBuilder { /// within the given value. If the given value is not an array and does not contain /// any arrays, this does nothing. pub(crate) fn increment_array_reference_count(&mut self, value: ValueId) { + self.update_array_reference_count(value, true); + } + + /// Insert instructions to decrement the reference count of any array(s) stored + /// within the given value. If the given value is not an array and does not contain + /// any arrays, this does nothing. + pub(crate) fn decrement_array_reference_count(&mut self, value: ValueId) { + self.update_array_reference_count(value, false); + } + + /// Increment or decrement the given value's reference count if it is an array. + /// If it is not an array, this does nothing. Note that inc_rc and dec_rc instructions + /// are ignored outside of unconstrained code. + pub(crate) fn update_array_reference_count(&mut self, value: ValueId, increment: bool) { match self.type_of_value(value) { Type::Numeric(_) => (), Type::Function => (), @@ -396,7 +410,12 @@ impl FunctionBuilder { typ @ Type::Array(..) | typ @ Type::Slice(..) => { // If there are nested arrays or slices, we wait until ArrayGet // is issued to increment the count of that array. - self.insert_instruction(Instruction::IncrementRc { value }, None); + let instruction = if increment { + Instruction::IncrementRc { value } + } else { + Instruction::DecrementRc { value } + }; + self.insert_instruction(instruction, None); // This is a bit odd, but in brillig the inc_rc instruction operates on // a copy of the array's metadata, so we need to re-store a loaded array diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs index 0b6c7074e45d..afade4b06169 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs @@ -194,6 +194,13 @@ pub(crate) enum Instruction { /// implemented via reference counting. In ACIR code this is done with im::Vector and these /// IncrementRc instructions are ignored. IncrementRc { value: ValueId }, + + /// An instruction to decrement the reference count of a value. + /// + /// This currently only has an effect in Brillig code where array sharing and copy on write is + /// implemented via reference counting. In ACIR code this is done with im::Vector and these + /// DecrementRc instructions are ignored. + DecrementRc { value: ValueId }, } impl Instruction { @@ -214,6 +221,7 @@ impl Instruction { Instruction::Constrain(..) | Instruction::Store { .. } | Instruction::IncrementRc { .. } + | Instruction::DecrementRc { .. } | Instruction::RangeCheck { .. } | Instruction::EnableSideEffects { .. } => InstructionResultType::None, Instruction::Allocate { .. } @@ -250,6 +258,7 @@ impl Instruction { | Load { .. } | Store { .. } | IncrementRc { .. } + | DecrementRc { .. } | RangeCheck { .. } => false, Call { func, .. } => match dfg[*func] { @@ -285,6 +294,7 @@ impl Instruction { | Store { .. } | EnableSideEffects { .. } | IncrementRc { .. } + | DecrementRc { .. } | RangeCheck { .. } => true, // Some `Intrinsic`s have side effects so we must check what kind of `Call` this is. @@ -353,6 +363,7 @@ impl Instruction { Instruction::ArraySet { array: f(*array), index: f(*index), value: f(*value) } } Instruction::IncrementRc { value } => Instruction::IncrementRc { value: f(*value) }, + Instruction::DecrementRc { value } => Instruction::DecrementRc { value: f(*value) }, Instruction::RangeCheck { value, max_bit_size, assert_message } => { Instruction::RangeCheck { value: f(*value), @@ -409,7 +420,9 @@ impl Instruction { Instruction::EnableSideEffects { condition } => { f(*condition); } - Instruction::IncrementRc { value } | Instruction::RangeCheck { value, .. } => { + Instruction::IncrementRc { value } + | Instruction::DecrementRc { value } + | Instruction::RangeCheck { value, .. } => { f(*value); } } @@ -554,6 +567,7 @@ impl Instruction { Instruction::Load { .. } => None, Instruction::Store { .. } => None, Instruction::IncrementRc { .. } => None, + Instruction::DecrementRc { .. } => None, Instruction::RangeCheck { value, max_bit_size, .. } => { if let Some(numeric_constant) = dfg.get_numeric_constant(*value) { if numeric_constant.num_bits() < *max_bit_size { diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/printer.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/printer.rs index 9bd43fab1ff5..6ef618fba6fe 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/printer.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/printer.rs @@ -188,6 +188,9 @@ fn display_instruction_inner( Instruction::IncrementRc { value } => { writeln!(f, "inc_rc {}", show(*value)) } + Instruction::DecrementRc { value } => { + writeln!(f, "dec_rc {}", show(*value)) + } Instruction::RangeCheck { value, max_bit_size, .. } => { writeln!(f, "range_check {} to {} bits", show(*value), *max_bit_size,) } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/die.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/die.rs index f7d8adb52757..4c7beff0fbe7 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/die.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/die.rs @@ -44,7 +44,7 @@ fn dead_instruction_elimination(function: &mut Function) { context.remove_unused_instructions_in_block(function, *block); } - context.remove_increment_rc_instructions(&mut function.dfg); + context.remove_rc_instructions(&mut function.dfg); } /// Per function context for tracking unused values and which instructions to remove. @@ -53,10 +53,10 @@ struct Context { used_values: HashSet, instructions_to_remove: HashSet, - /// IncrementRc instructions must be revisited after the main DIE pass since + /// IncrementRc & DecrementRc instructions must be revisited after the main DIE pass since /// they technically contain side-effects but we still want to remove them if their /// `value` parameter is not used elsewhere. - increment_rc_instructions: Vec<(InstructionId, BasicBlockId)>, + rc_instructions: Vec<(InstructionId, BasicBlockId)>, } impl Context { @@ -85,8 +85,9 @@ impl Context { } else { let instruction = &function.dfg[*instruction_id]; - if let Instruction::IncrementRc { .. } = instruction { - self.increment_rc_instructions.push((*instruction_id, block_id)); + use Instruction::*; + if matches!(instruction, IncrementRc { .. } | DecrementRc { .. }) { + self.rc_instructions.push((*instruction_id, block_id)); } else { instruction.for_each_value(|value| { self.mark_used_instruction_results(&function.dfg, value); @@ -145,16 +146,19 @@ impl Context { } } - fn remove_increment_rc_instructions(self, dfg: &mut DataFlowGraph) { - for (increment_rc, block) in self.increment_rc_instructions { - let value = match &dfg[increment_rc] { + fn remove_rc_instructions(self, dfg: &mut DataFlowGraph) { + for (rc, block) in self.rc_instructions { + let value = match &dfg[rc] { Instruction::IncrementRc { value } => *value, - other => unreachable!("Expected IncrementRc instruction, found {other:?}"), + Instruction::DecrementRc { value } => *value, + other => { + unreachable!("Expected IncrementRc or DecrementRc instruction, found {other:?}") + } }; - // This could be more efficient if we have to remove multiple IncrementRcs in a single block + // This could be more efficient if we have to remove multiple instructions in a single block if !self.used_values.contains(&value) { - dfg[block].instructions_mut().retain(|instruction| *instruction != increment_rc); + dfg[block].instructions_mut().retain(|instruction| *instruction != rc); } } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs index 9c760c013a9e..409b99958a91 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs @@ -10,6 +10,7 @@ use noirc_frontend::{BinaryOpKind, Signedness}; use crate::errors::RuntimeError; use crate::ssa::function_builder::FunctionBuilder; +use crate::ssa::ir::basic_block::BasicBlockId; use crate::ssa::ir::dfg::DataFlowGraph; use crate::ssa::ir::function::FunctionId as IrFunctionId; use crate::ssa::ir::function::{Function, RuntimeType}; @@ -1022,6 +1023,36 @@ impl<'a> FunctionContext<'a> { } } } + + /// Increments the reference count of all parameters. Returns the entry block of the function. + /// + /// This is done on parameters rather than call arguments so that we can optimize out + /// paired inc/dec instructions within brillig functions more easily. + pub(crate) fn increment_parameter_rcs(&mut self) -> BasicBlockId { + let entry = self.builder.current_function.entry_block(); + let parameters = self.builder.current_function.dfg.block_parameters(entry).to_vec(); + + for parameter in parameters { + self.builder.increment_array_reference_count(parameter); + } + + entry + } + + /// Ends a local scope of a function. + /// This will issue DecrementRc instructions for any arrays in the given starting scope + /// block's parameters. Arrays that are also used in terminator instructions for the scope are + /// ignored. + pub(crate) fn end_scope(&mut self, scope: BasicBlockId, terminator_args: &[ValueId]) { + let mut dropped_parameters = + self.builder.current_function.dfg.block_parameters(scope).to_vec(); + + dropped_parameters.retain(|parameter| !terminator_args.contains(parameter)); + + for parameter in dropped_parameters { + self.builder.decrement_array_reference_count(parameter); + } + } } /// True if the given operator cannot be encoded directly and needs diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs index f3fa5d1d2f87..3d8ae0bb3eb2 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs @@ -121,8 +121,11 @@ impl<'a> FunctionContext<'a> { /// Codegen a function's body and set its return value to that of its last parameter. /// For functions returning nothing, this will be an empty list. fn codegen_function_body(&mut self, body: &Expression) -> Result<(), RuntimeError> { + let entry_block = self.increment_parameter_rcs(); let return_value = self.codegen_expression(body)?; let results = return_value.into_value_list(self); + self.end_scope(entry_block, &results); + self.builder.terminate_with_return(results); Ok(()) } @@ -595,10 +598,8 @@ impl<'a> FunctionContext<'a> { arguments.append(&mut values); } - // If an array is passed as an argument we increase its reference count - for argument in &arguments { - self.builder.increment_array_reference_count(*argument); - } + // Don't need to increment array reference counts when passed in as arguments + // since it is done within the function to each parameter already. self.codegen_intrinsic_call_checks(function, &arguments, call.location); Ok(self.insert_call(function, arguments, &call.return_type, call.location)) diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index ae99e61e5342..5adb9eb5b7e1 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -10,8 +10,8 @@ use crate::{ macros_api::MacroProcessor, node_interner::{FunctionModifiers, TraitId, TypeAliasId}, parser::{SortedModule, SortedSubModule}, - FunctionDefinition, Ident, LetStatement, ModuleDeclaration, NoirFunction, NoirStruct, - NoirTrait, NoirTraitImpl, NoirTypeAlias, TraitImplItem, TraitItem, TypeImpl, + FunctionDefinition, Ident, ItemVisibility, LetStatement, ModuleDeclaration, NoirFunction, + NoirStruct, NoirTrait, NoirTraitImpl, NoirTypeAlias, TraitImplItem, TraitItem, TypeImpl, }; use super::{ @@ -232,6 +232,7 @@ impl<'a> ModCollector<'a> { let name = function.name_ident().clone(); let func_id = context.def_interner.push_empty_fn(); + let visibility = function.def.visibility; // First create dummy function in the DefInterner // So that we can get a FuncId @@ -248,7 +249,7 @@ impl<'a> ModCollector<'a> { // Add function to scope/ns of the module let result = self.def_collector.def_map.modules[self.module_id.0] - .declare_function(name, func_id); + .declare_function(name, visibility, func_id); if let Err((first_def, second_def)) = result { let error = DefCollectorErrorKind::Duplicate { @@ -407,7 +408,7 @@ impl<'a> ModCollector<'a> { let modifiers = FunctionModifiers { name: name.to_string(), - visibility: crate::ItemVisibility::Public, + visibility: ItemVisibility::Public, // TODO(Maddiaa): Investigate trait implementations with attributes see: https://github.com/noir-lang/noir/issues/2629 attributes: crate::token::Attributes::empty(), is_unconstrained: false, @@ -419,7 +420,7 @@ impl<'a> ModCollector<'a> { .push_function_definition(func_id, modifiers, trait_id.0, location); match self.def_collector.def_map.modules[trait_id.0.local_id.0] - .declare_function(name.clone(), func_id) + .declare_function(name.clone(), ItemVisibility::Public, func_id) { Ok(()) => { if let Some(body) = body { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/item_scope.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/item_scope.rs index 178b91e1e840..cd4eafdf6699 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/item_scope.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/item_scope.rs @@ -19,10 +19,11 @@ impl ItemScope { pub fn add_definition( &mut self, name: Ident, + visibility: ItemVisibility, mod_def: ModuleDefId, trait_id: Option, ) -> Result<(), (Ident, Ident)> { - self.add_item_to_namespace(name, mod_def, trait_id, false)?; + self.add_item_to_namespace(name, visibility, mod_def, trait_id, false)?; self.defs.push(mod_def); Ok(()) } @@ -33,6 +34,7 @@ impl ItemScope { pub fn add_item_to_namespace( &mut self, name: Ident, + visibility: ItemVisibility, mod_def: ModuleDefId, trait_id: Option, is_prelude: bool, @@ -41,6 +43,11 @@ impl ItemScope { if let Entry::Occupied(mut o) = map.entry(name.clone()) { let trait_hashmap = o.get_mut(); if let Entry::Occupied(mut n) = trait_hashmap.entry(trait_id) { + // Generally we want to reject having two of the same ident in the same namespace. + // The exception to this is when we're explicitly importing something + // which exists in the Noir stdlib prelude. + // + // In this case we ignore the prelude and favour the explicit import. let is_prelude = std::mem::replace(&mut n.get_mut().2, is_prelude); let old_ident = o.key(); @@ -50,12 +57,12 @@ impl ItemScope { Err((old_ident.clone(), name)) } } else { - trait_hashmap.insert(trait_id, (mod_def, ItemVisibility::Public, is_prelude)); + trait_hashmap.insert(trait_id, (mod_def, visibility, is_prelude)); Ok(()) } } else { let mut trait_hashmap = HashMap::new(); - trait_hashmap.insert(trait_id, (mod_def, ItemVisibility::Public, is_prelude)); + trait_hashmap.insert(trait_id, (mod_def, visibility, is_prelude)); map.insert(name, trait_hashmap); Ok(()) } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/module_data.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/module_data.rs index 309618dd0115..4dd38f0e3e57 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/module_data.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/module_data.rs @@ -4,7 +4,7 @@ use noirc_errors::Location; use crate::{ node_interner::{FuncId, GlobalId, StructId, TraitId, TypeAliasId}, - Ident, + Ident, ItemVisibility, }; use super::{ItemScope, LocalModuleId, ModuleDefId, ModuleId, PerNs}; @@ -48,18 +48,24 @@ impl ModuleData { fn declare( &mut self, name: Ident, + visibility: ItemVisibility, item_id: ModuleDefId, trait_id: Option, ) -> Result<(), (Ident, Ident)> { - self.scope.add_definition(name.clone(), item_id, trait_id)?; + self.scope.add_definition(name.clone(), visibility, item_id, trait_id)?; // definitions is a subset of self.scope so it is expected if self.scope.define_func_def // returns without error, so will self.definitions.define_func_def. - self.definitions.add_definition(name, item_id, trait_id) + self.definitions.add_definition(name, visibility, item_id, trait_id) } - pub fn declare_function(&mut self, name: Ident, id: FuncId) -> Result<(), (Ident, Ident)> { - self.declare(name, id.into(), None) + pub fn declare_function( + &mut self, + name: Ident, + visibility: ItemVisibility, + id: FuncId, + ) -> Result<(), (Ident, Ident)> { + self.declare(name, visibility, id.into(), None) } pub fn declare_trait_function( @@ -68,7 +74,7 @@ impl ModuleData { id: FuncId, trait_id: TraitId, ) -> Result<(), (Ident, Ident)> { - self.declare(name, id.into(), Some(trait_id)) + self.declare(name, ItemVisibility::Public, id.into(), Some(trait_id)) } pub fn remove_function(&mut self, name: &Ident) { @@ -77,11 +83,11 @@ impl ModuleData { } pub fn declare_global(&mut self, name: Ident, id: GlobalId) -> Result<(), (Ident, Ident)> { - self.declare(name, id.into(), None) + self.declare(name, ItemVisibility::Public, id.into(), None) } pub fn declare_struct(&mut self, name: Ident, id: StructId) -> Result<(), (Ident, Ident)> { - self.declare(name, ModuleDefId::TypeId(id), None) + self.declare(name, ItemVisibility::Public, ModuleDefId::TypeId(id), None) } pub fn declare_type_alias( @@ -89,11 +95,11 @@ impl ModuleData { name: Ident, id: TypeAliasId, ) -> Result<(), (Ident, Ident)> { - self.declare(name, id.into(), None) + self.declare(name, ItemVisibility::Public, id.into(), None) } pub fn declare_trait(&mut self, name: Ident, id: TraitId) -> Result<(), (Ident, Ident)> { - self.declare(name, ModuleDefId::TraitId(id), None) + self.declare(name, ItemVisibility::Public, ModuleDefId::TraitId(id), None) } pub fn declare_child_module( @@ -101,7 +107,7 @@ impl ModuleData { name: Ident, child_id: ModuleId, ) -> Result<(), (Ident, Ident)> { - self.declare(name, child_id.into(), None) + self.declare(name, ItemVisibility::Public, child_id.into(), None) } pub fn find_func_with_name(&self, name: &Ident) -> Option { @@ -114,7 +120,7 @@ impl ModuleData { id: ModuleDefId, is_prelude: bool, ) -> Result<(), (Ident, Ident)> { - self.scope.add_item_to_namespace(name, id, None, is_prelude) + self.scope.add_item_to_namespace(name, ItemVisibility::Public, id, None, is_prelude) } pub fn find_name(&self, name: &Ident) -> PerNs { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/impls.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/impls.rs index 4aa70f00cfc2..72f6adc37706 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/impls.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/impls.rs @@ -13,7 +13,7 @@ use crate::{ Context, }, node_interner::{FuncId, NodeInterner}, - Type, + ItemVisibility, Type, }; use super::{ @@ -67,7 +67,14 @@ pub(crate) fn collect_impls( // be accessed with the `TypeName::method` syntax. We'll check later whether the // object types in each method overlap or not. If they do, we issue an error. // If not, that is specialization which is allowed. - if module.declare_function(method.name_ident().clone(), *method_id).is_err() { + if module + .declare_function( + method.name_ident().clone(), + ItemVisibility::Public, + *method_id, + ) + .is_err() + { module.remove_function(method.name_ident()); } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 00b1b443430e..c33b83257b08 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -37,11 +37,11 @@ use crate::{ StatementKind, }; use crate::{ - ArrayLiteral, Distinctness, ForRange, FunctionDefinition, FunctionReturnType, Generics, - ItemVisibility, LValue, NoirStruct, NoirTypeAlias, Param, Path, PathKind, Pattern, Shared, - StructType, Type, TypeAlias, TypeVariable, TypeVariableKind, UnaryOp, UnresolvedGenerics, - UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression, - Visibility, ERROR_IDENT, + ArrayLiteral, BinaryOpKind, Distinctness, ForRange, FunctionDefinition, FunctionReturnType, + Generics, ItemVisibility, LValue, NoirStruct, NoirTypeAlias, Param, Path, PathKind, Pattern, + Shared, StructType, Type, TypeAlias, TypeVariable, TypeVariableKind, UnaryOp, + UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, + UnresolvedTypeExpression, Visibility, ERROR_IDENT, }; use fm::FileId; use iter_extended::vecmap; @@ -1943,10 +1943,65 @@ impl<'a> Resolver<'a> { rhs: ExprId, span: Span, ) -> Result> { + // Arbitrary amount of recursive calls to try before giving up + let fuel = 100; + self.try_eval_array_length_id_with_fuel(rhs, span, fuel) + } + + fn try_eval_array_length_id_with_fuel( + &self, + rhs: ExprId, + span: Span, + fuel: u32, + ) -> Result> { + if fuel == 0 { + // If we reach here, it is likely from evaluating cyclic globals. We expect an error to + // be issued for them after name resolution so issue no error now. + return Err(None); + } + match self.interner.expression(&rhs) { HirExpression::Literal(HirLiteral::Integer(int, false)) => { int.try_into_u128().ok_or(Some(ResolverError::IntegerTooLarge { span })) } + HirExpression::Ident(ident) => { + let definition = self.interner.definition(ident.id); + match definition.kind { + DefinitionKind::Global(global_id) => { + let let_statement = self.interner.get_global_let_statement(global_id); + if let Some(let_statement) = let_statement { + let expression = let_statement.expression; + self.try_eval_array_length_id_with_fuel(expression, span, fuel - 1) + } else { + Err(Some(ResolverError::InvalidArrayLengthExpr { span })) + } + } + _ => Err(Some(ResolverError::InvalidArrayLengthExpr { span })), + } + } + HirExpression::Infix(infix) => { + let lhs = self.try_eval_array_length_id_with_fuel(infix.lhs, span, fuel - 1)?; + let rhs = self.try_eval_array_length_id_with_fuel(infix.rhs, span, fuel - 1)?; + + match infix.operator.kind { + BinaryOpKind::Add => Ok(lhs + rhs), + BinaryOpKind::Subtract => Ok(lhs - rhs), + BinaryOpKind::Multiply => Ok(lhs * rhs), + BinaryOpKind::Divide => Ok(lhs / rhs), + BinaryOpKind::Equal => Ok((lhs == rhs) as u128), + BinaryOpKind::NotEqual => Ok((lhs != rhs) as u128), + BinaryOpKind::Less => Ok((lhs < rhs) as u128), + BinaryOpKind::LessEqual => Ok((lhs <= rhs) as u128), + BinaryOpKind::Greater => Ok((lhs > rhs) as u128), + BinaryOpKind::GreaterEqual => Ok((lhs >= rhs) as u128), + BinaryOpKind::And => Ok(lhs & rhs), + BinaryOpKind::Or => Ok(lhs | rhs), + BinaryOpKind::Xor => Ok(lhs ^ rhs), + BinaryOpKind::ShiftRight => Ok(lhs >> rhs), + BinaryOpKind::ShiftLeft => Ok(lhs << rhs), + BinaryOpKind::Modulo => Ok(lhs % rhs), + } + } _other => Err(Some(ResolverError::InvalidArrayLengthExpr { span })), } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs index 5d546954f0d9..04da558a6428 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs @@ -16,7 +16,7 @@ use crate::{ }, hir_def::traits::{TraitConstant, TraitFunction, TraitImpl, TraitType}, node_interner::{FuncId, NodeInterner, TraitId}, - Generics, Path, Shared, TraitItem, Type, TypeVariable, TypeVariableKind, + Generics, ItemVisibility, Path, Shared, TraitItem, Type, TypeVariable, TypeVariableKind, }; use super::{ @@ -301,7 +301,14 @@ fn collect_trait_impl( // be accessed with the `TypeName::method` syntax. We'll check later whether the // object types in each method overlap or not. If they do, we issue an error. // If not, that is specialization which is allowed. - if module.declare_function(method.name_ident().clone(), *method_id).is_err() { + if module + .declare_function( + method.name_ident().clone(), + ItemVisibility::Public, + *method_id, + ) + .is_err() + { module.remove_function(method.name_ident()); } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs index 5ab036eef5bf..60bc5b2470fc 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs @@ -127,11 +127,7 @@ impl Type { let fields = struct_type.get_fields(args); fields.iter().fold(0, |acc, (_, field_type)| acc + field_type.field_count()) } - Type::Alias(def, _) => { - // It is safe to access `typ` without instantiating generics here since generics - // cannot change the number of fields in `typ`. - def.borrow().typ.field_count() - } + Type::Alias(def, generics) => def.borrow().get_type(generics).field_count(), Type::Tuple(fields) => { fields.iter().fold(0, |acc, field_typ| acc + field_typ.field_count()) } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/tests.rs b/noir/noir-repo/compiler/noirc_frontend/src/tests.rs index 3f78bd43ba9b..b8ed6fb73d23 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/tests.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/tests.rs @@ -1213,4 +1213,26 @@ fn lambda$f1(mut env$l1: (Field)) -> Field { "#; assert_eq!(get_program_errors(src).len(), 0); } + + #[test] + fn operators_in_global_used_in_type() { + let src = r#" + global ONE = 1; + global COUNT = ONE + 2; + fn main() { + let _array: [Field; COUNT] = [1, 2, 3]; + } + "#; + assert_eq!(get_program_errors(src).len(), 0); + } + + // Regression for #4545 + #[test] + fn type_aliases_in_main() { + let src = r#" + type Outer = [u8; N]; + fn main(_arg: Outer<1>) {} + "#; + assert_eq!(get_program_errors(src).len(), 0); + } } diff --git a/noir/noir-repo/cspell.json b/noir/noir-repo/cspell.json index d961b600f40a..8cfc5e695a2e 100644 --- a/noir/noir-repo/cspell.json +++ b/noir/noir-repo/cspell.json @@ -52,6 +52,7 @@ "csat", "curvegroup", "databus", + "debouncer", "deflater", "deflatten", "deflattened", @@ -139,6 +140,7 @@ "plonkc", "PLONKish", "pprof", + "preimage", "preprocess", "prettytable", "printstd", diff --git a/noir/noir-repo/deny.toml b/noir/noir-repo/deny.toml index 578f84272637..eff233687e8e 100644 --- a/noir/noir-repo/deny.toml +++ b/noir/noir-repo/deny.toml @@ -69,6 +69,7 @@ exceptions = [ # https://tldrlegal.com/license/creative-commons-cc0-1.0-universal { allow = ["CC0-1.0"], name = "more-asserts" }, { allow = ["CC0-1.0"], name = "jsonrpc" }, + { allow = ["CC0-1.0"], name = "notify" }, { allow = ["MPL-2.0"], name = "sized-chunks" }, { allow = ["MPL-2.0"], name = "webpki-roots" }, diff --git a/noir/noir-repo/noir_stdlib/src/array.nr b/noir/noir-repo/noir_stdlib/src/array.nr index 3da4b6491744..baa4bef50ccd 100644 --- a/noir/noir-repo/noir_stdlib/src/array.nr +++ b/noir/noir-repo/noir_stdlib/src/array.nr @@ -1,4 +1,4 @@ -use crate::cmp::{Ord}; +use crate::cmp::Ord; // TODO: Once we fully move to the new SSA pass this module can be removed and replaced // by the methods in the `slice` module diff --git a/noir/noir-repo/noir_stdlib/src/hash.nr b/noir/noir-repo/noir_stdlib/src/hash.nr index fcf21436197b..896dae153711 100644 --- a/noir/noir-repo/noir_stdlib/src/hash.nr +++ b/noir/noir-repo/noir_stdlib/src/hash.nr @@ -4,6 +4,7 @@ mod poseidon2; mod pedersen; use crate::default::Default; +use crate::uint128::U128; #[foreign(sha256)] // docs:start:sha256 @@ -120,10 +121,102 @@ where } } -// TODO: add implementations for the remainder of primitive types. -impl Hash for Field{ +impl Hash for Field { fn hash(self, state: &mut H) where H: Hasher{ - let input: [Field] = [self]; - H::write(state, input); + H::write(state, [self]); + } +} + +impl Hash for u8 { + fn hash(self, state: &mut H) where H: Hasher{ + H::write(state, [self as Field]); + } +} + +impl Hash for u32 { + fn hash(self, state: &mut H) where H: Hasher{ + H::write(state, [self as Field]); + } +} + +impl Hash for u64 { + fn hash(self, state: &mut H) where H: Hasher{ + H::write(state, [self as Field]); + } +} + +impl Hash for i8 { + fn hash(self, state: &mut H) where H: Hasher{ + H::write(state, [self as Field]); + } +} + +impl Hash for i32 { + fn hash(self, state: &mut H) where H: Hasher{ + H::write(state, [self as Field]); + } +} + +impl Hash for i64 { + fn hash(self, state: &mut H) where H: Hasher{ + H::write(state, [self as Field]); + } +} + +impl Hash for bool { + fn hash(self, state: &mut H) where H: Hasher{ + H::write(state, [self as Field]); + } +} + +impl Hash for () { + fn hash(_self: Self, _state: &mut H) where H: Hasher {} +} + +impl Hash for U128 { + fn hash(self, state: &mut H) where H: Hasher{ + H::write(state, [self.lo as Field, self.hi as Field]); + } +} + +impl Hash for [T; N] where T: Hash { + fn hash(self, state: &mut H) where H: Hasher{ + for elem in self { + elem.hash(state); + } + } +} + +impl Hash for (A, B) where A: Hash, B: Hash { + fn hash(self, state: &mut H) where H: Hasher{ + self.0.hash(state); + self.1.hash(state); + } +} + +impl Hash for (A, B, C) where A: Hash, B: Hash, C: Hash { + fn hash(self, state: &mut H) where H: Hasher{ + self.0.hash(state); + self.1.hash(state); + self.2.hash(state); + } +} + +impl Hash for (A, B, C, D) where A: Hash, B: Hash, C: Hash, D: Hash { + fn hash(self, state: &mut H) where H: Hasher{ + self.0.hash(state); + self.1.hash(state); + self.2.hash(state); + self.3.hash(state); + } +} + +impl Hash for (A, B, C, D, E) where A: Hash, B: Hash, C: Hash, D: Hash, E: Hash { + fn hash(self, state: &mut H) where H: Hasher{ + self.0.hash(state); + self.1.hash(state); + self.2.hash(state); + self.3.hash(state); + self.4.hash(state); } } diff --git a/noir/noir-repo/noir_stdlib/src/sha256.nr b/noir/noir-repo/noir_stdlib/src/sha256.nr index 2f686a64165b..8ca6808568d2 100644 --- a/noir/noir-repo/noir_stdlib/src/sha256.nr +++ b/noir/noir-repo/noir_stdlib/src/sha256.nr @@ -6,9 +6,11 @@ fn msg_u8_to_u32(msg: [u8; 64]) -> [u32; 16] { let mut msg32: [u32; 16] = [0; 16]; for i in 0..16 { + let mut msg_field: Field = 0; for j in 0..4 { - msg32[15 - i] = (msg32[15 - i] << 8) + msg[64 - 4*(i + 1) + j] as u32; + msg_field = msg_field * 256 + msg[64 - 4*(i + 1) + j] as Field; } + msg32[15 - i] = msg_field as u32; } msg32 @@ -21,7 +23,7 @@ pub fn digest(msg: [u8; N]) -> [u8; 32] { let mut i: u64 = 0; // Message byte pointer for k in 0..N { // Populate msg_block - msg_block[i as Field] = msg[k]; + msg_block[i] = msg[k]; i = i + 1; if i == 64 { // Enough to hash block @@ -32,7 +34,7 @@ pub fn digest(msg: [u8; N]) -> [u8; 32] { } // Pad the rest such that we have a [u32; 2] block at the end representing the length // of the message, and a block of 1 0 ... 0 following the message (i.e. [1 << 7, 0, ..., 0]). - msg_block[i as Field] = 1 << 7; + msg_block[i] = 1 << 7; i = i + 1; // If i >= 57, there aren't enough bits in the current message block to accomplish this, so // the 1 and 0s fill up the current block, which we then compress accordingly. @@ -41,7 +43,7 @@ pub fn digest(msg: [u8; N]) -> [u8; 32] { if i < 64 { for _i in 57..64 { if i <= 63 { - msg_block[i as Field] = 0; + msg_block[i] = 0; i += 1; } } @@ -51,16 +53,16 @@ pub fn digest(msg: [u8; N]) -> [u8; 32] { i = 0; } + let len = 8 * msg.len(); + let len_bytes = (len as Field).to_le_bytes(8); for _i in 0..64 { // In any case, fill blocks up with zeros until the last 64 (i.e. until i = 56). if i < 56 { - msg_block[i as Field] = 0; + msg_block[i] = 0; i = i + 1; } else if i < 64 { - let mut len = 8 * msg.len(); for j in 0..8 { - msg_block[63 - j] = len as u8; - len >>= 8; + msg_block[63 - j] = len_bytes[j]; } i += 8; } @@ -70,9 +72,9 @@ pub fn digest(msg: [u8; N]) -> [u8; 32] { // Return final hash as byte array for j in 0..8 { + let h_bytes = (h[7 - j] as Field).to_le_bytes(4); for k in 0..4 { - out_h[31 - 4*j - k] = h[7 - j] as u8; - h[7-j] >>= 8; + out_h[31 - 4*j - k] = h_bytes[k]; } } diff --git a/noir/noir-repo/noir_stdlib/src/sha512.nr b/noir/noir-repo/noir_stdlib/src/sha512.nr index 4dfe78308e2b..a766ae50d559 100644 --- a/noir/noir-repo/noir_stdlib/src/sha512.nr +++ b/noir/noir-repo/noir_stdlib/src/sha512.nr @@ -77,9 +77,11 @@ fn msg_u8_to_u64(msg: [u8; 128]) -> [u64; 16] { let mut msg64: [u64; 16] = [0; 16]; for i in 0..16 { + let mut msg_field: Field = 0; for j in 0..8 { - msg64[15 - i] = (msg64[15 - i] << 8) + msg[128 - 8*(i + 1) + j] as u64; + msg_field = msg_field * 256 + msg[128 - 8*(i + 1) + j] as Field; } + msg64[15 - i] = msg_field as u64; } msg64 @@ -94,7 +96,7 @@ pub fn digest(msg: [u8; N]) -> [u8; 64] { let mut i: u64 = 0; // Message byte pointer for k in 0..msg.len() { // Populate msg_block - msg_block[i as Field] = msg[k]; + msg_block[i] = msg[k]; i = i + 1; if i == 128 { // Enough to hash block @@ -108,7 +110,7 @@ pub fn digest(msg: [u8; N]) -> [u8; 64] { } // Pad the rest such that we have a [u64; 2] block at the end representing the length // of the message, and a block of 1 0 ... 0 following the message (i.e. [1 << 7, 0, ..., 0]). - msg_block[i as Field] = 1 << 7; + msg_block[i] = 1 << 7; i += 1; // If i >= 113, there aren't enough bits in the current message block to accomplish this, so // the 1 and 0s fill up the current block, which we then compress accordingly. @@ -117,7 +119,7 @@ pub fn digest(msg: [u8; N]) -> [u8; 64] { if i < 128 { for _i in 113..128 { if i <= 127 { - msg_block[i as Field] = 0; + msg_block[i] = 0; i += 1; } } @@ -130,16 +132,16 @@ pub fn digest(msg: [u8; N]) -> [u8; 64] { i = 0; } + let len = 8 * msg.len(); + let len_bytes = (len as Field).to_le_bytes(16); for _i in 0..128 { // In any case, fill blocks up with zeros until the last 128 (i.e. until i = 112). if i < 112 { - msg_block[i as Field] = 0; + msg_block[i] = 0; i += 1; } else if i < 128 { - let mut len = 8 * msg.len(); for j in 0..16 { - msg_block[127 - j] = len as u8; - len >>= 8; + msg_block[127 - j] = len_bytes[j]; } i += 16; // Done. } @@ -151,9 +153,9 @@ pub fn digest(msg: [u8; N]) -> [u8; 64] { } // Return final hash as byte array for j in 0..8 { + let h_bytes = (h[7 - j] as Field).to_le_bytes(8); for k in 0..8 { - out_h[63 - 8*j - k] = h[7 - j] as u8; - h[7-j] >>= 8; + out_h[63 - 8*j - k] = h_bytes[k]; } } diff --git a/noir/noir-repo/test_programs/compile_failure/brillig_nested_slices/Prover.toml b/noir/noir-repo/test_programs/compile_failure/brillig_nested_slices/Prover.toml deleted file mode 100644 index c52564de922a..000000000000 --- a/noir/noir-repo/test_programs/compile_failure/brillig_nested_slices/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -a = "5" -b = "10" diff --git a/noir/noir-repo/test_programs/compile_failure/custom_entry_not_found/Prover.toml b/noir/noir-repo/test_programs/compile_failure/custom_entry_not_found/Prover.toml deleted file mode 100644 index 4dd6b4051592..000000000000 --- a/noir/noir-repo/test_programs/compile_failure/custom_entry_not_found/Prover.toml +++ /dev/null @@ -1 +0,0 @@ -x = "1" diff --git a/noir/noir-repo/test_programs/compile_failure/dep_impl_primitive/Prover.toml b/noir/noir-repo/test_programs/compile_failure/dep_impl_primitive/Prover.toml deleted file mode 100644 index 7d4290a117a4..000000000000 --- a/noir/noir-repo/test_programs/compile_failure/dep_impl_primitive/Prover.toml +++ /dev/null @@ -1 +0,0 @@ -x = 1 diff --git a/noir/noir-repo/test_programs/compile_failure/depend_on_bin/Prover.toml b/noir/noir-repo/test_programs/compile_failure/depend_on_bin/Prover.toml deleted file mode 100644 index 7d4290a117a4..000000000000 --- a/noir/noir-repo/test_programs/compile_failure/depend_on_bin/Prover.toml +++ /dev/null @@ -1 +0,0 @@ -x = 1 diff --git a/noir/noir-repo/test_programs/compile_failure/div_by_zero_modulo/Prover.toml b/noir/noir-repo/test_programs/compile_failure/div_by_zero_modulo/Prover.toml deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/noir/noir-repo/test_programs/compile_failure/dup_trait_implementation_4/Prover.toml b/noir/noir-repo/test_programs/compile_failure/dup_trait_implementation_4/Prover.toml deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/noir/noir-repo/test_programs/compile_failure/dup_trait_implementation_5/Prover.toml b/noir/noir-repo/test_programs/compile_failure/dup_trait_implementation_5/Prover.toml deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/noir/noir-repo/test_programs/compile_failure/dup_trait_items_1/Prover.toml b/noir/noir-repo/test_programs/compile_failure/dup_trait_items_1/Prover.toml deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/noir/noir-repo/test_programs/compile_failure/dup_trait_items_2/Prover.toml b/noir/noir-repo/test_programs/compile_failure/dup_trait_items_2/Prover.toml deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/noir/noir-repo/test_programs/compile_failure/dup_trait_items_3/Prover.toml b/noir/noir-repo/test_programs/compile_failure/dup_trait_items_3/Prover.toml deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/noir/noir-repo/test_programs/compile_failure/dup_trait_items_4/Prover.toml b/noir/noir-repo/test_programs/compile_failure/dup_trait_items_4/Prover.toml deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/noir/noir-repo/test_programs/compile_failure/dup_trait_items_5/Prover.toml b/noir/noir-repo/test_programs/compile_failure/dup_trait_items_5/Prover.toml deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/noir/noir-repo/test_programs/compile_failure/dup_trait_items_6/Prover.toml b/noir/noir-repo/test_programs/compile_failure/dup_trait_items_6/Prover.toml deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/noir/noir-repo/test_programs/compile_failure/hashmap_load_factor/Prover.toml b/noir/noir-repo/test_programs/compile_failure/hashmap_load_factor/Prover.toml deleted file mode 100644 index e54319c61e96..000000000000 --- a/noir/noir-repo/test_programs/compile_failure/hashmap_load_factor/Prover.toml +++ /dev/null @@ -1,26 +0,0 @@ -# Expected 6 key-value entries for hashmap capacity of 8. -# These must be distinct (both key-to-key, and value-to-value) for correct testing. - -[[input]] -key = 2 -value = 17 - -[[input]] -key = 3 -value = 19 - -[[input]] -key = 5 -value = 23 - -[[input]] -key = 7 -value = 29 - -[[input]] -key = 11 -value = 31 - -[[input]] -key = 41 -value = 43 \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/negate_unsigned/Prover.toml b/noir/noir-repo/test_programs/compile_failure/negate_unsigned/Prover.toml deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/noir/noir-repo/test_programs/compile_failure/orphaned_trait_impl/Prover.toml b/noir/noir-repo/test_programs/compile_failure/orphaned_trait_impl/Prover.toml deleted file mode 100644 index 2c1854573a40..000000000000 --- a/noir/noir-repo/test_programs/compile_failure/orphaned_trait_impl/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -x = 1 -y = 2 diff --git a/noir/noir-repo/test_programs/compile_failure/slice_remove_failure/Prover.toml b/noir/noir-repo/test_programs/compile_failure/slice_remove_failure/Prover.toml deleted file mode 100644 index f28f2f8cc48f..000000000000 --- a/noir/noir-repo/test_programs/compile_failure/slice_remove_failure/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -x = "5" -y = "10" diff --git a/noir/noir-repo/test_programs/compile_failure/workspace_missing_toml/crates/a/Prover.toml b/noir/noir-repo/test_programs/compile_failure/workspace_missing_toml/crates/a/Prover.toml deleted file mode 100644 index 465ef562de4c..000000000000 --- a/noir/noir-repo/test_programs/compile_failure/workspace_missing_toml/crates/a/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -x = "1" -y = "1" diff --git a/noir/noir-repo/test_programs/compile_failure/workspace_missing_toml/crates/b/Prover.toml b/noir/noir-repo/test_programs/compile_failure/workspace_missing_toml/crates/b/Prover.toml deleted file mode 100644 index a0397e894776..000000000000 --- a/noir/noir-repo/test_programs/compile_failure/workspace_missing_toml/crates/b/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -x = "1" -y = "0" diff --git a/noir/noir-repo/test_programs/compile_failure/assert_msg_runtime/Nargo.toml b/noir/noir-repo/test_programs/execution_failure/assert_msg_runtime/Nargo.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/assert_msg_runtime/Nargo.toml rename to noir/noir-repo/test_programs/execution_failure/assert_msg_runtime/Nargo.toml diff --git a/noir/noir-repo/test_programs/compile_failure/assert_msg_runtime/Prover.toml b/noir/noir-repo/test_programs/execution_failure/assert_msg_runtime/Prover.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/assert_msg_runtime/Prover.toml rename to noir/noir-repo/test_programs/execution_failure/assert_msg_runtime/Prover.toml diff --git a/noir/noir-repo/test_programs/compile_failure/assert_msg_runtime/src/main.nr b/noir/noir-repo/test_programs/execution_failure/assert_msg_runtime/src/main.nr similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/assert_msg_runtime/src/main.nr rename to noir/noir-repo/test_programs/execution_failure/assert_msg_runtime/src/main.nr diff --git a/noir/noir-repo/test_programs/compile_failure/brillig_assert_fail/Nargo.toml b/noir/noir-repo/test_programs/execution_failure/brillig_assert_fail/Nargo.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/brillig_assert_fail/Nargo.toml rename to noir/noir-repo/test_programs/execution_failure/brillig_assert_fail/Nargo.toml diff --git a/noir/noir-repo/test_programs/compile_failure/brillig_assert_fail/Prover.toml b/noir/noir-repo/test_programs/execution_failure/brillig_assert_fail/Prover.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/brillig_assert_fail/Prover.toml rename to noir/noir-repo/test_programs/execution_failure/brillig_assert_fail/Prover.toml diff --git a/noir/noir-repo/test_programs/compile_failure/brillig_assert_fail/src/main.nr b/noir/noir-repo/test_programs/execution_failure/brillig_assert_fail/src/main.nr similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/brillig_assert_fail/src/main.nr rename to noir/noir-repo/test_programs/execution_failure/brillig_assert_fail/src/main.nr diff --git a/noir/noir-repo/test_programs/compile_failure/brillig_assert_msg_runtime/Nargo.toml b/noir/noir-repo/test_programs/execution_failure/brillig_assert_msg_runtime/Nargo.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/brillig_assert_msg_runtime/Nargo.toml rename to noir/noir-repo/test_programs/execution_failure/brillig_assert_msg_runtime/Nargo.toml diff --git a/noir/noir-repo/test_programs/compile_failure/brillig_assert_msg_runtime/Prover.toml b/noir/noir-repo/test_programs/execution_failure/brillig_assert_msg_runtime/Prover.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/brillig_assert_msg_runtime/Prover.toml rename to noir/noir-repo/test_programs/execution_failure/brillig_assert_msg_runtime/Prover.toml diff --git a/noir/noir-repo/test_programs/compile_failure/brillig_assert_msg_runtime/src/main.nr b/noir/noir-repo/test_programs/execution_failure/brillig_assert_msg_runtime/src/main.nr similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/brillig_assert_msg_runtime/src/main.nr rename to noir/noir-repo/test_programs/execution_failure/brillig_assert_msg_runtime/src/main.nr diff --git a/noir/noir-repo/test_programs/compile_failure/div_by_zero_constants/Nargo.toml b/noir/noir-repo/test_programs/execution_failure/div_by_zero_constants/Nargo.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/div_by_zero_constants/Nargo.toml rename to noir/noir-repo/test_programs/execution_failure/div_by_zero_constants/Nargo.toml diff --git a/noir/noir-repo/test_programs/compile_failure/cyclic_dep/Prover.toml b/noir/noir-repo/test_programs/execution_failure/div_by_zero_constants/Prover.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/cyclic_dep/Prover.toml rename to noir/noir-repo/test_programs/execution_failure/div_by_zero_constants/Prover.toml diff --git a/noir/noir-repo/test_programs/compile_failure/div_by_zero_constants/src/main.nr b/noir/noir-repo/test_programs/execution_failure/div_by_zero_constants/src/main.nr similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/div_by_zero_constants/src/main.nr rename to noir/noir-repo/test_programs/execution_failure/div_by_zero_constants/src/main.nr diff --git a/noir/noir-repo/test_programs/compile_failure/div_by_zero_modulo/Nargo.toml b/noir/noir-repo/test_programs/execution_failure/div_by_zero_modulo/Nargo.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/div_by_zero_modulo/Nargo.toml rename to noir/noir-repo/test_programs/execution_failure/div_by_zero_modulo/Nargo.toml diff --git a/noir/noir-repo/test_programs/compile_failure/div_by_zero_constants/Prover.toml b/noir/noir-repo/test_programs/execution_failure/div_by_zero_modulo/Prover.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/div_by_zero_constants/Prover.toml rename to noir/noir-repo/test_programs/execution_failure/div_by_zero_modulo/Prover.toml diff --git a/noir/noir-repo/test_programs/compile_failure/div_by_zero_modulo/src/main.nr b/noir/noir-repo/test_programs/execution_failure/div_by_zero_modulo/src/main.nr similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/div_by_zero_modulo/src/main.nr rename to noir/noir-repo/test_programs/execution_failure/div_by_zero_modulo/src/main.nr diff --git a/noir/noir-repo/test_programs/compile_failure/div_by_zero_numerator_witness/Nargo.toml b/noir/noir-repo/test_programs/execution_failure/div_by_zero_numerator_witness/Nargo.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/div_by_zero_numerator_witness/Nargo.toml rename to noir/noir-repo/test_programs/execution_failure/div_by_zero_numerator_witness/Nargo.toml diff --git a/noir/noir-repo/test_programs/compile_failure/div_by_zero_numerator_witness/Prover.toml b/noir/noir-repo/test_programs/execution_failure/div_by_zero_numerator_witness/Prover.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/div_by_zero_numerator_witness/Prover.toml rename to noir/noir-repo/test_programs/execution_failure/div_by_zero_numerator_witness/Prover.toml diff --git a/noir/noir-repo/test_programs/compile_failure/div_by_zero_numerator_witness/src/main.nr b/noir/noir-repo/test_programs/execution_failure/div_by_zero_numerator_witness/src/main.nr similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/div_by_zero_numerator_witness/src/main.nr rename to noir/noir-repo/test_programs/execution_failure/div_by_zero_numerator_witness/src/main.nr diff --git a/noir/noir-repo/test_programs/compile_failure/div_by_zero_witness/Nargo.toml b/noir/noir-repo/test_programs/execution_failure/div_by_zero_witness/Nargo.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/div_by_zero_witness/Nargo.toml rename to noir/noir-repo/test_programs/execution_failure/div_by_zero_witness/Nargo.toml diff --git a/noir/noir-repo/test_programs/compile_failure/div_by_zero_witness/Prover.toml b/noir/noir-repo/test_programs/execution_failure/div_by_zero_witness/Prover.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/div_by_zero_witness/Prover.toml rename to noir/noir-repo/test_programs/execution_failure/div_by_zero_witness/Prover.toml diff --git a/noir/noir-repo/test_programs/compile_failure/div_by_zero_witness/src/main.nr b/noir/noir-repo/test_programs/execution_failure/div_by_zero_witness/src/main.nr similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/div_by_zero_witness/src/main.nr rename to noir/noir-repo/test_programs/execution_failure/div_by_zero_witness/src/main.nr diff --git a/noir/noir-repo/test_programs/compile_failure/dyn_index_fail_nested_array/Nargo.toml b/noir/noir-repo/test_programs/execution_failure/dyn_index_fail_nested_array/Nargo.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/dyn_index_fail_nested_array/Nargo.toml rename to noir/noir-repo/test_programs/execution_failure/dyn_index_fail_nested_array/Nargo.toml diff --git a/noir/noir-repo/test_programs/compile_failure/dyn_index_fail_nested_array/Prover.toml b/noir/noir-repo/test_programs/execution_failure/dyn_index_fail_nested_array/Prover.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/dyn_index_fail_nested_array/Prover.toml rename to noir/noir-repo/test_programs/execution_failure/dyn_index_fail_nested_array/Prover.toml diff --git a/noir/noir-repo/test_programs/compile_failure/dyn_index_fail_nested_array/src/main.nr b/noir/noir-repo/test_programs/execution_failure/dyn_index_fail_nested_array/src/main.nr similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/dyn_index_fail_nested_array/src/main.nr rename to noir/noir-repo/test_programs/execution_failure/dyn_index_fail_nested_array/src/main.nr diff --git a/noir/noir-repo/test_programs/compile_failure/dynamic_index_failure/Nargo.toml b/noir/noir-repo/test_programs/execution_failure/dynamic_index_failure/Nargo.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/dynamic_index_failure/Nargo.toml rename to noir/noir-repo/test_programs/execution_failure/dynamic_index_failure/Nargo.toml diff --git a/noir/noir-repo/test_programs/compile_failure/dynamic_index_failure/Prover.toml b/noir/noir-repo/test_programs/execution_failure/dynamic_index_failure/Prover.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/dynamic_index_failure/Prover.toml rename to noir/noir-repo/test_programs/execution_failure/dynamic_index_failure/Prover.toml diff --git a/noir/noir-repo/test_programs/compile_failure/dynamic_index_failure/src/main.nr b/noir/noir-repo/test_programs/execution_failure/dynamic_index_failure/src/main.nr similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/dynamic_index_failure/src/main.nr rename to noir/noir-repo/test_programs/execution_failure/dynamic_index_failure/src/main.nr diff --git a/noir/noir-repo/test_programs/compile_failure/option_expect/Nargo.toml b/noir/noir-repo/test_programs/execution_failure/option_expect/Nargo.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/option_expect/Nargo.toml rename to noir/noir-repo/test_programs/execution_failure/option_expect/Nargo.toml diff --git a/noir/noir-repo/test_programs/compile_failure/option_expect/src/main.nr b/noir/noir-repo/test_programs/execution_failure/option_expect/src/main.nr similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/option_expect/src/main.nr rename to noir/noir-repo/test_programs/execution_failure/option_expect/src/main.nr diff --git a/noir/noir-repo/test_programs/compile_failure/slice_access_failure/Nargo.toml b/noir/noir-repo/test_programs/execution_failure/slice_access_failure/Nargo.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/slice_access_failure/Nargo.toml rename to noir/noir-repo/test_programs/execution_failure/slice_access_failure/Nargo.toml diff --git a/noir/noir-repo/test_programs/compile_failure/radix_non_constant_length/Prover.toml b/noir/noir-repo/test_programs/execution_failure/slice_access_failure/Prover.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/radix_non_constant_length/Prover.toml rename to noir/noir-repo/test_programs/execution_failure/slice_access_failure/Prover.toml diff --git a/noir/noir-repo/test_programs/compile_failure/slice_access_failure/src/main.nr b/noir/noir-repo/test_programs/execution_failure/slice_access_failure/src/main.nr similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/slice_access_failure/src/main.nr rename to noir/noir-repo/test_programs/execution_failure/slice_access_failure/src/main.nr diff --git a/noir/noir-repo/test_programs/compile_failure/slice_insert_failure/Nargo.toml b/noir/noir-repo/test_programs/execution_failure/slice_insert_failure/Nargo.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/slice_insert_failure/Nargo.toml rename to noir/noir-repo/test_programs/execution_failure/slice_insert_failure/Nargo.toml diff --git a/noir/noir-repo/test_programs/compile_failure/slice_access_failure/Prover.toml b/noir/noir-repo/test_programs/execution_failure/slice_insert_failure/Prover.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/slice_access_failure/Prover.toml rename to noir/noir-repo/test_programs/execution_failure/slice_insert_failure/Prover.toml diff --git a/noir/noir-repo/test_programs/compile_failure/slice_insert_failure/src/main.nr b/noir/noir-repo/test_programs/execution_failure/slice_insert_failure/src/main.nr similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/slice_insert_failure/src/main.nr rename to noir/noir-repo/test_programs/execution_failure/slice_insert_failure/src/main.nr diff --git a/noir/noir-repo/test_programs/compile_failure/slice_remove_failure/Nargo.toml b/noir/noir-repo/test_programs/execution_failure/slice_remove_failure/Nargo.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/slice_remove_failure/Nargo.toml rename to noir/noir-repo/test_programs/execution_failure/slice_remove_failure/Nargo.toml diff --git a/noir/noir-repo/test_programs/compile_failure/slice_insert_failure/Prover.toml b/noir/noir-repo/test_programs/execution_failure/slice_remove_failure/Prover.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/slice_insert_failure/Prover.toml rename to noir/noir-repo/test_programs/execution_failure/slice_remove_failure/Prover.toml diff --git a/noir/noir-repo/test_programs/compile_failure/slice_remove_failure/src/main.nr b/noir/noir-repo/test_programs/execution_failure/slice_remove_failure/src/main.nr similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/slice_remove_failure/src/main.nr rename to noir/noir-repo/test_programs/execution_failure/slice_remove_failure/src/main.nr diff --git a/noir/noir-repo/test_programs/compile_failure/workspace_fail/Nargo.toml b/noir/noir-repo/test_programs/execution_failure/workspace_fail/Nargo.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/workspace_fail/Nargo.toml rename to noir/noir-repo/test_programs/execution_failure/workspace_fail/Nargo.toml diff --git a/noir/noir-repo/test_programs/compile_failure/workspace_fail/crates/a/Nargo.toml b/noir/noir-repo/test_programs/execution_failure/workspace_fail/crates/a/Nargo.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/workspace_fail/crates/a/Nargo.toml rename to noir/noir-repo/test_programs/execution_failure/workspace_fail/crates/a/Nargo.toml diff --git a/noir/noir-repo/test_programs/compile_failure/workspace_fail/crates/a/Prover.toml b/noir/noir-repo/test_programs/execution_failure/workspace_fail/crates/a/Prover.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/workspace_fail/crates/a/Prover.toml rename to noir/noir-repo/test_programs/execution_failure/workspace_fail/crates/a/Prover.toml diff --git a/noir/noir-repo/test_programs/compile_failure/workspace_fail/crates/a/src/main.nr b/noir/noir-repo/test_programs/execution_failure/workspace_fail/crates/a/src/main.nr similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/workspace_fail/crates/a/src/main.nr rename to noir/noir-repo/test_programs/execution_failure/workspace_fail/crates/a/src/main.nr diff --git a/noir/noir-repo/test_programs/compile_failure/workspace_fail/crates/b/Nargo.toml b/noir/noir-repo/test_programs/execution_failure/workspace_fail/crates/b/Nargo.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/workspace_fail/crates/b/Nargo.toml rename to noir/noir-repo/test_programs/execution_failure/workspace_fail/crates/b/Nargo.toml diff --git a/noir/noir-repo/test_programs/compile_failure/workspace_fail/crates/b/Prover.toml b/noir/noir-repo/test_programs/execution_failure/workspace_fail/crates/b/Prover.toml similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/workspace_fail/crates/b/Prover.toml rename to noir/noir-repo/test_programs/execution_failure/workspace_fail/crates/b/Prover.toml diff --git a/noir/noir-repo/test_programs/compile_failure/workspace_fail/crates/b/src/main.nr b/noir/noir-repo/test_programs/execution_failure/workspace_fail/crates/b/src/main.nr similarity index 100% rename from noir/noir-repo/test_programs/compile_failure/workspace_fail/crates/b/src/main.nr rename to noir/noir-repo/test_programs/execution_failure/workspace_fail/crates/b/src/main.nr diff --git a/noir/noir-repo/tooling/nargo_cli/Cargo.toml b/noir/noir-repo/tooling/nargo_cli/Cargo.toml index 57edbf5ae043..1629ae86edb4 100644 --- a/noir/noir-repo/tooling/nargo_cli/Cargo.toml +++ b/noir/noir-repo/tooling/nargo_cli/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "nargo_cli" description = "Noir's package manager" +default-run = "nargo" version.workspace = true authors.workspace = true edition.workspace = true @@ -50,6 +51,10 @@ tokio = { version = "1.0", features = ["io-std"] } dap.workspace = true clap-markdown = { git = "https://github.com/noir-lang/clap-markdown", rev = "450d759532c88f0dba70891ceecdbc9ff8f25d2b", optional = true } +notify = "6.1.1" +notify-debouncer-full = "0.3.1" +termion = "3.0.0" + # Backends backend-interface = { path = "../backend_interface" } @@ -86,4 +91,4 @@ name = "iai" harness = false [features] -codegen-docs = ["dep:clap-markdown"] \ No newline at end of file +codegen-docs = ["dep:clap-markdown"] diff --git a/noir/noir-repo/tooling/nargo_cli/build.rs b/noir/noir-repo/tooling/nargo_cli/build.rs index 1ca12b75dfb3..f68ccbfd50e0 100644 --- a/noir/noir-repo/tooling/nargo_cli/build.rs +++ b/noir/noir-repo/tooling/nargo_cli/build.rs @@ -41,6 +41,7 @@ fn main() { println!("cargo:rerun-if-changed={}", test_dir.as_os_str().to_str().unwrap()); generate_execution_success_tests(&mut test_file, &test_dir); + generate_execution_failure_tests(&mut test_file, &test_dir); generate_noir_test_success_tests(&mut test_file, &test_dir); generate_noir_test_failure_tests(&mut test_file, &test_dir); generate_compile_success_empty_tests(&mut test_file, &test_dir); @@ -86,6 +87,44 @@ fn execution_success_{test_name}() {{ } } +fn generate_execution_failure_tests(test_file: &mut File, test_data_dir: &Path) { + let test_sub_dir = "execution_failure"; + let test_data_dir = test_data_dir.join(test_sub_dir); + + let test_case_dirs = + fs::read_dir(test_data_dir).unwrap().flatten().filter(|c| c.path().is_dir()); + + for test_dir in test_case_dirs { + let test_name = + test_dir.file_name().into_string().expect("Directory can't be converted to string"); + if test_name.contains('-') { + panic!( + "Invalid test directory: {test_name}. Cannot include `-`, please convert to `_`" + ); + }; + let test_dir = &test_dir.path(); + + write!( + test_file, + r#" +#[test] +fn execution_failure_{test_name}() {{ + let test_program_dir = PathBuf::from("{test_dir}"); + + let mut cmd = Command::cargo_bin("nargo").unwrap(); + cmd.env("NARGO_BACKEND_PATH", path_to_mock_backend()); + cmd.arg("--program-dir").arg(test_program_dir); + cmd.arg("execute").arg("--force"); + + cmd.assert().failure().stderr(predicate::str::contains("The application panicked (crashed).").not()); +}} + "#, + test_dir = test_dir.display(), + ) + .expect("Could not write templated test file."); + } +} + fn generate_noir_test_success_tests(test_file: &mut File, test_data_dir: &Path) { let test_sub_dir = "noir_test_success"; let test_data_dir = test_data_dir.join(test_sub_dir); @@ -281,7 +320,7 @@ fn compile_failure_{test_name}() {{ let mut cmd = Command::cargo_bin("nargo").unwrap(); cmd.env("NARGO_BACKEND_PATH", path_to_mock_backend()); cmd.arg("--program-dir").arg(test_program_dir); - cmd.arg("execute").arg("--force"); + cmd.arg("compile").arg("--force"); cmd.assert().failure().stderr(predicate::str::contains("The application panicked (crashed).").not()); }} diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/check_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/check_cmd.rs index 242a640e4848..897073f4e201 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/check_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/check_cmd.rs @@ -24,6 +24,7 @@ use super::NargoConfig; /// Checks the constraint system for errors #[derive(Debug, Clone, Args)] +#[clap(visible_alias = "c")] pub(crate) struct CheckCommand { /// The name of the package to check #[clap(long, conflicts_with = "workspace")] diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs index 4309f0db3ea0..9b7bf9cdb0c5 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -1,4 +1,6 @@ +use std::io::Write; use std::path::Path; +use std::time::Duration; use fm::FileManager; use nargo::artifacts::program::ProgramArtifact; @@ -15,6 +17,8 @@ use noirc_frontend::graph::CrateName; use clap::Args; use noirc_frontend::hir::ParsedFiles; +use notify::{EventKind, RecursiveMode, Watcher}; +use notify_debouncer_full::new_debouncer; use crate::backends::Backend; use crate::errors::CliError; @@ -31,17 +35,21 @@ pub(crate) struct CompileCommand { #[clap(long, conflicts_with = "workspace")] package: Option, - /// Compile all packages in the workspace + /// Compile all packages in the workspace. #[clap(long, conflicts_with = "package")] workspace: bool, #[clap(flatten)] compile_options: CompileOptions, + + /// Watch workspace and recompile on changes. + #[clap(long, hide = true)] + watch: bool, } pub(crate) fn run( backend: &Backend, - args: CompileCommand, + mut args: CompileCommand, config: NargoConfig, ) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; @@ -54,28 +62,82 @@ pub(crate) fn run( selection, Some(NOIR_ARTIFACT_VERSION_STRING.to_owned()), )?; - let circuit_dir = workspace.target_directory_path(); + if args.compile_options.expression_width.is_none() { + args.compile_options.expression_width = Some(backend.get_backend_info_or_default()); + }; + + if args.watch { + watch_workspace(&workspace, &args.compile_options) + .map_err(|err| CliError::Generic(err.to_string()))?; + } else { + compile_workspace_full(&workspace, &args.compile_options)?; + } + + Ok(()) +} + +fn watch_workspace(workspace: &Workspace, compile_options: &CompileOptions) -> notify::Result<()> { + let (tx, rx) = std::sync::mpsc::channel(); + + // No specific tickrate, max debounce time 1 seconds + let mut debouncer = new_debouncer(Duration::from_secs(1), None, tx)?; + + // Add a path to be watched. All files and directories at that path and + // below will be monitored for changes. + debouncer.watcher().watch(&workspace.root_dir, RecursiveMode::Recursive)?; + + let mut screen = std::io::stdout(); + write!(screen, "{}", termion::cursor::Save).unwrap(); + screen.flush().unwrap(); + let _ = compile_workspace_full(workspace, compile_options); + for res in rx { + let debounced_events = res.map_err(|mut err| err.remove(0))?; + + // We only want to trigger a rebuild if a noir source file has been modified. + let noir_files_modified = debounced_events.iter().any(|event| { + let mut event_paths = event.event.paths.iter(); + let event_affects_noir_file = + event_paths.any(|path| path.extension().map_or(false, |ext| ext == "nr")); + + let is_relevant_event_kind = matches!( + event.kind, + EventKind::Create(_) | EventKind::Modify(_) | EventKind::Remove(_) + ); + + is_relevant_event_kind && event_affects_noir_file + }); + + if noir_files_modified { + write!(screen, "{}{}", termion::cursor::Restore, termion::clear::AfterCursor).unwrap(); + screen.flush().unwrap(); + let _ = compile_workspace_full(workspace, compile_options); + } + } + + screen.flush().unwrap(); + + Ok(()) +} + +fn compile_workspace_full( + workspace: &Workspace, + compile_options: &CompileOptions, +) -> Result<(), CliError> { let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); - insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + insert_all_files_for_workspace_into_file_manager(workspace, &mut workspace_file_manager); let parsed_files = parse_all(&workspace_file_manager); - let expression_width = args - .compile_options - .expression_width - .unwrap_or_else(|| backend.get_backend_info_or_default()); - let compiled_workspace = compile_workspace( - &workspace_file_manager, - &parsed_files, - &workspace, - &args.compile_options, - ); + let expression_width = + compile_options.expression_width.expect("expression width should have been set"); + let compiled_workspace = + compile_workspace(&workspace_file_manager, &parsed_files, workspace, compile_options); let (compiled_programs, compiled_contracts) = report_errors( compiled_workspace, &workspace_file_manager, - args.compile_options.deny_warnings, - args.compile_options.silence_warnings, + compile_options.deny_warnings, + compile_options.silence_warnings, )?; let (binary_packages, contract_packages): (Vec<_>, Vec<_>) = workspace @@ -85,11 +147,12 @@ pub(crate) fn run( .partition(|package| package.is_binary()); // Save build artifacts to disk. - let only_acir = args.compile_options.only_acir; + let only_acir = compile_options.only_acir; for (package, program) in binary_packages.into_iter().zip(compiled_programs) { let program = nargo::ops::transform_program(program, expression_width); save_program(program.clone(), &package, &workspace.target_directory_path(), only_acir); } + let circuit_dir = workspace.target_directory_path(); for (package, contract) in contract_packages.into_iter().zip(compiled_contracts) { let contract = nargo::ops::transform_contract(contract, expression_width); save_contract(contract, &package, &circuit_dir); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs index 85c0a4160a72..1be2fbf61d95 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -23,6 +23,7 @@ use crate::errors::CliError; /// Executes a circuit to calculate its return value #[derive(Debug, Clone, Args)] +#[clap(visible_alias = "e")] pub(crate) struct ExecuteCommand { /// Write the execution witness to named file witness_name: Option, diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs index 300e1a35be22..391e8061a077 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs @@ -30,6 +30,7 @@ use super::{compile_cmd::compile_workspace, NargoConfig}; /// 1. The number of ACIR opcodes /// 2. Counts the final number gates in the circuit used by a backend #[derive(Debug, Clone, Args)] +#[clap(visible_alias = "i")] pub(crate) struct InfoCommand { /// The name of the package to detail #[clap(long, conflicts_with = "workspace")] diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs index f0a9b3185b98..e413db0e5f3a 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs @@ -20,6 +20,7 @@ use crate::{backends::Backend, cli::execute_cmd::execute_program, errors::CliErr /// Create proof for this program. The proof is returned as a hex encoded string. #[derive(Debug, Clone, Args)] +#[clap(visible_alias = "p")] pub(crate) struct ProveCommand { /// The name of the toml file which contains the inputs for the prover #[clap(long, short, default_value = PROVER_INPUT_FILE)] diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs index 2828aaf01eb9..88a804d5cf42 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs @@ -25,6 +25,7 @@ use super::NargoConfig; /// Run the tests for this program #[derive(Debug, Clone, Args)] +#[clap(visible_alias = "t")] pub(crate) struct TestCommand { /// If given, only tests with names containing this string will be run test_name: Option, diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/verify_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/verify_cmd.rs index 1063b50ab6c1..3e23c9a3e9fb 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/verify_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/verify_cmd.rs @@ -17,6 +17,7 @@ use noirc_frontend::graph::CrateName; /// Given a proof and a program, verify whether the proof is valid #[derive(Debug, Clone, Args)] +#[clap(visible_alias = "v")] pub(crate) struct VerifyCommand { /// The name of the toml file which contains the inputs for the verifier #[clap(long, short, default_value = VERIFIER_INPUT_FILE)] diff --git a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/imports.rs b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/imports.rs index 2788f7781403..55eb259bcdda 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/imports.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/imports.rs @@ -102,7 +102,14 @@ impl UseTree { let mut iter = self.path.iter().peekable(); while let Some(segment) = iter.next() { - let segment_str = segment.rewrite(visitor, shape); + let mut segment_str = segment.rewrite(visitor, shape); + if segment_str.contains('{') + && !segment_str.contains(',') + && !segment_str.contains("::") + { + let empty = ""; + segment_str = segment_str.replace(['{', '}'], empty); + } result.push_str(&segment_str); if iter.peek().is_some() { diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/expected/contract.nr b/noir/noir-repo/tooling/nargo_fmt/tests/expected/contract.nr index c5b19a686d28..97a6ebd6b773 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/expected/contract.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/expected/contract.nr @@ -11,7 +11,7 @@ contract Benchmarking { context::Context, note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}, log::emit_unencrypted_log, state_vars::{Map, PublicMutable, PrivateSet}, types::type_serialization::field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, - types::address::{AztecAddress} + types::address::AztecAddress }; struct Storage { diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/expected/import_braces.nr b/noir/noir-repo/tooling/nargo_fmt/tests/expected/import_braces.nr new file mode 100644 index 000000000000..49c9d09001ef --- /dev/null +++ b/noir/noir-repo/tooling/nargo_fmt/tests/expected/import_braces.nr @@ -0,0 +1 @@ +use dep::std::hash::sha256; diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/input/contract.nr b/noir/noir-repo/tooling/nargo_fmt/tests/input/contract.nr index c5b19a686d28..97a6ebd6b773 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/input/contract.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/input/contract.nr @@ -11,7 +11,7 @@ contract Benchmarking { context::Context, note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}, log::emit_unencrypted_log, state_vars::{Map, PublicMutable, PrivateSet}, types::type_serialization::field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, - types::address::{AztecAddress} + types::address::AztecAddress }; struct Storage { diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/input/import_braces.nr b/noir/noir-repo/tooling/nargo_fmt/tests/input/import_braces.nr new file mode 100644 index 000000000000..88c7e9562a89 --- /dev/null +++ b/noir/noir-repo/tooling/nargo_fmt/tests/input/import_braces.nr @@ -0,0 +1 @@ +use dep::std::hash::{sha256}; \ No newline at end of file diff --git a/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap b/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap index 0b988240d5a4..524a933f3f0d 100644 --- a/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap +++ b/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap @@ -9,18 +9,18 @@ exports[`ContractClass creates a contract class from a contract compilation arti "selector": { "value": 2381782501 }, - "bytecode": "0x1f8b08000000000000ffed9d07741d45b6ae5bb61ce0481893b3450e06a3e49c64724ec6608c31b62c0b1b073962323643700ee460839c73c638478c6166983b393181811926dd3b7367bdf5e6be77df7a8ff5bacea9bdf4ab5c7daca3e992ff2355af5552f53ed5bdbffa7b7775aaeefa47100439416a6a1ea68b822327f9bd4cff2ffcd7a6a218d755e89233274b389b650967f32ce1cccd12ce1659c2d9324b385b650967eb2ce13c2e464ec5d62ca83dc5cd7bbc035de3664c6499a67959a0697e96697a421668da26c88e36eac42ce16c9b259c276509e7c959c2794a96709e9a259ca76509e7e959c2794696709e99259c676509e7d959c2794e96709e9b259ce7650967bb2ce12cc812cef3b384f3822ce1bc304b382fca12ce8bb384f3921839db03e7a5faff65faffe5faff15fabf94bd52ffbf4affefa0eb98abe7af565c61520f698a8ddf4ac2541aa68e61ea64fcd6394c5dc2d4354cddf46f05fab7ee61ea11a69e61ea15a6de5a833e61ba264cd786e9ba305d1fa61bc27463986e0ad3cd61ba254cb786e9b630dd1ea63bc2746798ee0ad3dd61ba274c7dc3746f98fa85e9be30dd1fa6fe617a204c030c9607c334304c0f856950981e0ed3e0300d095379988686a9224cc3c25419a647c2343c4c23c2f4689846866954984687694c98aac234364ce3c2343e4c13c234314c93c2f458982687e9f1303d11a6270dcd9e0ad3d3617a264ccf1a9ccf85694a98a686e9f9307d2b4c2f84e9c530bd14a697c3342d4cd3c334234c33c3342b4cb3c334274c73c3342f4cf3c3f44a985e0dd36b617a3d4c6f84e9cd30bd15a6b7c3f44e98de0dd382302d0cd37b9a457684f7c3541da645615a1ca625615a1aa665615a1ea615615a19a655615a1da635615a1ba675615a1fa60d61da18a64d61da1ca62d61fa204c5bc3f46198b685697b9876846967987685697798f684696f98f685697f980e84e960983e0ad3a1307d1ca6c361fa244c9f86e9db61fa4e98be1ba6cfc2f4bd30fd9ba1f9f7c3f48330fd304c3fd2b61febff3fd165e5fedd4fc3f4339dffb9feff0bfdff97faffe7c632bf0ad3af0ddb6fc2f45bc3f645987ea7f35feaff5fe9ffbfd7ffffa0ff7fadffff51ffff93feff67fdff2ffaff5ff5ff7fd7ffff43ffff9bfeff77fdff3ff5ff7f84e9a18254be755033950531b551a595c9673f22fea541ed4969d15cff26ff0bb43d57cfcb7fd1ae859e6f61d85beaf996c67a5aebf9d686bdad9e6f6bd84fd6f3271bf653f5fca986fd743d7fba61bf48cf5f04f64400f786b55dd99a6b530ed8245e9b81ad85b635075b4b591dd85a695b0bb0c9f66d09b6e3b4ad15d88ed7b6d6604b68db71a26598f2b4ad2c882b560a87a8f5e6c7bd5efdbcec84f87987aaf5b671c47b62fcbcc3d47adb3ae055f171925ed7891037276b5b5bb09da26d2781ed546d3b196ca769db29603b5ddb4e05db19da761ad8ced4b6d3c17696b69d01b6b3b5ed4cb09da36d6781ed5c6d3b1b6ce769db39606ba76de782ad40dbce03dbf9dad60e6c17685b01d82ed4b6f3c17691b65d00b68bb5ed42b05da26d17814ddadf8bc126e78b97689b6a3b8ecb8165b45ddaade432d26683ed7269afc17685b4d5606b2fed34d8ae04df62bb0ada1ab175d03669b7d46fdd74be2c886b3f29ae54ebed1ef77ac335abf5f68c7fbdc9678ebd821a5dcbc04f77d0aab7cec7d8afa9087de7e8247ec49e0bf95ba0ac94133de4d823ecea18d343e77ba759ae9bb15c3e94e961a97f59106ffd7b1a3c3d0de616907713b325253e66eb3c651cb3fda1ac197b721ed41863f676e07010b39d7dccd679ca38662ba1ac197b722edc1863f641e07010b3e56e62b6b8d0c76ceabe5910d8634fae871a63cc8e008ef863b6a38fd9ba4f19c7ecf350d68c3db9266e8c313b1938e28fd9cee5fedca0ce53c6313b0fca9ab127f7671a63ccbe081c0e62b6d2b7b3759e328ed9f7a0ac197b72afb031c6ecabc0117fcc767514b3253e6683d433d020b0c79edcb76e8c31bb0838e28fd9a1fefe6cdda78c6376279435634f9ea134c698dda0f3ea39c38ff5738673c0f6136d3b1778e38fed8a8e8e62bbd8c776aa6f4810d863549ee735c6d8dea7f32a8e7f0efd11c4f60b6d3b1f6cbfd4b60bc0f6b9b65d08f572b00f94fb7da0ce53c6fbc0afa1ac19cbf26cb931ee033f040e07315be163b6ce53c631fb57286bc69ef473688c31fb05703888d94a1fb3759e328ed9ff0d65cdd8bb4ce71b63cc4a5f5375bef0a53e5fb8026c5f695b7bb0fd5edbae04db1fb4ed2ab07dad6d1dc0f6476dbb1a6c7fd2b642b0fd59db8ac0f6176d2b06db5fb5ad046cffae6da560fb0f6deb08b6bf695b27b0fd5ddb3a83ed3fb5ad0bd8fea16d5db54d3def92be5772deda1a58cb82f8b66d02749129c7982f837cb15b9ec27ce0415fa5f1fb2a51752f09ea5ef752e0e9e8a0ee09f051179e8ec0d3297e9e645fd4cef1af37b98d4b0c4d13e0ab04ead5c541bd72c097ac5be6c55f3ed8703fef6261ec1a3f63710ef89275cb7c5760141bb63bf2fe8fec3faa6d3e3fa786d7c1be943c3ea3bf32e0107fb950e69fed6aca5eacd9f2e0776c833b19364771998c0bf125eb9679f19707f5e9d4f08cc57565ec6830ba6a2372c097acdbf49d07f922b7faa4e5e94ce2dbc179b7b54d13cdbb3780efae86ef52c337b69d32a53bb67505e6d8af7ff4b1ad47fceb2dc47365b94e113f78fe80d71371d5097dcb758af8117b2ee46fcaa9292be5440f6987855dedc3b22d91dd5cae8bb15c3e94e96ea97f59106ffd7b183c3d0c6675bce909c74207fb433206ba1b1c325f0adaf588d0ae3b6827652e03ed1c9c7b26b5eb66f0c87c47e091f61bdbb3a206e62922f08de7b0782d27bfe37980abed556430cabc6d7b7505c68e164607e784c5e98e87a5c028b66ec053e248b3a8ed5a42e2dbc575650ef8907373f3da2617cadcd9bca66c458e53b6623c7796a9aed7bcf16fa7e242dc3feac2e3781f2a72148f8578ffe69b20de5833db25b3bd89bac7e3aa2d2f3178645efc7966cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367e667563cf23c01fb6d49b94e248c66ff3757f7f993dfe2d3ebc26740ff74da1facb8109ffd493f882b8c3ae74299939bd5b0fd37f40733fb12456d4b177d63d36d4bf187fdc11ae21962a9c163faceb3e883cfa55133577da0cc3643e6b17f9ae857043caef6c76283c7f48d6d4609a96651edacab3e7d517166eb4f58109befe2a1ae9eebaaef9ea96f879ac7af4e86a6c96f921a36d526ddd3bca6de2e9ef366fadc198f1b928ff3392ef6cb405ff1b7b3c5b5fa27340b6a1f2b30d65df5d592fd4afa4674377ce74299f39bd56c1bec5357161c796cc03e5eb26e59e60a58b687b1ee36eeea9bb61f4a77e0967c4ba36e9d815bca5c02c7ee9feabca3636071a6ef48e03139fee34baabf4849063c78bc7371cee2e8385a88f118777f11b31fa4ed7c59ca601f5207fd77d31e8bc59f67f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b667e66c5633e43c767bfa5248c0dd4c726f93c43becf86cfc5b635abf1ebfa19a03c736a6fd419df51ce857794776936ecfb80df95b26d4b57cfd6a2b6a5f863ebfb9067d14769d6c3a29983ef3aa6fd66077e2351f4eb013caef6c7a86f77d8da8c2252cda2da59177d17d2c599ad9f42416cbe53fd455c3cd795fe22e6f1cbfcae11f693101b3e078ffa5e58b1613bd66d80ad5f9be4f19b0b2ec6b8c17836fb0a8a3fec27f185d656fa49c4df0e1417ba3c46c83e2a7d424a2c7595327f685653f68f3a8f7d854a615dffb4fc2e53ba3e09d8a63af87e6c72fbcaba64fbdabe5ddb075863f25d84ebcad1a98fa1412ee4ff67b39ab2524eca8ad6c2aef611f9ae14b29bcb753496cb8732bd2cf52f0be2adbff92de1de06b38a9dbf409cfd13cef55cb549bd2234ba0234923278ceebaa5fadd9469a7da6b14f642ba30c9e9f4a99ff076d54549f745b9f4a57e70b51fd39f17cc1764e63d6d1ec3bded4fb03e6ebeb1017fd0165dd6d82da7df20263fded61fdc2d52a883eb64899b6b0fe63f9dd2bdbb59ff0627f4329731a5cfbdda4f3995cfb1dabeb78dbb51f2e1755776c17e23e36623c220bc6b2942930e2b147047757cbb217462c2b5a99df3ec4eb523c4788ffbb91a9f6a6b75117d9a7f0fbfe52e67263bf89ff9c2975fee9ea1b99b22e69838a2d7595321d605f2bd4f9046c277ca7a8b7e57799d29d7f8a7eaaced7c45fe7e4f6bd56af4bb6ef3516dfd7016b4cbe8bd0b79c7f8a1fb1e742be171c4fa49ce8215a0bbbda47e41c0ed9cde5ba1bcbe543993e96fa9705f1d6ff1a83e71a8359c54e09c4596f78d7c2555bdd2742a3f6a09194c17bd7b6ef1adbee7534d479aaf9bdf4fce0c86ff7e271d2cd399bfd5d39f3feadedfca4bdc18fe727b7433b9bb09435ef4bcb7271f64fc7f781f0bc10df0772758d941fd4d633dfe070e9bb8de1bb4d03fa6e6bf86edb80bebde65e7326cd99c6fcc1e790cd80d1c5b10e8fab7561b41dff9a03a3ab77364b3260c46f5ee3f14e185d7c27bcbe630ae1b94e0b6074f1be71a6f7ab3b01237e6340185dbca39de977aaf1bd6d59ae1530ba18d708c750aa0ba36daca3d6f0dfc1b84645f51d0704c73a3a0e185d8c0d92086a8f677234c66ec028cb1d0f8c2e9e232582daf7d58ec688cf2b65b98463c674c776c77d7f8a33bd07d110fd0aa2ce35d0b783fbffc5d837a12e5af474cb93f6dc077d3bb8ff95d402c7b23c9a16f87ccec5d89a89a0f6b3b0a3f1e0334459ee24602c73c4d83b03c6326094e54e06c63e8e18cb3260ec038c623f05181ddc874c32f6c98011efd7c972a702e3b58e18afc980f15a6094e54e034617f71413e0b72e8cd701a32c773a305eef88f1ba0c18af074659ee0c60bcc111e3f51930de008cb2dc99c078a323c61b3260bc111865b9b380f126478c3766c0781330ca726703e3cd8e186fca80f1666094e5ce01c65b1c31de9c01e32dc028cb9d0b8cb73a62bc2503c65b8151963b0f186f73c4786b068cb701a32cd70e186f77c4785b068cb703a32c57008c773862bc3d03c63b8051963b1f18ef74c47847068c7702a32c770130dee588f1ce0c18ef024659ee4260bcdb11e35d1930de0d8cb2dc45c0788f23c6bb3360bc071865b98b81b1af23c67b3260ec0b8cb2dc25c078af23c6be1930de0b8c7d2d8cfd1c31de9b01633f6094e5ae04c6fbe2674c5e4bf7cb80f13ee0b93f7e9ea466f765c073bf5b9ee43714efb3f87a207e5fc96dd13fa87bdd1f009e01f1f324b7c50319f008433e2c879a3d183f6352b30119303e083c03e3e7496af660063c0341b3072d9a3d143f6352b38119303e043c83e2e7496af650063c8340b3872c9a3d1c3f6352b34119303e0c3c83e3e7496af670063c83831acd1eb66836247ec6a4668333601c023ce5f1f324351b92014f396836c4a2d9d0f819939a9567c03814782ae2e7496a3634039e0ad06ca845b361f1332635abc8807118f054c6cf93d46c58063c95a0d9308b668fc4cf98d4ac3203c647806778fc3c49cd1ec980673868f68845b311f13326351b9e01e308e079347e9ea4662332e07914341b61d16ca423c64733601c69e189fb9be88f5a7c8d7654f75141ddeb2e0cf9b01cf69318e3887174068c63805196c37e12558e18c764c058058cb25cc23163ba7e1255e07b6cfcbe93ed525550777dc6bae549db4f027d8f73a4c5d8a0ee5a8c73cb93b69f04fa1eef488b7141ddb5180f3c131c6891001f75e111867c580efb494c74c4382103c689c028cb613f89498e182766c03809186539ec27f19823c64919303e068cb21cf69398ec88f1b10c182703a32c87fd241e77c4383903c6c7815196c37e124f38627c3c03c627805196c37e124f3a627c2203c627815196c37e124f39627c3203c6a7805196c37e124f3b627c2a03c6a7815196c37e12cf38627c3a03c667805196c37e12cf3a627c2603c667815196c37e12cf39627c3603c6e7805196c37e12531c313e9701e3146094e5b09fc454478c5332609c0a8cb2dc48c78ce9ae5fa63672df51d72a8ddd77d4754963f7ede3dcc77953f0ede3dcc77953f0ede3dcc77953f0ede3dcc77953f0ede3dcc77953f0ede3dcc77953f0ede3dcc73993efe71df84e800f99728cf932c80b433e2c37d233366a46e429888fa710eb8ebebe4550f76f5978721cd51d7dbd40507761c836c6e7b380716416307a1d537d10ebc3a8785e74c4f342063c2f02cf4b8e785ecc80e725e079397e9e644cbd94018f30e4c37223b380f1f92c60f43a7a1d9918bd8e4d4747cfe8193da3673c168cd9d0867bc6ac88c7e2fa322a9e69f1f324357b39039e69a0992c77bf5bc6e2fa322a9ee9f1f324359b9601cf74d06c9a4533078cc5f565543c33e2e7496a363d039e19a0d9748b660e188bebcba87866c6cf93d46c46063c3341b31916cd1c3016d79751f1cc8a9f27a9d9cc0c78668166332d9a39602cae2fa3e2991d3f4f52b35919f0cc06cd66593473c0585c5f46c533277e9ea466b333e099039acdb668e680b1b8be8c8a676efc3c49cde664c03317349b63d1cc0163717d1915cfbcf879929acdcd80671e6836d7a2192be3c82c607c3e0b181deb585c5f46c533df11cfbc0c78e603cf2b8e78e667c0f30af0bc1a3f4f32a65ec9804718f261b99159c0f87c16307a1dbd8e4c8c5ec7a6a3a367f48c9e3133c66f6501a3dfd69e9195d1c1f555da77685e69e4bea3dea169ecbea3dea169ecbe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb3867f2fd5afcbe8b337d87f535e071f14eada37a16aaf5beaed7f54d8cfa29adde30b47ac5d02a1fcabc0efabde140bf1cf02beb9679f19729f3a504cc8e7c179f10aee338a8bff878ded043f97fd351dda3dafa371bb9efa8b6beb1fb8e6aeb1bbb6f1fe73ece9b826f1fe73ece9b826f1fe73ece597c63be455073de2edf5752eb780b7ecf81f2f2ddb25c28d3af55ea7f9bc0ef432e7cfb7dc81f2b9a826f1fe73ece9b826f1fe73ece9b826f1fe77c718ef1706d03f004064f9086e769329ece643c63c9788692f1dc47c6730b194f2f329ec9643cc5643cb3c8781e25e379898c671019cfdd643cd793f15c45c6f32c194f57329ef1643cc3c8781e20e3b98d8ca78c8ce709329e52329ed9643ca3c9785e26e3194cc6d3978ce705329e1bc978a690f17427e3994bc6733919cf44329ecbc8781e21e32924e379908ce704329e36643c7790f15c43c6f314194f27329e39643c55643cd3c878cac978fa91f15c4dc67333194f4f329ef9643c8f91f11491f18c20e379888ce72e329ee6643cd791f13c43c6d3858c671c194f7b329e0a329ee9643cfdc9786e25e3e94dc6f338194f0919cf28329e87c978ee21e36988ef7164c233958ce706329ee7c878ba91f14c20e39941c67329194f2519cf00329e3c329e7c329e0e643cb793f1f421e379928ca72319cf18329e21643cf792f1bc48c67313194f0f329e79643c93c8786692f10c27e31948c6730519cf89643c6dc978ee24e3c921e04904477e233901bfbf06b666c6b2eab352dd0a6a7e7f5bdb9bc132efe87c73cbbadf069b7cabea1dcbb2a8d3db5097329d2ffcd7a6a44ee8ab0ce6c55f1e70bc43c27327194f5b329e13c978ae20e31948c6339c8c672619cf24329e79643c3dc8786e22e379918ce75e329e21643c63c8783a92f13c49c6d3878ce776329e0e643cf9643c79643c03c8782ac9782e25e39941c633818ca71b19cf73643c3790f14c25e3798d8ce71e329e87c9784691f19490f13c4ec6d39b8ce756329efe643cd3c9782ac878da93f18c23e3e942c6f30c19cf75643ccdc978ee22e379888c6704194f1119cf63643cf3c9787a92f1dc4cc67335194f3f329e72329e69643c55643c73c8783a91f13c45c6730d19cf1d643c6dc8784e20e379908ca7908ce711329ecbc8782692f15c4ec633978ca73b19cf14329e1bc9785e20e3e94bc633988ce765329ed1643cb3c9784ac9789e20e32923e3b98d8ce701329e61643ce3c978ba92f13c4bc6731519cff5643c7793f10c22e379898ce751329e59643cc5643c93c9787a91f1dc42c6731f19cf50329eb1643c9dc9789e26e3b9d6c2f39a231e79df5dd62df3af91f876b01d0ad57adf7554a7057a5d2df57a855ffce54299a2e353ffd5f3215c56b8ccef1360dfef05a0d15b8eea628e8929f36f3572df6d0cdf6d9a88efb686efb64dc4b78f731fe74cbe17c4efbb18bf6d23538e315f06793cbeb8f82690a37ad63ab67f13a37e4aab8586566f195ae543997741bf850ef4b39d2fc8bcf8cb94f95202668c8b8220deb8782ffe3a15abbe34c781aeef19fa62bdde77a469d431e4fd46ee3bea18d2d87d471d431abb6f1fe73ece9b826f1fe73ece9b826f1fe73ece997c57eb7c8cd78d85e8a34550733d500d7e17eb7c4e8c7ed5ba1681df1ce0107fb950e615b817edf779bfcfc7e5db1fdb7c9c3705dfcc716ee6e519e265c0e6ea196f542c36c4f3e563e93b2a161bbbefa8586cecbe7d9cfb3867f2bd247edfc96788af05b5a774cf109700cf22075a38aa67f2da69a951a7d78c3ae543996aa8e75207f5cc01bfb26e995f0adb21db9815cf549dc7f15da4dc541246b12d72cb93dcbfa606b5a774fbd752e071b01f1439aa6772ff5a66d469aa457729530df55ce6a09eb67d47e697c176c83666c523efee0a6b02cabd40c228b6256e7992fbd70b41ed29ddfeb50c785cb43f8eea99dcbf961b757ac1a2bb94a9867a2e77504fdbbe23f3cb613b641bb3e291b14c843501e55e246114db52b73ca509a8b34ce9f6afe5c0e3a2fd7154cfe4feb5c2a8d38b16dda54c35d47385837adaf61d995f01dbc1337b661bb3e2917726853501e55e226114db32a73ca58509a8b34ce9dab115c0e3a29d77a47bb21d5b69d4e9258bee52a61aeab9d2413d6dfb8eccaf84ed9009f3822c64aece4266afb3d7398ab93a0b99bdce5ee728e6ea2c64f63a7b9da398abb390d9ebec758e62aece4266afb3d7398ab93a0b99bdce5ee728e6ea2c64f63a7b9da398abb390d9ebec758e62aece4266afb3d7398ab93a0b99bdce5ee728e6ea2c64f63a7b9da398abb390d9ebec758e62aece4266afb3d7398ab93a0b99bdce5ee728e6ea2c64f63a7b9da398abb390994167c5f3b2ce0b6b02cabd4cc228b6e56e7992efefbc1cd49e728cf932c8af049e150ef47154cf64bff755469d5eb6e82e65aaa19eab1cd4d3b6efc8fc2ad80e99302fc842e6ea2c6466d059f14cd379614d40b969248c625be19627d98e4d0b6a4fe9dab155c0e3a29d7754cf643bb6daa8d3348bee52a61aeab9da413d6dfb8eccaf86ede0993db38d59f14cd779614d40b9e9248c625be994a738f91ee2f4a0f694ae1d5b0d3c2eda7947ba27dbb135469da65b749732d550cf350eea69db77647e0d6c874c98176421737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc0c3a2b9e193a2fac0928378384516cab9cf294249f3bcc086a4fe99e3bac011e17cf651ce99e7ceeb0d6a8d30c8bee52a61aeab9d6413d6dfb8eccaf85edd0d89917642173b5676e10661f1b9e398ad9c786678e62f6b1e199a3987d6c78e628661f1b9e398ad9c786678e62f6b1e199a3987d6c78e628661f1b9e398ad9c786678e62f6b1e199a3987d6c78e628661f1b9e398ad9c786678e6266880dc53353e7853501e56692308a6db55b9ee4770f6606b5a774fd76d602cf1a07fa38aa67b2dfce3aa34e332dba4b996aa8e73a07f5b4ed3b32bf0eb68367f6cc3666c5334be7853501e56691308a6d8d5b9e643b362ba83da56bc7d6018f8b76de513d93edd87aa34eb32cba4b996aa8e77a07f5b4ed3b32bf1eb68367f6cc3666c5335be7853501e56693308a6dad5b9e643b363ba83da56bc7d6038f8b76de513d93edd806a34eb32dba4b996aa8e70607f5b4ed3b32bf01b68367f6cc3666c53347e7853501e5e690308a6d9d5b9ee204d459a674edd806e071d1ce3baa67b21ddb68d4698e457729530df5dce8a09eb67d47e637c276c83666c53357e7853501e5e692308a6dbd5b9ee4fe3537a83da5dbbf36028f8bf6c7513d93fbd726a34e732dba4b996aa8e72607f5b4ed3b32bf09b643b6312b9e793a2fac0928378f84516c1bdcf224f7af7941ed29ddfeb509785cb43f8eea99dcbf361b759a67d15dca54433d373ba8a76ddf91f9cdb01db28d59f1ccd779614d40b9f9248c62dbe8982701759629ddfeb519785cb43f8eea99dcbfb618759a6fd15dcabc0ff5dce2a09eb67d47e6b7008f4cd7028fabb80c0c9ec0a28f4c4f93f17426e3194bc633948ce73e329e5bc8787a91f14c26e32926e379948c671019cfdd643cd793f15c45c6f32c194f57329ef1643cc3c8781e20e3b98d8ca78c8ce709329e52329ed1643c83c978fa92f1dc48c633858ca73b19cfe5643c13c9781e21e32924e379908ce77d329e13c878da90f1dc41c6730d19cf53643c9dc878aac878cac978fa91f15c4dc67333194f4f329ec7c8788ac8784690f13c44c67317194f73329eebc8789e21e3e942c6338e8ca73d194f05194f7f329e85643cb792f1f426e3799c8ca7848c671419cfc3643cf790f1dc40c6f31c194f37329e09643c9792f15492f10c20e3c923e3c927e3e940c6733b194f1f329e27c9783a92f18c21e31942c6732f19cf4d643c3dc8782691f10c27e31948c6730519cf89643c6dc978ee24e3c921e0490447be8b9780df17824dde199b0fb60f747e13d89a597cc8b3882d60cbd5795947ab305d5f70e4ba512757efc9a1af3298177f79c0f10109cf9d643c6dc9784e24e3b9828c672019cf70329e49643c3dc8786e22e3b9978c670819cf18329e8e643c4f92f1f421e3b99d8ca703194f3e194f1e19cf00329e4a329e4bc9782690f17423e3798e8ce706329e7bc8781e26e31945c65342c6f338194f6f329e5bc9781692f1f427e3a920e3694fc6338e8ca70b19cf33643cd791f13427e3b98b8ce721329e11643c45643c8f91f1f424e3b9998ce76a329e7e643ce5643c55643c9dc8789e22e3b9868ce70e329e36643c2790f1bc4fc6f320194f2119cf23643c13c9782e27e3e94ec633858ce746329ebe643c83c9784693f19492f13c41c65346c6731b19cf03643cc3c878c693f17425e379968ce72a329eebc978ee26e31944c6f328194f3119cf64329e5e643cb790f1dc47c633948c672c194f67329ea7c978aeb5f02c74c4638e9b20f30b097cabf9eea08b9a12f03b7e67fd7d478c0b0d46997f1f1891d7b5666d0c9e368666c7d2b7aabfbcab23f7c0717be17be70cdbab4d0368d6d6e0696b68762c7d2b2de4d9b6bc3388db0bbf53cbb0bdf0bd6a07ed7369c2e051538e315f06f92d8ef57154cf427ceffa9b18d7abb4da6a68b5d0d02a1fca6c06fdb63ad02f07fccaba655efc7966cf1cc5ac78a42f89ed7b00fd4818c586e3627c183f4f69c2e05153baf6f143c7fa38aa67b21ddb16d875ff1074973218abdb1cd43307fccaba657e9bc5774110af16dbeba0c5760bcff606d642fc65cabc390b991974563cf2ae81b026a05c7f1246b16d059e1df1f394260c1e35a56b1f7738d6c7513d936dc2cec0aefb0ed05dcae0feb5d3413d73c0afac5be677c276c884795b16327b9debc7ac78e41d6d614d40b901248c62db0e3cbb62e7292e4c183c6a4ad78eed72ac8f9b7aa6dab1dd815df75da0bb94c1fd6bb7837ae6805f59b7ccef86ede0993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9e999b59f10cd479614d40b981248c62db093c7b62e7493d77401e35a57beeb0c7b13e6eea997aeeb037b0ebbe0774973218ab7b1dd43307fccaba657e2f6c07cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6ccdccc8a6790ce0b6b02ca0d226114db6ee0d9173f4f69c2e05153bae70efb1cebe3a89ec9e70efb03bbeefb40772983b1badf413d73c0afac5be6f7c376d8ef993db38559f10cd679614d40b9c1248c62db0b3c0762e7493d3f451e35a56bc70e38d6c74d3d53edd8c1c0aefb01d05dca60ac1e7450cf1cf02beb96f983b01d3261de9685cc5e67af7314b3d7d9eb1cc5ec75f63a47317b9dbdce51cc5e67af7314b3d7d9eb1cc5ec75f63a47317b9dbdce51cc5e67af7314b3d7b9e9e8ac78ca755e581350ae9c84516cfb81e7a3d8794a0a13068f9a728cf932c87fe4581f37f54c3d773814d875ff08749732b87f1d7250cf1cf02beb96f943b01d1a3bf3b62c64f6b1d130cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5cc101b8aa742e7853501e52a4818c57610783e8e9fa73461f0a829c7982f83fcc78ef57154cf64bf9dc3815df78f41772983fbd76107f5cc01bfb26e993f0cdbc1337b661bb3e2a9d479614d40b94a1246b11d029e4fe2e7294e183c6a4ad78e7de2581f47f54cb6639f0676dd3f01dda50cc6eaa70eea99037e65dd32ff296c876c63563cc3755e5813506e3809a3d80e038f83b84bf2e41b3c32ff09816f355fa5f379fa3f6eaf2a6064d85ef90da0591b83a78da1d9b1f4adea3f56e74fd0ff717b8d054686edd5a601346b6bf0b435343b96be9516e374fe44fd1fb7d7386064d85e6dddf214270c1e35a53bdff81478be133f4ff23aeed30c78be033cdf8e9fa7c8513d0bd57abf0bec71ad5769f599a1d5a78656f95006193e73a05f0ef89575cbbcf8f3cc9e398a19db42614d40b94f4818c5f66de071d16ea8ba5fa5d725eb6f11a61f9c5ce3d7c5fd35bcb7d052af5738c45f2e9439b75d0ddb4f345b1efc2edb4dd5e7906173f4ce5b91ed3eafcc8bbfbcc07eadefea1e6ad4bd8743c073c8a2d9418b66071c311e341865fe0030daeef31e74c41375df59fc619b718854337c0ff823e071755e1c1567aef7b94ccf2f3fb2f07c131f4f21c606fa7211abd8b6d5a5eeb67d27c6ba17e1332cf4e5601f481ea73ae875c9fad5b1e0bf4e76aa7929b60f729cea60d43917cafcf779356cff27cd71aa5970e47de1026d9732f2fb37da6eaea340af5be6bbebff182762f3c7c0dacf11bb1b5ab26986fbd6c7161d7b58b87b1070633c36c4b68ebaf781dbba87a1239b66b8ad3fb1e8d8d3c2dd93809b71bfee69e8c8a6d9d1f6eb7e16ee7e04dc8cfb753f434736cd8eb65ff7b770f727e066dcaffb1b3ab26976b4fd7a80857b000137e37e3dc0d0914db3a3edd7032ddc0309b819f7eb81868e6c9a1d6dbf1e64e11e44c0cdb85f0f327464d3ec68fbf5600bf760026ec6fd7a70505b4736cd8eb65f975bb8cb09b819f7eb72434736cd8eb65f5758b82b08b819f7eb0a434736cd8eb65f575ab82b09b819f7eb4a434736cd8eb65f0fb7700f27e066dcaf871b3ab26976b4fdbacac25d45c0cdb85f57193ab26976b4fd7aac857b2c0137e37e3dd6d0914db3a3edd7e32cdce308b819f7eb71868e6c9ad9f66b47fdcb32ee87fcb1537d52e3cf66f21e16f6257111538ee2a0d0515f93643fe40386561f1b5ae177fd0f827eaefa6445f51b137f9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec99f999f13d4f7cbe22e51ae21de0ba308a0d9f49b9b8cfafea7eb55e97acbf4598ee3cb5c66ffccf2d8a93cf01447f791ff36aa3ceb95066e7b9356c7d351b3e5fc4e7a2b66d7930f63ad4ed9d737c4f1f9f051dcbe79d1f59343b60d16cbf2346b3cd90f9fdc028fa1d001e57fbe34183c7f46d7b379c4db3a876d655dc47c599cd77416cbe8b87baf9164271a1fa46db71c191ed89d401f75d177198e9370170bf70f0dcbdc8d5fbffaa4efb8d3a1d32ea940f652e857aee7750cfbaee5b325d0b3caedaa3c0e0092cfac8d48c8ce769329ece643c63c9788692f15c44c6731f19cf19643cb790f11c47c6d38b8c6732194f3119cfa3643c83c878da91f1dc4dc6733219cff5643cb9643c5791f13c4bc6d3958c673c19cf30329e4bc8780e93f15c49c6f30019cf59643cb791f124c878cac8789e20e32925e3194dc633988ce77c329ebe643ca792f1dc48c6d3928c670a194f77329e89643c9793f13c42c67319194f2119cf83643ce790f1dc41c67302194f1b329e6bc8789e22e3e944c65345c6534ec67321194f3f329ed3c978ae26e3b9998ca735194f4f329ec7c8788ac8784690f13c44c6731e19cf5d643c2791f15c47c6d39c8ce719329e2e643ce3c878da93f15490f15c4cc6d39f8ce74c329e5bc9788e27e3e94dc6f338194f0919cf28329e87c9780ac878ee21e339858ce706329e16643caedf03cc94e739329e6e643c13c8782ac9782e25e31940c6733619cfed643c79643cf9643c1dc878fa90f13c49c6d3918c670c19cf10329e0bc878ee25e3398d8ce726329e56643c3dc8782691f10c27e31948c6732e19cf15643c7792f19c48c6d3968c27878027111cf92d26fcfed721b0edd779fcb66033cbfae4b9b09457c7a1db0b8e5c7733cbba0f581850a77d414d5dca74bef05f9b923aa1af3298177f79c0718084a72d19cf89643c7792f15c41c6732e19cf40329ee1643c93c8787a90f1b422e3b9898ce734329e7bc9782e20e31942c633868ca72319cf93643c7dc8783a90f1e493f1e491f1dc4ec6733619cf00329e4bc9782ac9782690f17423e3798e8ce723329e16643c3790f19c42c6730f194f0119cfc3643ca3c8784ac8781e27e3e94dc6733c19cfad643c6792f1f427e3b9988ca7828ca73d19cf38329e2e643ccf90f13427e3b98e8ce724329ebbc878ce23e379888c6704194f1119cf63643c3dc9785a93f1dc4cc6733519cfe9643cfdc8782e24e32927e3a922e3e944c6f31419cf35643c6dc8784e20e3b9838ce71c329e07c9780ac9782e23e379848ce772329e89643cddc978a690f1b424e3b9918ce754329ebe643ce793f10c26e3194dc6534ac6f304194f19194f828ce736329eb3c8781e20e3b9928ce73019cf25643cc3c878c693f17425e379968ce72a329e5c329eebc9784e26e3b99b8ca71d19cf20329e47c9788ac9782693f1f422e3398e8ce716329e33c878ee23e3b9888c672819cf58329ece643c4f93f13423e3b9d6e0c1dfd5bb58f27ed87efd3f177e9fa21baf367a5d52469e89a87b4b7b0d9baaef1e47f5dd1bd44c6530bf07ea2bec7b8167af239e7d068fe93b0ff23d40b3dd864d31ee72c4b8db6094f95dc028faed069edd8e78f6183ca6ef3cc8f704cd761a36c5b8c311e34e8351e67700a3e8b71378763ae2d965f098bef320df0f34db6ed814e336478cdb0d4699df068ca2df76e0d9ee886787c163face837c7fd0ec43c3a618b73a62fcd06094f9adc028fa7d083c1f3ae2d966f098bef3203f0034fbc0b029c62d8e183f3018657e0b308a7e1f00cf078e78b61a3ca6ef3cc80f04cd361b36c5b8c911e3668351e63701a3e8b71978363be2d962f098bef3203f0834db68d814e306478c1b0d4699df008ca2df46e0d9e8886793c163face83fc60d06cbd61538ceb1c31ae3718657e1d308a7eeb8167bd239e0d068fe93b0ff2e5a0d95ac3a618d738625c6b30cafc1a6014fdd602cf5a473ceb0c1ed3771ee42b40b3d5864d31ae72c4b8da6094f955c028faad069ed58e78d6183ca6ef3cc85782662b0d9b625ce18871a5c128f32b8051f45b093c2b1df1ac32784cdf79901f0e9a2d376c8a719923c6e506a3cc2f0346d16f39f02c77c4b3c2e0317de741be0a345b6ad814e312478c4b0d46995f028ca2df52e059ea886799c163face83fc58d06cb161538c8b1c312e3618657e11308a7e8b8167b1239e25068fe93b0ff2e340b36ac3a618df77c4586d30cafcfbc028fa55034fb5239e45068fe93b0ff27dc126bc45607b4fe78bc1b650e74bc0b640e74bc1f6aece7704db3b3adf096c6feb7c67b0bda5f35dc0f6a6ce7705db1b3adf0d6cafeb7c2fb0bda6f3bdc1f6aace9781ed159def03b6f93a7f0dd8e6e9fcb5609babf3d7816d8ece5f0fb6d93a7f03d866e9fc8d609ba9f337816d86cedf0cb6e93a7f0bd8a6e9fcad607b59e76f03db4b3a7f3bd85ed4f93bc0f682cedf09b66fe9fc5d607b5ee7ef06db549dbf076c2375fe5eb0ddaff3f781ed539d7f006cdfd6f907c1f61d9d7f086cdfd5f987c1f699ce0f01dbf7747e28d8fe4de78781edfb3aff08d87ea0f323c0f6439d7f146c3fd2f95160fbb1ce8f06db4f747e0cd87eaaf3e3c1f6339d9f00b69febfc44b0fd42e72781ed973aff18d83ed7f9c960fb95ce3f0eb65febfc1360fb8dce3f09b6dfeafc5360fb42e79f06dbef74fe19b07da9f3cf82ed2b9d7f0e6cbfd7f92960fb83ce4bbba6dad93fea7c41106f3bfb75503315806ff1a7cafc49e75b196564d95c2853aa3fe8a39e71a86f994a3b2cedb2b2493bfc1ed8a41d5e0836698717804ddae177c126edf03b609376f86db0493bfc16d8a41d7e136cd20ebf013669875f079bb4c3af81ad4ce75f059bb4c3af804ddae1f9609376781ed8a41d9e0b366987e7804ddae1d96093767816d8a41d9e0936698767804ddae1e9609376781ad8a41d7e196cd20ebf043669875f049bb4c32f804ddae16f814ddae1e7c126edf054b0c9fef235d8a46d1e0936699bef079bb4cd9f824ddae66f834ddae6ef804ddae6ef824ddae6cfc0266df3f7c0266df3bf814ddae6ef834ddae61f804ddae61f824ddae61f816db4ceff186cd236ff046cd236ff146cd236ff0c6cd236ff1c6cd236ff026cd236ff126cd2367f0e36699b7f0536699b7f0d36699b7f0336699b7f0b36699bbf009bb4cdbf039bb4cd5f824ddae6afc03645e7a5ad6e0d367956aca6c27f71c271789a812f612a0be26dfb712a83fc73507799a693f18c25e3799d8ce722329e95643c2bc878ce20e3f9808c670b19cf71643cfbc978f691f1cc21e379878c6710194f3b329e93c97872c978ae22e3a926e379958ce712329ec3643c5792f19c45c6b3998c671319cf72329e65643c09329ebd643c7bc878de27e39945c6f31619cf60329ef3c9784e25e36949c6d39d8ce772329ef9643c9791f12c25e35942c65348c6730e19cf46329e0d643c0bc9784e20e36943c6b39b8c671719cf0c329eafc978aac878de20e32927e3b9908ca71f19cfe9643c5793f1b426e3e949c633978c673119cf22329e77c978ce23e3594fc6b38e8ce724329e9d643c3bc8789a93f14c23e31947c6f31a194f7b329e0a329e8bc978fa93f19c49c6733c19cf54329ed9643c6f93f1fc9e8ca7808c672d19cf1a329e53c878b693f16c23e36941c6f31119cf2b643c95643cef91f10c20e3399b8c278f8c279f8ca70319cf48329e99643c6f92f15c40c6b39a8c671519cf69643c1f92f16c25e369a5ffb3f0f420e39947c6339c8c670119cf40329e73c978ae20e339918ca72d194f0e014f023802b0c9efcdc1f695ce1f069b7cafe723b07da9f3d560fb9dce4f01db33165b330b9f307c053679d7fa59b0c9fd992fc126ef70fc0e6c725c14ff6abe6fc191fccd6019f1d3dcc28ffe7e67e1923c6e6f59a62c88777ba3afb2e0c8ef29e501c7b3243c6dc9784e24e3b9828ce75c329e81643c0bc8788693f1cc23e3e941c6d38a8c672b19cf87643ca791f1ac22e3594dc6730119cf9b643c33c9784692f17420e3c927e3c923e3399b8c670019cf7b643c95643caf90f17c44c6d3828c671b19cf76329e53c878d690f1ac25e32920e3f93d19cfdb643cb3c978a692f11c4fc67326194f7f329e8bc9782ac878da93f1bc46c6338e8c671a194f73329e1d643c3bc9784e22e35947c6b39e8ce73c329e77c9781691f12c26e3994bc6d3938ca73519cfd5643ca793f1f423e3b9908ca79c8ce70d329e2a329eafc9786690f1ec22e3d94dc6d3868ce704329e85643c1bc8783692f19c43c65348c6b3848c672919cf65643cf3c9782e27e3e94ec6d3928ce754329ef3c9780693f1bc45c6338b8ce77d329e3d643c7bc97812643ccbc8789693f16c22e3d94cc6731619cf95643c87c9782e21e379958ca79a8ce72a329e5c329e93c978da91f10c22e379878c670e19cf3e329efd643cc791f16c21e3f9808ce70c329e15643c2bc9782e22e3799d8c672c19cf74329e66169ec38e78e45829eb96f9c304bed57bb8722f7ebffe9f80df71fce66a478c870d4699af0646b1ed039eee8e78f6183c7b2c5a1c2bdf4a0bf9f6c75efd3f01bfe3f70a5dc554778351e66d31b507787a38e2d965f0ecb26871ac7c2b2da4efa3f42149c0ef381e9eab98ea6130cabc2da6703cd79e8e7876183c3b2c5a1c2bdf4a0be96b287df813f03b8e7fe92aa67a1a8c326f8b291cafab9f239e6d06cf368b16c7cab7d242de3d93779613f03b8e27e42aa6fa198c326f8b291c1fa2bf239ead06cf568b16c7cab7d242be2521df444ac0eff87d7f5731d5df6094795b4ce1f7910738e2d962f06cb16871ac7c2b2de45b7572cd9e80dff1fbb6ae626a80c128f3b698da023c031df16c32783659b43856be951683745e9ec125e0f741c0e82aa6061a8c326f8ba94dc033c811cf06836783458b63e55b693158e7a54f66027e1f0c8cae626a90c128f3b698da003c831df1ac3378d659b43856be9516e53a2fef0c26e0f77260741553830d4699b7c5148ebf5bee88678dc1b3c6a2c5b1f2adb49077efd7eaff09f81dc7e31cec88b1dc6094f9c1c028361cefadc211cf2a836795458b63e55b6921dfd2926f3026e0771c1fcb554c55188c326f8b291cefa4d211cf0a836785458b63e55b69315ce757eaff09f87d3830ba8aa94a8351e66d31b502785638e25966f02c23f2adb49077e1a40f5b027eaf02c6958e18a3626a25308a6d19f02c73c4b3c4e05942e45b6921cf72e49d8b04fc3e1618973b628c8aa9e5c028b625c033d611cf22836791458b63e55b6921df8e59acff27e0771caf7d8923c6b106a3cc2f0146b12d029e458e78a2eee13584efa8fb510de13beade4a43f88eba4fd010bea3eeb13784efa8ebb786f01d752dd210bea3ee333484efa873fa86f01df57cbb217c473dab6d08df51cf1d1bfbfeed8f254deb58722cdbb5a67a2cf1ed39677b3e2e7edfc589a0f6358d9a728cf932c8e3f5cb62075a38aa67215e137e13e37a6dd7f08b0cadf2a10c5ea3babafe1b67f0c8bcf8cb46668c8b9cf87c1726c087bca3ac6c72afe53db0c93d8e8560937b200bc026f7d0de059bdccf7a076c72bfeb6db00dd7f99160937b97d81f49ee6dee005bb9ce633f98c13abf0d6cf29c08fb5fc8b3bead6093e7b5f8dc5f9eb96f019bf49bc0e7cdd2f76513d8a4ff123ee7943e681bc026fd08f1f95ab5ceaf039b8c2981cf75bed4f93560fb4ae7f179828cd5b90a6c4febfc54b07da1f35f83ed299d5f04b6dfea3cdef37952e7c782ed373aff16d87eadf36f82ed099d7f036c8febfc7eb0fd4ae7f7816db2ce63ffd0cf757e0fd81ed379ec97f84b9ddf05b65fe8fceb609ba4f3af816da2cebf0ab69febfc2b609ba0f3f3c1f6339d9f07b6f13a3f176c3fd5f93960fb89cecf06db189d9f05b61febfc4cb08dd6f919601ba5f3d3c1f6239d9f06b64775fef760fba1ce8f035b339d5f0236f97e32ded395771697814dc629c17bf5f2ad922ab0c9f87b2bc0d65ae7f1b98cbc97341c6cf26dfb4ab0c9fbff1560933192cac126e3380d069b7c0b6c10d8e47b6503c12663960e009b8cabda1f6cf2ede27e6093f7297b824dc608e90136f98e4a77b0c9d8773826b07cefb21a6cf24e108e132cdfddff126cf26ef9576093f19b704c60f9c6d5d360937149bf00db793aff14d8e47dcddf82ad40e79f04dbf93aff1bb05da0f3bf069b7cbff209b0c93b358f834dbea3ff2bb0c9bbd993c176a9ce7f0eb6cb74fe31b0c977887e0936192bf617606baff393c026efcc4f04db553aff73b0c9586713c026df57fd19d8e41b5fe3c156a4f33f055bb1ceff046c253a3f066ca53aff63b075d4f9d160eba4f3a3c0d659e77f04b62e3aff28d8baeabcb4336a7f56fbf9213d5f16c4775ea6fc7d1cd49ed25d1b0803f2c479ae9d0f3ce8eb60ec752f4e9ed7cb7edf4caf5762e820f8de1fbbefd435c501bdae167abdfb0ddfb950e653dd88a8e5f6c2ef655007590eafb165ddb2ccd5b0ec3e63dd6d747d0f38aaef7e8349b80f009394f9ecdc9ab24fe9c6b2352c13235bf2fa58622d000d712a83bc30b8d1aab810cf7bebc2730078e2df4f52d7eb2e6202f7adb8afd7cd7b4c66ace54399fda0df3e07fae1be2eeb9679f1e7993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9e999f59f1c8f3047cae2ce50e91308aed20f01c889fa7109fc3cafad5739d87e0b9cec1d8fdd67ebed752afb7d0a8732e94597d5e0ddb109dcf83df65bb456dcbfdb1d721fdb6147f79509f03c0e3605b26790e1a3ca6ef3c8b3e4ab37d16cdf63a6234db0c99df0b8cfb757e1ff0b8da1ff71b3ca66f6c330e906a16d5cebae897902ece6c7d100a62f35d3cd4d5735dd5674af5e5308f5f870c4db10f84d8f039781e2cf389fe9f007d3e017d8e651b60f64bc076ea6360dc1f3b6371ad67c0d2f65f6d688a7d205ed4da4a1f88f8db81e24297c708d947cdbe1558572933038e73b3741efb011d8275bd6bf95da61c63be0cf2d8a6ee8ebfcec9ed2bfd5765fbeeb6f8de09ac31f9aef52e478e4ee247ecb9907fe7bc9ab2524ef410ad851dc7ad427673b98f8de5f2a1cc1e4bfdcb8278ebbfdbe0d96d30abd8990b71f62e9cebb96a93f644687435682465f09cd7419f226b1b291ce24f9591eddfca2883e7a7526609b451aa2ed2ce4b3db11f131e035c9d2f1c32ea27f378be603ba731eba8e2e3ce536b785d5f0b340bec5ab3f4f5db02ed45dc7dfdb6400cd9ce4b65fd85b07ee16a15441f5ba4cc36e338eae27a12b7a5a9e701609232bba01dfa1ff5b8ae3b56d7e851d7757b1cf0e0b5864ce98eef788c71d1be38aa67a1edd8b5cfa8533e94b914eae9e03c26ed3ba9bbc1b78b6d8e5ac839d47e438b5c28f33da3ed88d251d681f701dcd6a5d87a3e5868a98b94f9b1d14eed72c0e472bbe179965aef414b5da5cc2fa0fdfb1ccee7f7ebdfb12dfd8be57799d2b507f84df9edf1d739b97de5fd46d9bedb2dbe3f04d6987cd7fa26859cef8b1fb1e742fecf70fc9672a287682dec6a1f91f73b91dd5c6ebfb15c3e94d961a97f59106ffdb71b3cdb0d66153bbf8138fb0b9cefbb6a3777446854081a49197c5660de6fc17b2778dc6fa8eb0299ff0818c5b61bf4fd1f4eef97a7d83e32d8ccfbe5b6f3c142831fcf07ff17b4b3094b59f7cf0152e736582fa94760d43530eaeae8fcb534c7d0b30cfc7400fb7e9d179de5373cc7953239ed52ffddddbfaa7d1f5bb8a51ef8bc6eafc1bdcfd015ef45b5046e15f7e6b5059ea73bbea62dc57331f37c08afc3a44c1eb0dbcee30e5bea621ea79b05475e0b7e6394c5ebec74cb99f98f8c65f09ec1410b93aded8bedbd9ca2c24293dfd6ee1d32986dbaca7e803127eb32f7153c1f923267c3764b58caaa36e9bf4eaed147b623de6bb7dd677175bc88bacf22fe14a3ed9d4917cf309ae2bb69ad635b6fd772db7336f6fe0cad8d7c3cbe8b2bf058914e8bbd161e57f734a3b4d86bf11d9f169d86dada399b167b2c3caeae31a3b4d863f11da31695b67b0b362d765b785c5d6b4469b1dbe23b3e2d3ad7baaf914e8b5d169ef8ef69a4d7029f8965c2bc8780b9b5918fc77769b9edd99d4d8b9d161e57cfeea2b4d869f11d9f16459d6cd7ec362d7658787634b0163b2cbee3d3a24b57db3d159b16db2d3c0eeeafa5d562bbc5778c71310cefafa5d3629b85675b036bb1cde23bc6f3c34ee9ee19a2161f5a785cddfb8bd2e2438bef18b518a27c6fad83165b2d3c5b1b588bad16dff16951de51f9fea00e5a7c60e1f9a081b5f8c0e23b3e2d867451beb7d4418b2d169e2d0dacc5168bef18afa19271b1b90e5a6cb6f06c6e602d365b7cc7a74545f25c6b531db4d864e1d9d4c05a6cb2f88e4f8bc2e43175631db4d868e1d9d8c05a6cb4f88e312e92d7931beaa0c5060bcf8606d66283c5778cc791645cacaf8316eb2d3ceb1b588bf516dff1695199bcffb4ae0e5aacb3f0ac6b602dd6597cc778cf2519176beba0c55a0bcfda06d662adc5777c5a94248fa96beaa0c51a0bcf9a06d6628dc5777c5a0c4b3e135b5d072d565b785637b016ab2dbe633cef4cb617abeaa0c52a0bcfaa06d66295c5778ce79dc9fb172beba0c54a0bcfca06d662a5c5778c6d67f2bc73451db45861e1713546649416b6f129633cef4c6ab1bc0e5a2cb7f0b81adb304a8be516df319e77268f23cbeaa0c5320b8fabb128a3b4b08d8319635c24dbcea575d062a9856769036bb1d4e23bc6fb5ac9b673491db45862e17135364794164b2cbe63bc1e49dee35b5c072d165b781637b0168b2dbe637c56943c075f54072d1659781635b0168bc0f781d87da7fa738b0fe98b7595a1452e94f98ed1172b4a475907be438b75a98ebd2ea97e65ef47d4a51aea22657e60f4e57bdf0193a3ba2663e63dbd2ee99bfeb1a5ae52e6a7ed6acafe5ce713b04d0ec3bafe68f95da61c63be0cf2a29faaf382f8eb9c8c55190748b6ef028bef77803526df45e83b4727f123f65cc87fddaea6ac94133d446b6157fbc8429d477673b945c672f95066a1a5fe6541bcf55f60f02c309893ef3d409c491cb969bb524c0b2334ba0a349232d867efb0239e8f0d1ee1107f39c191efa24a195916df45fdbbd16f57fa414a3da3fa48bee7a87e517d24c55fd4bba8661d557cfc00fa7ecab820326688b2c9182025b09ece864dd5b58ba3ba8a2f59b7cc7701461993a473c33316d795b193c1a878ba39d00cc7599129ddf1a21bf07475c0e3a89ec9e35077a34e5d8c3ae543197cb7b1bb837ae6805f59b7cc7707df2eb6396a21c7e4cb0d2d72a14c5e41eabf9c3f46e928eb50f1dbd95217573a7632783a597cf772aca3ac5bdac45e0de0bb87e1bba3e15beddb18636a4ab76ff700e69e0e98d57a7bc7bfde423c679478163f1da14e7d4083b8ea84eb9273cc3e86b6b990bfb0a0a6ac9493b272ec1476b51fc9b6447673b96ec672f950a697a5fe6541bcf5ef6df0f43698d579c31905351c0ef687640cf4323864be2368d73b42bb5ea09d94c1636f2747daf5347864be13f0c8f95577b0c9798af027e0f79206e036dbbdee166eb1e178849d2c8c1de3672c4e775ce8088c62eb093c3d1c69666eebcb0d7df09ca095514696cd85325d0a52ffe55d2db3acdaefcecfa9a957736d8fedbd35dda6b774a0178e071a803e81a1a14cc2d03aa81933344e9ee3839a3141274cac1a3fe49161f70c4b3df614b45c0313ffe758aad10c6c986f6eb10541eda14f73c126439fb6005b3343161c7255cacbd0892ee4423d64ddb906676b6089d3370e1b2b53bad069053c2e4259858e0c1dab43e7fef123260ec3f8686170d62776d46fcdd3948b5a97c441ae83ba2393ac5be6c59fd2275fe7c70e193ab2cff847268d1e3666e2048435772ecce7182298ff6dcb6090e0ce24eb696188737cfce294e218c5265f00fe641286d641cd38c631f2240355c61a1e3a64d4a8bb26958f1a31f4864963864e1c513506156d6d2817a5b6fcde126cb6a60ecbaa09775f5cb695c5669b7054e7d6609316fc38b009cff1606b0e79296f6e1927fbc8a5b07e096bf59b12a785ae78aba02604e4b0a4da17b50fa9cfa8aad30135b4b41a4a5a6d4e75c74e0d0dadbe22a7867e56433daba19dd550ce6ae8663554b31a9af9dc2035f4b2ba7b5910a48652be20480d957c51901a0af912e0fb0e305f16a44e3fd450c6ed83d450c5eaf6a17a7d5c7d6a4dbddfae4e63d5e5b13af553973aea344c9d7ea9d36c750b41dd4e52a736eab4519d12a9d318755ade5b6bdd274cd784e9da305d17a6ebc37443986e0cd34d61ba394cb784e9d630dd16a6dbc3744798ee0cd35d61ba3b4cf784a96f98ee0d52c369df17a6fb83d470db0f04a9a1b81f0c52c3743f14a486f07e38480def3d24480dfd3d34480d0b3e2c480d19fe48901a4e7c44901aaa7864901ada7874901a1e590d533e36480d89ae865a56c332ab219cd5d0ce6a6868358cb41a725a0d45ad86b27e2a480d91fd4c989e0d5243684f09d3d4303d1fa66f85e98530bd18a697c2f472901a965d0dd7ae86719f19a4867d9f1da4868957c3c7ab61e5d570f36a187a353cbd1ab65e0d67ff4698de0cd35b617a3b483d16508f43d46302750b5edd22568f69aa83d4edebc541ea31b37aecaeba21a86e19aa9bcaca20d58d4975eb52dddc54b73fd50d52750b55dd6455b761d58d5a752b57ddecd56b07ea350cf55a8a7a4d47bdb6a45ee352afb5a9d7fcd4ab9aead547f52aaf7ab5797f90ba357d30483dae54b7abd56d69758b5edd42ff344cdf0e5231f9dd307d16a6ef85e9dfc2f4fd30fd20480d19ad869756c353aba1acd510d76a386c3574b61a7a5b0dc9fd79901aea5b0d15fe9b2035dcf81761fa5d901af2fcab2035dcfd1fc2f47598fe18a63f85e9cf61fa4b98fe1aa67f0fd37f84e96f61fa7b98fe334cff086a8635c786a440b73ee7ebf92113270e1b3d7662c1c4aa82d193464d1c3176d4130593474c1c5e50f5d8b0f195a3aa26e3c2bfd50bcb98ec7dc68f1ff244c1883115c31e2fa89a34b1a0aab2a0bc6ad2988a5a07d2ffab173ae7488f432a2aa29de535ff17484f6c5e3fa7edf47232dafdcde9eb7641f37a0872597d16baad9e15ba571fc1e492af6fea7cb060c2a8aa8905850563c2bfe181b76af2b08a0e05f8db8450e409130b264c1c327e6241e5f8aad105451d70bd85c7d7a312f38f7703537266fdc4f9e4dcd4ff7a85d80be7d54381c5e7d58f74f379ff02e987f574fa597d6af8a3fa2cf45ff5240cda45ca326152f9c4f143864e8c5eb8c5bfb270a25d3daa7956bbfa55f3dbf571f6fdfa2cf4b77a12260aeae1ac7341dd9d05ff1f1bdedcb8b0020600", + "bytecode": "0x1f8b08000000000000ffed9d779c1545baf77b6008726644cc6b1c4ca8280e87cc0c3098136614111186610405862866d435908339820425670105258961734e6ed275dd74efddddcffbc77def7d83efdb754e3d3bbf29ab0f73c6aec3efcca9fe7c6a4ef533d5fd7cebd74f57a7eaae7f06415014a4a796613a23f8ea24ffafd2bfe55f6fea1ae3baca5d7216e509678b3ce16c99279cc579c2d92a4f385be709679b3ce16c9b279c87c5c8a9d85a040da7b879db39d0356ec6449e695a92079a96e699a687e781a6ed83fc68a38ec813ce0e79c279649e701e95279c47e709e73179c2796c9e701e97279cc7e709e737f284f3843ce13c314f384fca13ce93f384f3943ce13c354f38cbf284b3639e709e96279ca7e709e71979c279669e709e15236767e0eca47fcfd6bfe7e8df73f5af943d4fff9eaf7fbbe83a16ebf90b145798d4439aa4f1bf6e61ea1ea61e61ea69fcaf57987a87a94f98faeaff95e9ff5584a9324cfdc2d43f4c03b40603c37461982e0ad3c561ba244c9786e9b2305d1ea62bc2746598ae0ad3d5611a14a66bc2746d98ae0bd3f561ba214c3786e9a6300d0ed3cd61ba254c43c2746b98861a2cb7856958986e0fd3f030dd11a611611a19a6ea308d0a534d984687a9364c7786694c98c686e9ae30dd1da671611a1fa60961aa0bd3c4304d0ad3e4304d09d3d4304d0bd33d619a1ea67bc3745f98ee37347b204c0f86e9a1303d6c70ce08d323617a344c8f85e99b617a3c4c4f84e9c9303d15a699619a15a6d9619a13a6b9619a17a6f9615a10a685615a14a6a7c3f44c989e0dd373617a3e4c2f84e9c530bd14a697c3f44a985e0dd36b615aac5964475812a6d7c3b4344ccbc2b43c4c2bc2f44698de0cd3ca30ad0ad3ea30ad09d3da30ad0bd3fa306d08d3c6306d0ad3e6306d09d3d630bd15a66d61da1ea61d617a3b4cef846967987685e9dd30bd17a6dd61da13a6bd61da17a6fd617a3f4c07c2f441983e0cd34761fa384cdf0ad3b7c3f49d307d374cdf0bd3f70dcd7f10a61f86e94761fab1b6fd44fffe549795fb773f0bd3cf75fe17faf797faf757faf71363995f87e93786edb761fa9d61fb7d983ed5f9cff4ef1ff4efe7faf78ffaf70bfdfb27fdfb67fdfb17fdfb57fdfb37fdfb6ffaf7dff5ef7fe8dfbfebdf7fe8df7f86696bc774be6d503f550531b551dd6b53cf7e44fc4e41c34969d152ff4f7ecbb4bd58cfcbaf68d74acfb732ecadf57c6b633d6df57c5bc3de41cf7730ec47e9f9a30cfb317afe18c37e9c9e3fceb09fa1e7cf007b22807bc3daae6c2db5a9086c12af2dc0d64adb5a82adb5ac0e6c6db4ad15d864fbb606db61dad6066cedb4ad2dd812da76986819a6126dab0ae28a95f2916abda571af573f2f3b3c7ede516abded1df11e113fef68b5de0e0e78557c1ca9d77504c4cd51dad6016c476bdb91603b46db8e02dbb1da7634d88ed3b663c076bcb61d0bb66f68db71603b41db8e07db89daf60db09da46d2780ed646d3b116ca768db49603b55db4e065b99b69d0236dde406a782ed346d2b03dbe9dad6116c6768db69603b53db4e07db59da7606d8a4fd3d136c72be7896b6a9b6e3b0225846dba5dd4a2d236d36d8ce91f61a6ce74a5b0db6ced24e83ed3cf02db6f3a1ad115b176d93764bfdafafce570571ed27c95ab5de8ab8d71bae59adb75ffceb4d3d73ec1fd4eb5a057e2a40ab013a1f63bfa6aee8bb4827f123f662c85f0965a59ce821c71e6157c7984a9d1f9061b9bec672a550a6d252ffaa20defaf73378fa19ccad20ef2666bb75f331dbe829eb981d0265cdd893f3a0e618b38380c341ccf6f231dbe829eb98ad85b266ecc9b970738cd9db80c341cc56bb89d964b98fd9f47db320b0c79e5c0f35c7981d0b1cf1c76c0f1fb38d9fb28ed9c7a0ac197b724ddc1c63763a70c41fb3bdaafdb941a3a7ac6376219435634feecf34c7987d02381cc46cad6f671b3d651db38ba1ac197b72afb039c6ec33c0117fccf67114b3dd7ccc06e967a041608f3db96fdd1c63762970c41fb3a3fcfdd9c64f59c7ec4e286bc69e3c43698e31bb51e7d573869fe8e70c2781eda7da7632f0c61fdb353d1cc576d2c776ba6f4810d863549ee735c7d8dea3f32a8e7f01fd11c4f64b6deb08b65f69db6960fb44db4e877a39d807aafd3ed0e829eb7de03750d68c6579b6dc1cf7811f01878398adf131dbe829eb98fd1b9435634ffa3934c798fd3d703888d95a1fb38d9eb28ed9ff82b266ec9dadf3cd3166a5afa93a5ff84c9f2f9c0bb63f685b67b07dae6de781ed8fda763ed8bed0b62e60fb93b65d00b63f6b5b39d8fea26d5dc1f6576d4b82ed6fdad60d6cffa66dddc1f6efdad6036cffa16d3dc1f6776deb05b67f685b6fb0fd53dbfa689b7ade257dafe4bcb52df05705f16e5be97729eb96f9ae39f0dddef0dd3e87be3b18be3b587c271df84e800f998a8cf92ac827ddf29497020ffaea1ebfaf6eaaeedd82c6d7bd3bf0f47050f704f8680c4f0fe0e9193f4faaff6faff8d79bdac6dd0c4d13e0ab1bd4abb7837a15812f59b7cc8bbf52b061dbdadbc2d8277ec66411f89275cb7c1f60141bb6f5f2ce95ec3fea78d8a9a89ed7c1be943a27427f55c021fe8aa1cc151debcb76d66c25f07f3ceef5346c8ee2321517e24bd62df3e2af04ead333f78cc9c632f630185db51145e04bd6ed7dd76f07c9e371dcc1b58eb54d13df1539f0ddc7f0ddddf08d6da74c998e6d7d8039f66b4e7d6cab8c7fbde5787d22d786e207cf1ff01a2eae3aa16fb936143f622f86fc3545f565a59ce821edb0b0ab58966d89ece672bd8de54aa14c85a5fe5541bcf5af34782a0d6675bcb9088e850ef687540c54181c32df1db4ab8cd0ae02b49332678376aedab3be068fccf7041e69c77a018fab6ba2289e5c5c8f1dcc379ec3e2f5b3fc1fcf035c6dafae06a3ccdbb6571f60b49dab38b89ec978aed20318c5d61778ba39d22c6abb7623f1ed205652ed91f8907373d97fc55f3194e9d3b2beec5dd056ba88118c47991a7bcd1bff764aa6aec17b64c183dbcec175555747f1588ef76fbe0ce28d35b35dea616815758fc7555bdecde09179f1e7993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9e999f199f2761bf2d29d79384d1ecffe6ea3e7feafb877a5df80ce87f3bed0f962cc7fe31d20fe25ca3cec550a6b4453ddbff83fe60e6732aec23d9d3ad76a96d89fd31ab605efc615f2bdc960cfd9dca62f39d1ce5ea799bfa0698fa8ea6d9f7b3a7455317fd9f51d3224353ec8f7f9ec1a3e2b4b2653d9b8b677fd93e8b44ad241fe7b3bdd2c01eebf16f97648367d62d8286ed071e675cf5df91b65a9e975718be8ba1cc892deab70df6b3aa823ac872d8ef47d62dcb9c0bcb561aeb6eaf97158ed6c6fa7bc1b252e6146853f7b5a8d7cc415b99ccb6ef3a3e378fff389c7e8edf2d0b9eaec0e3a29d7174be518efb40dccff1cdfe69b6f31829837dfb1cf4abccd8df49fc7966cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367e667563ce6b3567cbfb63b09638efa3ea49e67c8b7caf0d9d4c616f57e5d3f8793674e9d8d3ae3bba3ff6c51cfb655e74b82aff67788da96aebe4f11b52dc51f7e7b069f05b978ae5b04be64dd498b16922f8bcd77fa39be8bb121e4397e3743d7ee164d5dedaff88c1535c5fdb587c183cf46a3beed93346c2efb0e45c585f8c37d290936c9e3fbd12eb6331e4bcc7e3de20f9f5f7f476bdb3e70b5ed93e52edb0d79362fcfeabb59ea2a657e086ddf8f751efb7060df91cf2cff9729d3736ad14fd5d9c1f735cb8b605db27d6ddff61c08ac31f9ee8aeb2ad269a0a14131e43f6d515f56ca4959d15ad8d53e22df80417673b91ec672a550a6bfa5fe5541bcf537bfb53ac06056b1f33388b3cfe0f8efaa4dea1fa1d1b9a0919471fccd466bff4ab35f21b6a36d8c32b22c7e8beeafd04645f51fb51d031c7c5b38e33100bfb76b1e171ad3cfb3d0fb69fd37b41771f7d3fa6f8821eca71518ebef0ceb17ae3641f4b145cafc5f63fde639b92c83fdc0feb59fc0f75c923a9fcd39f9a1babeb29d93e3725175c77d33eee313c604b2603c4999765a6bd9669511dc7d2ccb96462c2b5a99df0a2b09beaa9f9befaca5f7f901465d24aef11be452e628a88b9bf396f439a0ab6fcac9baa41d485aea2a658e877ded049d4fc076c2b6f91ccbff65ca740e8863b85f187f9d53dbf722bd2ed9be175a7c5f0cac31f9ee8abee51c50fc88bd18f267b7ac2f2be5440fd15ad8d53e22e751c86e2e57612c570a65065aea5f15c45bff0b0d9e0b0d66153b27439c9d03fdd05db5d5032334ea0c1a4919bca768fb0ea8ed5e87abf737a2cea5f0fd25f33e011e27dd9c37d9cf63cdfb6ab67384ce063f9e23f482763661296bde2f94e3659cfd86f15d895ee017df9570f5ede6bea05b15cce379c1a1f4ede23bb6ca5fd498097d73e03b6acc845cf8ee60f8ee9043df5e73af3993e60ec62048bd7f86df2c5553a6f3521c9740966b018c2ec67248040dbf3d7e30461cdf41966b098c2e8e0fd97efbbc1730ca72c5c0e8e2dd521c7fa3318cf88d613cce0ba3836fc5766deab762f19e5e6b60647a67139f4db5014617e7c54d7d570fcfe7dbc2afab7189ba65c198044659ee306074716f1caf651ac388d745b25c3b6074f10c2bdbf19df0dbf3786fd92563a663bbe3be28c96cefbd54bae5c978ae81be1d3c7b486981f7190fa6453fb73c19cf7dd0b783fb7e292d709cc1836981cf065d8c7b98081a3e873b180f3ebf94e58e04c62a478c03b260ac02c67fdd2b06c6818e18abb2601c088c623f1a181ddc7f4d310ecc8211ef53ca72c700e3458e182fcc82f1226094e58e054617f75213e0b7318c1703a32c771c305ee288f1e22c182f014659ee7860bcd411e32559305e0a8cb2dc3780f132478c9766c1781930ca722700e3e58e182fcb82f1726094e54e04c62b1c315e9e05e315c028cb9d048c573a62bc220bc62b8151963b1918af72c47865168c5701a32c770a305eed88f1aa2c18af064659ee54601ce488f1ea2c180701a32c57068cd738621c9405e335c028cb7504c66b1d315e9305e3b5c028cb9d068cd73962bc360bc6eb8051963b1d18af77c4785d168cd703a32c770630dee088f1fa2c186f004659ee4c60bcd111e30d5930de088cb2dc59c0789323c61bb360bc09186fb4300e76c47853168c838151963b0f186f8e9f31752d3d380bc69b81e796f879529add9c05cf2d6e7952dfd5bbd9e2ebd6f87da5b6c590a0f175bf157886c6cf93da16b766c1230ca5b01c6a765bfc8c29cd8666c1781bf00c8b9f27a5d96d59f00c03cd6eb368767bfc8c29cd8665c1783bf00c8f9f27a5d9ed59f00c07cd6eb7687647fc8c29cd8667c17807f08c889f27a5d91d59f08c08ea35bbc3a2d9c8f819539a8dc8827124f054c7cf93d26c64163cd5a0d9488b66a3e2674c69569d05e328e0a9899f27a5d9a82c786a40b35116cd46c7cf98d2ac260bc6d1c0531b3f4f4ab3d159f0d48266a32d9add193f634ab3da2c18ef049e31f1f3a434bb330b9e31a0d99d16cdc6c6cf98d26c4c168c6381e7aef879529a8dcd82e72ed06cac45b3bb1d31de9505e3dd169eb8bf937d97c5d77847751f1734beeec2500acb613f89098e18c767c13801186539ec2751e7887142168c75c028cb251c3366ea275107be27c6ef3bd52ed5058dd767a25b9e8cfd24d0f724475a4c0c1aafc524b73c19fb49a0efc98eb49814345e8bc9c033c5811609f0d1181e612885e5b09fc454478c53b2609c0a8cb21cf69398e688716a168cd3805196c37e12f738629c9605e33dc028cb613f89e98e18efc982713a30ca72d84fe25e478cd3b360bc17186539ec27719f23c67bb360bc0f186539ec2771bf23c6fbb260bc1f186539ec27f18023c6fbb3607c00186539ec27f1a023c607b2607c10186539ec27f19023c607b3607c08186539ec27f1b023c687b2607c18186539ec2731c311e3c35930ce0046590efb493ce2887146168c8f00a32c87fd241e75c4f848168c8f02a32c77b763c64cd72f8f3673df51d72acddd77d4754973f7ede3dcc77921f8f671eee3bc107cfb38f7715e08be7d9cfb382f04df3ece7d9c17826f1fe73ece0bc1b78f731fe74cbe1f73e03b013e642a32e6ab202f0ca5b0dcdd9eb15933224f597c3ce55877f4f54d82ba7fd3c253e4a8eee8eb7182ba0b43be313e96078cb88f7b1d9bcee858c764531915cf138e781ecf82e709e079d211cf1359f03c093c4fc5cf938aa927b3e011865258eeee3c607c2c0f18bd8e5e472646af63e1e8e8193da367f48c8782311fda70cf9817f1986c2aa3e299193f4f4ab3a7b2e099099ac972b7b8654c369551f1cc8a9f27a5d9cc2c78668166332d9a39604c369551f1cc8e9f27a5d9ac2c78668366b32c9a39604c369551f1cc899f27a5d9ec2c78e68066b32d9a39604c369551f1cc8d9f27a5d99c2c78e68266732c9a39604c369551f1cc8b9f27a5d9dc2c78e68166732d9a39604c369551f1cc8f9f27a5d9bc2c78e68366f32c9a39604c369551f12c889f27a5d9fc2c78168066f32d9a39604c369551f12c8c9f27a5d9822c781682660b2c9ab132de9d078c8fe501a3631d934d65543c8b1cf12ccc826711f03ced886751163c4f03cf33f1f3a462eae92c7884a11496bb3b0f181fcb0346afa3d79189d1eb58383a7a46cfe819b363fc661e30fa6ded1959191d5c5f657c87e6e966ee3bea1d9ae6ee3bea1d9ae6eedbc7b98ff342f0ede3dcc77921f8f671eee3bc107cfb38f7715e08be7d9cfb382f04df3ece7d9c17826f1fe73ece0bc1b78f731fe785e0dbc7b98ff342f0ede3dcc77921f8f671eee3bc107cfb38f7715e08be7d9cfb382f04df3ece7d9c17826f1fe73ece0bc1b78f731fe785e0dbc7b98ff342f0ede3dcc77921f8f671eee3bc107cfb38f7715e08be7d9cfb382f04df3ece7d9c17826f1fe73ece997c3f1bbfef64b6df987916785c7cf3c6513dcbd57a9fd3ebfa3246fd9456cf1b5a3d6d68550a659e03fd9e77a05f11f89575cbbcf8cb96b91301b323dfc9c3c3751c06f5171f8f197a28ff2f38aa7b545bff4233f71dd5d63777df516d7d73f7ede3dcc77921f8f671eee3bc107cfb38f771cee21bf3ad82faf376f9fea95ac78bf0ff22282fdf152e863253daa47fdb077e1f72e1dbef43fe585108be7d9cfb382f04df3ece7d9c17826f1fe73ece0bc1b78f731fe785e0dbc7b98ff342f0ede3dcc77921f8f671ce17e7180f9539e0090c9e2003cf42329e69643c73c878c690f10c23e3b9968ce722329e07c978ba93f14c24e31945c6733319cf95643c1790f1f427e3994ec6d3878c672e19cf5d643c4f92f10c27e3b99e8ce712329e87c97892643c93c9784693f1dc4ac67335194f1519cf7d643cbdc878ce21e3194fc6338f8ce76c329e11643c4f91f1dc48c67338194f7b329ecbc8781e27e3399f8ca7828ce711329e05643c53c978ee24e3b98d8ca79c8ce71a329e2e643c1792f13c40c6d3838c673e194f1d19cf4c329e6a329ec1643ce792f15c41c6d3928ca71f19cf22329e7bc878fa92f18c25e3e94cc6733b19cf75643c1793f13c44c6d38d8c671219cf2c329e1a329e21643c5791f10c20e3b9978ca73719cf38329e4e643c7790f1dc40c6938bef9966c35342c6534ac6732919cfa3643c33c878ba92f14c21e3994dc6534bc633948c671019cf40329efbc9787a92f14c20e31949c6731319cf13643c4790f17420e3b99c8ca7888027117c750c9304fcff59b0b53096559f7d9ddbb1feff2f697b0b58e6659d6f6959f74b60936fc9be6c5916757a09ea52a5f3e55f6f4ae984beaa605efc9500c7cb243c9793f17420e339828ce709329e9bc8784692f14c20e3e949c6733f19cf40329e41643c43c9786ac9786693f14c21e3e94ac633838ce751329e4bc9784ac9784ac8789e25e3b9818ce70e329e4e643ce3c8787a93f1dc4bc633808ce72a329e21643c35643cb3c8782691f17423e379888ce762329eebc8786e27e3e94cc633968ca72f19cf3d643c8bc878fa91f1b424e3b9828ce75c329ec1643cd5643c33c978eac878e693f1f420e379808ce742329e2e643cd790f19493f1dc46c6732719cf54329e05643c8f90f15490f19c4fc6f33819cf65643cedc9780e27e3b9918ce729329e11643c6793f1cc23e3194fc6730e194f2f329efbc878aac878ae26e3b9958c673419cf64329e2419cfc3643c9790f15c4fc6339c8ce749329ebbc878e692f1f421e3994ec6d39f8ce702329e2bc9786e26e31945c633918ca73b19cf83643c1791f15c4bc6338c8c670c19cf1c329e69643c0bc9782a2d3ccf3ae291f7dd65dd32ff2c896f07dba15cadf71547757a55afabb55eaff08bbf622833a35dfa573dffc06585cbfc3e01be9bf32a68f4aaa3bac8f62832b60ffa7ed1916f737c3e997fb199fb6e6ff86e5f20be3b18be3b14886f1fe73ece0bc1b78f731fe785e0dbc7b98f7326df0eae0d92f89d34998a8cf92ac8e3f5828befcb39aa6783ebc42f63d44f69f59aa195796d550a655e01fd5e73a09fedda53e6c55fb6cc9d0898312eca8278e36271fc754aaa7e878781ae8b0d7db15e4b1c691a750c59d2cc7d471d439abbefa8634873f7ede3dcc77921f8f671eee3bc107cfb38f771cee4fb759d8ff1bab11c7db40aeaaf075e07bfcb74be2846bf6a5d4bc16f117088bf6228f3bfe0b9a6dfe7fd3e1f976f7f6cf3715e08be7d9cfb382f04df3ece7d9c17826f1fe73ece0bc1b78f731fe785e09b39cecdbcf4173f1bd85cf5e78f8ac55cbc4b70287d47c56273f71d158bcdddb78f731fe74cbe973bf09d001f3265eae3b71c78963ae07154cfd4b38d15469d9e35ea540a65f018bfc2413d8bc0afac5be657008f4c95c0e3220e1ab3cd91672119cf34329e39643c63c8788691f15c4bc6731119cf83643cddc9782692f18c22e3b9998ce74a329e0bc878fa93f14c27e3e943c633978ce72e329e27c9788693f15c4fc6730919cfc3643c49329ec9643ca3c9786e25e3b99a8ca78a8ce73e329e5e643ce790f18c27e39947c633828ce729329e1bc9780e27e3694fc6731919cfe3643ce793f15490f13c42c6b3808c672a19cf9d643cb791f19493f12c21e3b9868ca70b19cf85643c0f90f1f420e3994fc65347c633938ca79a8c673019cfb9643c5790f1b424e3e947c6b3888ce71e329ebe643c63c9783a93f1dc4ec6731d19cfc5643c0f91f17423e39944c6338b8ca7868c670819cf6b643c5791f10c20e3b9978ca73719cf38329e4e643c7790f1dc40c65342c6534ac6732919cfa3643c33c878ba92f14c21e3994dc6534bc633948c671019cf40329efbc9787a92f14c20e31949c6731319cf13643c4790f17420e3b99c8ca7888027117cf5ddff04fcff35b0c93beacf82ed0d9d5f0ab616161f2d757e05d88a755ed6d1264c2f74fceaba512757efe5a3af2a98177f25c0f10609cfe5643c1dc8788e20e379828ce726329e91643c13c8787a92f1dc4fc633908c671019cf50329e5a329ed9643c53c878ba92f1cc20e379948ce752329e52329e12329e1bc878ee20e3e944c6338e8ca73719cfbd643c03c878ae22e3798d8c6708194f0d19cf2c329e49643cddc8781e22e3b9988ce73a329edbc9783a93f18c25e3e94bc6730f19cf22329e7e643c2dc978ae20e339978c6730194f3519cf4c329e3a329ef9643c3dc8781e20e3b9908ca70b19cf35643c4bc878cac9786e23e3b9938c672a19cf02329e47c8782ac878ce27e3799c8ce732329ef6643c8793f1dc48c6f31419cf08329e79643ce3c978ce21e3e945c6731f194f1519cfd5643cb792f18c26e3994cc69324e379988ce712329eebc9788693f13c49c6731719cf5c329e3e643cd3c978fa93f15c40c6732519cfcd643ca3c8782692f17427e379908ce722329e6bc9788691f18c21e39943c6338d8c6721194f656e7892eadd76e96b1d00174e55905f013c4b1ce8e3a89ee5f85d832f635cafd2ea4d43abd70cad4aa1cc72d0ef4d07fa15815f59b7cc8bbf7c64563c8feabced3b108f92308a6d895b9ed47efb68d070cab4dfbe093c2eda3547f54ced5f2b8d3a3d6ad15dca60acae74504fdbbe23f32b613be41bb3e2795ce7853501e51e276114db0ab73ca9fdebf1a0e19469ff5a093c2eda1f47f54ced5fab8c3a3d6ed15dca60acae72504fdbbe23f3ab603be41bb3e27942e7853501e59e206114db9b6e79ba27a0ce3265dabf56018f8bf6c7513d53fbd76aa34e4f5874973218abab1dd4d3b6efc8fc6ad80e9ed933db98158f3cdb11d604947b9284516c2b9df2742f4f409d65cad48ead061e17edbc23dd53edd81aa34e4f5a74973218ab6b1cd4d3b6efc8fc1a8befb2205e2dd636428bb5169eb539d642fc65cbbc3c0f99bdce5ee72866afb3d7398ad9ebec758e62f63a7b9da398bdce5ee72866afb3d7398ad9ebec758e62f63a7b9da398bdce5ee72866afb3d7398ad9ebec758e62f63a7b9da398bdce5ee72866afb3d7398ad9ebec758e62f63a7b9da398bdce5ee72866afb3d7398ad9ebec758e62f63a7b9da3981974563cf2ed4a614d40b9a74818c5b6ca2d4feabda0a782865391315f05f9b5c0b3da813e8eea99ea43becea8d35316dda50cee5feb1cd4d3b6efc8fc3ad80ed930afc94366af73d39815cf4c9d17d604949b49c228b6d56e7952edd8cca0e194a91d5b073c2eda7947f54cb563eb8d3acdb4e82e6570ff5aefa09eb67d47e6d7c376f0cc9ed9c6ac7866e9bcb026a0dc2c1246b1ad75ca934cbddf382b6838656ac7d6038f8b76de91eea9766c8351a75916dda50cc6ea0607f5b4ed3b32bf01b64336cc6bf290d9ebec758e62f63a7b9da398bdce5ee72866afb3d7398ad9ebec758e62f63a7b9da398bdce5ee72866afb3d7398ad9ebec758e62f63a178ece8a67b6ce0b6b02cacd266114db3aa73cdd52cf1d66070da74ccf1d3600cffad879d2cf1d1ce89e7aeeb0d1a8d36c8bee5206f7af8d0eea69db77647e236c87e6cebc260f997d6ce486d9c786678e62f6b1e199a3987d6c78e628661f1b9e398ad9c786678e62f6b1e199a3987d6c78e628661f1b9e398ad9c786678e62f6b1e199a3987d6c78e628661f1b9e398ad9c786678e62f6b1e199a398196243f1ccd179614d40b939248c625bef9627f5dd833941c32953bf9d8dc0b3c1813e8eea99eab7b3c9a8d31c8bee5206f7af4d0eea69db77647e136c07cfec996dcc8a67aece0b6b02cacd256114db06b73ca9766c6ed070cad48e6d021e17edbca37aa6dab1cd469de65a74973218ab9b1dd4d3b6efc8fc66d80e9ed933db9815cf3c9d17d604949b47c228b68d6e7952edd8bca0e194a91ddb0c3c2eda7947f54cb5635b8c3acdb3e82e653056b738a8a76ddf91f92db01d3cb367b6312b9ef93a2fac0928379f84516c9bdcf2241350679932b5635b80c7453befa89ea9766cab51a7f916dda50cc6ea5607f5b4ed3b32bf15b643be312b9e053a2fac0928b78084516c9bddf2a4f6af0541c329d3feb515785cb43f8eea99dabfde32eab4c0a2bb94c1587dcb413d6dfb8eccbf05db21df9815cf429d17d604945b48c228b62d6e7952fbd7c2a0e19469ff7a0b785cb43f8eea99dabfb619755a68d15dca60ac6e73504fdbbe23f3db603be41bb3e259a4f3c29a80728b4818c586c78b458e784a0d9e528b1687cab79aafd0f912fd9b80ff5700a3abf67091c128f318e3c8eb5ab3f6064f7b43b343e95bd5bf52e70fd7bfb8bd2a8191617bb5cf81661d0c9e0e866687d2b7d2a29fce1fa17f717bf5034686edd501781cb4cfdd13068f9a329d6f6c73ac8fa37aa6ce37b60776ddf1382465f0d8bddd413d6de71232bf1db68367f6cc3666c53358e7853501e50693308a0daf5376c4cfd33d61f0a829533bb6c3b13e8eea996ac7de0eecbaef00dda50cc6eadb0eea59047e65dd32ff366c876c98d7e421b3d7b969cc8a6788ce0b6b02ca0d216114db76e079277e9eee0983474d99dab1771cebe3a89ea9766c6760d7fd1dd05dcae0feb5d3413d8bc0afac5be677c276c886794d1e327b9d9bc6ac7886eabcb026a0dc501246b1bd0d3cbb62e7498f07843c6acad48eed72ac8f9b7aa6dbb17703bbeebb40772983fbd7bb0eea59047e65dd32ff2e6c07cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6ccdccc8a6798ce0b6b02ca0d236114db4ee0792f769ef47307e45153a6e70eef39d6c74d3dd3cf1d760776dddf03dda50cc6ea6e07f52c02bfb26e99df0ddbc1337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993d3337b3e219aef3c29a8072c34918c5f62ef0ec899fa77bc2e05153a6e70e7b1cebe3a89ea9e70e7b03bbee7b40772983b1bad7413d8bc0afac5be6f7c276d8eb993db38559f18cd079614d40b911248c62db0d3cfb62e7493f3f451e35656ac7f639d6c74d3dd3edd8fec0aefb3ed05dca60acee7750cf22f02beb96f9fdb01db2615e9387cc5e67af7314b3d7d9eb1cc5ec75f63a47317b9dbdce51cc5e67af7314b3d7d9eb1cc5ec75f63a47317b9dbdce51cc5e67af7314b3d7b97074563cd53a2fac0928574dc228b6bdc0f37eec3cddca13068f9a8a8cf92ac8bfef581f37f54c3f773810d8757f1f749732b87f1d7050cf22f02beb96f903b01d9a3bf39a3c64f6b1911b661f1b9e398ad9c786678e62f6b1e199a3987d6c78e628661f1b9e398ad9c786678e62f6b1e199a3987d6c78e628661f1b9e398ad9c786678e62f6b1e199a3987d6c78e628661f1b9e398ad9c786678e6266880dc553a3f3c29a807235248c62db0f3c1fc4cfd33d61f0a8a9c898af82fc078ef57154cf54bf9d0f03bbee1f80ee5206f7af0f1dd4b308fccaba65fe43d80e9ed933db98154fadce0b6b02cad592308aed00f07c143f4f3261f0a829533bf691637d1cd533d58e7d1cd875ff0874973218ab1f3ba86711f89575cbfcc7b01df28d59f18cd179614d40b931248c62fb10781cc45d8aa7d4e091f98f087cabf93a9d2fd1bfb8bdea8091617b95e640b3f6064f7b43b343e95bd57fa2ce1fae7f717b4d044686edd53e079a7530783a189a1d4adf4a8b493a7f84fec5ed35091819b657871c687628dbc343b96f1fca38f59a1f3acd8b0ea1e6458750f322af3995e60e8e2f493c9605c0805315e43f069e6fc7cf93ba2ff771163cdf069e6fc5cfd3d5513dcbd57abf03ec71ad5769f55d43ab8f0dad4aa10c327cd7817e45e057d62df3e2cf337be628663cb715d60494fb8884516cdf021e17ed86aafbf97a5db2fe5661fae4e87abf2e9e97e0bde2d67abdc221fe8aa1cca4b27ab6df69b612f8bf6c37559f0386cdd13bcc5d6dcfed645efc950439bb779bf15e326ae1e27953b6c7fd03169e2fe3e329c7fd1c7ded7754f76c9efdedb7f0c458f7ae51cf3df7c55ff754fbd145af4bd6aff6d1ff71b453cdbbe3be27ed4717a3cec5506650593ddb7f42fb616b2b5cef9b724e6eee9b2d82faf64cb8cab4dd7c26f4a5b64bb90fa03cb63915fa17f7cf0aa8abab7631ea1e13b68b66dbed527bf3b9a4e9bb1474f9805433db730ad4b1d2c25d49c08df198cbfd4cd66d7b465669e8c8a6196eeb0f2c3af6b370f723e066dcaffb193ab26976b0fd7ab0857b300137e37e3dd8d0914db383edd7432cdc4308b819f7eb21868e6c9a1d6cbf1e6ae11e4ac0cdb85f0f357464d3ec60fbf5300bf730026ec6fd7a98a1239b6607dbaf875bb887137033eed7c30d1dd9343bd87e3dc2c23d82809b71bf1e1134d4914db383edd7d516ee6a026ec6fdbadad0914db383edd73516ee1a026ec6fdbac6d0914db383edd7b516ee5a026ec6fdbad6d0914db383edd7632cdc6308b819f7ebc6f6db67ddafeb2cdc7504dc8cfb759da1239b6607dbaf275ab827127033eed7130d1dd9343bd87e3dc9c23d89809b71bf9e64e8c8a6996dbf76f42e61d6ef367ee8549ff418d31f66c1f33ef0b88829477150eea89f4baa6fea3e43ab0f0dad70ec8efda09f83be3019bf4920fe3cb367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed933f333e37719f1f98a94fb8084516cf84ccac57d7e55f70bf4ba64fdadc234e8d87abffb63f79b2c471d5aebf50a87f82b8632279c5acf76bd662b09bebadd702c6edc967b63af437a5b9af12ff3e2af04eab30f781cbc9f9fe2d96ff0ecb76881ef9dc6e33b39ca8dc6c972f57dbcc382faedbcd7a80f6aba2776ff0d352d3234dde3d8772268b83d8501a72ac8238f8b67c38eea996a0b761b7532352e85329da09ebb1dd4b308fccaba657e37f0c8d402785cc56060f004167d64aa24e39946c633868ce70c329e61643cc793f15c4bc6731819cf45643c0f92f17427e39948c6338a8ce754329e9bc9788e22e3b9928ce702329e62329efe643cd3c978fa90f1dc45c6731619cf70329ef3c8784e20e3b99e8c2741c6730919cfc3643c49329ec9643ca3c9783a92f1dc4ac6730c19cfd5643cadc978aac878ee23e3e945c6730e19cf78329eb3c9784690f19c44c6732319cfe1643cedc9782e23e379848ca7828ce77c329ea9643c7792f19c4ec6731b194f3919cf71643cd790f17421e3b9908ca72d19cf03643c3dc878eac878aac9784e21e3194cc6732e19cf91643c5790f1b424e3e947c6730f194f5f329eb1643c9dc978ce24e3b99d8ce71b643cd791f1b423e3b9988c671f19cf43643cddc8782691f1d490f11c20e32923e31942c6733419cf55643cadc8780690f1dc4bc6d39b8c671c194f27329e3bc8784e24e3b9818ca7848ca7948ce752329e19643c5dc978a690f1d492f19c46c633948ce758329e41643c6dc8780692f1dc4fc6d3938c670219cf48329e93c9786e22e339828ca70319cfe5643c45043c89e0abdf624ac0fff7834dbe19f43ed85a58d627cfa9a5bc3a2e2eedf8d575b7b0ac7b8f8501757a0fea52a5f3e55f6f4ae984beaa605efc9500c71e129ecbc9783a90f11c41c6731319cfc9643c23c9782690f1f424e3b99f8c6720194f1b329e41643cc792f10c25e3398d8ca7968c670a194f57329e19643c9792f19492f19490f1dc40c6732219cf1d643c9dc878c691f1f426e3b9978c6700194f2b329eabc8788e26e31942c65346c673808ca7868c6712194f37329e87c878f691f15c4cc6d38e8ce73a329e6f90f1dc4ec67326194f67329eb1643c7dc978ee21e3e947c6d3928ce70a329e23c978ce25e3194cc6730a194f35194f1d194f0f329e07c878da92f15c48c6d3858ce71a329ee3c878cac9786e23e3399d8ce74e329ea9643ce793f15490f13c42c67319194f7b329ec3c9786e24e339898c670419cfd9643ce3c978ce21e3e945c6731f194f15194f6b329eabc9788e21e3b9958ca72319cf68329ec9643c49329e87c9782e21e34990f15c4fc6730219cf79643cc3c978ce22e3b98b8ca70f19cf74329efe643cc5643c1790f15c49c6731419cfcd643ca792f18c22e39948c6d39d8ce741329e8bc8780e23e3b9968ce778329e61643c6790f18c21e39946c65349c6d3c2e0c1ffab77c3f6e9bc7c3ba818fe3f59772e6fafd72565e419b1ba57f1ae6153f5dde5a8beef06f55315ccef82fa0afbbbc0f3ae239ef70c1ed37709e42b41b39d864d31bee38871a7c128f3ef00a3e8b71378763ae2d965f098be4b20df0f347bdbb029c61d8e18df3618657e07308a7e6f03cfdb8e78de31784cdf25901f0c9a6d376c8a719b23c6ed06a3cc6f0346d16f3bf06c77c4b3c3e0317d97407e0868f69661538c5b1d31be6530cafc566014fdde029eb71cf16c33784cdf25901f0a9a6d316c8a71b323c62d06a3cc6f0646d16f0bf06c71c4b3d5e0317d97407e1868b6c9b029c68d8e1837198c32bf111845bf4dc0b3c911cf6683c7f45d02f9e1a0d906c3a618d73b62dc6030cafc7a6014fd3600cf06473c1b0d1ed37709e4478066eb0c9b625ceb88719dc128f36b8151f45b073ceb1cf1ac37784cdf2590af06cdd61836c5b8da11e31a8351e65703a3e8b70678d638e2596bf098be4b205f039aad326c8a71a523c65506a3ccaf0446d16f15f0ac72c4b3dae0317d9740be16347bd3b029c6371c31be6930cafc1bc028fabd093c6f3ae25969f098be4b203f06345b61d814e372478c2b0c46995f0e8ca2df0ae059e188e70d83c7f45d02f93ad06c9961538c4b1d312e3318657e29308a7ecb806799239ee5068fe9bb04f21341b3d70d9b625ce288f1758351e69700a3e8f73af0bcee8867a9c163fa2e81fc24d06cb161538caf39625c6c30cafc6bc028fa2d069ec58e7896183ca6ef12c8df0836e1ed0bb65775be0fd85ed1f9de607b59e77b81ed259def09b61775be07d85ed0f9ee607b5ee7bb81ed399d4f82ed599def0ab66774be3fd89ed6f901605ba4f355605ba8f303c1b640e72f04db7c9dbf086cf374fe62b0cdd5f94bc03647e72f05db6c9dbf0c6cb374fe72b0cdd4f92bc0f694ce5f09b62775fe2ab03da1f35783ed719d1f04b66feafc35607b4ce7af05dba33a7f1dd8eed6f9ebc1768bcedf00b60f75fe26b07da4f33783ed639dbf156cdfd2f9dbc0f66d9dbf1d6cdfd1f93bc0f65d9d1f09b6efe9fc28b07d5fe74783ed073a7f27d87ea8f363c1f6239dbf0b6c3fd6f97160fb89ce8f07db4f757e02d87ea6f393c1f6739d9f02b65fe8fc54b0fd52e7a781ed573a7f0fd83ed1f9e960fbb5cedf0bb6dfe8fc7d60fbadcedf0fb6dfe9fc0360fbbdce3f08b64f75fe21b07da6f30f83ed0f3a3f036c9febfc2360fba3ce4bbba6dad93fe97c59106f3bfb45503f95816ff1a7cafc59e7db186564d962287396ee50a89e71a86f994a3b2cedb2b2493bfc2ad8a41d7e056cd20ebf0c3669875f029bb4c32f824ddae117c026edf0f3609376f839b0493bfc2cd8a41d7e066cd20e3f0db62a9d5f0436698717824ddae105609376783ed8a41d9e07366987e7824ddae1396093767836d8a41d9e0536698767824ddae1a7c026edf093609376f809b0493bfc38d8a41dfe26d8a41d7e0c6cd20e3f0a366987ef069bb4c3b7804df6972fc0266df3876093b6f923b049dbfc31d8a46dfe16d8a46dfe36d8a46dfe0ed8a46dfe2ed8a46dfe1ed8a46dfe3ed8a46dfe01d8a46dfe21d8a46dfe11d8a46dfe31d8c6ebfc4fc0266df34fc1266df3cfc0266df3cfc1266df32fc0266df32fc1266df3afc0266df3276093b6f9d76093b6f9376093b6f9b76093b6f9776093b6f9f76093b6f953b049dbfc19d8a46dfe03d81ed17969abdb824d9e15aba9fc6b4e380e4f0bf0252c5541bc6d3f4e5590c7bacb5449c633978c670c19cf8b643c6790f10c23e3399e8ce730329ec5643c13c9781691f1ac20e3594ec6f31a19cfa9643c9bc8783692f11c45c6f32e19cf2e329e0bc8788ac9786693f13c4fc6731619cf70329ef3c8784e20e34990f12c20e35946c6b3948ce715329e8e643c1bc878d693f11c43c6b3938ce71d329ed6643c5f90f1cc24e339878ce759329eb3c9784690f19c44c67338194f7b329e0a329ef3c978e691f1bc4ec6b3848ce725329ed3c978d691f1ac25e32927e3398e8ce76d329e1d643c5dc878da92f13c49c65347c6f334194f3519cf29643c83c978ce25e339928ca725194f3f329e5bc878e690f1bc40c6d3998ce74c329e35643cabc9783e27e3f90619cf76329e6d643cedc878f691f14c22e35948c65343c6f32a19cf01329e32329e21643c4793f1b422e3f9908c671619cf73643cabc8785692f19c48c6f31619cf56329e12329e52329ef9643cb5643c2f93f19c46c633948ce758329e36643c4f91f13c43c6f32619cf1b643c2793f16c21e3d94cc67304194f07329edd643cef91f11411f0248023009bfcbf25d8e43b3c07c0f699ceef039b7cc36731d83ed5f947c0f690c5d6c2c2270c33c026efca7e0636b93ff330d8e49d894fc126e70de25fcdafeef855fe16b08cf86969e1477f9f5ab8248fdb5b96a90ae2dddee8ab2ab07ff3aec8603cd43cef91f1ec26e3e940c6730419cf66329e2d643c2793f1bc41c6f32619cf33643c4f91f1b421e339968c672819cf69643c2f93f1d492f1cc27e32925e32921e3d94ac6f31619cf89643c2bc9785691f13c47c6338b8ce743329e56643c4793f10c21e32923e33940c6f32a194f0d19cf42329e49643cfbc878da91f16c23e3d94ec6f30d329ecfc9785693f1ac21e339938ca73319cf0b643c73c8786e21e3e947c6d3928ce748329e73c9780693f19c42c6534dc6f334194f1d19cf93643c6dc978ba90f1ec20e3799b8ce738329e72329eb5643cebc8784e27e379898c670919cfeb643cf3c878ce27e3a920e3694fc6733819cf49643c23c878ce26e379968ce71c329e99643c5f90f1b426e379878c672719cf31643cebc9783690f17424e379858c672919cf32329e05643c09329e13c878ce23e3194ec6731619cff3643cb3c9788ac9782e20e3d945c6f32e19cf51643c1bc9783691f19c4ac6f31a19cf72329e15643c8bc8782692f12c26e3398c8ce778329e61643c6790f1bc48c633868c672e194f25194f0b0bcf01473cf2ad1859b7cc1f68e6be7719be771588ef770cdfef1488ef1d86ef1d05e27b9be17b5b81f8de6af8de5a20be371bbe371788ef8d86ef8d05e27bbde17b7d81f85e6bf85e5b20be571bbe571788ef9586ef9505e2fb0dc3f71b05e27bb9e17b7981f85e6af85e5a20be9718be9714886fe6eb6ff59d30e9abbc5bff26e0ff15c0b8d811e3018351e61703a3d8f07bd4158e78a2aedd2b087c2b2de45e963cf34cc0ff2b81d1554c55188c326f8ba95dc053e98827ea9e4325816fa585bc8b2d7d2a13f07f1c7fd9554c551a8c326f8ba97780a79f239ea87b25fd087c2b2de4dd6779e72f01ffc7f1d65dc5543f8351e66d31b50378063be289bac73398c0b7d242be1526dfa449c0ff717c46573135d86094795b4ce1f8b9431cf144dd9b1a42e05b6921dfda956f5e26e0ff387e93ab981a6230cabc2da670fcb8a18e78a2eea90d25f0adb49067c1f28df604fc7f1830ba8aa9a106a3ccdb620ac7bb19e68827ea5ee03002df4a8be13a2f7dac12f0ffe1c0e82aa686198c326f8ba98dc033dc114fd43dcce104be951623745edee148c0ff4700a3ab981a6e30cabc2da6d603cf08473c51f75e4710f8565a54ebfc3afd9b80ff5703a3ab981a6130cabc2da6d6024fb5239ea87bc6d504be9516353a2fdf9c4bc0ff71fcf7118e18ab0d46991f018c625b0d3c358e78a2ee75d710f8565ac8b7fd57e9df04fc1fc7637515533506a3ccdb620ac783ae75c413758fbe96c0b7d2628ccecb983009f8ff1860741553b506a3ccdb620ac7af1ce38827ead9c21802df4a0bf936d70afd9b80ffd701a3ab981a6330cabc2da696034f9d239ea506cf528b1687cab7d242fa722fd3bf09f8ff44607415537506a3ccdb626a29f04c74c413f52c6722816fa5857c5bfb75fd9b80ff4f0246573135d16094795b4c2d019e498e78a29e414dca81efa8e729b9f01df56c2017bea3ee73e7c277d43ddb5cf88ebaff980bdf51f7d272e13beabe502e7c47dde3c885efa8ebf55cf88ebaf6cc85efa8eba85cf88eba26c885efa8f3db5cf88e3a57cb85efa8f30edf9efbf63c6edf87f2dca150dbf343790c3d94c7127f6de0af0d72e5db1f4bfcb541ae7c17eab5816fcf73df9ecbf55751107d3df68623dfcb0ddf328fcf59963bf2bdd4f02df3f8cc60a923df4b0cdf328ff7bf9738f25d6af896f92539f0dddef0dd3e87be3b18be3b587c3bd8dec944d0f0fa5b1870aa823cc6c0eb0eb47054cf72b5de657a5d5fc6b85edb7d1b737f298532cb403fd76d87acdb6c3bf29119e3a2283edfe509f021df255336797efc2ad8a4dd7f056cd22fe065b0c9b1e925b0c933a917c126cfac5e00db189dff106cf2ec18fbeccbf3ff1d60abd679ec2b3e42e7b7814dfa52611f65e90fb7156cd2a711fbc64abfd4cd6093bec5d82753fa876f049bf4f1c7be80f29ec67ab0c9bb36d8074dde975a0bb67d3a8f7d9fe43b34abc13643e75781ed0f3abf126c0feafc2d60fbbdce7f01b6dfe9fc12b03da0f3af83edb73abf0c6cf7ebfcf360fb8dce3f07b6fb74fe59b0ddabf3f82edbaf75fe3db07da2f3f80ed5749ddf05b65fe93cbebb738fcebf03b65feafc33609ba6f34f836daace2f02db2f747e21d87eaef30bc03645e7e783ed673a3f0f6c93757e2ed87eaaf373c03641e76783ed273a3f0b6ce3757e26d8c6e9fc5360fbb1ce3f09b61fe9fce760bb4be79782ad85ce2f079b8c1989fd548a75fe0db0b5d279ec7f24dff79f04b6363a3f116c6d75be0e6cf26db8316093f1a06bc196d0f91ab095e87c35d8e4fc6c04d864fc93e1609373a961603b42e787824dce7b86804dc6b31c0c36f906693fb01dadf39560936feb5780ed589d3f003619736c31d8e4bb75fbc02663313f0c36f95ef50cb09da8f37f009b8cc3f220d84ed6f9df83ed149dff1dd8e41b9e0f80ad4ce77f0bb68e3a7f3fd84ed3f9df804dc6c8ba0f6c67e8fcbd6093b1837f0d36f9def32760eba4f3d3c176b6ceff0a6c3296c83d6093f1417f09b6ce3a3f0d6cf21deea9603b5fe77f013619efefe760936f0c4f019b8cebf633b075d5f9c9604beafc4fc1d64de72780adbbceff046c3d747e3cd87aeafc38b0f5d2f91f83adb7ceff086c7d745eda19b53fabfd7cbf9eaf0ae23b2f53fede0f1a4e99ae0d840179e23cd72e051ef4b537f6ba2753e7f5b2dfb7d0eb9518da0bbe77c7ee3b7d4db147afab955eef6ec3773194395b370e6ab977e1ff555007590eef63c9ba65990b60d9f78c75b7d7f5dde3a8bebb0d26e1de034c52e6bc53ebcbfe40e7dbc23231b2a5ae8f25d602d010a72ac80b831bad92e578dedb189e3dc0b337769ef4f5ba8b98c07d2beeeb75f33eae196ba5506637e8f79e03fd705f9775cbbcf8f3cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfcccfac78f6eb3c3e579672fb4918c5b617785cdce7c7e7b0f8ccebbd53ebfdee8ddd6fc3e77badf57acb8d3a1743992fe199d33e9d2f81ffcb768bda960e9e1366dc96e2af04ea83cf82f63be2d96bf0ecb56821f9b2d87c2747b9d13859aefab2a867ecfb0c5df75b3475b5bfeed5eb2a3234c5fdf57d83079f8d9600ef07fa3701ebf900eae0601fcf1817e20ff7a5bd6093fcfbc0e8623be3b144da03791e2efef0b9f8af8ce7e2f16ffb64b9cb76439ef99bcfdbb1ae52e677d0f67daaf3d837643faceb1f96ffcb94e939b5e8a7eabc33fe3aa7b6aff46994edbbd3e2fb6d608dc9778377688a74123f622f86fcdfa13f8794133d446b61c7f1ca91dd5cee7d63b95228b3cb52ffaa20defaef3478761acc2a763e8738fb071cff5db549bb2234ba003492327b41a37d8e78f61a3cc221fe5419d9fe6d8c32b26c3194f99fd046a9ba483b2ff5c4be2d780c78d751fdc497ac5be6c51f9e1bef0146b38e2a3e061d5bcfbb3776defceaffd5a62cfd8bed7a5cfdbf64ddedf5b2c21118eb2f87f5ff8b2b883eb6fc6bfb96d5afdf65ffb27d469d85650f304999f665f5652fd5f96ccef50fd5755bd4b9fe2e073c89a0e1b5b79a321ddff118e3a27d7154cf72dbb1eb3da34ea550a613d4d3c1794cc6778177826f17db1cb59073a8dd8616c550a66359fa57da8e281df15a754f4eea92b49e0f965bea22653a95d5d7a52dd8e36472b9ddf03c4bad77afa5ae52e6bcb2fab25d743e01db09dbd27e96ffcb94a93dc0b178b6c75fe7d4f69577de64fb6eb7f87e0b5863f2dde05b2072be2f7ec45e0cf9cab2fab2524ef410ad855ded23f2ce1fb29bcbed36962b85323b2cf5af0ae2adff768367bbc1ac62a76b597d5ee2c865bbb92342a372d048cae0fd6339b6e37b77b6e3fe5e47dc51c7fdbdc068b69b78eee2926d9fc166de43b59d0f4a195916cf07af2a4bffaa763661296bde1b76711f13df410da01e8151579930061c5c1b76c76b2769a7c44f17b0efd579d1b98ba15d3194195c96fe7578de6dbd77695edfe13585709bfb16befb31b4ac9e1bc74edcab7f4bc0f691fe75749dd6dd76cf50386cf70c4794d5b3e3b2c2f5a1a52ea281946d117cf59efa974659bcef966939336f8e43a9f4fdc82867f383d73cb1bdabd1b5bc1c995a58b4c0fbde52ae28f8ea989bb21f60cc99f751ba18ebc1fb287565e95f6993ccb2aa4dfa1f47d7eb23db51b4c3f60463f27d60acd2f9f2af3775b5d55fe6c59f62fcc0a8839bb62bfdbe5236f781f7018f8bb6dd511b5d8ec7d8b6b1adb74fb5edf8ffbea1550e9fd75a8ff9e633f7b6463e1edfc91adbfd279b16bb2d3cae9ea34469b1dbe23b3e2d7a8eb21d3f6c5ae4b2ef439416ef597cc7a8452ddef7cca4c5bb161e57f7baa3b478d7e23b3e2d7a95677aae815aecb2f0b8baf710a585f8cb96f93d02e6b6463e1edfddab6df7c96c5aecb4f0b8ba6e8ed262a7c5777c5a74ed89f7e83269f18e8527fefb7399b578c7e23b3e2d7af7c17b7899b478dbc2e3ea996e94166f5b7cc71817a36df7726c5aecb0f0ecc8b1163b2cbe633c3fec69bbd766d362bb85c7c17dd78c5a6cb7f88e518b9178df359316db2c3cdb72acc5368beff8b4a8ee61bb276cd3e22d0b8fab7bc2515abc65f11d9f16237b2bdf5b1ba1c5560bcfd61c6bb1d5e23bc66ba8545c6c6984165b2c3c5b72acc5168beff8b4a8499d6b6d6e84169b2d3c9b73acc5668beff8b4284f1d533735428b4d169e4d39d66293c5778c7191ba9edcd8082d365a7836e6588b8d16df311e475271b1a1115a6cb0f06cc8b1161b2cbee3d3a23675ff697d23b4586fe1599f632dd65b7cc778cf251517eb1aa1c53a0bcfba1c6bb1cee23b3e2dbaa58ea96b1ba1c55a0bcfda1c6bb1d6e23b3e2d46a79e89ad6984166b2c3c6b72acc51a8bef18cf3b53edc5ea4668b1dac2b33ac75aacb6f88ef1bc3375ff625523b45865e15995632d56597cc7d876a6ce3b5736428b95169e9539d662a5c5778ce79d292dde6c84166f5a78deccb1166f5a7cc778de993a8ebcd1082ddeb0f0b81a03254a8b372cbe638c8b54dbb9a2115aacb0f0acc8b1162b2cbe63bcaf956a3b9737428be5161e57e3354469b1dce23bc6eb91d43dbe658dd062998567598eb55866f11de3b3a2d439f8d24668b1d4c2b334c75a2c05dffb62f79deecf2d3ea42fd6f98616c550e6948ee95fe98b15a5a3ac03fb95615d5e8fbd2ee97e654b22eaf23ad445ca9c0175691b3819a3a8bba3baa66266b15e97f44dffc0525729734ec7fab29d753e01dbe44358575fcbff652a32e6ab202ffaa93abf1a7f9d53b12a63c8c8f67dd5e2fb65608dc97757f45da493f8117b31e4fb74ac2f2be5440fd15ad8d53ef29ace23bbb9dc5263b95228f39aa5fe5541bcf57fd5e079d5604ebdf700712671e4a6ed4a33bd16a1d1f9a09194c13e7b1f38e231fb100a87f8536564fbb731ca601f4a297321b451d8af54ea9908beda6f52d56fb1a3fa892f59b7cc8bbf52b0ed0346b38e2a3e3e81be9f3256848c23a16c322e4437584f2fc3a6eadadb515dc597ac5be67b03a38c53d12bf78cc9c632f63418154f5f079ae1d81b32653a5ef4059e3e0e781cd533751caa30ead4dba8532994c1771b2b1cd4b308fccaba65be027cbbd8e6a8851c93cf31b4288632238cf3c7281d651d2a7e7b59ead2df715d64ddd22ef5cf81ef4ac3770fc3772268b89d8320f3fe5509ccfd1c30abf50e887fbde578de2631257e7a409d06820671d509d725e779030d6d8b213f0dcef3a49c9495e397b0ab58966d89ece6727d8de54aa14c7f4bfdab8278eb3fc0e0196030ab63f75d706ee7607f48c5407f8343e67b80760322b4eb0fda49193cfef574a45d3f8347e67b028f9ce354804dce15843f01ffef96036eb3ddabb0708b0dc789eb6961ec113f63ea5ca7a7c128f33d80516cfd80a7d29166e6b63ec7d0078fcb6d8c32b26c3194990dc7c684a5acdaef3a15d5d7aba5b6c7f6ee986ed35b3bd00bc7690c409fc0d0502661681bd48fe518274fbba07eacc62953eb268fbc73f40da3d38f1e05add8c0c4df224b355a800df32d2db6206838246531d86448ca56606b61c88243614a7919d2ce855ca887acbbd8e06c0b2c71fac6e13c65ca143a6d80c74528abd091213d75e8dc3279ecd4d1181fad0ccea6c48efa5fcb0ce5a2d6e56a3b98fb4415cc9b3158ecc87f4ba86f15cc8b3fb56d4a757ee2c851770f9c7ce7b4f1a3274c9d8242993b36e68b82861bc0fc8d12dcd54e87018015c6c6a195512f6c30e47fb261dac5cfd91dc7cc35b509c09f4ced40b7c31ce8a6d62f63df8e1a396edc75d3aac78d1d75e9b409a3a68ead9b805bb3ada15cd49696ffb7069bad89c7b26ac2660b976d63b1d9261c65b82dd8e4c87518d884a71dd85a425eca9b5bc649b87682f5cb2ea5fea7c469a52bde26a80f01391cab7655edbfeaf3b1ea34480d75ac8636569b530d5dacee18aaa189d557ecd4d0c36aa86135b4f009417ae8603554f0c9417a2860f5b58bb2203db4ef69417ae8de3382f4d0bc6701dfb781f9ec207ddaa586d6ed1ca487ce55b72ed5abebea336feadd7a75faae6e0ba8535e7589a74e3fd569a7babc50b72fd4ad2c754aa74e97d5a9a03a7d53972303b4d603c37461982e0ad3c561ba244c9786e9b2305d1ea62bc2746598ae0ad3d5611a14a66bc2746d98ae0bd3f561ba214c3786e9a6203dbcf3cd417af87535fcf3ad417a68e8db82f4b0d1b707e921a5ef08d2c34d8f0cd243518f0ad2c3548f0ed24358df19a487b71e1ba487c9bd3b480fb53b3e480fd7ab86c356c364abe1b3d530bf6a486035a4b01a6a580d4bac8630564320aba191ef0fd2432eab219b1f0ad2c33ecf08d323617a344c8f85e99b617a3c4c4f04e9e1c1d5b0e13383f430e36af8f139417ab8f279417a787335ecb91a0e5d0d93ae864f57c3aaab61ded5f0ef6a58f817c2f462985e0ad28f24d4a318f58842ddfe57b7a7d523a2d783f4adf36541fa11b77ae4afba40a82e21aa8bccaa20dd854a7529535dec549743d505537549555d74559765d5855b7569575dfcd52b0fea1510f54a8c7a4548bd32a55e2153afd4a9570cd56ba2eab54bf51ab17aad7a6f90be2dbe3f483f2a55b7c3d5a30175cb5cddbeff384cdf0ad231f99d307d374cdf0bd3f7c3f48330fd30480f6bac863b56c325aba195d530cc6ac8663594b31a0a5a0d1bfd49901e7a5a0d5dfddb203d24f6efc3f469983e0bd2c36b7f1ea63f86e98b30fd294c7f0ed35fc2f4d730fd2d4cff16a67f0fd37f84e9ef61fa4798fe19d40fb38d0dc909baf5d15730c1c8a953478f9f38b56c6a5dd9f869e3a68e9d38eebeb2e963a78e29abbb67f4e4da7175d371e16feb85658cf08193278fbcaf6cec849ad1f796d54d9b5a56575b565d376d424d8383f85ff442277dd5e3c89a9a6867fff57548ff4f139d1ea6db45197dfd8acc752b69d904418e6cca423d5b36ad4293f5114c2e756f4c9f07974d195737b5acbc6c42f8373cf0d64d1f5dd3a50cff37251479cad4b22953474e9e5a563bb96e7c59d72eb8de87db35a112ffddce0dcc9927344d9c4efa3b4b4d0ab15f9eda0405fef3d4a691b62efb1aa4edca9ae6b4acac09353cab290b5dd944c29bca22659932ad7aeae491a3a6462f7cebd759f88ea654734213ab7972c726383bbd290b0decd834c23b9ae26c5616ce82ff0f9c57cf6b84550600", "isInternal": false }, { "selector": { "value": 2603445359 }, - "bytecode": "0x1f8b08000000000000ffed9d67701cc7b1c7f700100cc72308e64c28514c000f8744800994c41c642a8b4a0449502245121409e51c6ccb966dd9720eb264cb414e720e72ce39e724dbb225dbb265ebcb73bdf7ea55a9deccdeb4f1c76876853b6f83b3b8deaae6cd36e6b67fdddb33bb3733bb7c2608824c50dcaa959c143c77a3bf779bcffc7fb6352778ac3c276726259c5529e1ac4e09674d4a3847a584b336259ca353c23926259c6313e4d46c55c1e02d69de710c714d9a319bb2988e4f414c73298be98414c4b42e48471f3531259cf529e19c9412cec929e19c9212cea929e19c9612cee929e19c9112ce9929e19c9512ced929e19c9312ceb929e19c9712cef929e16c4809e70929e13c31259c27a584f3e494709e9220e712e05c603e4f359f0bcde722f3b9d87cd277969acf46e3638dd96f52b24cb32969b6fe5650d2a2a455499bf5b776251d4a962be9347f6b307feb52b242c94a25ab94ac56b2c6c461ad92d3949caee40c25eb94ac57b241c946259b946c56b245c95625db946c5772a6921728d9a1e42c25672b3947c9b94ace5372be920b945c68b1ec547291928b955ca2e452259729d9a5a447c96e257b94ec55d2ab649f92cb955ca164bf92034aae547250c921258795f42939a2e42a2547951c53d2afe46a25d728b956c9754aaeb7627683921b95dca4e4668bf31625b72ab94dc9ed4aee5072a792bb94bc50c98b94bc58c9dd4a5ea2e4a54aee51f232252f57f20a25f72a79a5925729b94fc9ab95bc46c96b95bc4ec9eb95bc41c91b95bc49c99b95bc45c9fd86851ac25b953ca0e441256f53f276250f29798792772a799792772b7958c97b94bc57c9fb94bc5fc907943ca2e4834a3ea4e4c34a3ea2e4a34a3ea6e4e34a3ea1e4934a3ea5e451259f56f219259f55f239259f57f205255f54f225255f56f215255f55f235255f57f20d25df54f22d25df56f21d25df55f23d2be6df57f203253f54f223a3fbb1f9fc89a94be3623f55f23353feb9f9fc85f9fca5f9fc95f59d5f2bf98da5fbad92c72cddef94fcde94ff603e1f379f7f349f7f329f4f98cf27cde79fcde75fcce75fcde753e6f36fe6f3efe6f369f3f90ff3f94ff3f98c92dba714cb638281ad3b48a88f6add97d7732a14fc05c1e04dc7a2dafc8d3e1b8cbec6ecd327c56e94d91f65e96bcd7ead759c31667f8ca5af37fbf5967eb2d99f6ce9a79afda9967ebad99f6ee94f36fb27833e1bc098abd16b5db551654047f95a05ba5146570dba5a3a1ce8461bdd28d0d1f9ad05dd58a31b0dba714637067459a31b4bb15432dee8ba83a47225dfa38f9b4bfab8661e6a42f2bc7bf471eb98782726cfdbab8f5bcfc0abf3639239d644c89bc946570f3ad3dd04934037d5e826836e9ad14d01dd74a39b0aba1946370d74338d6e3ae86619dd0cd0cd36ba99a09b6374b34037d7e866836e9ed1cd01dd7ca39b0bba06a39b07ba138c6e3ee84e34ba06d0d11a97134077b2d19d08ba538cee24d0515f7b32e8e8def014a3d3fdc4980c7cc7e8a98f0abf43fd33e81652df0cba45d42f836e31f5c9a05b02b649b714fa15d2351a1df551fa6f5da6dc1d24d5260a619b5891f471d591f57157257fdc70de6e753010d76eb0b30262b5c694135c1bd48cb63346c80ee96ba0bc09ea523d8a075d67885d5f4f569af29a98ef7559dfcb419d950effbb8364fd5f65f1acb2984781ff3c39db52909c1df25672ce9e0f75eddca37b9e9198b35b81832167db256787bc959cb3bd50d7ce3dbaef1d8939bb13381872b68727670b79c9d9e2185910b8738f7efb8cc49cbd023892cfd936c9d9a16f25e7eced50d7ce3dfafd3b1273f61ae0483e673b7ae4de60c85bc9397b2fd4b5738fc6624662cede051c0c39db2bfdec90b79273f67ea86be71e8d0b8ec49cbd0f3892cfd94ea69c6d919c0d8af39d41e0ce3d1aa31e8939fb2070249fb37b647c76e85bc939fb28d4b5738fe64b4662ce3e62ca7a9ee1c7669e610ee87e6274738137f9dcdedbca94db05c9ede23a902070e728cddd8dc4dcfebc29eb3cfe39ac3d20dd2f8cee04d0fdd2e84e04ddaf8cee24f08ba10df4481b18f256721bf80dd4b57399e69147621bf8217030e4ec1ec9d9216f25e7ec5350d7ce3d5ad3301273f677c0c190b3bd92b343de4aced9ff86ba76ee2d34e59198b3b4ae54df2ffcc1dc2f2c06dde346b704747f34baa5a0fb93d13582ee09a36b02dd9346b70c747f36ba3ce8fe6274cda0fbabd11540f794d1b580ee6f46d70ababf1b5d1be89e36ba76d0fdc3e83a40f74fa35b0eba678caed3e8f47c17adbdfab6d1e9734bf1e80e923bb7e17aab60f096b1f6bba1dcc8cb93cf05839f45205bcb92b7d5a27d6f0a86eefb32e0c933f89e051b43e1c9034f73f23ce1bad342f2c70dcf719315d32cd86a02bf5a18fcca802d3a36ed93bd1ce8b02f697130b626cf58c8802d3a36edb70223e9b06fa36b0cb51fdd373764067819da52787d467bddc041f66aa0cedc2903754f366ce3e1efd4078c8732f6fdcd968e2957c35c215b746cda2f0023f9d83cfc8c85a132e62d46ae7e2303b6e8d8b6edf18ef8e898b53a62d6c6c4d86a31d27e1b3052fc5a879fb1305446bb5f60ea939a87da27515c9a873f66433aaf39d0e1fd5f9b83b13d79c6f0bcb6598cb4df0e8ca46b011eaeeb61547bf5c536c77d08e6335db3e8fa43f66aa04e47f540ddad703d65e8430ba5de9b629f9efc792ae4f17a36141ee673d7cc948f79ec3b9f0d92cd35bbcd375bb1c2368f7d39573f19d597933d61166661166661166661166661166661166661166661166661166661166661f69f396a5eceb59ee1783292ae003c1ce3fce13baaccb1700ee83198d7497edea290c7b97a5ac7b8c8f2b906eafc5f6680ed71c73a099c3b5f66e998d62985e712d72975c33ed9c3751bb86e8a61ed49c8b3d4e2b16d8f77c4c7c775243eadd1885aa7e553cc72a0c3f5704d4c3c5179d6e4b0dd9098edc21e9eb653c8ebf701e977ea517f62b7115cfbb6c4d2e93ea9ab7ac06f8e1c2875de19af1b544e721e17f30d6d25bfdea630687d425530f85a81f7140c6b5406cd57d3da8876cb760dd4195b15fcfbdc2c87bf7707cf5d23a4eb7458c7a6ef2c82ef7658c7aee3f337b63f6c076e2ad75abe350237d5995035e0e3e74c99e97ea680eb6703e00d2c9f68c3f519c9dfef15d78bb494c0d3063c1c6bd798ee6bf3988f49af17e9b062e5ba5fa63aed10bf0e86f8c5ad59237bc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc2ec3f33beff8258f119e982278cc3b4c6269ccfa07719e1bcd803550376b9e70069ce69b1e5333ea3fc74d500db43a68cef08703def8ee7926b6e2dea5c92bdf1c1739fd3673a97437ef7439b23661d8e982d6762b4fb0cda5f0e8c14bf0ee0e16a8fed168f6d1bfb8c364f6316d5cf72ad5f89ca33d73a8586c46c17d78b70ccebd27a11fbfa55b0628aeb244887f3e0f86e159fdfff62af5dc07e0ad76825df6f1606cd01db6b05c91eae93f886892dad9348be1f28e439af11d446694d488bc357aaf35db8ce7ddf9471ad50018ef598e3efb4c5ad49c03e35f17770e68b73fcf4ee4a3abf5d0edb2b813521dbcd683b6384ec90be06cabfad1aa84bf5281e146b62d76d84de6588ecf6f79aadefe5a04ea7c3ffee2059ffbb2c9e2e8b59e7ce8f20cf1e837b3dae3ea93322468b20465407ef79b9ae5ff69a6d7bad32f6a3a3ad3af4dd1aa8f324f451a5bc2b8aeb7e21ea1a80f70bf67561286bc72b7d3de0bfa0bf487a3de0bf20875cf7a574fcc5707ce21a1d445f5ba8ceff5ad75186f57a437aef95ebb71ff1e27a43aaf32cf45579b32e37ea778ceb390baedf0d51cf7d903dbca72ac577ec1792be36623e220be6f2bfafd126d6948f1d11dccb1cdfcd467c976245ebcbf177b21d3f1d874ef84e77227128f6375d962fd4a63ac117aa530fbef0dc3315ef3f93f775f0fd10f541ad0e5fa9ce347817dc0c53cec279c2bef254c7df698bbbffa4f8699f87fb9dea68db8777aa2fa81ea86bbf1b9d625dea3bd5dbadeff9f84ef5d99067a7c2b3165c7df5ca88182d8618511d7cd6d1fefd1f758d399eef25b5fb4dbc4e0e279b3d7eebba3fa13a780f4d75daa09fcd3aeadae3d2740d49727d3a3e0fb414ece2f3404b99e2990b06c733677170daaeb36cd70da3ed7acb76fd30da96984bcc7d8a39c3ff3d51f6ff8581ff6745550a18ab53c0589302c6512960ac4d01e3e814308e4901e3d814308e4b016316188fe7b59d213e05cffebfa7d87b0db4cdf03e8730168dc1d063d1c4cb137bef83b619dea152f2ff37c0fc7f613597fb7f61e5e07b9352c03839058c5352c03835058cd352c0383d058c3352c03833058cb352c0383b058c7352c03837058cf352c0383f058c0d29603c21058c27a680f1a414309e9c02c65352c0b8401813615cc2cb58f0edff71ce0683d79a3d1f0ff3bb47c37728bade73caf17fe396ea3bf37b879bcb7d4f1faeb1e0fdbf1effb3770972aca128f55d8271ff3f361363a15c46aeb5e4b88e7a283cf81caaebf91606c642b98c5ccfa0e0339143e171fd5fbdbccf041563560e23d79ab152d734e2b382ed8e98313016ca65e47aee009f891c0a8febd9c5665ec642b98c5ceb73b36063283c9d10b3e58e98313016ca65647abe2c8c5967093cf81c56a723660c8c85721935cf0aa6987595c0b30262d6e588994f8cc893f43bd1bb1cb6389edb2bd5776240c6b129601c9702465c27c1d17fc5ad93e8e28d4fa1dcf8709dafb87512689be139913016f85cc0f3c562152f4fec3a09b4bd9a2916f8dcc6f3c56235f0703c4792051b43e121861c7c6f520a1827a780714a0a18a7a680715a0a18a7a78071460a1867a68071560a1867a780714e0a18e7a680715e0a18e7a780117fab32dc2bc6fe7e593dc26d47fd5619e9b6a37e978c74db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf2bc1b6e4b9e4b94fb6d330c62f8c238f11791a92e3c9a3ef68abdb03dfbb1d3c1926dfd1d65a0f7c2786b431ae4901e38a14304a1c8b6b10cb61d43ca731f1ac2d81e734e0399d89e7b412784e079e3392e70973eaf41278882107df5b9102c635296094384a1c7d629438564e1c8551188551188f07631afa70614c453e16ca65d43ceb92e709637646093ceb2066f4bd665ec642b98c9a677df23c61ccd695c0b31e62b6ce113306c642b98c9a6743f23c61ccd697c0b30162b6de113306c642b98c9a6763f23c61cc3694c0b31162b6c1113306c642b98c9a6753f23c61cc3696c0b30962b6d1113306c642b98c9a6773f23c61cc3695c0b31962b6c9113306c642b98c9a674bf23c61cc3697c0b30562b6d9113306c642b98c9a676bf23c61ccb694c0b31562b6c5113306c642b98c9a675bf23c61ccb696c0b30d62b6d511335f1957a480714d0a1899e358289751f36c67e2d95602cf76e0399389677b093c6702cf0b92e70973eacc1278882107df5b9102c635296094384a1c7d629438564e1c85511885b134c6ee1430cab916465f19197e5fc53e4373e608b75d67d9aeab10db51cfd08c74db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf2bc1b6e4b9e47925d8963c973caf04db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf2bc1b6e4b9e47925d8963c973caf04db92e792e795605bf25cf2bc126c4b9e4b9efb647b47f2b60ba53ec3ba0378389ea965f233af8f7b9639d6b309c64fc7ea6c2b56675ab1ca419db3207e6733c42f0376e9d8b44ff64a653ed5036626db8509ea1863c17fb2b1c68a87b67f0e93ef517dfd3923dc76545f3fd26d47f5f523ddb6e4b9e47925d8963c973caf04db92e792e7bed8c6f2a860e0be9ddeafa48f712efc3d63b1eaad06eaac1a5dfcac0ba40d71d8963624d78a4ab02d792e795e09b625cf25cf2bc1b6e4b99f797e5ef2b6c3b931fc7da1b7b8b9b1f380e75c865830f999d73e9d6ff9748ee5530eeae03b6bcf67f0330376e9d8b47f3e9c87b4316b9ed5a64cac59a8b7da1346d29dcbcb13b6afd5c1e02dae7d9d0f3c0ceda099c9cfb07d5d60f9b4da1177aa83b97a01839faeb643fb17c079481bb3e6596bcac49a857a6b3d6124dd79bc3c61fb5a1b0cdee2dad705c0c3d1ff30f919b6af0b2d9fd63ae24e7530572f64f0d3d57668ff42380f6963d63ca79932b166a1de699e3092ee7c5e9ed62cf84c5b5cfbba107838fa1f263fc3f6b5d3f2e93447dca90ee6ea4e063f5d6d87f677c27910666176316b1efa3fe589350bf54ef784917417b0f2b4e6b3e0336d71fdd84ee0e1e8e799e21ef66317593e9dee883bd5c15cbd88c14f57dba1fd8be03c94c2bc2685cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc12e7f29835cf19a64cac59a87786278ca4bb9097277c7ee78c60f096b1f6bba17c11f0ec64880f939fe1baf78b2d9fce70c49dea60fbba98c14f57dba1fd8be13c94c2bc2685cc12e7f29835cf3a5326d62cd45be70923e976f2f284fdd8ba60f016d78f5d0c3c1cfd3c939f613f7689e5d33a47dca90eb6af4b18fc74b51ddabf04ce83300bb38b59f3ac376562cd42bdf59e3092ee22569e42f81ce2fa60f016d78f5d023c1cfd3c53dcc37eec52cba7f58eb8531dccd54b19fc74b51ddabf14ce4329cc6b52c82c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c2b27ce9a678329136b16ea6df084917417b3f2b484f30e1b82c15bdcbcc3a5c0c3312fc314f770dee132cba70d8eb8531d6c5f9731f8e96a3bb47f199c8791cebc2685cc921bc3c32cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc5ec436e689e8da64cac59a8b7d11346d25dc2cb13bef7606330788b5bb77319f05cca101f263fc3753bbb2c9f363ae24e75b07ded62f0d3d576687f179c875dc22ccc0e66cdb3c99489350bf53679c248ba4b7979c27e6c5330788bebc776010f473fcfe467d88ff5583e6d72c49dea60aef630f8e96a3bb44ff6845998a39835cf665326d62cd4dbec0923e92ee3e509fbb1cdc1e02dae1feb019e5d0cf161f233ecc7765b3e6d76c49dea60aeee66f0d3d576687f379c0761166617b3e6d962cac49a857a5b3c6124dd2e5e9e42167ca62dae1fdb0d3c1cfd3c939f613fb6c7f2698b23ee540773750f839faeb643fb7be03ca48d59f36c356562cd42bdad9e3092ae8797276c5f5b83c15b5cfbda033c1cfd0f939f61fbda6bf9b4d51177aa83b9ba97c14f57dba1fdbd701ed2c6ac79b69932b166a1de364f1849b79b97276c5fdb82c15b5cfbda0b3c1cfd0f939f61fbeab57cdae6883bd5c15ced65f0d3d57668bf17ce43da9835cf765326d62cd4dbee0923e9b09fa2ad0a18b7333106166360c50779e679c6b3c3339e199ef14cf28c67ac673c8b3ce3a9f68c67b9673c6d9ef1143ce399ef19cf4ccf78267bc633ce339ea59ef1d478c6b3c0339ec59ef1ccf28c678a673c59cf781a3de319e5194f97673c9d9ef12cf48ca7dd339e16cf789679c633db339ea99ef12cf18c67bc673c39cf789a3ce3a9f58c67a5673c733ce399e619cf04cf78ea3ce319ed19cf2acf783a3ce369f58c27ef19cf5ccf78a67bc633d1339e7acf78c678c693f180271b3c771d4316febe037455d677f5f565f79481bfd3bc71157c679f29573b8edd0b3a9a67dee7f82ec6896b2e1c6d75c33ed91b0f1cfb3ce119e3194fbd673c133de399ee19cf5ccf78f29ef1b47ac6d3e119cf2acf78467bc653e719cf04cf78a679c633c7339e959ef1d47ac6d3e4194fce339ef19ef12cf18c67aa673cb33de359e6194f8b673ced9ef12cf48ca7d3339e2ecf784679c6d3e8194fd6339e299ef1ccf28c67b1673c0b3ce3a9f18c67a9673ce33ce399ec19cf4ccf78e67bc653f08ca7cd339ee59ef1547bc6b3c8339eb19ef14cf28c6786673c3b3ce399e7194f95836707134fd4b3cd3b3cb1cd701ef2fab89733f974853956ad392ef193bd1aa873921978d4f31ff85de2b2e7ffb1ed5c0131e27aaf44cee2a1fdbd23dc769d65bbae426cd75bb6eb2bc4b6e4b9e47925d8963c973caf04db92e792e73eda7e3639db6df27ea9a1f3c8fb9ce279e47d4ef13cf23ea7781e799f533c8fbccf299e47dee714cf23ef738ae759e0198fbccf299e47dee714cfd3e819cf28cf78e47d4ef13c0b3de391f739c5f3c8fb9ce279e47d4ef13ce33de391f739c5f3d47ac6e3dbfb9c7c7b1fbcbc5f2a9e6782673cf27ea9781e79bf543c8fbc5f2a9e47de2f15cf23ef978ae719e3194fc6039ee77bbf14be17ea0a53de0b3a5a5f1af71eaa2c1ce70ad0d1782e1d435faf0e4d792e43157c67bf83eb72873db2b3dff1dde1883bdaea867db287efabdaef09cf18cf78ea3de399e819cf74cf78e67ac693f78ca7d5339e0ecf785679c633da339e3acf782678c633cd339e399ef1ecf08c67a5673cb59ef13479c693f38c67bc673c4b3ce399ea19cf6ccf789679c6d3e2194fbb673c0b3de3e9f48ca7cb339e519ef1347ac693f58c678a673cb33ce359ec19cf02cf786a3ce359ea19cf38cf78267bc633d3339ef99ef1143ce369f38c67b9673cd59ef12cf28c67ac673c933ce399e119cf3ccf78aa1c3c5cef8c8a7abe7e38de57f57cb6f5fe52888bdeb2f0f7e1788e6b87c548fbb8ee0179896729134fd47b01967a605bfb4fbf452798cf2cfc1d9fc3e1caa9a51623edbb720ad7353632f144bdcfa0d103db3a164da64c6b00b2f0f72660e4caa9468b91f65d3955cfcbd39a059f698b5b6b846d8ee31c32f999c7f697e03b34f23a56dbad583559b1ca419de158971ed51f903d6116e62866cd437329c48ad7b3e178ce6c288caeeb2b034fd83f2e0b066f71fde376e0e1b87e30f919f663072c9f9639e24e7530570f30f8e96a3bb47fc061bb21483616570e2116573a78ae1ce65890bd529977a490d987386b1e5a8b48acb8be39ef0923e996f2f284fd633e18bcc5f58f57020fc7f583c9cfb04f3868f99477c49dea60fb3ac8e0a7abedd0fe41380fa5301f4821b3c4b93c66cd437310c49a857a054f1849b79d95a790cf82cfb4c5f563078187a39f678a7bd88f1db27c2a38e24e75b07d1d62f0d3d57668ff109c0761166661166661166661166661166661166661166661166661166661166661f69b59f3d0b3b1c49a857a2d9e3092ee4a569ee2bc434b30788b9b7738043c1cf3324c710fe71d0e5b3eb538e24e7530570f33f8e96a3bb47f18ce83300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330fbcdac79e89dedc49a857aad9e3092ee202f4ff8dc566b30788b9b77380c3c8718e2c3e46738efd067f9d4ea883bd5c15ced63f0d3d57668bf0fce83300bb38b59f3d0bbda88350bf5da3c6124dd21569ee2fc695b30788bebc7fa8087a39f678a7bd88f1db17c6a73c49dea60ae1e61f0d3d57668ff089c8752980fa49059e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e6296380f0fb30f71d63cf47f08126b16eab57bc248bac3ac3c2de1bc437b30788b9b7738023c1cf3324c710fe71daeb27c6a77c49dea60fbba8ac14f57dba1fdabe03c8c74e603296496dc181e66c90d618e6296dc10e62866c90d618e6296dc10e62866c90d618e6296dc10e62866c90d618e6296dc10e62866c90d618e6296dc10e62866c90d618e6296dc10e62866c90d618e6296dc10e628661f7243f3749832b166a15e87278ca4ebe3e509df7bd0110cdee2d6ed5c053c4718e2c3e467b86ee7a8e5538723ee5407dbd751063f5d6d87f68fc27910666176316b9ee5a64cac59a8b7dc1346d21de1e52964c167dae2fab1a3c0c3d1cf33f919f663c72c9f963be24e7530578f31f8e96a3bb47f0cce43da98354fa729136b16ea757ac2483abc2e7732f1e42c9e9c2316c7cbb6deef32e5f1e6330b7fef0246aefeb0d362a47dcc71e4259e2e269e3a8ba7ce118be3655bfbbfd2942798cf2cfc7d253072e55497c548fbae9caa039e954c3cf5164fbd2316c7cbb68ec52a539e683eb3f0f755c0c895532b2d46da77e5543df0ac62e289ea93560d83eda8f6351cb6a37265386c4bcca363ced0eec2f18155c1e02deebe1aaf2d1c7d15939f79d7f57b95e5135ebff11ef5785d9f845998a39899ee735bb3966d8a4f60f1d076943916c3f93bbbcbf2290dbfb3e3980fa49059e25c1eb3b6dd9fbcedd6ac659be213583cb4f533c782c9cfb03fb83a70c798ece5a00ee6e9d50c7e66c02e1d9bf6af86f3500af38114324b9ccb63d6b6af49dc76f1fdc3689be213583cb45dc31c0b1e3f8bfdc1b5813bc6642f0775304faf65f0330376e9d8b47f2d9c0761166661166661166661166661166661166661166661166661166661166661f69b59dbbe2e71dbc5f17bb44df1092c1edaae638e058f9fc5f1fbeb03778cc95e0eeae039bf9ec1cf0cd8a563d3fef5701e84599885599885599885599885599885599885599885599885599885599885d96f666dfb86e46d87cfe3a06d8a4f60f1d07603732c98fc0cc7ef6f0cdc31267b39a883e7fc46063f3360978e4dfb37c27910666176316bdb37256ebb389f87b6293e81c543db4dccb1e0f1b3d81fdc1cb8634cf6725007cff9cd0c7e66c02e1d9bf66f86f3500af38114324b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc12e7ca89b3b67d4be2b65bc2f17bb44df1092c1eda6e618e058f9fc5f1fb5b03778cc95e0eea609edecae06706ecd2b169ff56380f239df9400a992537868759724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398ad987dcd0b66f4bde76f83c3bdaa6f804160f6db731c782c9cf70fdcbed813bc6642f0775304f6f67f0330376e9d8b44ff6845998a398b5ed3b92b75dc85ab6293e81c543db1dccb160f233ec0fee0cdc31267b39a883e7fc4e063f3360978e4dfb77c279481b339ebf4c72b6c3759b64a3ca7c6add5da65c0dba179a720de85e64caa340f76253ae05dddda63c1a742f01df48f752535e02ba7b4c7915e85e66ca2b41f77253ee02dd2b4cb91374f79af251d0bdd2948f81ee55a6dc0fbafb4cf96ad0bdda94af01dd6b4cf95ad0bdd694af03ddeb4cf97ad0bdde946f00dd1b4cf946d0bdd1946f02dd9b4cf966d0bdd9946f01dd5b4cf956d0dd6fca0b40f75687ee0153be0d740f9af2eda07b9b29ef00dddb4d792ce81e32e571a07b0794e9f39da63c1e74ef32e51ce8de6dca1340f7b029d781ee3da63c1174ef35e57ad0bdcf942781eefda63c19741f30e529a07bc494a782ee83a63c0d741f32e5e9a0fbb029cf00dd474c7926e83e6acab340f731539e0dba8f9bf21cd07dc294e782ee93a63c0f749f32e5f9a07bd494f1fc7eda94ef001df52b77828efa95bb4047fdca0b4147fdca8b4047fdca8b4147fdcadda0a37ee525a0a3bc7b29e828efee011de5ddcb404779f772d051debd02749477f7828ef2ee95a0a3bc7b15e828efee031de5ddab414779f71ad051debd16749477af031de5ddeb414779f706d051debd117494776f021de5dd9b414779f716d051dedd0f3acabbb7828ef2ee01d051de3d08ba06537e1be84e30e5b783ee44537e0874279932f633279bf23b41778a29bf0b74d417be1b74a79af2c3a05b68caef01dd22537e2fe8169bf2fb40b7c494df0fbaa5a6fc01d0359af223a06b32e50f826e99297f08747953fe30e89a4df923a02b98f24741d762ca1f035dab297f1c746da6fc09d0b59bf22741d761ca9f02dd72537e1474741da77e46b767dd2e290e1423ad239f9b1cbe906e0cf8d21d247b4f47b6e8d8b4df028c740e0ac3cf58182a63b3c5a879da18628679455bdc6fa636e06965e061f233fccdd46ef9d462f994833aa7829fed0c7e66c02e1d9bf6dbc136c739c758d49ae32eb4625103755acd454e5f4fe3e248c7d0f95b70f8c215c7668ba7d961bb93398e746cea133b87c17687653b6fd9c66b016d716dbb0398973330ebe376257fdcb06daf30c7a27c263b79f06925c420299fd076c608d9217d0d94b74c19a84bf5281e74ed2476dd8ee85c22bbfdbd36eb7b39a8d3e9f0bf3b48d6ff2e8ba7cb62d6bf27baa70c7030b48730073a2d0edacf43ecba2262d709b1a33a78ed6d648add728b87f61b8187eeafda4147f729c48ff7784dc3c06df77bed0e6ed2750063a383b1903c63789fd56831d27e011849b71c783a9862669feb85567cf09e60b45587be5b037576c17539eba8abdb5d4366c02ffafdff6c906c9f5ecb102f1c9b08203e811543da88614c30307e9124cfb860607ce2587fdfd19ecb7bcfeaedd99b01b41a0b133f330e37aa4087e56a872e08060fc3e070300dc3e070709515161cfea1fafa679c768b863a7a0fedef3ff770efe13d47af3fd2dfbb776bdfe5483dcaa247d2280f901475b48d0906068cba836427826a2d5b71c933063e4727cfd3cce46778d11b6bf9546bf994833aa3e06f6319fccc805d3a36ed8f75d84eb0230a63316e08b118e7e01937ccb1c04177d2614ba5bfe3c44d95e50bb668f4c9cef3441d22830be0f81903a7ffa61bfb28e3cce860e06453efa9ef68f549d0a3b5faaaa54763f5e8abee82f4e8aabea0e9d1533d5aaa4747f568a81efdd4a39d7a74538f66ead14b3d5aa947271b82e2e8a31e6dd4a38b7a34f11460fb36f0ea5ff4fa0aa94703f5e89f1eedd37756fa0e40df8de8bb6f7da7a87f3dea3b04fdab568f70e8abadbe93d157697d65d5778afa0e51dfd1eb3b5c3d43b65ac91a13ebb54a4e5372ba923394ac53b25ec906251b956c52b259c916255b956c53b25dc9994a5e101447f6cf5272b69273949cabe43c25e72bb940c9854a762ab948c9c54a2e5172a992cb94ec52d2a364b7923d4af62ae955b24fc9e54aae50b23f28ae0aba52c9412587941c56d2a7e48892ab82e22c9d9e95d3b3707ad64dcfb2e959353d8ba667cdf42c999e15d3b3607ad64bcf72e959addb82e26c949e89d0330f7aa641cf2ce899043d737077509c19d03301f704c5917e3db2af47f2f5c8bd1ea9d723f37a245e8fbceb91763db2ae47d2f5c8b91e29d723e37a245c8f7ceb916e3db2ad47b2f5c8f5834171645a8f44eb91673dd2ac4796f548b21e397e38288e0ceb91603df2ab477af5c8ae1ec9d523b77aa4568fccea91583df2aa475af5c8aa1e49d523a77aa4548f8cea91d0cf28f9ac92cf29f9bc922f28f9a2922f29f9b292af28f9aa92af29f9ba926f28f9a6926f05c5bcfc8e92ef2af99e92ef2bf981921f2af991921f2bf989929f2af999929f2bf985925f2af995925f2bf98d92df2a794cc9ef94fc5ec91f943caee48f4afea4e409254f2af9b392bf28f9ab92a794fc4dc9df953cade41f4afea9e499606066053b9131a6e7a151fe9efefede4347fa1bfafb1a0e5d7db07fff9183d7375cbbbfff8a86be6b7a8fee3bd8772d7ef9ebe6cb3485b1f6e8d19eeb1bf61fdedb7b5d43dfd5fd0d7dfb1a76f75d7d78ef31fcd213e64b739e6bb167efde6863fff59f90fe4f9946479b3e91268736c5fb36aeba8c804c2ce74badd5e539b4d25c75e8d7fbd9c5bbdd866307fbfa1bf20d87d5bf3d07d5777af73635e0df8ea9201feb6f38d6df73b4bf61dfd1be430dcd4d78dc13c797e144cb9432be74d994a17b1efc3f390dd8cbf1d90300", + "bytecode": "0x1f8b08000000000000ffed9d77741cc791c6679118164b1024c11ca04433015c2c12012630674a9464e5409004455a24419150b22c4bb224e79cb3e5749673ce675db4efce77bef3d96739fb9c6dc941f7cf3ddfbb7bcfefba67bb8c0fcd9935169a026bb035ef15b7a7b677ead7df54f70eba67874f054190098a5bb5b18b8273377abfcfbde69fded696e0b1f29c9c99947056a584b33a259c3529e1ac4d09675d4a3827a58473724a38a724c869d9aa82915bd2bc5319744d9a319b324deb53a0692e659a4e4b81a60d413ac6a8e929e16c4c09e78c9470ce4c09e7ac947036a58473764a38e7a484736e4a38e7a584737e4a3817a48473614a3817a58473714a3897a484b339259c17a484f3c294705e9412ce8b53c27949829c2b8173a97b7d867b5de65e97bbd715ee953eb3cabdb6b836d6b8fd5663ab2d9bb136efbd82b176631dc63abdf7ba8c751b5b63acc7bdd7ecdeeb35b6d6d83a63eb8d6d30b6d1e9b0c9d866635b8c6d35b6cdd876633b8ced34b6cbd86e637b8ced35b6cfd87e63971abbccd80163971bbbc2d895c69e69ec2a63571bbbc6d8b51ecb75c6ae377683b11b8ddd64ec6663078df51b3b64ecb0b123c6068c1d35768bb163c68e1b7b96b15b8d9d3076d2d8296383c64e1bbbcdd81963678d0d19bbddd81dc6ee347697b1bb3dcd9e6dec1e63cf3176afc7f95c63f719bbdfd803c69e67ec41630f197bd8d8f38dbdc0d80b8dbdc8d88b8dbdc4d84b8dbdccd8cb8dbdc2d82b8dbdcad8ab8dbdc6d86b8dbdced8eb8dbdc1d81b8dbdc9d89b8dbdc5d85b8dbdcdb1504778bbb177187bc4d83b8dbdcbd8bb8dbdc7d87b8dfd85b1f7197bd4d8fb8d7dc0d8078d7dc8d8878d7dc4d8478d7dccd8c78d7dc2d8278d7dcad8a78d7dc6d8678d7dced8e78d7dc1d8178dfda5b12f197bccd85f19fb6b637f63ec6f8dfd9db1bf37f665635f31f60fc6fed1d83f19fbaab17f36f62fc6bee669feafc6fecdd8d78dfdbbf37dc3bd7ed3d5a579b1ff30f62d577edcbd7edbbd7ec7bd7ed7fbccf78c7ddff3fdc0d80f3ddf8f8cfda72bffd8bdfec4bdfed4bdfeccbdfedcbdfec2bdfed2bdfecabdfedabd3ee15e9f74afbf71afbf75afbf73afbf77af4f19bbaca9589e1c0c6f7d41426354c7d1bc5d5321f197062337ab45b57b8f5e9b9dbfc6edd32b6957ebf66b3d7f9ddbaff38e33d9ed4ff6fc8d6ebfd1f3cf74fb333d7f93db6ff2fc73dcfe1ccf7fb1dbbf18fcd900e65c9ddffaaa9d2b033ecad72af0d53a5f35f8eae870e09be47cb5e0a3f35b07be29ce37097c539d6f32f8b2ce3785b43456ef7c7d4152b992efb7c7cd257d5cb70e352d79dec3f6b80d4cbcd393e71db0c76d64e0b5f931c31d6b3ae4cd4ce76b04df2ce79b013e3704fda9cf59df6ce79b05be39ced704beb9ce371b7cf39c6f0ef8e63bdf5cf02d70be79e05be87cf3c1b7c8f916806fb1f32d04df12e75b04be66e75b0cbe0b9c6f09f82e74be66f0d13d2e1780ef62e7bb107c9738df45e0a3b1f662f0d1b5e125ce67c789c919f88cf3d318157e86c667f02da3b1197ccb695c06df0a1a93c1b71262936f158c2be46b713e1aa3ec7bbdaedc1724d5270a619f589bf471cd91ed71d7277fdc70dd6e4330ac6b1fc4590b5a6d74e504ef0d6ac3d819671487fc3550de0575a91ee941df33c46ebf4fd6b9f2c6129febf53e97833aeb22dadf1724dbfef51ecf7a8fb916dacf93b3ed05cdd9516f65e7ecd550d7cf3dbae6998839bb17381872b64b7376d45bd9393b0075fddca3ebde8998b3d7010743cef6f3e46c21af395b9c230b82e8dca3bf7d2662ce1e038ee473b6537376f45bd939fb00d4f5738ffefe9d88397b0770249fb3ddfd7a6d30eaadec9c7d05d4f5738fe6622662ce3e041c0c393ba0e3eca8b7b273f66d50d7cf3d9a179c8839fb6ae0483e677b9872b65d733628ae77064174eed11cf544ccd9478023f99c3dacf3b3a3dfcaced9cf435d3ff768bd6422e6ec475cd9ae337cc3ad332c04df379d6f11f0269fdb473a9872bba0b95dbc0f2408a27394d6ee26626e3fe6ca368f1f877b0fc8f76de7bb007cdf71be0bc1f75de7bb08dac5d007fab50f8c7a2bbb0f7c1feafab94cebc813b10f7c1d381872f6b0e6eca8b7b273f609a8ebe71eddd3301173f647c0c190b3039ab3a3decaced93f405d3ff796b9f244cc59baafd45e2ffcd85d2fac00df4f9c6f25f87eea7cabc0f733e76b01dfcf9daf157cbf70bed5e0fba5f3e5c1f72be76b03dfaf9daf00be279caf1d7c4f3a5f07f87ee37c9de0fbadf37581ef77ced70dbedf3bdf1af03de57c3dce67d7bbe8deabaf3a9f3db7a4515f90ecb9a57b2ce9d8b4bf6a1c623778b11bc63176a317bb3122760b43ec2cc4a02de3edf741b98597279f0b46fefe8362ad4e3e56bb6d7b6b30fab6af069e3c43dbb31063343c79e0694b9e27bcd7b790fc71c373dcea699a8558add0ae7686766520161d9bf6295e0e7c387eb747307624cf58c8402c3a36ed770023f9f0fb84bed7a9ffd8efc3a599615e86be145e1361bc3ee0a0783550e7f7b386ebae706cf5f03e7eb7b6793ea6bc0cf38262d1b1699fe2d5437bdac69fb1305ac6bcc7c835466420161ddb8f8dfdbd65fc351bd579cd81ef3c8c4985b18e49f5c0361ed72971e75a4a6c8eefab0cc4a0b18d34a77835506776f570dd1d30ee32f4bf42b9d76f381e249fc7853cf6ebd1f0b4030f47df67eaaf79fcdeff63906cae757a5ab5795ae5a04e07e8d7c9a05fa9eb108aa7cccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaacccf299f1fe0b5cdfa47aab843092af003c1cf3fce1f3a3dcb1e8f8765de73bb0ae93fcba45218f6b96748fe172afcd3550e7c9cc30db0f603ddd5f1bc435cd55bcda8dea3e8bfae0dcb558ce35c4b875e0a8f5cbe6c462170e73adb7d967a8d8e790b57abaae8ad094e13e95119a663c4df13ec5951e8fcdd379d5c36c1c6b7fe5ae45a256544e726d0fef31e03d2fc5f18372a12a18397ee0f74c57e2b147ae61d27a799717bb06eafc4f66f8dcac81f7fb8273ef79b275babd63d36796c367bbbd6337b8cf12479d77fc56f82cd5f93f1853df5e15fc49338efb3f705c0ea0adb8f54119d7cd93ff1e2eaee3b797c1d3093c1ce30cd3f5461efb40d2ebf8dd9e5651d73154a70bf4eb66d02fea5a94f6299e322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb332cb67c6df8a126b16ea1584308ed3bd0fe17a063dff05d7a65e5a351c977b1d8ed69c56786dae813a5fab1a667ba52bd707e7deef10772e19d6f34a9e4b8a570fedc1b520aedf7377783c1d115a50b939b1d8c575fce4351e5ec76ff7742d4468cad55f718d1535c5fedae6f1e0da687d70eebd255938ce78dc3b149717140ffb5207f8a88cbf8fe638cff85de2dfd743f170fdfa51a76d43c075ee0b79ce7183d6e669adbe3da2ad54e7c330f67dd495f11e0ebc77e4b188f7692bb54e4dfab13ccb2e5f5cf7a567c0d1f9ed8d88bd0e58138add86b133ce280ef96ba0fca5aae1ba548ff420ad89ddf6117a2618b2fb9f6bf33e97833a3d11edef0b926d7fafc7d3eb31dbdcf904e4d963f0fdcf3526f5c468b41c34a23a781dc4754f9e3f46faf737e27d7b93bc3a78cd4275be026354dcfda351f71cae616a5fdc3d87140faf8d3b81d16fa37f9f67a5dfa7f5388c1749dfa7f538e410dea71578c75f01c727ae4941fc770bd5f99e777cff9a9c3e83f781519d1fc278d1e0ee59ac0fcebdfec67ba6c6e3efabb8fba4291e5ed760dffe736dc7be99f4f713e604b2603e519d5f79e7ac3b867b75c4679f8cf92c69d5e2caf8f78baf9fd5a1073ed397880ec53edfebb585f2ba07da4275fecbbb064cfebaa5780d987c5b475e93d038d011d156aaf3dfd0d7fe00d778749e70bcaaab3ef77dda4a5d03927eb6cde3fd7c608c2de1f9c0b5d5c375fde7fc92d6e53e1fb8cbfb9cc4e703ff2fe4591ddc87ce3556af8bd16805684475f0b741f43d82cff28dfa8ee1bab73fee3b26ea199438b637548f3f9b3faf16758d4075e8b3788d30cb3137389dfdbafe7c217d5f2679df30fe56a215e2e26f255a99f4cc836e7db08fd705e733769e2976dc33a7f3e3103bee99d3e311bbd18bdd388eb15573d55c92e60ccf440e7f7f86cf2cb55ba9eb5262c8c1e7aa52c0589d02c69a1430d6a680b12e058c9352c03839058c5352c03835058c59603c9fdfed0cfa14c6aa0fd7f92a75ad81b15b98b428e7ffef60febf544a5efb606c86bfe9422d5a82d16b817fe7713cfba1dcffeb8518f0ff2e989102c69929609c9502c6a61430ce4e01e39c1430ce4d01e3bc1430ce4f01e38214302e4c01e3a214302e4e01e392143036a780f18214305e9802c68b52c078710a182f4901e352654c8471252f6361ac8c9687e3fffc7b3affe718034f3eea9e53a6df9e94fdffad313f9fb46daccf8dc37b4b78ff4fb8a7f76c3b8e7b47ca7db65da9ff6f9589b1305646aefbd8f1773ca3e1c1df4546fdb68681b1305646aedfbfe06ff446c3d3059a754668c6c058182b23d7bd72e5decb89bf4deb8ad08c81b1305646aedf3c648391f737ff391efc1d447784660c8c85b13272dd979c8518a3e1e901cdd64468c6c058182b23d36fdb42cd7acae0c1df80f54468c6c058182ba3e559cba4596f193c6b41b3de08cd2431224fd2cfc9ee8d88c5f19bc172db4e0cc83825058c5353c088f749708c5fa5ee93e8e5d5a730567db8ce57a9fb243036c3ef63422df0f7107f4e8bf5bc3c25ef93c0d81b98b4c0dfabfc392d36000fc7ef67b21063343cc49083cfcd4801e3cc1430ce4a0163530a1867a780714e0a18e7a680715e0a18e7a78071410a1817a68071510a1817a78071490a18f16f55866bc5927fbf6c98e0b1e3fe5699e8b1e3fe2e99e8b135cf35cf2b21b6e6b9e67925c4d63cd73caf84d89ae79ae795105bf35cf3bc12626b9e6b9e57426ccd73cd7349b1d330c7af8c138f11799a93e3c963db31569f80b6f745f06498da8eb13609683b31a48d71630a18d7a68051752cde83381646cbb399896753193c9b81670b13cfe63278b600cfd6e479c29cda52060f31e4e0736b53c0b831058caaa3ea28895175ac1c1d955119955119cf07631ac670654c453e16c6ca6879b625cf136ab6b50c9e6da0197dae8d97b1305646cbb33d799e50b36d65f06c07cdb64568c6c058182ba3e5d9913c4fa8d9f63278768066db233463602c8c95d1f2ec4c9e27d46c47193c3b41b31d119a313016c6ca68797625cf136ab6b30c9e5da0d9ce08cd18180b6365b43cbb93e70935db5506cf6ed06c5784660c8c85b1325a9e3dc9f3849aed2e83670f68b63b423306c6c258192dcfdee47942cdf694c1b31734db13a119036361ac8c96675ff23ca1667bcbe0d9079aed8dd04c2ae3da14306e4c0123b38e85b1325a9efd4c3cfbcae0d90f3c9732f1ec2f83e752e0b92c799e30a72e2d83871872f0b9b52960dc980246d5517594c4a83a568e8ecaa88cca581e635f0a18f55c2ba3544686bfaf4afe86e6d2091ebbc18bdd5021b1e37e4333d1636b9e6b9e57426ccd73cdf34a88ad79ae795e09b135cf35cf2b21b6e6b9e67925c4d63cd73caf84d89ae79ae795105bf35cf3bc12626b9e6b9e57426ccd73cdf34a88ad79ae795e09b135cf35cf2b21b6e6b9e67925c4d63cd73caf84d89ae79ae795105bf35cf3bc12626b9e6b9e57426ccd73cdf34a88ad79ae795e09b135cf35cf2b21b6e6b9e67925c4d63cd73caf84d89ae79ae792621f483e76a1dc67cc1c001e8e67de30b5336f8f7bb93bd61f13d4cf6a7585a7d5a59e5639a87339e87705837e19884bc7a67d8a572ef333043033c52e4c33c79802eda7181b3d3d6cfc2b99da1e37d65f39c163c78df5133d76dc583fd1636b9e6b9e57426ccd73cdf34a88ad79ae792e2536966b83e1eb767afea93dc633e1fd8cc76ab71aa873d9a4e26b43a07d8823b6f621fdaea884d89ae79ae795105bf35cf3bc12626b9e6b9e57426ccd73cdf34a88ad79ae795e09b135cf35cf2b21b6e6b9bc3cc77ca81a079ec0e3094af06c10c6b35b18cf0e613c6b84f12c16c6d3298c67ae309e82309e19c278b60ae399228c67b9309e6a613c9b84f1e485f1ec15c6b34418cf0a613cf384f1cc14c63355184f8d309ecdc278560be3d9278c678f309e5e613c4b85f1f408e3d9268ca74b18cf7c613cedc2786609e359298c272b8ca755184fad309e9dc2785a84f12c13c6b35f18cf3a613c0b84f13409e3a917c69313c653278c67bd309e5dc278b60be3e916c6b350184f87309ed9c2785609e399268ca74118cf16613c9384f12c12c6334718cf74613c8dc278260be3198fe70d95c39311c0930dce7d265916de3f00be2aefb376bc6a6b1a7eff2ae7af82cf5cedcad511c7be0a7cf4dbf0ab233e8b3a5d056de973e5fcd3db429d30561fec53bc7ae0b85a08cf01613c9385f1340ae3992e8c678e309e45c2782609e3d9228ca74118cf34613cab84f1cc16c6d3218c67a1309e6e613cdb85f1ec12c6b35e184f9d309e9c309e7a613c4dc2781608e359278c67bf309e65c2785a84f1ec14c6532b8ca755184f5618cf4a613cb384f1b40be3992f8ca74b18cf36613c3dc278960ae3e915c6b34718cf3e613cab85f16c16c653238c67aa309e99c278e609e359218c6789309ebdc278f2c2783609e3a916c6b35c18cf14613c5b85f1cc10c65310c63357184fa7309ec5c278d608e3d9218c67b7309e0dc278aa227818feffcb9087ee5fa363d3fe0121b119ce43f8ff7e5ec3d4a66bddb1eadc71899fe2d5409debdc8581bd1f053f4b5cfefd8678efdcb5a0d1b54c6da1f391f1ce0f73ec02de57190043e0e91344f070dc8fcad4ce117998e0ff3f9bb75a5de769e59fbb1cd4b906f4bb8e41bfa8dcfe531f70af6964b63cf4dd41ac59a8b7410823f9aee4e509fbed8660e456aadf5e073c1c6318533bc3fe75bdd7a60d11ba531dccd5eb19da19d57768ff7a380f6963b63c9b5c9958b3506f931046f25dcbcb13f6af4dc1c8ad54ffba1e7838c61fa67686fdeb06af4d9b2274a73a98ab3730b433aaefd0fe0d701ed2c66c7936bb32b166a1de66218ce4bb8e97a7230b6da6ad54ffba017838c61fa67686fdeb46af4d9b2374a73a98ab3732b433aaefd0fe8d701e945999a3982d0ffdc68458b3506f8b1046f25dcfcad391cf429b692b358edd083c1ce33c93eee1387693d7a62d11ba531dccd59b18da19d57768ffa688d8cd41b25adc3c0a2d6e8ee0b9799cb5a078e5325f934266d559758e63569d55e73866d559758e63569d55e73866d559758e63569d5567bba9ceaab3eaac3a27c1ac3aabce71ccaab3ea1cc7ac3aabce71ccaab3ea1cc7ac3aabce71ccaab3ea1cc7ac3aabce71ccaab3ea1cc7ac3aabce71ccaab3ea1cc7ac3aabce71ccaab3ea1cc72c4167cb43cf8821d62cd4db2a84917c37f0f284bf0bda1a8cdc32de7e1f946f069e1b19f4616a67780ff941af4d5b2374a73ad8bf0e32b433aaefd0fe41380f07cb60be2985ccaaf3d8982d0f3d2b9658b3506f9b1046f2ddc8cb138e63db82915ba971ec20f0708cf34ced0cc7b17eaf4ddb2274a73ad8bffa19da19d577689fe229b332c7315b1efa3f6c88350bf5b60b6124dfcdac3c85f0f78ddb83915ba971ac1f780e26ce531cc718740fc7b1435e9bb647e84e7530570f31b433aaefd0fe21380fe530df944266d559758e63569d55e73866d559758e63569d55e73866d559758e63569d55e73866d559758e63569d55e73866d559758e63569d2b4767cb43ff7708b166a1de0e218ce43bc8cad31eae3bec08466e196fbf0fca8780a73f719ee2ba0383eee1bac361af4d3b2274a73ad8bf0e33b433aaefd0fe61380f139df9a614326b6e8c0fb3e68632c7316b6e28731cb3e68632c7316b6e28731cb3e68632c7316b6e28731cb3e68632c7316b6e28731cb3e68632c7316b6e28731cb3e68632c7316b6e28731cb3e68632c7316b6e28731cb384dcb03c3b5d9958b3506fa71046f2f5f3f284cf3dd8198cdc4addb77318780e31e8c3d4cef0be9d235e9b7646e84e75b07f1d61686754dfa1fd23701e945999a3982dcf2e5726d62cd4db2584917c877879c2716c5730722b358e1d011e8e719ea99de13836e0b5695784ee5407737580a19d517d87f607e03c28b33247315b9eddae4cac59a8b75b0823f90ef3f284e3d8ee60e4566a1c1b001e8e719ea99de13876d46bd3ee08dda90ee6ea51867646f51dda3f0ae7419995398ad9f2ec716562cd42bd3d4218c9778497a7908536d3566a1c3b0a3c1ce33c533bc371ec16af4d7b2274a73a98abb730b433aaefd0fe2d701ed2c66c79f6ba32b166a1de5e218ce41be0e509fbd7de60e456aa7fdd023c1ce30f533bc3fe75cc6bd3de08dda90ee6ea31867646f51dda3f06e7216dcc96679f2b136b16eaed13c248bea3bc3c61ffda178cdc4af5af63c0c331fe30b533ec5fc7bd36ed8bd09dea60ae1e67686754dfa1fde3701ed2c66c79f6bb32b166a1de7e218ce4c3ef8bfd4c3c398f2717a1c5448cdde0c56ea890d88d5eecc60a89ad79ae795e09b135cf35cf2b21b6e6b9e67925c4aed45c53cd2b53f3cc79d43c731e35cfa8e62235ff6372b13b715ca98258c798da895b1f94717e8eb635c278160be3e914c63357184f4118cf0c613c5384f12c17c6532d8c272f8c6789309e15c278e609e399298c67aa309e1a613cab85f1f40ae3592a8ca747184f97309ef9c278da85f1cc12c6b352184f56184fab309e5a613c2dc2789609e359278c6781309e26613cf5c27872c2780e08e3a913c6b35e184fb7309e85c2783a84f1cc16c6b34a18cf34613c0dc2782609e359248c678e309ee9c2781a85f14c16c69311c0930dcefd3d0afe9ea01a7c747fff7ef03dcb950f80af2a22061de738f868fe948e61c79b754de73254c1676e8de07a56443c8a736bc467c743778cd507fb14af1e386e15c23359184fa3309ee9c278e608e359248c6792309e06613cd384f1ac12c6335b184f87309e85c278ba85f1ac17c653278ce780309e9c309e7a613c4dc2781608e359278c6799309e16613cb5c2785a85f16485f1ac14c6334b184fbb309ef9c278ba84f1f408e3592a8ca75718cf6a613c35c278a60ae399298c679e309e15c2789608e3c90be3a916c6b35c18cf14613c3384f11484f1cc15c6d3298c67b1309e35c278aa22780e30f1c43d4fe18080d8763f0fbad82d0bef8fc7ef000f788cb47f0c18919778f24c3c71cfa0c80b886ddb4f7f4bd01a5c16dec7df7171e554de63a4fda89cc2fbd25633f1c43db763b580d8560b9abba47b00b2f03efe6e812ba7567b8cb41f95538dbc3ce1ff2dd1128cdc4add6b847d8ee31c32b5338ffd2fc16768443e8bbac5d30a9fa13a1ef7c9c78d07144f9995398ed9f2d0da05b1e2f7d978fcee6d348c51dfaf0c3ce1f8d81a8cdc4a8d8fc78087e3fb83a99de13876c26b536b84ee540773f504433ba3fa0eed9f8888dd1c24abc5c95168713282e7e4386b41f1ca653e904266093a5b9e55ae4cac59a8b74a0823f9f2bc3ce1f8b82a18b9951a1f4f020fc7f707533bc331e194d7a65511ba531dec5fa718da19d57768ff149c8772984fa49059751e1bb3e5a1396462cd42bd821046f21d63e529e4b3d066da4a8d63a78087639c67d23d1cc706bd36152274a73ad8bf0619da19d577687f10ce83322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb332cb66b63cf4db4662cd42bd76218ce43bc9ca535c77680f466ea5d61d068187635d8649f770dde1b4d7a6f608dda90ee6ea69867646f51dda3f0de7419995599995599995599995599995599995599995599995599995599995599965335b1e7ae636b166a15e871046f29de2e5097fb7d5118cdc4aad3b9c061e8e7519a67686eb0eb7796dea88d09dea60aedec6d0cea8be43fbb7c1795066658e62b63cf46c2b62cd42bd4e218ce41b64e529ae9f760623b752e3d86dc0c331ce33e91e8e6367bc367546e84e753057cf30b433aaefd0fe19380fe5309f4821b3eaac3ac731abceaa731cb3eaac3ac731abceaa731cb3eaac3ac731abceaa731cb3eaac3ac731abceaa731cb3eaac3ac731abce95a3b3e5a1ff738d58b350af4b0823f94eb3f2b487eb0e5dc1c8add4bac319e0e1589761d23d5c7738ebb5a92b4277aa83fdeb2c433ba3fa0eed9f85f330d1994fa4905973637c98353794398e59734399e398353794398e59734399e398353794398e59734399e398353794398e59734399e398353794398e59734399e398353794398e59734399e398353794398e59734399e39825e486e5e9766562cd42bd6e218ce4bb8d97277cee417730722b75dfce59e039c3a00f533bc3fb7686bc367547e84e75b07f0d31b433aaefd0fe109c076556e62866cbb3c69589350bf5d6086124df195e9e4216da4c5ba9716c087838c679a67686e3d8ed5e9bd644e84e7530576f67686754dfa1fddbe13ca48dd9f2f4b832b166a15e8f1046f2e1f7720f134fcee3c9456871be62dbfd5e57ae77af5978bf1718b9c6c31e8f91f631c79197787a99781a3c9e86082dce576cdbfe75ae3ccdbd66e1fd75c0c89553bd1e23ed47e55403f0ac63e269f4781a23b4385fb1ad16eb5d79ba7bcdc2fbeb81912ba7d6798cb41f95538dc0b39e89276e4c5a3f0eb1e3fad778c48ecb95f188ad9aabe6aab96acea979e63c6a9e398f9a675473519a335c4785f3bd14230006dcfaa08c7f2b705c7b32b5331ff5f7d87aaf4df8f718ce399cafbf37945999e39899e62d3ab25e6cd227f078681b62d6623ce74d7bbd36a561deb414f3891432abce6363b6b1ef483e7647d68b4dfa041e0f6d77306bc1d4ce703cb83388d698e2e5a00ee6e99d0cedcc405c3a36eddf09e7a11ce6132964569dc7c66c63df9578ece2f3e43136e913783cb4ddc5ac054f3b8be3c1dd41b4c6142f0775304fef66686706e2d2b169ff6e380fcaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaacccca2c9bd9c67e76e2b18bf3f7189bf4093c1eda9ecdac054f3b8bf3f7f704d11a53bc1cd4c1737e0f433b3310978e4dfbf7c0795066655666655666655666655666655666655666655666655666655666655666d9cc36f673928f1dfe1e0763933e81c743db7398b5606a67387f7f6f10ad31c5cb411d3ce7f732b4330371e9d8b47f2f9c076556e628661bfbb989c72eaee7616cd227f078687b2eb3163ced2c8e07f705d11a53bc1cd4c1737e1f433b3310978e4dfbf7c1792887f9440a995567d5398e5975569de3985567d5398e5975569de3985567d5398e5975569de3985567d5398e5975569de3985567d5398e5975ae1c9d6decfb138fdd1ecedf636cd227f07868bb9f590b9e7616e7ef1f08a235a67839a88379fa00433b3310978e4dfb14af12984fa4905973637c98353794398e59734399e398353794398e59734399e398353794398e59734399e398353794398e59734399e398353794398e59734399e398353794398e59734399e398353794398e59734399e39825e4868dfdbce46387bf67c7d8a44fe0f1d0f63c662d98da19defff26010ad31c5cb411dccd30719da9981b8746cda7f10ce83322b7314b38dfd50f2b10b592f36e913783cb43dc4ac05533bc3f1e0e1205a638a97833a78ce1f66686706e2d2b169ff61380f6963c6f397492e7678df26c5a872afd6f77c57ae06df0b5cb9067c2f74e55af0bdc895ebc0f762579e04be9740dbc8f752575e09be97b9f27af0bddc95d781ef15aedc0bbe57ba720ff85ee5ca43e07bb52bdf0ebed7b8f21de07bad2bdf09bed7b9f25de07bbd2bdf0dbe37b8f2b3c1f74657be077c6f72e5e780efcdae7c2ff8dee2cacf05df5b5df93ef0bdcd95ef07dfdb5df901f0bdc3959782ef9108df3b5df979e07b972b3f08be77bbf201f0bdc795a780efbdae3c157c7f01657a7d9f2bd783ef5157ce81effdae3c0d7c1f70e506f07dd095a783ef43aedc08be0fbbf20cf07dc4956782efa3ae3c0b7c1f73e526f07ddc956783ef13ae3c077c9f74e5b9e0fb942bcf03dfa75d793ef83ee3ca0bc0f759575e08becfb9f222f07dde951783ef0baebc047c5f74653cbf7fe9ca0f818fc69587c147e3caf3c147e3ca0bc047e3ca0bc147e3ca8bc047e3ca8bc147e3ca4bc04779f752f051debd0c7c94772f071fe5dd2bc04779f74af051debd0a7c9477af061fe5dd6bc04779f75af051debd0e7c9477af071fe5dd1bc04779f746f051debd097c94776f061fe5dd5bc04779f756f051debd0d7c94776f071fe5dd3bc04779f708f828efde093ecabb7781afd995df0dbe0b5cf93de0bbd095df0bbe8b5c19c7998b5df97de0bbc4951f051f8d85ef07df335cf903e05be6ca1f04df7257fe10f856b8f287c1b7d2953f02be55aefc51f0b5b8f2c7c0d7eaca1f07df6a57fe04f8f2aefc49f0b5b9f2a7c05770e54f83afdd953f03be0e57fe2cf83a5df973e0eb72e5cf83afdb95bf00be35aefc45f0d1f7388d33b63fdb7e493a9046d6476d6e8d680bf926435bfa8264afe928161d9bf6db8191ce4161fc190ba3656cf3182d4f2783669857b495fa9ba913783a187898da19fecdd4e5b5a9dd6b530eea3c03dad9c5d0ce0cc4a563d37e17c4e638e7a8459d3bee324f8b1aa853ebbed0ecf769291de918367f0b116de9616e0b1d9bc6a59e7188ddedc5ce7bb1713ca6ad54ffea06e6350cccf6b8bdc91f37ec5f6bddb128a7284e1edab40e3448aa4d183be38ce290bf06caf39b86eb523dd283bebf88dde6329d4b64f73fd7e97d2e07757a22dadf1724dbfe5e8fa7d763b6d7f40d4dc31c0cfd21cc811e8f83f6f3a05d6f8c763da01dd5c1efbf1626edd6783cb4df023c748dd3053eba56207ebcce6a1d076e7fdceb8ae0265f3730b644301692670caf755a3c46da2f0023f9d6004f379366feb95ee6e983dfcb93bc3af4d91aa8b31abe1bb311756dbf5b9a196e17fd0dfec720d931bd8e412f9c1f08409fc0d3903662981c0ccf2124c93335189e23383b3478a6ff9681cb07fa8f6400adc6c3c4d74c4433aac087e5ea085f108c9c0ac129599a0ac129d92a4f169c82a1faf64f29db2c9a6e1838797ce899a7064e1d3e73f7e9a181237b076f41ea5a8f1e49e35a80a4e8a36d72303c69d31724bb1853e7c52a953c93e17512bc4f75f24f6f6b636a67f8a537c56b539dd7a61cd4a985f7a630b4330371e9d8b43f252276820351a8c5d4516831358267ea386b8113dfe4c39e4aefe3e24995d716ecd1d8263fcf136d10055c0ac7cf3838fb9eedecb5ae319382e1934da3a7bda2b527c1ce98da6f2d3b236a6740ed10646738ed8ca6fd52b333967686d2ce48da19483be3686718ed8ca29d41b433867686b03928ce00da193f3bc36767f42e01b6af02affdabda7e43da19393b036767dcec9595bd02b05723f6eadb5e29dad90f7b8560ffb2b4b30cf6dbd65ec9d86f69fbcd6aaf14ed15a2bda2b757b876956a83b18d4eeb4dc6361bdb626cabb16dc6b61bdb616ca7b15dc6761bdb636cafb17dc6f61bbbd4d865417176fd72635718bbd2d8338d5d65ec6a63d718bbd6d875c6ae377683b11b8ddd64ec6663078df51b3b64ecb0b123c6068c1d35768bb163c68e1b7b96b15b83e21d3a278d9d323668ecb4b1db8c9d31763628ae98d91532bb226657c0ec8a975de1b22b5a7605cbae58d9152abb226557a0ee0f8a2b4c76a5c8ae0cd95501bb0a6067fded2cff0b83e22cbe9db57f49509c95b7b3f076d6ddceb2db59753b8b6e67cded2cb99d15b7b3e076d6dbce72db596d3b8b6d67aded2cb59d95b6b3d076d6d9ce323f12146791edacb19d25b6b3c27616d8cefada59de4783e22cae9db5b5b3b47656d6cec2da59573bcb6a6755ed2caa9d35b5b3a47656d4ce82da594f3bcb696735ed2ca69db5b4b3947656f24bc61e33f657c6fedad8df18fb5b637f67ecef8d7dd9d8578cfd83b17f34f64f41312fffd9d8bf18fb9ab17f35f66fc6be6eecdf8d7dc3d8378dfd87b16f197bdcd8b78d7dc7d8778d7dcfd8f78dfdc0d80f8dfdc8d87f1afbb1b19f18fba9b19f19fbb9b15f18fba5b15f19fbb5b1278c3d69ec37c67e6bec77c67e6feca96078750307913fb81d9a69ef1f1a1a38797aa87968b0f9e4ed27868e9f3e7177f39dc7878e350fde3170e6e889c13bf1c3ef73c3162d236c3a73a6ffeee6e3a78e0cdcd53c78fb50f3e0d1e64383b79f3a72163ff465f7a185e746ec3f72243ed8b7aa9e06e977c718f497ee73b440b3ab74db9e188b204f8de54333abc7d6a04bddb70efdf57e45f16ab7f9ec89c1a1e67cf329f36fff09f3998123adcdf8de5923f2d9a1e6b343fd67869a8f9e193cd9dcd68ac7bd76ca181a51d334860fb5368dbee5c1ff03c304b133250a0400", "isInternal": false } ], - "packedBytecode": "0x000000028df71de500000046871f8b08000000000000ffed9d07741d45b6ae5bb61ce0481893b3450e06a3e49c64724ec6608c31b62c0b1b073962323643700ee460839c73c638478c6166983b393181811926dd3b7367bdf5e6be77df7a8ff5bacea9bdf4ab5c7daca3e992ff2355af5552f53ed5bdbffa7b7775aaeefa47100439416a6a1ea68b822327f9bd4cff2ffcd7a6a218d755e89233274b389b650967f32ce1cccd12ce1659c2d9324b385b650967eb2ce13c2e464ec5d62ca83dc5cd7bbc035de3664c6499a67959a0697e96697a421668da26c88e36eac42ce16c9b259c276509e7c959c2794a96709e9a259ca76509e7e959c2794696709e99259c676509e7d959c2794e96709e9b259ce7650967bb2ce12cc812cef3b384f3822ce1bc304b382fca12ce8bb384f3921839db03e7a5faff65faffe5faff15fabf94bd52ffbf4affefa0eb98abe7af565c61520f698a8ddf4ac2541aa68e61ea64fcd6394c5dc2d4354cddf46f05fab7ee61ea11a69e61ea15a6de5a833e61ba264cd786e9ba305d1fa61bc27463986e0ad3cd61ba254cb786e9b630dd1ea63bc2746798ee0ad3dd61ba274c7dc3746f98fa85e9be30dd1fa6fe617a204c030c9607c334304c0f856950981e0ed3e0300d095379988686a9224cc3c25419a647c2343c4c23c2f4689846866954984687694c98aac234364ce3c2343e4c13c234314c93c2f458982687e9f1303d11a6270dcd9e0ad3d3617a264ccf1a9ccf85694a98a686e9f9307d2b4c2f84e9c530bd14a697c3342d4cd3c334234c33c3342b4cb3c334274c73c3342f4cf3c3f44a985e0dd36b617a3d4c6f84e9cd30bd15a6b7c3f44e98de0dd382302d0cd37b9a457684f7c3541da645615a1ca625615a1aa665615a1ea615615a19a655615a1da635615a1ba675615a1fa60d61da18a64d61da1ca62d61fa204c5bc3f46198b685697b9876846967987685697798f684696f98f685697f980e84e960983e0ad3a1307d1ca6c361fa244c9f86e9db61fa4e98be1ba6cfc2f4bd30fd9ba1f9f7c3f48330fd304c3fd2b61febff3fd165e5fedd4fc3f4339dffb9feff0bfdff97faffe7c632bf0ad3af0ddb6fc2f45bc3f645987ea7f35feaff5fe9ffbfd7ffffa0ff7fadffff51ffff93feff67fdff2ffaff5ff5ff7fd7ffff43ffff9bfeff77fdff3ff5ff7f84e9a18254be755033950531b551a595c9673f22fea541ed4969d15cff26ff0bb43d57cfcb7fd1ae859e6f61d85beaf996c67a5aebf9d686bdad9e6f6bd84fd6f3271bf653f5fca986fd743d7fba61bf48cf5f04f64400f786b55dd99a6b530ed8245e9b81ad85b635075b4b591dd85a695b0bb0c9f66d09b6e3b4ad15d88ed7b6d6604b68db71a26598f2b4ad2c882b560a87a8f5e6c7bd5efdbcec84f87987aaf5b671c47b62fcbcc3d47adb3ae055f171925ed7891037276b5b5bb09da26d2781ed546d3b196ca769db29603b5ddb4e05db19da761ad8ced4b6d3c17696b69d01b6b3b5ed4cb09da36d6781ed5c6d3b1b6ce769db39606ba76de782ad40dbce03dbf9dad60e6c17685b01d82ed4b6f3c17691b65d00b68bb5ed42b05da26d17814ddadf8bc126e78b97689b6a3b8ecb8165b45ddaade432d26683ed7269afc17685b4d5606b2fed34d8ae04df62bb0ada1ab175d03669b7d46fdd74be2c886b3f29ae54ebed1ef77ac335abf5f68c7fbdc9678ebd821a5dcbc04f77d0aab7cec7d8afa9087de7e8247ec49e0bf95ba0ac94133de4d823ecea18d343e77ba759ae9bb15c3e94e961a97f59106ffd7b1a3c3d0de616907713b325253e66eb3c651cb3fda1ac197b721ed41863f676e07010b39d7dccd679ca38662ba1ac197b722edc1863f641e07010b3e56e62b6b8d0c76ceabe5910d8634fae871a63cc8e008ef863b6a38fd9ba4f19c7ecf350d68c3db9266e8c313b1938e28fd9cee5fedca0ce53c6313b0fca9ab127f7671a63ccbe081c0e62b6d2b7b3759e328ed9f7a0ac197b72afb031c6ecabc0117fcc767514b3253e6683d433d020b0c79edcb76e8c31bb0838e28fd9a1fefe6cdda78c6376279435634f9ea134c698dda0f3ea39c38ff5738673c0f6136d3b1778e38fed8a8e8e62bbd8c776aa6f4810d863549ee735c6d8dea7f32a8e7f0efd11c4f60b6d3b1f6cbfd4b60bc0f6b9b65d08f572b00f94fb7da0ce53c6fbc0afa1ac19cbf26cb931ee033f040e07315be163b6ce53c631fb57286bc69ef473688c31fb05703888d94a1fb3759e328ed9ff0d65cdd8bb4ce71b63cc4a5f5375bef0a53e5fb8026c5f695b7bb0fd5edbae04db1fb4ed2ab07dad6d1dc0f6476dbb1a6c7fd2b642b0fd59db8ac0f6176d2b06db5fb5ad046cffae6da560fb0f6deb08b6bf695b27b0fd5ddb3a83ed3fb5ad0bd8fea16d5db54d3def92be5772deda1a58cb82f8b66d02749129c7982f837cb15b9ec27ce0415fa5f1fb2a51752f09ea5ef752e0e9e8a0ee09f051179e8ec0d3297e9e645fd4cef1af37b98d4b0c4d13e0ab04ead5c541bd72c097ac5be6c55f3ed8703fef6261ec1a3f63710ef89275cb7c5760141bb63bf2fe8fec3faa6d3e3fa786d7c1be943c3ea3bf32e0107fb950e69fed6aca5eacd9f2e0776c833b19364771998c0bf125eb9679f19707f5e9d4f08cc57565ec6830ba6a2372c097acdbf49d07f922b7faa4e5e94ce2dbc179b7b54d13cdbb3780efae86ef52c337b69d32a53bb67505e6d8af7ff4b1ad47fceb2dc47365b94e113f78fe80d71371d5097dcb758af8117b2ee46fcaa9292be5440f6987855dedc3b22d91dd5cae8bb15c3e94e96ea97f59106ffd7b183c3d0c6675bce909c74207fb433206ba1b1c325f0adaf588d0ae3b6827652e03ed1c9c7b26b5eb66f0c87c47e091f61bdbb3a206e62922f08de7b0782d27bfe37980abed556430cabc6d7b7505c68e164607e784c5e98e87a5c028b66ec053e248b3a8ed5a42e2dbc575650ef8907373f3da2617cadcd9bca66c458e53b6623c7796a9aed7bcf16fa7e242dc3feac2e3781f2a72148f8578ffe69b20de5833db25b3bd89bac7e3aa2d2f3178645efc7966cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367e667563cf23c01fb6d49b94e248c66ff3757f7f993dfe2d3ebc26740ff74da1facb8109ffd493f882b8c3ae74299939bd5b0fd37f40733fb12456d4b177d63d36d4bf187fdc11ae21962a9c163faceb3e883cfa55133577da0cc3643e6b17f9ae857043caef6c76283c7f48d6d4609a96651edacab3e7d517166eb4f58109befe2a1ae9eebaaef9ea96f879ac7af4e86a6c96f921a36d526ddd3bca6de2e9ef366fadc198f1b928ff3392ef6cb405ff1b7b3c5b5fa27340b6a1f2b30d65df5d592fd4afa4674377ce74299f39bd56c1bec5357161c796cc03e5eb26e59e60a58b687b1ee36eeea9bb61f4a77e0967c4ba36e9d815bca5c02c7ee9feabca3636071a6ef48e03139fee34baabf4849063c78bc7371cee2e8385a88f118777f11b31fa4ed7c59ca601f5207fd77d31e8bc59f67f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b667e66c5633e43c767bfa5248c0dd4c726f93c43becf86cfc5b635abf1ebfa19a03c736a6fd419df51ce857794776936ecfb80df95b26d4b57cfd6a2b6a5f863ebfb9067d14769d6c3a29983ef3aa6fd66077e2351f4eb013caef6c7a86f77d8da8c2252cda2da59177d17d2c599ad9f42416cbe53fd455c3cd795fe22e6f1cbfcae11f693101b3e078ffa5e58b1613bd66d80ad5f9be4f19b0b2ec6b8c17836fb0a8a3fec27f185d656fa49c4df0e1417ba3c46c83e2a7d424a2c7595327f685653f68f3a8f7d854a615dffb4fc2e53ba3e09d8a63af87e6c72fbcaba64fbdabe5ddb075863f25d84ebcad1a98fa1412ee4ff67b39ab2524eca8ad6c2aef611f9ae14b29bcb753496cb8732bd2cf52f0be2adbff92de1de06b38a9dbf409cfd13cef55cb549bd2234ba0234923278ceebaa5fadd9469a7da6b14f642ba30c9e9f4a99ff076d54549f745b9f4a57e70b51fd39f17cc1764e63d6d1ec3bded4fb03e6ebeb1017fd0165dd6d82da7df20263fded61fdc2d52a883eb64899b6b0fe63f9dd2bdbb59ff0627f4329731a5cfbdda4f3995cfb1dabeb78dbb51f2e1755776c17e23e36623c220bc6b2942930e2b147047757cbb217462c2b5a99df3ec4eb523c4788ffbb91a9f6a6b75117d9a7f0fbfe52e67263bf89ff9c2975fee9ea1b99b22e69838a2d7595321d605f2bd4f9046c277ca7a8b7e57799d29d7f8a7eaaced7c45fe7e4f6bd56af4bb6ef3516dfd7016b4cbe8bd0b79c7f8a1fb1e742be171c4fa49ce8215a0bbbda47e41c0ed9cde5ba1bcbe543993e96fa9705f1d6ff1a83e71a8359c54e09c4596f78d7c2555bdd2742a3f6a09194c17bd7b6ef1adbee7534d479aaf9bdf4fce0c86ff7e271d2cd399bfd5d39f3feadedfca4bdc18fe727b7433b9bb09435ef4bcb7271f64fc7f781f0bc10df0772758d941fd4d633dfe070e9bb8de1bb4d03fa6e6bf86edb80bebde65e7326cd99c6fcc1e790cd80d1c5b10e8fab7561b41dff9a03a3ab77364b3260c46f5ee3f14e185d7c27bcbe630ae1b94e0b6074f1be71a6f7ab3b01237e6340185dbca39de977aaf1bd6d59ae1530ba18d708c750aa0ba36daca3d6f0dfc1b84645f51d0704c73a3a0e185d8c0d92086a8f677234c66ec028cb1d0f8c2e9e232582daf7d58ec688cf2b65b98463c674c776c77d7f8a33bd07d110fd0aa2ce35d0b783fbffc5d837a12e5af474cb93f6dc077d3bb8ff95d402c7b23c9a16f87ccec5d89a89a0f6b3b0a3f1e0334459ee24602c73c4d83b03c6326094e54e06c63e8e18cb3260ec038c623f05181ddc874c32f6c98011efd7c972a702e3b58e18afc980f15a6094e54e034617f71413e0b72e8cd701a32c773a305eef88f1ba0c18af074659ee0c60bcc111e3f51930de008cb2dc99c078a323c61b3260bc111865b9b380f126478c3766c0781330ca726703e3cd8e186fca80f1666094e5ce01c65b1c31de9c01e32dc028cb9d0b8cb73a62bc2503c65b8151963b0f186f73c4786b068cb701a32cd70e186f77c4785b068cb703a32c57008c773862bc3d03c63b8051963b1f18ef74c47847068c7702a32c770130dee588f1ce0c18ef024659ee4260bcdb11e35d1930de0d8cb2dc45c0788f23c6bb3360bc071865b98b81b1af23c67b3260ec0b8cb2dc25c078af23c6be1930de0b8c7d2d8cfd1c31de9b01633f6094e5ae04c6fbe2674c5e4bf7cb80f13ee0b93f7e9ea466f765c073bf5b9ee43714efb3f87a207e5fc96dd13fa87bdd1f009e01f1f324b7c50319f008433e2c879a3d183f6352b30119303e083c03e3e7496af660063c0341b3072d9a3d143f6352b38119303e043c83e2e7496af650063c8340b3872c9a3d1c3f6352b34119303e0c3c83e3e7496af670063c83831acd1eb66836247ec6a4668333601c023ce5f1f324351b92014f396836c4a2d9d0f819939a9567c03814782ae2e7496a3634039e0ad06ca845b361f1332635abc8807118f054c6cf93d46c58063c95a0d9308b668fc4cf98d4ac3203c647806778fc3c49cd1ec980673868f68845b311f13326351b9e01e308e079347e9ea4662332e07914341b61d16ca423c64733601c69e189fb9be88f5a7c8d7654f75141ddeb2e0cf9b01cf69318e3887174068c63805196c37e12558e18c764c058058cb25cc23163ba7e1255e07b6cfcbe93ed525550777dc6bae549db4f027d8f73a4c5d8a0ee5a8c73cb93b69f04fa1eef488b7141ddb5180f3c131c6891001f75e111867c580efb494c74c4382103c689c028cb613f89498e182766c03809186539ec27f19823c64919303e068cb21cf69398ec88f1b10c182703a32c87fd241e77c4383903c6c7815196c37e124f38627c3c03c627805196c37e124f3a627c2203c627815196c37e124f39627c3203c6a7805196c37e124f3b627c2a03c6a7815196c37e12cf38627c3a03c667805196c37e12cf3a627c2603c667815196c37e12cf39627c3603c6e7805196c37e12531c313e9701e3146094e5b09fc454478c5332609c0a8cb2dc48c78ce9ae5fa63672df51d72a8ddd77d4754963f7ede3dcc77953f0ede3dcc77953f0ede3dcc77953f0ede3dcc77953f0ede3dcc77953f0ede3dcc77953f0ede3dcc73993efe71df84e800f99728cf932c80b433e2c37d233366a46e429888fa710eb8ebebe4550f76f5978721cd51d7dbd40507761c836c6e7b380716416307a1d537d10ebc3a8785e74c4f342063c2f02cf4b8e785ecc80e725e079397e9e644cbd94018f30e4c37223b380f1f92c60f43a7a1d9918bd8e4d4747cfe8193da3673c168cd9d0867bc6ac88c7e2fa322a9e69f1f324357b39039e69a0992c77bf5bc6e2fa322a9ee9f1f324359b9601cf74d06c9a4533078cc5f565543c33e2e7496a363d039e19a0d9748b660e188bebcba87866c6cf93d46c46063c3341b31916cd1c3016d79751f1cc8a9f27a9d9cc0c78668166332d9a39602cae2fa3e2991d3f4f52b35919f0cc06cd66593473c0585c5f46c533277e9ea466b333e099039acdb668e680b1b8be8c8a676efc3c49cde664c03317349b63d1cc0163717d1915cfbcf879929acdcd80671e6836d7a2192be3c82c607c3e0b181deb585c5f46c533df11cfbc0c78e603cf2b8e78e667c0f30af0bc1a3f4f32a65ec9804718f261b99159c0f87c16307a1dbd8e4c8c5ec7a6a3a367f48c9e3133c66f6501a3dfd69e9195d1c1f555da77685e69e4bea3dea169ecbea3dea169ecbe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb3867f2fd5afcbe8b337d87f535e071f14eada37a16aaf5beaed7f54d8cfa29adde30b47ac5d02a1fcabc0efabde140bf1cf02beb9679f19729f3a504cc8e7c179f10aee338a8bff878ded043f97fd351dda3dafa371bb9efa8b6beb1fb8e6aeb1bbb6f1fe73ece9b826f1fe73ece9b826f1fe73ece597c63be455073de2edf5752eb780b7ecf81f2f2ddb25c28d3af55ea7f9bc0ef432e7cfb7dc81f2b9a826f1fe73ece9b826f1fe73ece9b826f1fe77c718ef1706d03f004064f9086e769329ece643c63c9788692f1dc47c6730b194f2f329ec9643cc5643cb3c8781e25e379898c671019cfdd643cd793f15c45c6f32c194f57329ef1643cc3c8781e20e3b98d8ca78c8ce709329e52329ed9643ca3c9785e26e3194cc6d3978ce705329e1bc978a690f17427e3994bc6733919cf44329ecbc8781e21e32924e379908ce704329e36643c7790f15c43c6f314194f27329e39643c55643cd3c878cac978fa91f15c4dc67333194f4f329ef9643c8f91f11491f18c20e379888ce72e329ee6643cd791f13c43c6d3858c671c194f7b329e0a329ee9643cfdc9786e25e3e94dc6f338194f0919cf28329e87c978ee21e36988ef7164c233958ce706329ee7c878ba91f14c20e39941c67329194f2519cf00329e3c329e7c329e0e643cb793f1f421e379928ca72319cf18329e21643cf792f1bc48c67313194f0f329e79643c93c8786692f10c27e31948c6730519cf89643c6dc978ee24e3c921e04904477e233901bfbf06b666c6b2eab352dd0a6a7e7f5bdb9bc132efe87c73cbbadf069b7cabea1dcbb2a8d3db5097329d2ffcd7a6a44ee8ab0ce6c55f1e70bc43c27327194f5b329e13c978ae20e31948c6339c8c672619cf24329e79643c3dc8786e22e379918ce75e329e21643c63c8783a92f13c49c6d3878ce776329e0e643cf9643c79643c03c8782ac9782e25e39941c633818ca71b19cf73643c3790f14c25e3798d8ce71e329e87c9784691f19490f13c4ec6d39b8ce756329efe643cd3c9782ac878da93f18c23e3e942c6f30c19cf75643ccdc978ee22e379888c6704194f1119cf63643cf3c9787a92f1dc4cc67335194f3f329e72329e69643c55643c73c8783a91f13c45c6730d19cf1d643c6dc8784e20e379908ca7908ce711329ecbc8782692f15c4ec633978ca73b19cf14329e1bc9785e20e3e94bc633988ce765329ed1643cb3c9784ac9789e20e32923e3b98d8ce701329e61643ce3c978ba92f13c4bc6731519cff5643c7793f10c22e379898ce751329e59643cc5643c93c9787a91f1dc42c6731f19cf50329eb1643c9dc9789e26e3b9d6c2f39a231e79df5dd62df3af91f876b01d0ad57adf7554a7057a5d2df57a855ffce54299a2e353ffd5f3215c56b8ccef1360dfef05a0d15b8eea628e8929f36f3572df6d0cdf6d9a88efb686efb64dc4b78f731fe74cbe17c4efbb18bf6d23538e315f06793cbeb8f82690a37ad63ab67f13a37e4aab8586566f195ae543997741bf850ef4b39d2fc8bcf8cb94f95202668c8b8220deb8782ffe3a15abbe34c781aeef19fa62bdde77a469d431e4fd46ee3bea18d2d87d471d431abb6f1fe73ece9b826f1fe73ece9b826f1fe73ece997c57eb7c8cd78d85e8a34550733d500d7e17eb7c4e8c7ed5ba1681df1ce0107fb950e615b817edf779bfcfc7e5db1fdb7c9c3705dfcc716ee6e519e265c0e6ea196f542c36c4f3e563e93b2a161bbbefa8586cecbe7d9cfb3867f2bd247edfc96788af05b5a774cf109700cf22075a38aa67f2da69a951a7d78c3ae543996aa8e75207f5cc01bfb26e995f0adb21db9815cf549dc7f15da4dc541246b12d72cb93dcbfa606b5a774fbd752e071b01f1439aa6772ff5a66d469aa457729530df55ce6a09eb67d47e697c176c83666c523efee0a6b02cabd40c228b6256e7992fbd70b41ed29ddfeb50c785cb43f8eea99dcbf961b757ac1a2bb94a9867a2e77504fdbbe23f3cb613b641bb3e291b14c843501e55e246114db52b73ca509a8b34ce9f6afe5c0e3a2fd7154cfe4feb5c2a8d38b16dda54c35d47385837adaf61d995f01dbc1337b661bb3e2917726853501e55e226114db32a73ca58509a8b34ce9dab115c0e3a29d77a47bb21d5b69d4e9258bee52a61aeab9d2413d6dfb8eccaf84ed9009f3822c64aece4266afb3d7398ab93a0b99bdce5ee728e6ea2c64f63a7b9da398abb390d9ebec758e62aece4266afb3d7398ab93a0b99bdce5ee728e6ea2c64f63a7b9da398abb390d9ebec758e62aece4266afb3d7398ab93a0b99bdce5ee728e6ea2c64f63a7b9da398abb390d9ebec758e62aece4266afb3d7398ab93a0b99bdce5ee728e6ea2c64f63a7b9da398abb390994167c5f3b2ce0b6b02cabd4cc228b6e56e7992efefbc1cd49e728cf932c8af049e150ef47154cf64bff755469d5eb6e82e65aaa19eab1cd4d3b6efc8fc2ad80e99302fc842e6ea2c6466d059f14cd379614d40b969248c625be19627d98e4d0b6a4fe9dab155c0e3a29d7754cf643bb6daa8d3348bee52a61aeab9da413d6dfb8eccaf86ede0993db38d59f14cd779614d40b9e9248c625be994a738f91ee2f4a0f694ae1d5b0d3c2eda7947ba27dbb135469da65b749732d550cf350eea69db77647e0d6c874c98176421737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc0c3a2b9e193a2fac0928378384516cab9cf294249f3bcc086a4fe99e3bac011e17cf651ce99e7ceeb0d6a8d30c8bee52a61aeab9d6413d6dfb8eccaf85edd0d89917642173b5676e10661f1b9e398ad9c786678e62f6b1e199a3987d6c78e628661f1b9e398ad9c786678e62f6b1e199a3987d6c78e628661f1b9e398ad9c786678e62f6b1e199a3987d6c78e628661f1b9e398ad9c786678e6266880dc53353e7853501e56692308a6db55b9ee4770f6606b5a774fd76d602cf1a07fa38aa67b2dfce3aa34e332dba4b996aa8e73a07f5b4ed3b32bf0eb68367f6cc3666c5334be7853501e56691308a6d8d5b9e643b362ba83da56bc7d6018f8b76de513d93edd87aa34eb32cba4b996aa8e77a07f5b4ed3b32bf1eb68367f6cc3666c5335be7853501e56693308a6dad5b9e643b363ba83da56bc7d6038f8b76de513d93edd806a34eb32dba4b996aa8e70607f5b4ed3b32bf01b68367f6cc3666c53347e7853501e5e690308a6d9d5b9ee204d459a674edd806e071d1ce3baa67b21ddb68d4698e457729530df5dce8a09eb67d47e637c276c83666c53357e7853501e5e692308a6dbd5b9ee4fe3537a83da5dbbf36028f8bf6c7513d93fbd726a34e732dba4b996aa8e72607f5b4ed3b32bf09b643b6312b9e793a2fac0928378f84516c1bdcf224f7af7941ed29ddfeb509785cb43f8eea99dcbf361b759a67d15dca54433d373ba8a76ddf91f9cdb01db28d59f1ccd779614d40b9f9248c62dbe8982701759629ddfeb519785cb43f8eea99dcbfb618759a6fd15dcabc0ff5dce2a09eb67d47e6b7008f4cd7028fabb80c0c9ec0a28f4c4f93f17426e3194bc633948ce73e329e5bc8787a91f14c26e32926e379948c671019cfdd643cd793f15c45c6f32c194f57329ef1643cc3c8781e20e3b98d8ca78c8ce709329e52329ed1643c83c978fa92f1dc48c633858ca73b19cfe5643c13c9781e21e32924e379908ce77d329e13c878da90f1dc41c6730d19cf53643c9dc878aac878cac978fa91f15c4dc67333194f4f329ec7c8788ac8784690f13c44c67317194f73329eebc8789e21e3e942c6338e8ca73d194f05194f7f329e85643cb792f1f426e3799c8ca7848c671419cfc3643cf790f1dc40c6f31c194f37329e09643c9792f15492f10c20e3c923e3c927e3e940c6733b194f1f329e27c9783a92f18c21e31942c6732f19cf4d643c3dc8782691f10c27e31948c6730519cf89643c6dc978ee24e3c921e0490447be8b9780df17824dde199b0fb60f747e13d89a597cc8b3882d60cbd5795947ab305d5f70e4ba512757efc9a1af3298177f79c0f10109cf9d643c6dc9784e24e3b9828c672019cf70329e49643c3dc8786e22e3b9978c670819cf18329e8e643c4f92f1f421e3b99d8ca703194f3e194f1e19cf00329e4a329e4bc9782690f17423e3798e8ce706329e7bc8781e26e31945c65342c6f338194f6f329e5bc9781692f1f427e3a920e3694fc6338e8ca70b19cf33643cd791f13427e3b98b8ce721329e11643c45643c8f91f1f424e3b9998ce76a329e7e643ce5643c55643c9dc8789e22e3b9868ce70e329e36643c2790f1bc4fc6f320194f2119cf23643c13c9782e27e3e94ec633858ce746329ebe643c83c9784693f19492f13c41c65346c6731b19cf03643cc3c878c693f17425e379968ce72a329eebc978ee26e31944c6f328194f3119cf64329e5e643cb790f1dc47c633948c672c194f67329ea7c978aeb5f02c74c4638e9b20f30b097cabf9eea08b9a12f03b7e67fd7d478c0b0d46997f1f1891d7b5666d0c9e368666c7d2b7aabfbcab23f7c0717be17be70cdbab4d0368d6d6e0696b68762c7d2b2de4d9b6bc3388db0bbf53cbb0bdf0bd6a07ed7369c2e051538e315f06f92d8ef57154cf427ceffa9b18d7abb4da6a68b5d0d02a1fca6c06fdb63ad02f07fccaba655efc7966cf1cc5ac78a42f89ed7b00fd4818c586e3627c183f4f69c2e05153baf6f143c7fa38aa67b21ddb16d875ff1074973218abdb1cd43307fccaba657e9bc5774110af16dbeba0c5760bcff606d642fc65cabc390b991974563cf2ae81b026a05c7f1246b16d059e1df1f394260c1e35a56b1f7738d6c7513d936dc2cec0aefb0ed05dcae0feb5d3413d73c0afac5be677c276c884795b16327b9debc7ac78e41d6d614d40b901248c62db0e3cbb62e7292e4c183c6a4ad78eed72ac8f9b7aa6dab1dd815df75da0bb94c1fd6bb7837ae6805f59b7ccef86ede0993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9e999b59f10cd479614d40b981248c62db093c7b62e7493d77401e35a57beeb0c7b13e6eea997aeeb037b0ebbe0774973218ab7b1dd43307fccaba657e2f6c07cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6ccdccc8a6790ce0b6b02ca0d226114db6ee0d9173f4f69c2e05153bae70efb1cebe3a89ec9e70efb03bbeefb40772983b1badf413d73c0afac5be6f7c376d8ef993db38559f10cd679614d40b9c1248c62db0b3c0762e7493d3f451e35a56bc70e38d6c74d3d53edd8c1c0aefb01d05dca60ac1e7450cf1cf02beb96f983b01d3261de9685cc5e67af7314b3d7d9eb1cc5ec75f63a47317b9dbdce51cc5e67af7314b3d7d9eb1cc5ec75f63a47317b9dbdce51cc5e67af7314b3d7b9e9e8ac78ca755e581350ae9c84516cfb81e7a3d8794a0a13068f9a728cf932c87fe4581f37f54c3d773814d875ff08749732b87f1d7250cf1cf02beb96f943b01d1a3bf3b62c64f6b1d130cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5cc101b8aa742e7853501e52a4818c57610783e8e9fa73461f0a829c7982f83fcc78ef57154cf64bf9dc3815df78f41772983fbd76107f5cc01bfb26e993f0cdbc1337b661bb3e2a9d479614d40b94a1246b11d029e4fe2e7294e183c6a4ad78e7de2581f47f54cb6639f0676dd3f01dda50cc6eaa70eea99037e65dd32ff296c876c63563cc3755e5813506e3809a3d80e038f83b84bf2e41b3c32ff09816f355fa5f379fa3f6eaf2a6064d85ef90da0591b83a78da1d9b1f4adea3f56e74fd0ff717b8d054686edd5a601346b6bf0b435343b96be9516e374fe44fd1fb7d7386064d85e6dddf214270c1e35a53bdff81478be133f4ff23aeed30c78be033cdf8e9fa7c8513d0bd57abf0bec71ad5769f599a1d5a78656f95006193e73a05f0ef89575cbbcf8f3cc9e398a19db42614d40b94f4818c5f66de071d16ea8ba5fa5d725eb6f11a61f9c5ce3d7c5fd35bcb7d052af5738c45f2e9439b75d0ddb4f345b1efc2edb4dd5e7906173f4ce5b91ed3eafcc8bbfbcc07eadefea1e6ad4bd8743c073c8a2d9418b66071c311e341865fe0030daeef31e74c41375df59fc619b718854337c0ff823e071755e1c1567aef7b94ccf2f3fb2f07c131f4f21c606fa7211abd8b6d5a5eeb67d27c6ba17e1332cf4e5601f481ea73ae875c9fad5b1e0bf4e76aa7929b60f729cea60d43917cafcf779356cff27cd71aa5970e47de1026d9732f2fb37da6eaea340af5be6bbebff182762f3c7c0dacf11bb1b5ab26986fbd6c7161d7b58b87b1070633c36c4b68ebaf781dbba87a1239b66b8ad3fb1e8d8d3c2dd93809b71bfee69e8c8a6d9d1f6eb7e16ee7e04dc8cfb753f434736cd8eb65ff7b770f727e066dcaffb1b3ab26976b4fd7a80857b000137e37e3dc0d0914db3a3edd7032ddc0309b819f7eb81868e6c9a1d6dbf1e64e11e44c0cdb85f0f327464d3ec68fbf5600bf760026ec6fd7a70505b4736cd8eb65f975bb8cb09b819f7eb72434736cd8eb65f5758b82b08b819f7eb0a434736cd8eb65f575ab82b09b819f7eb4a434736cd8eb65f0fb7700f27e066dcaf871b3ab26976b4fdbacac25d45c0cdb85f57193ab26976b4fd7aac857b2c0137e37e3dd6d0914db3a3edd7e32cdce308b819f7eb71868e6c9ad9f66b47fdcb32ee87fcb1537d52e3cf66f21e16f6257111538ee2a0d0515f93643fe40386561f1b5ae177fd0f827eaefa6445f51b137f9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec99f999f13d4f7cbe22e51ae21de0ba308a0d9f49b9b8cfafea7eb55e97acbf4598ee3cb5c66ffccf2d8a93cf01447f791ff36aa3ceb95066e7b9356c7d351b3e5fc4e7a2b66d7930f63ad4ed9d737c4f1f9f051dcbe79d1f59343b60d16cbf2346b3cd90f9fdc028fa1d001e57fbe34183c7f46d7b379c4db3a876d655dc47c599cd77416cbe8b87baf9164271a1fa46db71c191ed89d401f75d177198e9370170bf70f0dcbdc8d5fbffaa4efb8d3a1d32ea940f652e857aee7750cfbaee5b325d0b3caedaa3c0e0092cfac8d48c8ce769329ece643c63c9788692f15c44c6731f19cf19643cb790f11c47c6d38b8c6732194f3119cfa3643c83c878da91f1dc4dc6733219cff5643cb9643c5791f13c4bc6d3958c673c19cf30329e4bc8780e93f15c49c6f30019cf59643cb791f124c878cac8789e20e32925e3194dc633988ce77c329ebe643ca792f1dc48c6d3928c670a194f77329e89643c9793f13c42c67319194f2119cf83643ce790f1dc41c67302194f1b329e6bc8789e22e3e944c65345c6534ec67321194f3f329ed3c978ae26e3b9998ca735194f4f329ec7c8788ac8784690f13c44c6731e19cf5d643c2791f15c47c6d39c8ce719329e2e643ce3c878da93f15490f15c4cc6d39f8ce74c329e5bc9788e27e3e94dc6f338194f0919cf28329e87c9780ac878ee21e339858ce706329e16643caedf03cc94e739329e6e643c13c8782ac9782e25e31940c6733619cfed643c79643cf9643c1dc878fa90f13c49c6d3918c670c19cf10329e0bc878ee25e3398d8ce726329e56643c3dc8782691f10c27e31948c6732e19cf15643c7792f19c48c6d3968c27878027111cf92d26fcfed721b0edd779fcb66033cbfae4b9b09457c7a1db0b8e5c7733cbba0f581850a77d414d5dca74bef05f9b923aa1af3298177f79c0718084a72d19cf89643c7792f15c41c6732e19cf40329ee1643c93c8787a90f1b422e3b9898ce734329e7bc9782e20e31942c633868ca72319cf93643c7dc8783a90f1e493f1e491f1dc4ec6733619cf00329e4bc9782ac9782690f17423e3798e8ce723329e16643c3790f19c42c6730f194f0119cfc3643ca3c8784ac8781e27e3e94dc6733c19cfad643c6792f1f427e3b9988ca7828ca73d19cf38329e2e643ccf90f13427e3b98e8ce724329ebbc878ce23e379888c6704194f1119cf63643c3dc9785a93f1dc4cc6733519cfe9643cfdc8782e24e32927e3a922e3e944c6f31419cf35643c6dc8784e20e3b9838ce71c329e07c9780ac9782e23e379848ce772329e89643cddc978a690f1b424e3b9918ce754329ebe643ce793f10c26e3194dc6534ac6f304194f19194f828ce736329eb3c8781e20e3b9928ce73019cf25643cc3c878c693f17425e379968ce72a329e5c329eebc9784e26e3b99b8ca71d19cf20329e47c9788ac9782693f1f422e3398e8ce716329e33c878ee23e3b9888c672819cf58329ece643c4f93f13423e3b9d6e0c1dfd5bb58f27ed87efd3f177e9fa21baf367a5d52469e89a87b4b7b0d9baaef1e47f5dd1bd44c6530bf07ea2bec7b8167af239e7d068fe93b0ff23d40b3dd864d31ee72c4b8db6094f95dc028faed069edd8e78f6183ca6ef3cc8f704cd761a36c5b8c311e34e8351e67700a3e8b71378763ae2d965f098bef320df0f34db6ed814e336478cdb0d4699df068ca2df76e0d9ee886787c163face837c7fd0ec43c3a618b73a62fcd06094f9adc028fa7d083c1f3ae2d966f098bef3203f0034fbc0b029c62d8e183f3018657e0b308a7e1f00cf078e78b61a3ca6ef3cc80f04cd361b36c5b8c911e3668351e63701a3e8b71978363be2d962f098bef3203f0834db68d814e306478c1b0d4699df008ca2df46e0d9e8886793c163face83fc60d06cbd61538ceb1c31ae3718657e1d308a7eeb8167bd239e0d068fe93b0ff2e5a0d95ac3a618d738625c6b30cafc1a6014fdd602cf5a473ceb0c1ed3771ee42b40b3d5864d31ae72c4b8da6094f955c028faad069ed58e78d6183ca6ef3cc85782662b0d9b625ce18871a5c128f32b8051f45b093c2b1df1ac32784cdf79901f0e9a2d376c8a719923c6e506a3cc2f0346d16f39f02c77c4b3c2e0317de741be0a345b6ad814e312478c4b0d46995f028ca2df52e059ea886799c163face83fc58d06cb161538c8b1c312e3618657e11308a7e8b8167b1239e25068fe93b0ff2e340b36ac3a618df77c4586d30cafcfbc028fa55034fb5239e45068fe93b0ff27dc126bc45607b4fe78bc1b650e74bc0b640e74bc1f6aece7704db3b3adf096c6feb7c67b0bda5f35dc0f6a6ce7705db1b3adf0d6cafeb7c2fb0bda6f3bdc1f6aace9781ed159def03b6f93a7f0dd8e6e9fcb5609babf3d7816d8ece5f0fb6d93a7f03d866e9fc8d609ba9f337816d86cedf0cb6e93a7f0bd8a6e9fcad607b59e76f03db4b3a7f3bd85ed4f93bc0f682cedf09b66fe9fc5d607b5ee7ef06db549dbf076c2375fe5eb0ddaff3f781ed539d7f006cdfd6f907c1f61d9d7f086cdfd5f987c1f699ce0f01dbf7747e28d8fe4de78781edfb3aff08d87ea0f323c0f6439d7f146c3fd2f95160fbb1ce8f06db4f747e0cd87eaaf3e3c1f6339d9f00b69febfc44b0fd42e72781ed973aff18d83ed7f9c960fb95ce3f0eb65febfc1360fb8dce3f09b6dfeafc5360fb42e79f06dbef74fe19b07da9f3cf82ed2b9d7f0e6cbfd7f92960fb83ce4bbba6dad93fea7c41106f3bfb75503315806ff1a7cafc49e75b196564d95c2853aa3fe8a39e71a86f994a3b2cedb2b2493bfc1ed8a41d5e0836698717804ddae177c126edf03b609376f86db0493bfc16d8a41d7e136cd20ebf013669875f079bb4c3af81ad4ce75f059bb4c3af804ddae1f9609376781ed8a41d9e0b366987e7804ddae1d96093767816d8a41d9e0936698767804ddae1e9609376781ad8a41d7e196cd20ebf043669875f049bb4c32f804ddae16f814ddae1e7c126edf054b0c9fef235d8a46d1e0936699bef079bb4cd9f824ddae66f834ddae6ef804ddae6ef824ddae6cfc0266df3f7c0266df3bf814ddae6ef834ddae61f804ddae61f824ddae61f816db4ceff186cd236ff046cd236ff146cd236ff0c6cd236ff1c6cd236ff026cd236ff126cd2367f0e36699b7f0536699b7f0d36699b7f0336699b7f0b36699bbf009bb4cdbf039bb4cd5f824ddae6afc03645e7a5ad6e0d367956aca6c27f71c271789a812f612a0be26dfb712a83fc73507799a693f18c25e3799d8ce722329e95643c2bc878ce20e3f9808c670b19cf71643cfbc978f691f1cc21e379878c6710194f3b329e93c97872c978ae22e3a926e379958ce712329ec3643c5792f19c45c6b3998c671319cf72329e65643c09329ebd643c7bc878de27e39945c6f31619cf60329ef3c9784e25e36949c6d39d8ce772329ef9643c9791f12c25e35942c65348c6730e19cf46329e0d643c0bc9784e20e36943c6b39b8c671719cf0c329eafc978aac878de20e32927e3b9908ca71f19cfe9643c5793f1b426e3e949c633978c673119cf22329e77c978ce23e3594fc6b38e8ce724329e9d643c3bc8789a93f14c23e31947c6f31a194f7b329e0a329e8bc978fa93f19c49c6733c19cf54329ed9643c6f93f1fc9e8ca7808c672d19cf1a329e53c878b693f16c23e36941c6f31119cf2b643c95643cef91f10c20e3399b8c278f8c279f8ca70319cf48329e99643c6f92f15c40c6b39a8c671519cf69643c1f92f16c25e369a5ffb3f0f420e39947c6339c8c670119cf40329e73c978ae20e339918ca72d194f0e014f023802b0c9efcdc1f695ce1f069b7cafe723b07da9f3d560fb9dce4f01db33165b330b9f307c053679d7fa59b0c9fd992fc126ef70fc0e6c725c14ff6abe6fc191fccd6019f1d3dcc28ffe7e67e1923c6e6f59a62c88777ba3afb2e0c8ef29e501c7b3243c6dc9784e24e3b9828ce75c329e81643c0bc8788693f1cc23e3e941c6d38a8c672b19cf87643ca791f1ac22e3594dc6730119cf9b643c33c9784692f17420e3c927e3c923e3399b8c670019cf7b643c95643caf90f17c44c6d3828c671b19cf76329e53c878d690f1ac25e32920e3f93d19cfdb643cb3c978a692f11c4fc67326194f7f329e8bc9782ac878da93f1bc46c6338e8c671a194f73329e1d643c3bc9784e22e35947c6b39e8ce73c329e77c9781691f12c26e3994bc6d3938ca73519cfd5643ca793f1f423e3b9908ca79c8ce70d329e2a329eafc9786690f1ec22e3d94dc6d3868ce704329e85643c1bc8783692f19c43c65348c6b3848c672919cf65643cf3c9782e27e3e94ec6d3928ce754329ef3c9780693f1bc45c6338b8ce77d329e3d643c7bc97812643ccbc8789693f16c22e3d94cc6731619cf95643c87c9782e21e379958ca79a8ce72a329e5c329e93c978da91f10c22e379878c670e19cf3e329efd643cc791f16c21e3f9808ce70c329e15643c2bc9782e22e3799d8c672c19cf74329e66169ec38e78e45829eb96f9c304bed57bb8722f7ebffe9f80df71fce66a478c870d4699af0646b1ed039eee8e78f6183c7b2c5a1c2bdf4a0bf9f6c75efd3f01bfe3f70a5dc554778351e66d31b507787a38e2d965f0ecb26871ac7c2b2da4efa3f42149c0ef381e9eab98ea6130cabc2da6703cd79e8e7876183c3b2c5a1c2bdf4a0be96b287df813f03b8e7fe92aa67a1a8c326f8b291cafab9f239e6d06cf368b16c7cab7d242de3d93779613f03b8e27e42aa6fa198c326f8b291c1fa2bf239ead06cf568b16c7cab7d242be2521df444ac0eff87d7f5731d5df6094795b4ce1f7910738e2d962f06cb16871ac7c2b2de45b7572cd9e80dff1fbb6ae626a80c128f3b698da023c031df16c32783659b43856be951683745e9ec125e0f741c0e82aa6061a8c326f8ba94dc033c811cf06836783458b63e55b693158e7a54f66027e1f0c8cae626a90c128f3b698da003c831df1ac3378d659b43856be9516e53a2fef0c26e0f77260741553830d4699b7c5148ebf5bee88678dc1b3c6a2c5b1f2adb49077efd7eaff09f81dc7e31cec88b1dc6094f9c1c028361cefadc211cf2a836795458b63e55b6921dfd2926f3026e0771c1fcb554c55188c326f8b291cefa4d211cf0a836785458b63e55b69315ce757eaff09f87d3830ba8aa94a8351e66d31b502785638e25966f02c23f2adb49077e1a40f5b027eaf02c6958e18a3626a25308a6d19f02c73c4b3c4e05942e45b6921cf72e49d8b04fc3e1618973b628c8aa9e5c028b625c033d611cf22836791458b63e55b6921df8e59acff27e0771caf7d8923c6b106a3cc2f0146b12d029e458e78a2eee13584efa8fb510de13beade4a43f88eba4fd010bea3eeb13784efa8ebb786f01d752dd210bea3ee333484efa873fa86f01df57cbb217c473dab6d08df51cf1d1bfbfeed8f254deb58722cdbb5a67a2cf1ed39677b3e2e7edfc589a0f6358d9a728cf932c8e3f5cb62075a38aa67215e137e13e37a6dd7f08b0cadf2a10c5ea3babafe1b67f0c8bcf8cb46668c8b9cf87c1726c087bca3ac6c72afe53db0c93d8e8560937b200bc026f7d0de059bdccf7a076c72bfeb6db00dd7f99160937b97d81f49ee6dee005bb9ce633f98c13abf0d6cf29c08fb5fc8b3bead6093e7b5f8dc5f9eb96f019bf49bc0e7cdd2f76513d8a4ff123ee7943e681bc026fd08f1f95ab5ceaf039b8c2981cf75bed4f93560fb4ae7f179828cd5b90a6c4febfc54b07da1f35f83ed299d5f04b6dfea3cdef37952e7c782ed373aff16d87eadf36f82ed099d7f036c8febfc7eb0fd4ae7f7816db2ce63ffd0cf757e0fd81ed379ec97f84b9ddf05b65fe8fceb609ba4f3af816da2cebf0ab69febfc2b609ba0f3f3c1f6339d9f07b6f13a3f176c3fd5f93960fb89cecf06db189d9f05b61febfc4cb08dd6f919601ba5f3d3c1f6239d9f06b64775fef760fba1ce8f035b339d5f0236f97e32ded395771697814dc629c17bf5f2ad922ab0c9f87b2bc0d65ae7f1b98cbc97341c6cf26dfb4ab0c9fbff1560933192cac126e3380d069b7c0b6c10d8e47b6503c12663960e009b8cabda1f6cf2ede27e6093f7297b824dc608e90136f98e4a77b0c9d8773826b07cefb21a6cf24e108e132cdfddff126cf26ef9576093f19b704c60f9c6d5d360937149bf00db793aff14d8e47dcddf82ad40e79f04dbf93aff1bb05da0f3bf069b7cbff209b0c93b358f834dbea3ff2bb0c9bbd993c176a9ce7f0eb6cb74fe31b0c977887e0936192bf617606baff393c026efcc4f04db553aff73b0c9586713c026df57fd19d8e41b5fe3c156a4f33f055bb1ceff046c253a3f066ca53aff63b075d4f9d160eba4f3a3c0d659e77f04b62e3aff28d8baeabcb4336a7f56fbf9213d5f16c4775ea6fc7d1cd49ed25d1b0803f2c479ae9d0f3ce8eb60ec752f4e9ed7cb7edf4caf5762e820f8de1fbbefd435c501bdae167abdfb0ddfb950e653dd88a8e5f6c2ef655007590eafb165ddb2ccd5b0ec3e63dd6d747d0f38aaef7e8349b80f009394f9ecdc9ab24fe9c6b2352c13235bf2fa58622d000d712a83bc30b8d1aab810cf7bebc2730078e2df4f52d7eb2e6202f7adb8afd7cd7b4c66ace54399fda0df3e07fae1be2eeb9679f1e7993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9e999f59f1c8f3047cae2ce50e91308aed20f01c889fa7109fc3cafad5739d87e0b9cec1d8fdd67ebed752afb7d0a8732e94597d5e0ddb109dcf83df65bb456dcbfdb1d721fdb6147f79509f03c0e3605b26790e1a3ca6ef3c8b3e4ab37d16cdf63a6234db0c99df0b8cfb757e1ff0b8da1ff71b3ca66f6c330e906a16d5cebae897902ece6c7d100a62f35d3cd4d5735dd5674af5e5308f5f870c4db10f84d8f039781e2cf389fe9f007d3e017d8e651b60f64bc076ea6360dc1f3b6371ad67c0d2f65f6d688a7d205ed4da4a1f88f8db81e24297c708d947cdbe1558572933038e73b3741efb011d8275bd6bf95da61c63be0cf2d8a6ee8ebfcec9ed2bfd5765fbeeb6f8de09ac31f9aef52e478e4ee247ecb9907fe7bc9ab2524ef410ad851dc7ad427673b98f8de5f2a1cc1e4bfdcb8278ebbfdbe0d96d30abd8990b71f62e9cebb96a93f644687435682465f09cd7419f226b1b291ce24f9591eddfca2883e7a7526609b451aa2ed2ce4b3db11f131e035c9d2f1c32ea27f378be603ba731eba8e2e3ce536b785d5f0b340bec5ab3f4f5db02ed45dc7dfdb6400cd9ce4b65fd85b07ee16a15441f5ba4cc36e338eae27a12b7a5a9e701609232bba01dfa1ff5b8ae3b56d7e851d7757b1cf0e0b5864ce98eef788c71d1be38aa67a1edd8b5cfa8533e94b914eae9e03c26ed3ba9bbc1b78b6d8e5ac839d47e438b5c28f33da3ed88d251d681f701dcd6a5d87a3e5868a98b94f9b1d14eed72c0e472bbe179965aef414b5da5cc2fa0fdfb1ccee7f7ebdfb12dfd8be57799d2b507f84df9edf1d739b97de5fd46d9bedb2dbe3f04d6987cd7fa26859cef8b1fb1e742fecf70fc9672a287682dec6a1f91f73b91dd5c6ebfb15c3e94d961a97f59106ffdb71b3cdb0d66153bbf8138fb0b9cefbb6a3777446854081a49197c5660de6fc17b2778dc6fa8eb0299ff0818c5b61bf4fd1f4eef97a7d83e32d8ccfbe5b6f3c142831fcf07ff17b4b3094b59f7cf0152e736582fa94760d43530eaeae8fcb534c7d0b30cfc7400fb7e9d179de5373cc7953239ed52ffddddbfaa7d1f5bb8a51ef8bc6eafc1bdcfd015ef45b5046e15f7e6b5059ea73bbea62dc57331f37c08afc3a44c1eb0dbcee30e5bea621ea79b05475e0b7e6394c5ebec74cb99f98f8c65f09ec1410b93aded8bedbd9ca2c24293dfd6ee1d32986dbaca7e803127eb32f7153c1f923267c3764b58caaa36e9bf4eaed147b623de6bb7dd677175bc88bacf22fe14a3ed9d4917cf309ae2bb69ad635b6fd772db7336f6fe0cad8d7c3cbe8b2bf058914e8bbd161e57f734a3b4d86bf11d9f169d86dada399b167b2c3caeae31a3b4d863f11da31695b67b0b362d765b785c5d6b4469b1dbe23b3e2d3ad7baaf914e8b5d169ef8ef69a4d7029f8965c2bc8780b9b5918fc77769b9edd99d4d8b9d161e57cfeea2b4d869f11d9f16459d6cd7ec362d7658787634b0163b2cbee3d3a24b57db3d159b16db2d3c0eeeafa5d562bbc5778c71310cefafa5d3629b85675b036bb1cde23bc6f3c34ee9ee19a2161f5a785cddfb8bd2e2438bef18b518a27c6fad83165b2d3c5b1b588bad16dff16951de51f9fea00e5a7c60e1f9a081b5f8c0e23b3e2d867451beb7d4418b2d169e2d0dacc5168bef18afa19271b1b90e5a6cb6f06c6e602d365b7cc7a74545f25c6b531db4d864e1d9d4c05a6cb2f88e4f8bc2e43175631db4d868e1d9d8c05a6cb4f88e312e92d7931beaa0c5060bcf8606d66283c5778cc791645cacaf8316eb2d3ceb1b588bf516dff1695199bcffb4ae0e5aacb3f0ac6b602dd6597cc778cf2519176beba0c55a0bcfda06d662adc5777c5a94248fa96beaa0c51a0bcf9a06d6628dc5777c5a0c4b3e135b5d072d565b785637b016ab2dbe633cef4cb617abeaa0c52a0bcfaa06d66295c5778ce79dc9fb172beba0c54a0bcfca06d662a5c5778c6d67f2bc73451db45861e1713546649416b6f129633cef4c6ab1bc0e5a2cb7f0b81adb304a8be516df319e77268f23cbeaa0c5320b8fabb128a3b4b08d8319635c24dbcea575d062a9856769036bb1d4e23bc6fb5ac9b673491db45862e17135364794164b2cbe63bc1e49dee35b5c072d165b781637b0168b2dbe637c56943c075f54072d1659781635b0168bc0f781d87da7fa738b0fe98b7595a1452e94f98ed1172b4a475907be438b75a98ebd2ea97e65ef47d4a51aea22657e60f4e57bdf0193a3ba2663e63dbd2ee99bfeb1a5ae52e6a7ed6acafe5ce713b04d0ec3bafe68f95da61c63be0cf2a29faaf382f8eb9c8c55190748b6ef028bef77803526df45e83b4727f123f65cc87fddaea6ac94133d446b6157fbc8429d477673b945c672f95066a1a5fe6541bcf55f60f02c309893ef3d409c491cb969bb524c0b2334ba0a349232d867efb0239e8f0d1ee1107f39c191efa24a195916df45fdbbd16f57fa414a3da3fa48bee7a87e517d24c55fd4bba8661d557cfc00fa7ecab820326688b2c9182025b09ece864dd5b58ba3ba8a2f59b7cc7701461993a473c33316d795b193c1a878ba39d00cc7599129ddf1a21bf07475c0e3a89ec9e35077a34e5d8c3ae543197cb7b1bb837ae6805f59b7cc7707df2eb6396a21c7e4cb0d2d72a14c5e41eabf9c3f46e928eb50f1dbd95217573a7632783a597cf772aca3ac5bdac45e0de0bb87e1bba3e15beddb18636a4ab76ff700e69e0e98d57a7bc7bfde423c679478163f1da14e7d4083b8ea84eb9273cc3e86b6b990bfb0a0a6ac9493b272ec1476b51fc9b6447673b96ec672f950a697a5fe6541bcf5ef6df0f43698d579c31905351c0ef687640cf4323864be2368d73b42bb5ea09d94c1636f2747daf5347864be13f0c8f95577b0c9798af027e0f79206e036dbbdee166eb1e178849d2c8c1de3672c4e775ce8088c62eb093c3d1c69666eebcb0d7df09ca095514696cd85325d0a52ffe55d2db3acdaefcecfa9a957736d8fedbd35dda6b774a0178e071a803e81a1a14cc2d03aa81933344e9ee3839a3141274cac1a3fe49161f70c4b3df614b45c0313ffe758aad10c6c986f6eb10541eda14f73c126439fb6005b3343161c7255cacbd0892ee4423d64ddb906676b6089d3370e1b2b53bad069053c2e4259858e0c1dab43e7fef123260ec3f8686170d62776d46fcdd3948b5a97c441ae83ba2393ac5be6c59fd2275fe7c70e193ab2cff847268d1e3666e2048435772ecce7182298ff6dcb6090e0ce24eb696188737cfce294e218c5265f00fe641286d641cd38c631f2240355c61a1e3a64d4a8bb26958f1a31f4864963864e1c513506156d6d2817a5b6fcde126cb6a60ecbaa09775f5cb695c5669b7054e7d6609316fc38b009cff1606b0e79296f6e1927fbc8a5b07e096bf59b12a785ae78aba02604e4b0a4da17b50fa9cfa8aad30135b4b41a4a5a6d4e75c74e0d0dadbe22a7867e56433daba19dd550ce6ae8663554b31a9af9dc2035f4b2ba7b5910a48652be20480d957c51901a0af912e0fb0e305f16a44e3fd450c6ed83d450c5eaf6a17a7d5c7d6a4dbddfae4e63d5e5b13af553973aea344c9d7ea9d36c750b41dd4e52a736eab4519d12a9d318755ade5b6bdd274cd784e9da305d17a6ebc37443986e0cd34d61ba394cb784e9d630dd16a6dbc3744798ee0cd35d61ba3b4cf784a96f98ee0d52c369df17a6fb83d470db0f04a9a1b81f0c52c3743f14a486f07e38480def3d24480dfd3d34480d0b3e2c480d19fe48901a4e7c44901aaa7864901ada7874901a1e590d533e36480d89ae865a56c332ab219cd5d0ce6a6868358cb41a725a0d45ad86b27e2a480d91fd4c989e0d5243684f09d3d4303d1fa66f85e98530bd18a697c2f472901a965d0dd7ae86719f19a4867d9f1da4868957c3c7ab61e5d570f36a187a353cbd1ab65e0d67ff4698de0cd35b617a3b483d16508f43d46302750b5edd22568f69aa83d4edebc541ea31b37aecaeba21a86e19aa9bcaca20d58d4975eb52dddc54b73fd50d52750b55dd6455b761d58d5a752b57ddecd56b07ea350cf55a8a7a4d47bdb6a45ee352afb5a9d7fcd4ab9aead547f52aaf7ab5797f90ba357d30483dae54b7abd56d69758b5edd42ff344cdf0e5231f9dd307d16a6ef85e9dfc2f4fd30fd20480d19ad869756c353aba1acd510d76a386c3574b61a7a5b0dc9fd79901aea5b0d15fe9b2035dcf81761fa5d901af2fcab2035dcfd1fc2f47598fe18a63f85e9cf61fa4b98fe1aa67f0fd37f84e96f61fa7b98fe334cff086a8635c786a440b73ee7ebf92113270e1b3d7662c1c4aa82d193464d1c3176d4130593474c1c5e50f5d8b0f195a3aa26e3c2bfd50bcb98ec7dc68f1ff244c1883115c31e2fa89a34b1a0aab2a0bc6ad2988a5a07d2ffab173ae7488f432a2aa29de535ff17484f6c5e3fa7edf47232dafdcde9eb7641f37a0872597d16baad9e15ba571fc1e492af6fea7cb060c2a8aa8905850563c2bfe181b76af2b08a0e05f8db8450e409130b264c1c327e6241e5f8aad105451d70bd85c7d7a312f38f7703537266fdc4f9e4dcd4ff7a85d80be7d54381c5e7d58f74f379ff02e987f574fa597d6af8a3fa2cf45ff5240cda45ca326152f9c4f143864e8c5eb8c5bfb270a25d3daa7956bbfa55f3dbf571f6fdfa2cf4b77a12260aeae1ac7341dd9d05ff1f1bdedcb8b00206009b2d6c6f000000275d1f8b08000000000000ffed9d67701cc7b1c7f700100cc72308e64c28514c000f8744800994c41c642a8b4a0449502245121409e51c6ccb966dd9720eb264cb414e720e72ce39e724dbb225dbb265ebcb73bdf7ea55a9deccdeb4f1c76876853b6f83b3b8deaae6cd36e6b67fdddb33bb3733bb7c2608824c50dcaa959c143c77a3bf779bcffc7fb6352778ac3c276726259c5529e1ac4e09674d4a3847a584b336259ca353c23926259c6313e4d46c55c1e02d69de710c714d9a319bb2988e4f414c73298be98414c4b42e48471f3531259cf529e19c9412cec929e19c9212cea929e19c9612cee929e19c9112ce9929e19c9512ced929e19c9312ceb929e19c9712cef929e16c4809e70929e13c31259c27a584f3e494709e9220e712e05c603e4f359f0bcde722f3b9d87cd277969acf46e3638dd96f52b24cb32969b6fe5650d2a2a455499bf5b776251d4a962be9347f6b307feb52b242c94a25ab94ac56b2c6c461ad92d3949caee40c25eb94ac57b241c946259b946c56b245c95625db946c5772a6921728d9a1e42c25672b3947c9b94ace5372be920b945c68b1ec547291928b955ca2e452259729d9a5a447c96e257b94ec55d2ab649f92cb955ca164bf92034aae547250c921258795f42939a2e42a2547951c53d2afe46a25d728b956c9754aaeb7627683921b95dca4e4668bf31625b72ab94dc9ed4aee5072a792bb94bc50c98b94bc58c9dd4a5ea2e4a54aee51f232252f57f20a25f72a79a5925729b94fc9ab95bc46c96b95bc4ec9eb95bc41c91b95bc49c99b95bc45c9fd86851ac25b953ca0e441256f53f276250f29798792772a799792772b7958c97b94bc57c9fb94bc5fc907943ca2e4834a3ea4e4c34a3ea2e4a34a3ea6e4e34a3ea1e4934a3ea5e451259f56f219259f55f239259f57f205255f54f225255f56f215255f55f235255f57f20d25df54f22d25df56f21d25df55f23d2be6df57f203253f54f223a3fbb1f9fc89a94be3623f55f23353feb9f9fc85f9fca5f9fc95f59d5f2bf98da5fbad92c72cddef94fcde94ff603e1f379f7f349f7f329f4f98cf27cde79fcde75fcce75fcde753e6f36fe6f3efe6f369f3f90ff3f94ff3f98c92dba714cb638281ad3b48a88f6add97d7732a14fc05c1e04dc7a2dafc8d3e1b8cbec6ecd327c56e94d91f65e96bcd7ead759c31667f8ca5af37fbf5967eb2d99f6ce9a79afda9967ebad99f6ee94f36fb27833e1bc098abd16b5db551654047f95a05ba5146570dba5a3a1ce8461bdd28d0d1f9ad05dd58a31b0dba714637067459a31b4bb15432dee8ba83a47225dfa38f9b4bfab8661e6a42f2bc7bf471eb98782726cfdbab8f5bcfc0abf3639239d644c89bc946570f3ad3dd04934037d5e826836e9ad14d01dd74a39b0aba1946370d74338d6e3ae86619dd0cd0cd36ba99a09b6374b34037d7e866836e9ed1cd01dd7ca39b0bba06a39b07ba138c6e3ee84e34ba06d0d11a97134077b2d19d08ba538cee24d0515f7b32e8e8def014a3d3fdc4980c7cc7e8a98f0abf43fd33e81652df0cba45d42f836e31f5c9a05b02b649b714fa15d2351a1df551fa6f5da6dc1d24d5260a619b5891f471d591f57157257fdc70de6e753010d76eb0b30262b5c694135c1bd48cb63346c80ee96ba0bc09ea523d8a075d67885d5f4f569af29a98ef7559dfcb419d950effbb8364fd5f65f1acb2984781ff3c39db52909c1df25672ce9e0f75eddca37b9e9198b35b81832167db256787bc959cb3bd50d7ce3dbaef1d8939bb13381872b68727670b79c9d9e2185910b8738f7efb8cc49cbd023892cfd936c9d9a16f25e7eced50d7ce3dfafd3b1273f61ae0483e673b7ae4de60c85bc9397b2fd4b5738fc6624662cede051c0c39db2bfdec90b79273f67ea86be71e8d0b8ec49cbd0f3892cfd94ea69c6d919c0d8af39d41e0ce3d1aa31e8939fb2070249fb37b647c76e85bc939fb28d4b5738fe64b4662ce3e62ca7a9ee1c7669e610ee87e6274738137f9dcdedbca94db05c9ede23a902070e728cddd8dc4dcfebc29eb3cfe39ac3d20dd2f8cee04d0fdd2e84e04ddaf8cee24f08ba10df4481b18f256721bf80dd4b57399e69147621bf8217030e4ec1ec9d9216f25e7ec5350d7ce3d5ad3301273f677c0c190b3bd92b343de4aced9ff86ba76ee2d34e59198b3b4ae54df2ffcc1dc2f2c06dde346b704747f34baa5a0fb93d13582ee09a36b02dd9346b70c747f36ba3ce8fe6274cda0fbabd11540f794d1b580ee6f46d70ababf1b5d1be89e36ba76d0fdc3e83a40f74fa35b0eba678caed3e8f47c17adbdfab6d1e9734bf1e80e923bb7e17aab60f096b1f6bba1dcc8cb93cf05839f45205bcb92b7d5a27d6f0a86eefb32e0c933f89e051b43e1c9034f73f23ce1bad342f2c70dcf719315d32cd86a02bf5a18fcca802d3a36ed93bd1ce8b02f697130b626cf58c8802d3a36edb70223e9b06fa36b0cb51fdd373764067819da52787d467bddc041f66aa0cedc2903754f366ce3e1efd4078c8732f6fdcd968e2957c35c215b746cda2f0023f9d83cfc8c85a132e62d46ae7e2303b6e8d8b6edf18ef8e898b53a62d6c6c4d86a31d27e1b3052fc5a879fb1305446bb5f60ea939a87da27515c9a873f66433aaf39d0e1fd5f9b83b13d79c6f0bcb6598cb4df0e8ca46b011eaeeb61547bf5c536c77d08e6335db3e8fa43f66aa04e47f540ddad703d65e8430ba5de9b629f9efc792ae4f17a36141ee673d7cc948f79ec3b9f0d92cd35bbcd375bb1c2368f7d39573f19d597933d61166661166661166661166661166661166661166661166661166661166661f69f396a5eceb59ee1783292ae003c1ce3fce13baaccb1700ee83198d7497edea290c7b97a5ac7b8c8f2b906eafc5f6680ed71c73a099c3b5f66e998d62985e712d72975c33ed9c3751bb86e8a61ed49c8b3d4e2b16d8f77c4c7c775243eadd1885aa7e553cc72a0c3f5704d4c3c5179d6e4b0dd9098edc21e9eb653c8ebf701e977ea517f62b7115cfbb6c4d2e93ea9ab7ac06f8e1c2875de19af1b544e721e17f30d6d25bfdea630687d425530f85a81f7140c6b5406cd57d3da8876cb760dd4195b15fcfbdc2c87bf7707cf5d23a4eb7458c7a6ef2c82ef7658c7aee3f337b63f6c076e2ad75abe350237d5995035e0e3e74c99e97ea680eb6703e00d2c9f68c3f519c9dfef15d78bb494c0d3063c1c6bd798ee6bf3988f49af17e9b062e5ba5fa63aed10bf0e86f8c5ad59237bc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc2ec3f33beff8258f119e982278cc3b4c6269ccfa07719e1bcd803550376b9e70069ce69b1e5333ea3fc74d500db43a68cef08703def8ee7926b6e2dea5c92bdf1c1739fd3673a97437ef7439b23661d8e982d6762b4fb0cda5f0e8c14bf0ee0e16a8fed168f6d1bfb8c364f6316d5cf72ad5f89ca33d73a8586c46c17d78b70ccebd27a11fbfa55b0628aeb244887f3e0f86e159fdfff62af5dc07e0ad76825df6f1606cd01db6b05c91eae93f886892dad9348be1f28e439af11d446694d488bc357aaf35db8ce7ddf9471ad50018ef598e3efb4c5ad49c03e35f17770e68b73fcf4ee4a3abf5d0edb2b813521dbcd683b6384ec90be06cabfad1aa84bf5281e146b62d76d84de6588ecf6f79aadefe5a04ea7c3ffee2059ffbb2c9e2e8b59e7ce8f20cf1e837b3dae3ea93322468b20465407ef79b9ae5ff69a6d7bad32f6a3a3ad3af4dd1aa8f324f451a5bc2b8aeb7e21ea1a80f70bf67561286bc72b7d3de0bfa0bf487a3de0bf20875cf7a574fcc5707ce21a1d445f5ba8ceff5ad75186f57a437aef95ebb71ff1e27a43aaf32cf45579b32e37ea778ceb390baedf0d51cf7d903dbca72ac577ec1792be36623e220be6f2bfafd126d6948f1d11dccb1cdfcd467c976245ebcbf177b21d3f1d874ef84e77227128f6375d962fd4a63ac117aa530fbef0dc3315ef3f93f775f0fd10f541ad0e5fa9ce347817dc0c53cec279c2bef254c7df698bbbffa4f8699f87fb9dea68db8777aa2fa81ea86bbf1b9d625dea3bd5dbadeff9f84ef5d99067a7c2b3165c7df5ca88182d8618511d7cd6d1fefd1f758d399eef25b5fb4dbc4e0e279b3d7eebba3fa13a780f4d75daa09fcd3aeadae3d2740d49727d3a3e0fb414ece2f3404b99e2990b06c733677170daaeb36cd70da3ed7acb76fd30da96984bcc7d8a39c3ff3d51f6ff8581ff6745550a18ab53c0589302c6512960ac4d01e3e814308e4901e3d814308e4b016316188fe7b59d213e05cffebfa7d87b0db4cdf03e8730168dc1d063d1c4cb137bef83b619dea152f2ff37c0fc7f613597fb7f61e5e07b9352c03839058c5352c03835058cd352c0383d058c3352c03833058cb352c0383b058c7352c03837058cf352c0383f058c0d29603c21058c27a680f1a414309e9c02c65352c0b8401813615cc2cb58f0edff71ce0683d79a3d1f0ff3bb47c37728bade73caf17fe396ea3bf37b879bcb7d4f1faeb1e0fdbf1effb3770972aca128f55d8271ff3f361363a15c46aeb5e4b88e7a283cf81caaebf91606c642b98c5ccfa0e0339143e171fd5fbdbccf041563560e23d79ab152d734e2b382ed8e98313016ca65e47aee009f891c0a8febd9c5665ec642b98c5ceb73b36063283c9d10b3e58e98313016ca65647abe2c8c5967093cf81c56a723660c8c85721935cf0aa6987595c0b30262d6e588994f8cc893f43bd1bb1cb6389edb2bd5776240c6b129601c9702465c27c1d17fc5ad93e8e28d4fa1dcf8709dafb87512689be139913016f85cc0f3c562152f4fec3a09b4bd9a2916f8dcc6f3c56235f0703c4792051b43e121861c7c6f520a1827a780714a0a18a7a680715a0a18a7a78071460a1867a68071560a1867a780714e0a18e7a680715e0a18e7a780117fab32dc2bc6fe7e593dc26d47fd5619e9b6a37e978c74db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf2bc1b6e4b9e4b94fb6d330c62f8c238f11791a92e3c9a3ef68abdb03dfbb1d3c1926dfd1d65a0f7c2786b431ae4901e38a14304a1c8b6b10cb61d43ca731f1ac2d81e734e0399d89e7b412784e079e3392e70973eaf41278882107df5b9102c635296094384a1c7d629438564e1c8551188551188f07631afa70614c453e16ca65d43ceb92e709637646093ceb2066f4bd665ec642b98c9a677df23c61ccd695c0b31e62b6ce113306c642b98c9a6743f23c61ccd697c0b30162b6de113306c642b98c9a6763f23c61cc3694c0b31162b6c1113306c642b98c9a6753f23c61cc3696c0b30962b6d1113306c642b98c9a6773f23c61cc3695c0b31962b6c9113306c642b98c9a674bf23c61cc3697c0b30562b6d9113306c642b98c9a676bf23c61ccb694c0b31562b6c5113306c642b98c9a675bf23c61ccb696c0b30d62b6d511335f1957a480714d0a1899e358289751f36c67e2d95602cf76e0399389677b093c6702cf0b92e70973eacc1278882107df5b9102c635296094384a1c7d629438564e1c85511885b134c6ee1430cab916465f19197e5fc53e4373e608b75d67d9aeab10db51cfd08c74db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf2bc1b6e4b9e47925d8963c973caf04db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf2bc1b6e4b9e47925d8963c973caf04db92e792e795605bf25cf2bc126c4b9e4b9efb647b47f2b60ba53ec3ba0378389ea965f233af8f7b9639d6b309c64fc7ea6c2b56675ab1ca419db3207e6733c42f0376e9d8b44ff64a653ed5036626db8509ea1863c17fb2b1c68a87b67f0e93ef517dfd3923dc76545f3fd26d47f5f523ddb6e4b9e47925d8963c973caf04db92e792e7bed8c6f2a860e0be9ddeafa48f712efc3d63b1eaad06eaac1a5dfcac0ba40d71d8963624d78a4ab02d792e795e09b625cf25cf2bc1b6e4b99f797e5ef2b6c3b931fc7da1b7b8b9b1f380e75c865830f999d73e9d6ff9748ee5530eeae03b6bcf67f0330376e9d8b47f3e9c87b4316b9ed5a64cac59a8b7da1346d29dcbcb13b6afd5c1e02dae7d9d0f3c0ceda099c9cfb07d5d60f9b4da1177aa83b97a01839faeb643fb17c079481bb3e6596bcac49a857a6b3d6124dd79bc3c61fb5a1b0cdee2dad705c0c3d1ff30f919b6af0b2d9fd63ae24e7530572f64f0d3d57668ff42380f6963d63ca79932b166a1de699e3092ee7c5e9ed62cf84c5b5cfbba107838fa1f263fc3f6b5d3f2e93447dca90ee6ea4e063f5d6d87f677c27910666176316b1efa3fe589350bf54ef784917417b0f2b4e6b3e0336d71fdd84ee0e1e8e799e21ef66317593e9dee883bd5c15cbd88c14f57dba1fd8be03c94c2bc2685cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc12e7f29835cf19a64cac59a87786278ca4bb9097277c7ee78c60f096b1f6bba17c11f0ec64880f939fe1baf78b2d9fce70c49dea60fbba98c14f57dba1fd8be13c94c2bc2685cc12e7f29835cf3a5326d62cd45be70923e976f2f284fdd8ba60f016d78f5d0c3c1cfd3c939f613f7689e5d33a47dca90eb6af4b18fc74b51ddabf04ce83300bb38b59f3ac376562cd42bdf59e3092ee22569e42f81ce2fa60f016d78f5d023c1cfd3c53dcc37eec52cba7f58eb8531dccd54b19fc74b51ddabf14ce4329cc6b52c82c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c2b27ce9a678329136b16ea6df084917417b3f2b484f30e1b82c15bdcbcc3a5c0c3312fc314f770dee132cba70d8eb8531d6c5f9731f8e96a3bb47f199c8791cebc2685cc921bc3c32cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc5ec436e689e8da64cac59a8b7d11346d25dc2cb13bef7606330788b5bb77319f05cca101f263fc3753bbb2c9f363ae24e75b07ded62f0d3d576687f179c875dc22ccc0e66cdb3c99489350bf53679c248ba4b7979c27e6c5330788bebc776010f473fcfe467d88ff5583e6d72c49dea60aef630f8e96a3bb44ff6845998a39835cf665326d62cd4dbec0923e92ee3e509fbb1cdc1e02dae1feb019e5d0cf161f233ecc7765b3e6d76c49dea60aeee66f0d3d576687f379c0761166617b3e6d962cac49a857a5b3c6124dd2e5e9e42167ca62dae1fdb0d3c1cfd3c939f613fb6c7f2698b23ee540773750f839faeb643fb7be03ca48d59f36c356562cd42bdad9e3092ae8797276c5f5b83c15b5cfbda033c1cfd0f939f61fbda6bf9b4d51177aa83b9ba97c14f57dba1fdbd701ed2c6ac79b69932b166a1de364f1849b79b97276c5fdb82c15b5cfbda0b3c1cfd0f939f61fbeab57cdae6883bd5c15ced65f0d3d57668bf17ce43da9835cf765326d62cd4dbee0923e9b09fa2ad0a18b7333106166360c50779e679c6b3c3339e199ef14cf28c67ac673c8b3ce3a9f68c67b9673c6d9ef1143ce399ef19cf4ccf78267bc633ce339ea59ef1d478c6b3c0339ec59ef1ccf28c678a673c59cf781a3de319e5194f97673c9d9ef12cf48ca7dd339e16cf789679c633db339ea99ef12cf18c67bc673c39cf789a3ce3a9f58c67a5673c733ce399e619cf04cf78ea3ce319ed19cf2acf783a3ce369f58c27ef19cf5ccf78a67bc633d1339e7acf78c678c693f180271b3c771d4316febe037455d677f5f565f79481bfd3bc71157c679f29573b8edd0b3a9a67dee7f82ec6896b2e1c6d75c33ed91b0f1cfb3ce119e3194fbd673c133de399ee19cf5ccf78f29ef1b47ac6d3e119cf2acf78467bc653e719cf04cf78a679c633c7339e959ef1d47ac6d3e4194fce339ef19ef12cf18c67aa673cb33de359e6194f8b673ced9ef12cf48ca7d3339e2ecf784679c6d3e8194fd6339e299ef1ccf28c67b1673c0b3ce3a9f18c67a9673ce33ce399ec19cf4ccf78e67bc653f08ca7cd339ee59ef1547bc6b3c8339eb19ef14cf28c6786673c3b3ce399e7194f95836707134fd4b3cd3b3cb1cd701ef2fab89733f974853956ad392ef193bd1aa873921978d4f31ff85de2b2e7ffb1ed5c0131e27aaf44cee2a1fdbd23dc769d65bbae426cd75bb6eb2bc4b6e4b9e47925d8963c973caf04db92e792e73eda7e3639db6df27ea9a1f3c8fb9ce279e47d4ef13cf23ea7781e799f533c8fbccf299e47dee714cf23ef738ae759e0198fbccf299e47dee714cfd3e819cf28cf78e47d4ef13c0b3de391f739c5f3c8fb9ce279e47d4ef13ce33de391f739c5f3d47ac6e3dbfb9c7c7b1fbcbc5f2a9e6782673cf27ea9781e79bf543c8fbc5f2a9e47de2f15cf23ef978ae719e3194fc6039ee77bbf14be17ea0a53de0b3a5a5f1af71eaa2c1ce70ad0d1782e1d435faf0e4d792e43157c67bf83eb72873db2b3dff1dde1883bdaea867db287efabdaef09cf18cf78ea3de399e819cf74cf78e67ac693f78ca7d5339e0ecf785679c633da339e3acf782678c633cd339e399ef1ecf08c67a5673cb59ef13479c693f38c67bc673c4b3ce399ea19cf6ccf789679c6d3e2194fbb673c0b3de3e9f48ca7cb339e519ef1347ac693f58c678a673cb33ce359ec19cf02cf786a3ce359ea19cf38cf78267bc633d3339ef99ef1143ce369f38c67b9673cd59ef12cf28c67ac673c933ce399e119cf3ccf78aa1c3c5cef8c8a7abe7e38de57f57cb6f5fe52888bdeb2f0f7e1788e6b87c548fbb8ee0179896729134fd47b01967a605bfb4fbf452798cf2cfc1d9fc3e1caa9a51623edbb720ad7353632f144bdcfa0d103db3a164da64c6b00b2f0f72660e4caa9468b91f65d3955cfcbd39a059f698b5b6b846d8ee31c32f999c7f697e03b34f23a56dbad583559b1ca419de158971ed51f903d6116e62866cd437329c48ad7b3e178ce6c288caeeb2b034fd83f2e0b066f71fde376e0e1b87e30f919f663072c9f9639e24e7530570f30f8e96a3bb47fc061bb21483616570e2116573a78ae1ce65890bd529977a490d987386b1e5a8b48acb8be39ef0923e996f2f284fd633e18bcc5f58f57020fc7f583c9cfb04f3868f99477c49dea60fb3ac8e0a7abedd0fe41380fa5301f4821b3c4b93c66cd437310c49a857a054f1849b79d95a790cf82cfb4c5f563078187a39f678a7bd88f1db27c2a38e24e75b07d1d62f0d3d57668ff109c0761166661166661166661166661166661166661166661166661166661166661f69b59f3d0b3b1c49a857a2d9e3092ee4a569ee2bc434b30788b9b7738043c1cf3324c710fe71d0e5b3eb538e24e7530570f33f8e96a3bb47f18ce83300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330fbcdac79e89dedc49a857aad9e3092ee202f4ff8dc566b30788b9b77380c3c8718e2c3e46738efd067f9d4ea883bd5c15ced63f0d3d57668bf0fce83300bb38b59f3d0bbda88350bf5da3c6124dd21569ee2fc695b30788bebc7fa8087a39f678a7bd88f1db17c6a73c49dea60ae1e61f0d3d57668ff089c8752980fa49059e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e6296380f0fb30f71d63cf47f08126b16eab57bc248bac3ac3c2de1bc437b30788b9b7738023c1cf3324c710fe71daeb27c6a77c49dea60fbba8ac14f57dba1fdabe03c8c74e603296496dc181e66c90d618e6296dc10e62866c90d618e6296dc10e62866c90d618e6296dc10e62866c90d618e6296dc10e62866c90d618e6296dc10e62866c90d618e6296dc10e62866c90d618e6296dc10e628661f7243f3749832b166a15e87278ca4ebe3e509df7bd0110cdee2d6ed5c053c4718e2c3e467b86ee7a8e5538723ee5407dbd751063f5d6d87f68fc27910666176316b9ee5a64cac59a8b7dc1346d21de1e52964c167dae2fab1a3c0c3d1cf33f919f663c72c9f963be24e7530578f31f8e96a3bb47f0cce43da98354fa729136b16ea757ac2483abc2e7732f1e42c9e9c2316c7cbb6deef32e5f1e6330b7fef0246aefeb0d362a47dcc71e4259e2e269e3a8ba7ce118be3655bfbbfd2942798cf2cfc7d253072e55497c548fbae9caa039e954c3cf5164fbd2316c7cbb68ec52a539e683eb3f0f755c0c895532b2d46da77e5543df0ac62e289ea93560d83eda8f6351cb6a37265386c4bcca363ced0eec2f18155c1e02deebe1aaf2d1c7d15939f79d7f57b95e5135ebff11ef5785d9f845998a39899ee735bb3966d8a4f60f1d076943916c3f93bbbcbf2290dbfb3e3980fa49059e25c1eb3b6dd9fbcedd6ac659be213583cb4f533c782c9cfb03fb83a70c798ece5a00ee6e9d50c7e66c02e1d9bf6af86f3500af38114324b9ccb63d6b6af49dc76f1fdc3689be213583cb45dc31c0b1e3f8bfdc1b5813bc6642f0775304faf65f0330376e9d8b47f2d9c0761166661166661166661166661166661166661166661166661166661166661f69b59dbbe2e71dbc5f17bb44df1092c1edaae638e058f9fc5f1fbeb03778cc95e0eeae039bf9ec1cf0cd8a563d3fef5701e84599885599885599885599885599885599885599885599885599885599885d96f666dfb86e46d87cfe3a06d8a4f60f1d07603732c98fc0cc7ef6f0cdc31267b39a883e7fc46063f3360978e4dfb37c27910666176316bdb37256ebb389f87b6293e81c543db4dccb1e0f1b3d81fdc1cb8634cf6725007cff9cd0c7e66c02e1d9bf66f86f3500af38114324b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc12e7ca89b3b67d4be2b65bc2f17bb44df1092c1eda6e618e058f9fc5f1fb5b03778cc95e0eea609edecae06706ecd2b169ff56380f239df9400a992537868759724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398ad987dcd0b66f4bde76f83c3bdaa6f804160f6db731c782c9cf70fdcbed813bc6642f0775304f6f67f0330376e9d8b44ff6845998a398b5ed3b92b75dc85ab6293e81c543db1dccb160f233ec0fee0cdc31267b39a883e7fc4e063f3360978e4dfb77c279481b339ebf4c72b6c3759b64a3ca7c6add5da65c0dba179a720de85e64caa340f76253ae05dddda63c1a742f01df48f752535e02ba7b4c7915e85e66ca2b41f77253ee02dd2b4cb91374f79af251d0bdd2948f81ee55a6dc0fbafb4cf96ad0bdda94af01dd6b4cf95ad0bdd694af03ddeb4cf97ad0bdde946f00dd1b4cf946d0bdd1946f02dd9b4cf966d0bdd9946f01dd5b4cf956d0dd6fca0b40f75687ee0153be0d740f9af2eda07b9b29ef00dddb4d792ce81e32e571a07b0794e9f39da63c1e74ef32e51ce8de6dca1340f7b029d781ee3da63c1174ef35e57ad0bdcf942781eefda63c19741f30e529a07bc494a782ee83a63c0d741f32e5e9a0fbb029cf00dd474c7926e83e6acab340f731539e0dba8f9bf21cd07dc294e782ee93a63c0f749f32e5f9a07bd494f1fc7eda94ef001df52b77828efa95bb4047fdca0b4147fdca8b4047fdca8b4147fdcadda0a37ee525a0a3bc7b29e828efee011de5ddcb404779f772d051debd02749477f7828ef2ee95a0a3bc7b15e828efee031de5ddab414779f71ad051debd16749477af031de5ddeb414779f706d051debd117494776f021de5dd9b414779f716d051dedd0f3acabbb7828ef2ee01d051de3d08ba06537e1be84e30e5b783ee44537e0874279932f633279bf23b41778a29bf0b74d417be1b74a79af2c3a05b68caef01dd22537e2fe8169bf2fb40b7c494df0fbaa5a6fc01d0359af223a06b32e50f826e99297f08747953fe30e89a4df923a02b98f24741d762ca1f035dab297f1c746da6fc09d0b59bf22741d761ca9f02dd72537e1474741da77e46b767dd2e290e1423ad239f9b1cbe906e0cf8d21d247b4f47b6e8d8b4df028c740e0ac3cf58182a63b3c5a879da18628679455bdc6fa636e06965e061f233fccdd46ef9d462f994833aa7829fed0c7e66c02e1d9bf6dbc136c739c758d49ae32eb4625103755acd454e5f4fe3e248c7d0f95b70f8c215c7668ba7d961bb93398e746cea133b87c17687653b6fd9c66b016d716dbb0398973330ebe376257fdcb06daf30c7a27c263b79f06925c420299fd076c608d9217d0d94b74c19a84bf5281e74ed2476dd8ee85c22bbfdbd36eb7b39a8d3e9f0bf3b48d6ff2e8ba7cb62d6bf27baa70c7030b48730073a2d0edacf43ecba2262d709b1a33a78ed6d648add728b87f61b8187eeafda4147f729c48ff7784dc3c06df77bed0e6ed2750063a383b1903c63789fd56831d27e011849b71c783a9862669feb85567cf09e60b45587be5b037576c17539eba8abdb5d4366c02ffafdff6c906c9f5ecb102f1c9b08203e811543da88614c30307e9124cfb860607ce2587fdfd19ecb7bcfeaedd99b01b41a0b133f330e37aa4087e56a872e08060fc3e070300dc3e070709515161cfea1fafa679c768b863a7a0fedef3ff770efe13d47af3fd2dfbb776bdfe5483dcaa247d2280f901475b48d0906068cba836427826a2d5b71c933063e4727cfd3cce46778d11b6bf9546bf994833aa3e06f6319fccc805d3a36ed8f75d84eb0230a63316e08b118e7e01937ccb1c04177d2614ba5bfe3c44d95e50bb668f4c9cef3441d22830be0f81903a7ffa61bfb28e3cce860e06453efa9ef68f549d0a3b5faaaa54763f5e8abee82f4e8aabea0e9d1533d5aaa4747f568a81efdd4a39d7a74538f66ead14b3d5aa947271b82e2e8a31e6dd4a38b7a34f11460fb36f0ea5ff4fa0aa94703f5e89f1eedd37756fa0e40df8de8bb6f7da7a87f3dea3b04fdab568f70e8abadbe93d157697d65d5778afa0e51dfd1eb3b5c3d43b65ac91a13ebb54a4e5372ba923394ac53b25ec906251b956c52b259c916255b956c53b25dc9994a5e101447f6cf5272b69273949cabe43c25e72bb940c9854a762ab948c9c54a2e5172a992cb94ec52d2a364b7923d4af62ae955b24fc9e54aae50b23f28ae0aba52c9412587941c56d2a7e48892ab82e22c9d9e95d3b3707ad64dcfb2e959353d8ba667cdf42c999e15d3b3607ad64bcf72e959addb82e26c949e89d0330f7aa641cf2ce899043d737077509c19d03301f704c5917e3db2af47f2f5c8bd1ea9d723f37a245e8fbceb91763db2ae47d2f5c8b91e29d723e37a245c8f7ceb916e3db2ad47b2f5c8f5834171645a8f44eb91673dd2ac4796f548b21e397e38288e0ceb91603df2ab477af5c8ae1ec9d523b77aa4568fccea91583df2aa475af5c8aa1e49d523a77aa4548f8cea91d0cf28f9ac92cf29f9bc922f28f9a2922f29f9b292af28f9aa92af29f9ba926f28f9a6926f05c5bcfc8e92ef2af99e92ef2bf981921f2af991921f2bf989929f2af999929f2bf985925f2af995925f2bf98d92df2a794cc9ef94fc5ec91f943caee48f4afea4e409254f2af9b392bf28f9ab92a794fc4dc9df953cade41f4afea9e499606066053b9131a6e7a151fe9efefede4347fa1bfafb1a0e5d7db07fff9183d7375cbbbfff8a86be6b7a8fee3bd8772d7ef9ebe6cb3485b1f6e8d19eeb1bf61fdedb7b5d43dfd5fd0d7dfb1a76f75d7d78ef31fcd213e64b739e6bb167efde6863fff59f90fe4f9946479b3e91268736c5fb36aeba8c804c2ce74badd5e539b4d25c75e8d7fbd9c5bbdd866307fbfa1bf20d87d5bf3d07d5777af73635e0df8ea9201feb6f38d6df73b4bf61dfd1be430dcd4d78dc13c797e144cb9432be74d994a17b1efc3f390dd8cbf1d90300", + "packedBytecode": "0x000000028df71de500000047cf1f8b08000000000000ffed9d779c1545baf77b6008726644cc6b1c4ca8280e87cc0c3098136614111186610405862866d435908339820425670105258961734e6ed275dd74efddddcffbc77def7d83efdb754e3d3bbf29ab0f73c6aec3efcca9fe7c6a4ef533d5fd7cebd74f57a7eaae7f06415014a4a796613a23f8ea24ffafd2bfe55f6fea1ae3baca5d7216e509678b3ce16c99279cc579c2d92a4f385be709679b3ce16c9b279c87c5c8a9d85a040da7b879db39d0356ec6449e695a92079a96e699a687e781a6ed83fc68a38ec813ce0e79c279649e701e95279c47e709e73179c2796c9e701e97279cc7e709e737f284f3843ce13c314f384fca13ce93f384f3943ce13c354f38cbf284b3639e709e96279ca7e709e71979c279669e709e15236767e0eca47fcfd6bfe7e8df73f5af943d4fff9eaf7fbbe83a16ebf90b145798d4439aa4f1bf6e61ea1ea61e61ea69fcaf57987a87a94f98faeaff95e9ff5584a9324cfdc2d43f4c03b40603c37461982e0ad3c561ba244c9786e9b2305d1ea62bc2746598ae0ad3d5611a14a66bc2746d98ae0bd3f561ba214c3786e9a6300d0ed3cd61ba254c43c2746b98861a2cb7856958986e0fd3f030dd11a611611a19a6ea308d0a534d984687a9364c7786694c98c686e9ae30dd1da671611a1fa60961aa0bd3c4304d0ad3e4304d09d3d4304d0bd33d619a1ea67bc3745f98ee37347b204c0f86e9a1303d6c70ce08d323617a344c8f85e99b617a3c4c4f84e9c9303d15a699619a15a6d9619a13a6b9619a17a6f9615a10a685615a14a6a7c3f44c989e0dd373617a3e4c2f84e9c530bd14a697c3f44a985e0dd36b615aac5964475812a6d7c3b4344ccbc2b43c4c2bc2f44698de0cd3ca30ad0ad3ea30ad09d3da30ad0bd3fa306d08d3c6306d0ad3e6306d09d3d630bd15a66d61da1ea61d617a3b4cef846967987685e9dd30bd17a6dd61da13a6bd61da17a6fd617a3f4c07c2f441983e0cd34761fa384cdf0ad3b7c3f49d307d374cdf0bd3f70dcd7f10a61f86e94761fab1b6fd44fffe549795fb773f0bd3cf75fe17faf797faf757faf71363995f87e93786edb761fa9d61fb7d983ed5f9cff4ef1ff4efe7faf78ffaf70bfdfb27fdfb67fdfb17fdfb57fdfb37fdfb6ffaf7dff5ef7fe8dfbfebdf7fe8df7f86696bc774be6d503f550531b551dd6b53cf7e44fc4e41c34969d152ff4f7ecbb4bd58cfcbaf68d74acfb732ecadf57c6b633d6df57c5bc3de41cf7730ec47e9f9a30cfb317afe18c37e9c9e3fceb09fa1e7cf007b22807bc3daae6c2db5a9086c12af2dc0d64adb5a82adb5ac0e6c6db4ad15d864fbb606db61dad6066cedb4ad2dd812da76986819a6126dab0ae28a95f2916abda571af573f2f3b3c7ede516abded1df11e113fef68b5de0e0e78557c1ca9d77504c4cd51dad6016c476bdb91603b46db8e02dbb1da7634d88ed3b663c076bcb61d0bb66f68db71603b41db8e07db89daf60db09da46d2780ed646d3b116ca768db49603b55db4e065b99b69d0236dde406a782ed346d2b03dbe9dad6116c6768db69603b53db4e07db59da7606d8a4fd3d136c72be7896b6a9b6e3b0225846dba5dd4a2d236d36d8ce91f61a6ce74a5b0db6ced24e83ed3cf02db6f3a1ad115b176d93764bfdafafce570571ed27c95ab5de8ab8d71bae59adb75ffceb4d3d73ec1fd4eb5a057e2a40ab013a1f63bfa6aee8bb4827f123f662c85f0965a59ce821c71e6157c7984a9d1f9061b9bec672a550a6d252ffaa20defaf73378fa19ccad20ef2666bb75f331dbe829eb981d0265cdd893f3a0e618b38380c341ccf6f231dbe829eb98ad85b266ecc9b970738cd9db80c341cc56bb89d964b98fd9f47db320b0c79e5c0f35c7981d0b1cf1c76c0f1fb38d9fb28ed9c7a0ac197b724ddc1c63763a70c41fb3bdaafdb941a3a7ac6376219435634feecf34c7987d02381cc46cad6f671b3d651db38ba1ac197b72afb039c6ec33c0117fccf67114b3dd7ccc06e967a041608f3db96fdd1c63762970c41fb3a3fcfdd9c64f59c7ec4e286bc69e3c43698e31bb51e7d573869fe8e70c2781eda7da7632f0c61fdb353d1cc576d2c776ba6f4810d863549ee735c7d8dea3f32a8e7f01fd11c4f64b6deb08b65f69db6960fb44db4e877a39d807aafd3ed0e829eb7de03750d68c6579b6dc1cf7811f01878398adf131dbe829eb98fd1b9435634ffa3934c798fd3d703888d95a1fb38d9eb28ed9ff82b266ec9dadf3cd3166a5afa93a5ff84c9f2f9c0bb63f685b67b07dae6de781ed8fda763ed8bed0b62e60fb93b65d00b63f6b5b39d8fea26d5dc1f6576d4b82ed6fdad60d6cffa66dddc1f6efdad6036cffa16d3dc1f6776deb05b67f685b6fb0fd53dbfa689b7ade257dafe4bcb52df05705f16e5be97729eb96f9ae39f0dddef0dd3e87be3b18be3b587c271df84e800f998a8cf92ac827ddf29497020ffaea1ebfaf6eaaeedd82c6d7bd3bf0f47050f704f8680c4f0fe0e9193f4faaff6faff8d79bdac6dd0c4d13e0ab1bd4abb7837a15812f59b7cc8bbf52b061dbdadbc2d8277ec66411f89275cb7c1f60141bb6f5f2ce95ec3fea78d8a9a89ed7c1be943a27427f55c021fe8aa1cc151debcb76d66c25f07f3ceef5346c8ee2321517e24bd62df3e2af04ead333f78cc9c632f630185db51145e04bd6ed7dd76f07c9e371dcc1b58eb54d13df1539f0ddc7f0ddddf08d6da74c998e6d7d8039f66b4e7d6cab8c7fbde5787d22d786e207cf1ff01a2eae3aa16fb936143f622f86fc3545f565a59ce821edb0b0ab58966d89ece672bd8de54aa14c85a5fe5541bcf5af34782a0d6675bcb9088e850ef687540c54181c32df1db4ab8cd0ae02b49332678376aedab3be068fccf7041e69c77a018fab6ba2289e5c5c8f1dcc379ec3e2f5b3fc1fcf035c6dafae06a3ccdbb6571f60b49dab38b89ec978aed20318c5d61778ba39d22c6abb7623f1ed205652ed91f8907373d97fc55f3194e9d3b2beec5dd056ba88118c47991a7bcd1bff764aa6aec17b64c183dbcec175555747f1588ef76fbe0ce28d35b35dea616815758fc7555bdecde09179f1e7993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9e999f199f2761bf2d29d79384d1ecffe6ea3e7feafb877a5df80ce87f3bed0f962cc7fe31d20fe25ca3cec550a6b4453ddbff83fe60e6732aec23d9d3ad76a96d89fd31ab605efc615f2bdc960cfd9dca62f39d1ce5ea799bfa0698fa8ea6d9f7b3a7455317fd9f51d3224353ec8f7f9ec1a3e2b4b2653d9b8b677fd93e8b44ad241fe7b3bdd2c01eebf16f97648367d62d8286ed071e675cf5df91b65a9e975718be8ba1cc892deab70df6b3aa823ac872d8ef47d62dcb9c0bcb561aeb6eaf97158ed6c6fa7bc1b252e6146853f7b5a8d7cc415b99ccb6ef3a3e378fff389c7e8edf2d0b9eaec0e3a29d7174be518efb40dccff1cdfe69b6f31829837dfb1cf4abccd8df49fc7966cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367e667563ce6b3567cbfb63b09638efa3ea49e67c8b7caf0d9d4c616f57e5d3f8793674e9d8d3ae3bba3ff6c51cfb655e74b82aff67788da96aebe4f11b52dc51f7e7b069f05b978ae5b04be64dd498b16922f8bcd77fa39be8bb121e4397e3743d7ee164d5dedaff88c1535c5fdb587c183cf46a3beed93346c2efb0e45c585f8c37d290936c9e3fbd12eb6331e4bcc7e3de20f9f5f7f476bdb3e70b5ed93e52edb0d79362fcfeabb59ea2a657e086ddf8f751efb7060df91cf2cff9729d3736ad14fd5d9c1f735cb8b605db27d6ddff61c08ac31f9ee8aeb2ad269a0a14131e43f6d515f56ca4959d15ad8d53e22df80417673b91ec672a550a6bfa5fe5541bcf537bfb53ac06056b1f33388b3cfe0f8efaa4dea1fa1d1b9a0919471fccd466bff4ab35f21b6a36d8c32b22c7e8beeafd04645f51fb51d031c7c5b38e33100bfb76b1e171ad3cfb3d0fb69fd37b41771f7d3fa6f8821eca71518ebef0ceb17ae3641f4b145cafc5f63fde639b92c83fdc0feb59fc0f75c923a9fcd39f9a1babeb29d93e3725175c77d33eee313c604b2603c4999765a6bd9669511dc7d2ccb96462c2b5a99df0a2b09beaa9f9befaca5f7f901465d24aef11be452e628a88b9bf396f439a0ab6fcac9baa41d485aea2a658e877ded049d4fc076c2b6f91ccbff65ca740e8863b85f187f9d53dbf722bd2ed9be175a7c5f0cac31f9ee8abee51c50fc88bd18f267b7ac2f2be5440fd15ad8d53e22e751c86e2e57612c570a65065aea5f15c45bff0b0d9e0b0d66153b27439c9d03fdd05db5d5032334ea0c1a4919bca768fb0ea8ed5e87abf737a2cea5f0fd25f33e011e27dd9c37d9cf63cdfb6ab67384ce063f9e23f482763661296bde2f94e3659cfd86f15d895ee017df9570f5ede6bea05b15cce379c1a1f4ede23bb6ca5fd498097d73e03b6acc845cf8ee60f8ee9043df5e73af3993e60ec62048bd7f86df2c5553a6f3521c9740966b018c2ec67248040dbf3d7e30461cdf41966b098c2e8e0fd97efbbc1730ca72c5c0e8e2dd521c7fa3318cf88d613cce0ba3836fc5766deab762f19e5e6b60647a67139f4db5014617e7c54d7d570fcfe7dbc2afab7189ba65c198044659ee306074716f1caf651ac388d745b25c3b6074f10c2bdbf19df0dbf3786fd92563a663bbe3be28c96cefbd54bae5c978ae81be1d3c7b486981f7190fa6453fb73c19cf7dd0b783fb7e292d709cc1836981cf065d8c7b98081a3e873b180f3ebf94e58e04c62a478c03b260ac02c67fdd2b06c6818e18abb2601c088c623f1a181ddc7f4d310ecc8211ef53ca72c700e3458e182fcc82f1226094e58e054617f75213e0b7318c1703a32c771c305ee288f1e22c182f014659ee7860bcd411e32559305e0a8cb2dc3780f132478c9766c1781930ca722700e3e58e182fcb82f1726094e54e04c62b1c315e9e05e315c028cb9d048c573a62bc220bc62b8151963b1918af72c47865168c5701a32c770a305eed88f1aa2c18af064659ee54601ce488f1ea2c180701a32c57068cd738621c9405e335c028cb7504c66b1d315e9305e3b5c028cb9d068cd73962bc360bc6eb8051963b1d18af77c4785d168cd703a32c770630dee088f1fa2c186f004659ee4c60bcd111e30d5930de088cb2dc59c0789323c61bb360bc09186fb4300e76c47853168c838151963b0f186f8e9f31752d3d380bc69b81e796f879529add9c05cf2d6e7952dfd5bbd9e2ebd6f87da5b6c590a0f175bf157886c6cf93da16b766c1230ca5b01c6a765bfc8c29cd8666c1781bf00c8b9f27a5d96d59f00c03cd6eb368767bfc8c29cd8665c1783bf00c8f9f27a5d9ed59f00c07cd6eb7687647fc8c29cd8667c17807f08c889f27a5d91d59f08c08ea35bbc3a2d9c8f819539a8dc8827124f054c7cf93d26c64163cd5a0d9488b66a3e2674c69569d05e328e0a9899f27a5d9a82c786a40b35116cd46c7cf98d2ac260bc6d1c0531b3f4f4ab3d159f0d48266a32d9add193f634ab3da2c18ef049e31f1f3a434bb330b9e31a0d99d16cdc6c6cf98d26c4c168c6381e7aef879529a8dcd82e72ed06cac45b3bb1d31de9505e3dd169eb8bf937d97c5d77847751f1734beeec2500acb613f89098e18c767c13801186539ec2751e7887142168c75c028cb251c3366ea275107be27c6ef3bd52ed5058dd767a25b9e8cfd24d0f724475a4c0c1aafc524b73c19fb49a0efc98eb49814345e8bc9c033c5811609f0d1181e612885e5b09fc454478c53b2609c0a8cb21cf69398e688716a168cd3805196c37e12f738629c9605e33dc028cb613f89e98e18efc982713a30ca72d84fe25e478cd3b360bc17186539ec27719f23c67bb360bc0f186539ec2771bf23c6fbb260bc1f186539ec27f18023c6fbb3607c00186539ec27f1a023c607b2607c10186539ec27f19023c607b3607c08186539ec27f1b023c687b2607c18186539ec2731c311e3c35930ce0046590efb493ce2887146168c8f00a32c87fd241e75c4f848168c8f02a32c77b763c64cd72f8f3673df51d72acddd77d4754973f7ede3dcc77921f8f671eee3bc107cfb38f7715e08be7d9cfb382f04df3ece7d9c17826f1fe73ece0bc1b78f731fe74cbe1f73e03b013e642a32e6ab202f0ca5b0dcdd9eb15933224f597c3ce55877f4f54d82ba7fd3c253e4a8eee8eb7182ba0b43be313e96078cb88f7b1d9bcee858c764531915cf138e781ecf82e709e079d211cf1359f03c093c4fc5cf938aa927b3e011865258eeee3c607c2c0f18bd8e5e472646af63e1e8e8193da367f48c8782311fda70cf9817f1986c2aa3e299193f4f4ab3a7b2e099099ac972b7b8654c369551f1cc8a9f27a5d9cc2c78668166332d9a39604c369551f1cc8e9f27a5d9ac2c78668366b32c9a39604c369551f1cc899f27a5d9ec2c78e68066b32d9a39604c369551f1cc8d9f27a5d99c2c78e68266732c9a39604c369551f1cc8b9f27a5d9dc2c78e68166732d9a39604c369551f1cc8f9f27a5d9bc2c78e68366f32c9a39604c369551f12c889f27a5d9fc2c78168066f32d9a39604c369551f12c8c9f27a5d9822c781682660b2c9ab132de9d078c8fe501a3631d934d65543c8b1cf12ccc826711f03ced886751163c4f03cf33f1f3a462eae92c7884a11496bb3b0f181fcb0346afa3d79189d1eb58383a7a46cfe819b363fc661e30fa6ded1959191d5c5f657c87e6e966ee3bea1d9ae6ee3bea1d9ae6eedbc7b98ff342f0ede3dcc77921f8f671eee3bc107cfb38f7715e08be7d9cfb382f04df3ece7d9c17826f1fe73ece0bc1b78f731fe785e0dbc7b98ff342f0ede3dcc77921f8f671eee3bc107cfb38f7715e08be7d9cfb382f04df3ece7d9c17826f1fe73ece0bc1b78f731fe785e0dbc7b98ff342f0ede3dcc77921f8f671eee3bc107cfb38f7715e08be7d9cfb382f04df3ece7d9c17826f1fe73ece997c3f1bbfef64b6df987916785c7cf3c6513dcbd57a9fd3ebfa3246fd9456cf1b5a3d6d68550a659e03fd9e77a05f11f89575cbbcf8cb96b91301b323dfc9c3c3751c06f5171f8f197a28ff2f38aa7b545bff4233f71dd5d63777df516d7d73f7ede3dcc77921f8f671eee3bc107cfb38f771cee21bf3ad82faf376f9fea95ac78bf0ff22282fdf152e863253daa47fdb077e1f72e1dbef43fe585108be7d9cfb382f04df3ece7d9c17826f1fe73ece0bc1b78f731fe785e0dbc7b98ff342f0ede3dcc77921f8f671ce17e7180f9539e0090c9e2003cf42329e69643c73c878c690f10c23e3b9968ce722329e07c978ba93f14c24e31945c6733319cf95643c1790f1f427e3994ec6d3878c672e19cf5d643c4f92f10c27e3b99e8ce712329e87c97892643c93c9784693f1dc4ac67335194f1519cf7d643cbdc878ce21e3194fc6338f8ce76c329e11643c4f91f1dc48c67338194f7b329ecbc8781e27e3399f8ca7828ce711329e05643c53c978ee24e3b98d8ca79c8ce71a329e2e643c1792f13c40c6d3838c673e194f1d19cf4c329e6a329ec1643ce792f15c41c6d3928ca71f19cf22329e7bc878fa92f18c25e3e94cc6733b19cf75643c1793f13c44c6d38d8c671219cf2c329e1a329e21643c5791f10c20e3b9978ca73719cf38329e4e643c7790f1dc40c6938bef9966c35342c6534ac6732919cfa3643c33c878ba92f14c21e3994dc6534bc633948c671019cf40329efbc9787a92f14c20e31949c6731319cf13643c4790f17420e3b99c8ca7888027117c750c9304fcff59b0b53096559f7d9ddbb1feff2f697b0b58e6659d6f6959f74b60936fc9be6c5916757a09ea52a5f3e55f6f4ae984beaa605efc9500c7cb243c9793f17420e339828ce709329e9bc8784692f14c20e3e949c6733f19cf40329e41643c43c9786ac9786693f14c21e3e94ac633838ce751329e4bc9784ac9784ac8789e25e3b9818ce70e329e4e643ce3c8787a93f1dc4bc633808ce72a329e21643c35643cb3c8782691f17423e379888ce762329eebc8786e27e3e94cc633968ca72f19cf3d643c8bc878fa91f1b424e3b9828ce75c329ec1643cd5643c33c978eac878e693f1f420e379808ce742329e2e643cd790f19493f1dc46c6732719cf54329e05643c8f90f15490f19c4fc6f33819cf65643cedc9780e27e3b9918ce729329e11643c6793f1cc23e3194fc6730e194f2f329efbc878aac878ae26e3b9958c673419cf64329e2419cfc3643c9790f15c4fc6339c8ce749329ebbc878e692f1f421e3994ec6d39f8ce702329e2bc9786e26e31945c633918ca73b19cf83643c1791f15c4bc6338c8c670c19cf1c329e69643c0bc9782a2d3ccf3ae291f7dd65dd32ff2c896f07dba15cadf71547757a55afabb55eaff08bbf622833a35dfa573dffc06585cbfc3e01be9bf32a68f4aaa3bac8f62832b60ffa7ed1916f737c3e997fb199fb6e6ff86e5f20be3b18be3b14886f1fe73ece0bc1b78f731fe785e0dbc7b98f7326df0eae0d92f89d34998a8cf92ac8e3f5828befcb39aa6783ebc42f63d44f69f59aa195796d550a655e01fd5e73a09fedda53e6c55fb6cc9d0898312eca8278e36271fc754aaa7e878781ae8b0d7db15e4b1c691a750c59d2cc7d471d439abbefa8634873f7ede3dcc77921f8f671eee3bc107cfb38f771cee4fb759d8ff1bab11c7db40aeaaf075e07bfcb74be2846bf6a5d4bc16f117088bf6228f3bfe0b9a6dfe7fd3e1f976f7f6cf3715e08be7d9cfb382f04df3ece7d9c17826f1fe73ece0bc1b78f731fe785e09b39cecdbcf4173f1bd85cf5e78f8ac55cbc4b70287d47c56273f71d158bcdddb78f731fe74cbe973bf09d001f3265eae3b71c78963ae07154cfd4b38d15469d9e35ea540a65f018bfc2413d8bc0afac5be657008f4c95c0e3220e1ab3cd91672119cf34329e39643c63c8788691f15c4bc6731119cf83643cddc9782692f18c22e3b9998ce74a329e0bc878fa93f14c27e3e943c633978ce72e329e27c9788693f15c4fc6730919cfc3643c49329ec9643ca3c9786e25e3b99a8ca78a8ce73e329e5e643ce790f18c27e39947c633828ce729329e1bc9780e27e3694fc6731919cfe3643ce793f15490f13c42c6b3808c672a19cf9d643cb791f19493f12c21e3b9868ca70b19cf85643c0f90f1f420e3994fc65347c633938ca79a8c673019cfb9643c5790f1b424e3e947c6b3888ce71e329ebe643c63c9783a93f1dc4ec6731d19cfc5643c0f91f17423e39944c6338b8ca7868c670819cf6b643c5791f10c20e3b9978ca73719cf38329e4e643c7790f1dc40c65342c6534ac6732919cfa3643c33c878ba92f14c21e3994dc6534bc633948c671019cf40329efbc9787a92f14c20e31949c6731319cf13643c4790f17420e3b99c8ca7888027117cf5ddff04fcff35b0c93beacf82ed0d9d5f0ab616161f2d757e05d88a755ed6d1264c2f74fceaba512757efe5a3af2a98177f25c0f10609cfe5643c1dc8788e20e379828ce726329e91643c13c8787a92f1dc4fc633908c671019cf50329e5a329ed9643c53c878ba92f1cc20e379948ce752329e52329e12329e1bc878ee20e3e944c6338e8ca73719cfbd643c03c878ae22e3798d8c6708194f0d19cf2c329e49643cddc8781e22e3b9988ce73a329edbc9783a93f18c25e3e94bc6730f19cf22329e7e643c2dc978ae20e339978c6730194f3519cf4c329e3a329ef9643c3dc8781e20e3b9908ca70b19cf35643c4bc878cac9786e23e3b9938c672a19cf02329e47c8782ac878ce27e3799c8ce732329ef6643c8793f1dc48c6f31419cf08329e79643ce3c978ce21e3e945c6731f194f1519cfd5643cb792f18c26e3994cc69324e379988ce712329eebc9788693f13c49c6731719cf5c329e3e643cd3c978fa93f15c40c6732519cfcd643ca3c8782692f17427e379908ce722329e6bc9788691f18c21e39943c6338d8c6721194f656e7892eadd76e96b1d00174e55905f013c4b1ce8e3a89ee5f85d832f635cafd2ea4d43abd70cad4aa1cc72d0ef4d07fa15815f59b7cc8bbf7c64563c8feabced3b108f92308a6d895b9ed47efb68d070cab4dfbe093c2eda3547f54ced5f2b8d3a3d6ad15dca60acae74504fdbbe23f32b613be41bb3e2795ce7853501e51e276114db0ab73ca9fdebf1a0e19469ff5a093c2eda1f47f54ced5fab8c3a3d6ed15dca60acae72504fdbbe23f3ab603be41bb3e27942e7853501e59e206114db9b6e79ba27a0ce3265dabf56018f8bf6c7513d53fbd76aa34e4f5874973218abab1dd4d3b6efc8fc6ad80e9ed933db98158f3cdb11d604947b9284516c2b9df2742f4f409d65cad48ead061e17edbc23dd53edd81aa34e4f5a74973218ab6b1cd4d3b6efc8fc1a8befb2205e2dd636428bb5169eb539d642fc65cbbc3c0f99bdce5ee72866afb3d7398ad9ebec758e62f63a7b9da398bdce5ee72866afb3d7398ad9ebec758e62f63a7b9da398bdce5ee72866afb3d7398ad9ebec758e62f63a7b9da398bdce5ee72866afb3d7398ad9ebec758e62f63a7b9da398bdce5ee72866afb3d7398ad9ebec758e62f63a7b9da3981974563cf2ed4a614d40b9a74818c5b6ca2d4feabda0a782865391315f05f9b5c0b3da813e8eea99ea43becea8d35316dda50cee5feb1cd4d3b6efc8fc3ad80ed930afc94366af73d39815cf4c9d17d604949b49c228b6d56e7952edd8cca0e194a91d5b073c2eda7947f54cb563eb8d3acdb4e82e6570ff5aefa09eb67d47e6d7c376f0cc9ed9c6ac7866e9bcb026a0dc2c1246b1ad75ca934cbddf382b6838656ac7d6038f8b76de91eea9766c8351a75916dda50cc6ea0607f5b4ed3b32bf01b64336cc6bf290d9ebec758e62f63a7b9da398bdce5ee72866afb3d7398ad9ebec758e62f63a7b9da398bdce5ee72866afb3d7398ad9ebec758e62f63a178ece8a67b6ce0b6b02cacd266114db3aa73cdd52cf1d66070da74ccf1d3600cffad879d2cf1d1ce89e7aeeb0d1a8d36c8bee5206f7af8d0eea69db77647e236c87e6cebc260f997d6ce486d9c786678e62f6b1e199a3987d6c78e628661f1b9e398ad9c786678e62f6b1e199a3987d6c78e628661f1b9e398ad9c786678e62f6b1e199a3987d6c78e628661f1b9e398ad9c786678e62f6b1e199a398196243f1ccd179614d40b939248c625bef9627f5dd833941c32953bf9d8dc0b3c1813e8eea99eab7b3c9a8d31c8bee5206f7af4d0eea69db77647e136c07cfec996dcc8a67aece0b6b02cacd256114db06b73ca9766c6ed070cad48e6d021e17edbca37aa6dab1cd469de65a74973218ab9b1dd4d3b6efc8fc66d80e9ed933db9815cf3c9d17d604949b47c228b68d6e7952edd8bca0e194a91ddb0c3c2eda7947f54cb5635b8c3acdb3e82e653056b738a8a76ddf91f92db01d3cb367b6312b9ef93a2fac0928379f84516c9bdcf2241350679932b5635b80c7453befa89ea9766cab51a7f916dda50cc6ea5607f5b4ed3b32bf15b643be312b9e053a2fac0928b78084516c9bddf2a4f6af0541c329d3feb515785cb43f8eea99dabfde32eab4c0a2bb94c1587dcb413d6dfb8eccbf05db21df9815cf429d17d604945b48c228b62d6e7952fbd7c2a0e19469ff7a0b785cb43f8eea99dabfb619755a68d15dca60ac6e73504fdbbe23f3db603be41bb3e259a4f3c29a80728b4818c586c78b458e784a0d9e528b1687cab79aafd0f912fd9b80ff5700a3abf67091c128f318e3c8eb5ab3f6064f7b43b343e95bd5bf52e70fd7bfb8bd2a8191617bb5cf81661d0c9e0e866687d2b7d2a29fce1fa17f717bf5034686edd501781cb4cfdd13068f9a329d6f6c73ac8fa37aa6ce37b60776ddf1382465f0d8bddd413d6de71232bf1db68367f6cc3666c53358e7853501e50693308a0daf5376c4cfd33d61f0a829533bb6c3b13e8eea996ac7de0eecbaef00dda50cc6eadb0eea59047e65dd32ff366c876c98d7e421b3d7b969cc8a6788ce0b6b02ca0d216114db76e079277e9eee0983474d99dab1771cebe3a89ea9766c6760d7fd1dd05dcae0feb5d3413d8bc0afac5be677c276c886794d1e327b9d9bc6ac7886eabcb026a0dc501246b1bd0d3cbb62e7498f07843c6acad48eed72ac8f9b7aa6dbb17703bbeebb40772983fbd7bb0eea59047e65dd32ff2e6c07cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6ccdccc8a6798ce0b6b02ca0d236114db4ee0792f769ef47307e45153a6e70eef39d6c74d3dd3cf1d760776dddf03dda50cc6ea6e07f52c02bfb26e99df0ddbc1337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993d3337b3e219aef3c29a8072c34918c5f62ef0ec899fa77bc2e05153a6e70e7b1cebe3a89ea9e70e7b03bbee7b40772983b1bad7413d8bc0afac5be6f7c276d8eb993db38559f18cd079614d40b911248c62db0d3cfb62e7493f3f451e35656ac7f639d6c74d3dd3edd8fec0aefb3ed05dca60acee7750cf22f02beb96f9fdb01db2615e9387cc5e67af7314b3d7d9eb1cc5ec75f63a47317b9dbdce51cc5e67af7314b3d7d9eb1cc5ec75f63a47317b9dbdce51cc5e67af7314b3d7b97074563cd53a2fac0928574dc228b6bdc0f37eec3cddca13068f9a8a8cf92ac8bfef581f37f54c3f773810d8757f1f749732b87f1d7050cf22f02beb96f903b01d9a3bf39a3c64f6b1911b661f1b9e398ad9c786678e62f6b1e199a3987d6c78e628661f1b9e398ad9c786678e62f6b1e199a3987d6c78e628661f1b9e398ad9c786678e62f6b1e199a3987d6c78e628661f1b9e398ad9c786678e6266880dc553a3f3c29a807235248c62db0f3c1fc4cfd33d61f0a8a9c898af82fc078ef57154cf54bf9d0f03bbee1f80ee5206f7af0f1dd4b308fccaba65fe43d80e9ed933db98154fadce0b6b02cad592308aed00f07c143f4f3261f0a829533bf691637d1cd533d58e7d1cd875ff0874973218ab1f3ba86711f89575cbfcc7b01df28d59f18cd179614d40b931248c62fb10781cc45d8aa7d4e091f98f087cabf93a9d2fd1bfb8bdea8091617b95e640b3f6064f7b43b343e95bd57fa2ce1fae7f717b4d044686edd53e079a7530783a189a1d4adf4a8b493a7f84fec5ed35091819b657871c687628dbc343b96f1fca38f59a1f3acd8b0ea1e6458750f322af3995e60e8e2f493c9605c0805315e43f069e6fc7cf93ba2ff771163cdf069e6fc5cfd3d5513dcbd57abf03ec71ad5769f55d43ab8f0dad4aa10c327cd7817e45e057d62df3e2cf337be628663cb715d60494fb8884516cdf021e17ed86aafbf97a5db2fe5661fae4e87abf2e9e97e0bde2d67abdc221fe8aa1cca4b27ab6df69b612f8bf6c37559f0386cdd13bcc5d6dcfed645efc950439bb779bf15e326ae1e27953b6c7fd03169e2fe3e329c7fd1c7ded7754f76c9efdedb7f0c458f7ae51cf3df7c55ff754fbd145af4bd6aff6d1ff71b453cdbbe3be27ed4717a3cec5506650593ddb7f42fb616b2b5cef9b724e6eee9b2d82faf64cb8cab4dd7c26f4a5b64bb90fa03cb63915fa17f7cf0aa8abab7631ea1e13b68b66dbed527bf3b9a4e9bb1474f9805433db730ad4b1d2c25d49c08df198cbfd4cd66d7b465669e8c8a6196eeb0f2c3af6b370f723e066dcaffb193ab26976b0fd7ab0857b300137e37e3dd8d0914db383edd7432cdc4308b819f7eb21868e6c9a1d6cbf1e6ae11e4ac0cdb85f0f357464d3ec60fbf5300bf730026ec6fd7a98a1239b6607dbaf875bb887137033eed7c30d1dd9343bd87e3dc2c23d82809b71bf1e1134d4914db383edd7d516ee6a026ec6fdbadad0914db383edd73516ee1a026ec6fdbac6d0914db383edd7b516ee5a026ec6fdbad6d0914db383edd7632cdc6308b819f7ebc6f6db67ddafeb2cdc7504dc8cfb759da1239b6607dbaf275ab827127033eed7130d1dd9343bd87e3dc9c23d89809b71bf9e64e8c8a6996dbf76f42e61d6ef367ee8549ff418d31f66c1f33ef0b88829477150eea89f4baa6fea3e43ab0f0dad70ec8efda09f83be3019bf4920fe3cb367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed933f333e37719f1f98a94fb8084516cf84ccac57d7e55f70bf4ba64fdadc234e8d87abffb63f79b2c471d5aebf50a87f82b8632279c5acf76bd662b09bebadd702c6edc967b63af437a5b9af12ff3e2af04eab30f781cbc9f9fe2d96ff0ecb76881ef9dc6e33b39ca8dc6c972f57dbcc382faedbcd7a80f6aba2776ff0d352d3234dde3d8772268b83d8501a72ac8238f8b67c38eea996a0b761b7532352e85329da09ebb1dd4b308fccaba657e37f0c8d402785cc56060f004167d64aa24e39946c633868ce70c329e61643cc793f15c4bc6731819cf45643c0f92f17427e39948c6338a8ce754329e9bc9788e22e3b9928ce702329e62329efe643cd3c978fa90f1dc45c6731619cf70329ef3c8784e20e3b99e8c2741c6730919cfc3643c49329ec9643ca3c9783a92f1dc4ac6730c19cfd5643cadc978aac878ee23e3e945c6730e19cf78329eb3c9784690f19c44c6732319cfe1643cedc9782e23e379848ca7828ce77c329ea9643c7792f19c4ec6731b194f3919cf71643cd790f17421e3b9908ca72d19cf03643c3dc878eac878aac9784e21e3194cc6732e19cf91643c5790f1b424e3e947c6730f194f5f329eb1643c9dc978ce24e3b99d8ce71b643cd791f1b423e3b9988c671f19cf43643cddc8782691f1d490f11c20e32923e31942c6733419cf55643cadc8780690f1dc4bc6d39b8c671c194f27329e3bc8784e24e3b9818ca7848ca7948ce752329e19643c5dc978a690f1d492f19c46c633948ce758329e41643c6dc8780692f1dc4fc6d3938c670219cf48329e93c9786e22e339828ca70319cfe5643c45043c89e0abdf624ac0fff7834dbe19f43ed85a58d627cfa9a5bc3a2e2eedf8d575b7b0ac7b8f8501757a0fea52a5f3e55f6f4ae984beaa605efc9500c71e129ecbc9783a90f11c41c6731319cfc9643c23c9782690f1f424e3b99f8c6720194f1b329e41643cc792f10c25e3398d8ca7968c670a194f57329e19643c9792f19492f19490f1dc40c6732219cf1d643c9dc878c691f1f426e3b9978c6700194f2b329eabc8788e26e31942c65346c673808ca7868c6712194f37329e87c878f691f15c4cc6d38e8ce73a329e6f90f1dc4ec67326194f67329eb1643c7dc978ee21e3e947c6d3928ce70a329e23c978ce25e3194cc6730a194f35194f1d194f0f329e07c878da92f15c48c6d3858ce71a329ee3c878cac9786e23e3399d8ce74e329ea9643ce793f15490f13c42c67319194f7b329ec3c9786e24e339898c670419cfd9643ce3c978ce21e3e945c6731f194f15194f6b329eabc9788e21e3b9958ca72319cf68329ec9643c49329e87c9782e21e34990f15c4fc6730219cf79643cc3c978ce22e3b98b8ca70f19cf74329efe643cc5643c1790f15c49c6731419cfcd643ca792f18c22e39948c6d39d8ce741329e8bc8780e23e3b9968ce778329e61643c6790f18c21e39946c65349c6d3c2e0c1ffab77c3f6e9bc7c3ba818fe3f59772e6fafd72565e419b1ba57f1ae6153f5dde5a8beef06f55315ccef82fa0afbbbc0f3ae239ef70c1ed37709e42b41b39d864d31bee38871a7c128f3ef00a3e8b71378763ae2d965f098be4b20df0f347bdbb029c61d8e18df3618657e07308a7e6f03cfdb8e78de31784cdf25901f0c9a6d376c8a719b23c6ed06a3cc6f0346d16f3bf06c77c4b3c3e0317d97407e0868f69661538c5b1d31be6530cafc566014fdde029eb71cf16c33784cdf25901f0a9a6d316c8a71b323c62d06a3cc6f0646d16f0bf06c71c4b3d5e0317d97407e1868b6c9b029c68d8e1837198c32bf111845bf4dc0b3c911cf6683c7f45d02f9e1a0d906c3a618d73b62dc6030cafc7a6014fd3600cf06473c1b0d1ed37709e4478066eb0c9b625ceb88719dc128f36b8151f45b073ceb1cf1ac37784cdf2590af06cdd61836c5b8da11e31a8351e65703a3e8b70678d638e2596bf098be4b205f039aad326c8a71a523c65506a3ccaf0446d16f15f0ac72c4b3dae0317d9740be16347bd3b029c6371c31be6930cafc1bc028fabd093c6f3ae25969f098be4b203f06345b61d814e372478c2b0c46995f0e8ca2df0ae059e188e70d83c7f45d02f93ad06c9961538c4b1d312e3318657e29308a7ecb806799239ee5068fe9bb04f21341b3d70d9b625ce288f1758351e69700a3e8f73af0bcee8867a9c163fa2e81fc24d06cb161538caf39625c6c30cafc6bc028fa2d069ec58e7896183ca6ef12c8df0836e1ed0bb65775be0fd85ed1f9de607b59e77b81ed259def09b61775be07d85ed0f9ee607b5ee7bb81ed399d4f82ed599def0ab66774be3fd89ed6f901605ba4f355605ba8f303c1b640e72f04db7c9dbf086cf374fe62b0cdd5f94bc03647e72f05db6c9dbf0c6cb374fe72b0cdd4f92bc0f694ce5f09b62775fe2ab03da1f35783ed719d1f04b66feafc35607b4ce7af05dba33a7f1dd8eed6f9ebc1768bcedf00b60f75fe26b07da4f33783ed639dbf156cdfd2f9dbc0f66d9dbf1d6cdfd1f93bc0f65d9d1f09b6efe9fc28b07d5fe74783ed073a7f27d87ea8f363c1f6239dbf0b6c3fd6f97160fb89ce8f07db4f757e02d87ea6f393c1f6739d9f02b65fe8fc54b0fd52e7a781ed573a7f0fd83ed1f9e960fbb5cedf0bb6dfe8fc7d60fbadcedf0fb6dfe9fc0360fbbdce3f08b64f75fe21b07da6f30f83ed0f3a3f036c9febfc2360fba3ce4bbba6dad93fe97c59106f3bfb45503f95816ff1a7cafc59e7db186564d962287396ee50a89e71a86f994a3b2cedb2b2493bfc2ad8a41d7e056cd20ebf0c3669875f029bb4c32f824ddae117c026edf0f3609376f839b0493bfc2cd8a41d7e066cd20e3f0db62a9d5f0436698717824ddae105609376783ed8a41d9e07366987e7824ddae1396093767836d8a41d9e0536698767824ddae1a7c026edf093609376f809b0493bfc38d8a41dfe26d8a41d7e0c6cd20e3f0a366987ef069bb4c3b7804df6972fc0266df3876093b6f923b049dbfc31d8a46dfe16d8a46dfe36d8a46dfe0ed8a46dfe2ed8a46dfe1ed8a46dfe3ed8a46dfe01d8a46dfe21d8a46dfe11d8a46dfe31d8c6ebfc4fc0266df34fc1266df3cfc0266df3cfc1266df32fc0266df32fc1266df3afc0266df3276093b6f9d76093b6f9376093b6f9b76093b6f9776093b6f9f76093b6f953b049dbfc19d8a46dfe03d81ed17969abdb824d9e15aba9fc6b4e380e4f0bf0252c5541bc6d3f4e5590c7bacb5449c633978c670c19cf8b643c6790f10c23e3399e8ce730329ec5643c13c9781691f1ac20e3594ec6f31a19cfa9643c9bc8783692f11c45c6f32e19cf2e329e0bc8788ac9786693f13c4fc6731619cf70329ef3c8784e20e34990f12c20e35946c6b3948ce715329e8e643c1bc878d693f11c43c6b3938ce71d329ed6643c5f90f1cc24e339878ce759329eb3c9784690f19c44c67338194f7b329e0a329ef3c978e691f1bc4ec6b3848ce725329ed3c978d691f1ac25e32927e3398e8ce76d329e1d643c5dc878da92f13c49c65347c6f334194f3519cf29643c83c978ce25e339928ca725194f3f329e5bc878e690f1bc40c6d3998ce74c329e35643cabc9783e27e3f90619cf76329e6d643cedc878f691f14c22e35948c65343c6f32a19cf01329e32329e21643c4793f1b422e3f9908c671619cf73643cabc8785692f19c48c6f31619cf56329e12329e52329ef9643cb5643c2f93f19c46c633948ce758329e36643c4f91f13c43c6f32619cf1b643c2793f16c21e3d94cc67304194f07329edd643cef91f11411f0248023009bfcbf25d8e43b3c07c0f699ceef039b7cc36731d83ed5f947c0f690c5d6c2c2270c33c026efca7e0636b93ff330d8e49d894fc126e70de25fcdafeef855fe16b08cf86969e1477f9f5ab8248fdb5b96a90ae2dddee8ab2ab07ff3aec8603cd43cef91f1ec26e3e940c6730419cf66329e2d643c2793f1bc41c6f32619cf33643c4f91f1b421e339968c672819cf69643c2f93f1d492f1cc27e32925e32921e3d94ac6f31619cf89643c2bc9785691f13c47c6338b8ce743329e56643c4793f10c21e32923e33940c6f32a194f0d19cf42329e49643cfbc878da91f16c23e3d94ec6f30d329ecfc9785693f1ac21e339938ca73319cf0b643c73c8786e21e3e947c6d3928ce748329e73c9780693f19c42c6534dc6f334194f1d19cf93643c6dc978ba90f1ec20e3799b8ce738329e72329eb5643cebc8784e27e379898c670919cfeb643cf3c878ce27e3a920e3694fc6733819cf49643c23c878ce26e379968ce71c329e99643c5f90f1b426e379878c672719cf31643cebc9783690f17424e379858c672919cf32329e05643c09329e13c878ce23e3194ec6731619cff3643cb3c9788ac9782e20e3d945c6f32e19cf51643c1bc9783691f19c4ac6f31a19cf72329e15643c8bc8782692f12c26e3398c8ce778329e61643c6790f1bc48c633868c672e194f25194f0b0bcf01473cf2ad1859b7cc1f68e6be7719be771588ef770cdfef1488ef1d86ef1d05e27b9be17b5b81f8de6af8de5a20be371bbe371788ef8d86ef8d05e27bbde17b7d81f85e6bf85e5b20be571bbe571788ef9586ef9505e2fb0dc3f71b05e27bb9e17b7981f85e6af85e5a20be9718be9714886fe6eb6ff59d30e9abbc5bff26e0ff15c0b8d811e3018351e61703a3d8f07bd4158e78a2aedd2b087c2b2de45e963cf34cc0ff2b81d1554c55188c326f8ba95dc053e98827ea9e4325816fa585bc8b2d7d2a13f07f1c7fd9554c551a8c326f8ba97780a79f239ea87b25fd087c2b2de4dd6779e72f01ffc7f1d65dc5543f8351e66d31b50378063be289bac73398c0b7d242be1526dfa449c0ff717c46573135d86094795b4ce1f8b9431cf144dd9b1a42e05b6921dfda956f5e26e0ff387e93ab981a6230cabc2da670fcb8a18e78a2eea90d25f0adb49067c1f28df604fc7f1830ba8aa9a106a3ccdb620ac7bb19e68827ea5ee03002df4a8be13a2f7dac12f0ffe1c0e82aa686198c326f8ba98dc033dc114fd43dcce104be951623745edee148c0ff4700a3ab981a6e30cabc2da6d603cf08473c51f75e4710f8565a54ebfc3afd9b80ff5703a3ab981a6130cabc2da6d6024fb5239ea87bc6d504be9516353a2fdf9c4bc0ff71fcf7118e18ab0d46991f018c625b0d3c358e78a2ee75d710f8565ac8b7fd57e9df04fc1fc7637515533506a3ccdb620ac783ae75c413758fbe96c0b7d2628ccecb983009f8ff1860741553b506a3ccdb620ac7af1ce38827ead9c21802df4a0bf936d70afd9b80ffd701a3ab981a6330cabc2da696034f9d239ea506cf528b1687cab7d242fa722fd3bf09f8ff44607415537506a3ccdb626a29f04c74c413f52c6722816fa5857c5bfb75fd9b80ff4f0246573135d16094795b4c2d019e498e78a29e414dca81efa8e729b9f01df56c2017bea3ee73e7c277d43ddb5cf88ebaff980bdf51f7d272e13beabe502e7c47dde3c885efa8ebf55cf88ebaf6cc85efa8eba85cf88eba26c885efa8f3db5cf88e3a57cb85efa8f30edf9efbf63c6edf87f2dca150dbf343790c3d94c7127f6de0af0d72e5db1f4bfcb541ae7c17eab5816fcf73df9ecbf55751107d3df68623dfcb0ddf328fcf59963bf2bdd4f02df3f8cc60a923df4b0cdf328ff7bf9738f25d6af896f92539f0dddef0dd3e87be3b18be3b587c3bd8dec944d0f0fa5b1870aa823cc6c0eb0eb47054cf72b5de657a5d5fc6b85edb7d1b737f298532cb403fd76d87acdb6c3bf29119e3a2283edfe509f021df255336797efc2ad8a4dd7f056cd22fe065b0c9b1e925b0c933a917c126cfac5e00db189dff106cf2ec18fbeccbf3ff1d60abd679ec2b3e42e7b7814dfa52611f65e90fb7156cd2a711fbc64abfd4cd6093bec5d82753fa876f049bf4f1c7be80f29ec67ab0c9bb36d8074dde975a0bb67d3a8f7d9fe43b34abc13643e75781ed0f3abf126c0feafc2d60fbbdce7f01b6dfe9fc12b03da0f3af83edb73abf0c6cf7ebfcf360fb8dce3f07b6fb74fe59b0ddabf3f82edbaf75fe3db07da2f3f80ed5749ddf05b65fe93cbebb738fcebf03b65feafc33609ba6f34f836daace2f02db2f747e21d87eaef30bc03645e7e783ed673a3f0f6c93757e2ed87eaaf373c03641e76783ed273a3f0b6ce3757e26d8c6e9fc5360fbb1ce3f09b61fe9fce760bb4be79782ad85ce2f079b8c1989fd548a75fe0db0b5d279ec7f24dff79f04b6363a3f116c6d75be0e6cf26db8316093f1a06bc196d0f91ab095e87c35d8e4fc6c04d864fc93e1609373a961603b42e787824dce7b86804dc6b31c0c36f906693fb01dadf39560936feb5780ed589d3f003619736c31d8e4bb75fbc02663313f0c36f95ef50cb09da8f37f009b8cc3f220d84ed6f9df83ed149dff1dd8e41b9e0f80ad4ce77f0bb68e3a7f3fd84ed3f9df804dc6c8ba0f6c67e8fcbd6093b1837f0d36f9def32760eba4f3d3c176b6ceff0a6c3296c83d6093f1417f09b6ce3a3f0d6cf21deea9603b5fe77f013619efefe760936f0c4f019b8cebf633b075d5f9c9604beafc4fc1d64de72780adbbceff046c3d747e3cd87aeafc38b0f5d2f91f83adb7ceff086c7d745eda19b53fabfd7cbf9eaf0ae23b2f53fede0f1a4e99ae0d840179e23cd72e051ef4b537f6ba2753e7f5b2dfb7d0eb9518da0bbe77c7ee3b7d4db147afab955eef6ec3773194395b370e6ab977e1ff555007590eef63c9ba65990b60d9f78c75b7d7f5dde3a8bebb0d26e1de034c52e6bc53ebcbfe40e7dbc23231b2a5ae8f25d602d010a72ac80b831bad92e578dedb189e3dc0b337769ef4f5ba8b98c07d2beeeb75f33eae196ba5506637e8f79e03fd705f9775cbbcf8f3cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfcccfac78f6eb3c3e579672fb4918c5b617785cdce7c7e7b0f8ccebbd53ebfdee8ddd6fc3e77badf57acb8d3a1743992fe199d33e9d2f81ffcb768bda960e9e1366dc96e2af04ea83cf82f63be2d96bf0ecb56821f9b2d87c2747b9d13859aefab2a867ecfb0c5df75b3475b5bfeed5eb2a3234c5fdf57d83079f8d9600ef07fa3701ebf900eae0601fcf1817e20ff7a5bd6093fcfbc0e8623be3b144da03791e2efef0b9f8af8ce7e2f16ffb64b9cb76439ef99bcfdbb1ae52e677d0f67daaf3d837643faceb1f96ffcb94e939b5e8a7eabc33fe3aa7b6aff46994edbbd3e2fb6d608dc9778377688a74123f622f86fcdfa13f8794133d446b61c7f1ca91dd5cee7d63b95228b3cb52ffaa20defaef3478761acc2a763e8738fb071cff5db549bb2234ba003492327b41a37d8e78f61a3cc221fe5419d9fe6d8c32b26c3194f99fd046a9ba483b2ff5c4be2d780c78d751fdc497ac5be6c51f9e1bef0146b38e2a3e061d5bcfbb3776defceaffd5a62cfd8bed7a5cfdbf64ddedf5b2c21118eb2f87f5ff8b2b883eb6fc6bfb96d5afdf65ffb27d469d85650f304999f665f5652fd5f96ccef50fd5755bd4b9fe2e073c89a0e1b5b79a321ddff118e3a27d7154cf72dbb1eb3da34ea550a613d4d3c1794cc6778177826f17db1cb59073a8dd8616c550a66359fa57da8e281df15a754f4eea92b49e0f965bea22653a95d5d7a52dd8e36472b9ddf03c4bad77afa5ae52e6bcb2fab25d743e01db09dbd27e96ffcb94a93dc0b178b6c75fe7d4f69577de64fb6eb7f87e0b5863f2dde05b2072be2f7ec45e0cf9cab2fab2524ef410ad855ded23f2ce1fb29bcbed36962b85323b2cf5af0ae2adff768367bbc1ac62a76b597d5ee2c865bbb92342a372d048cae0fd6339b6e37b77b6e3fe5e47dc51c7fdbdc068b69b78eee2926d9fc166de43b59d0f4a195916cf07af2a4bffaa763661296bde1b76711f13df410da01e8151579930061c5c1b76c76b2769a7c44f17b0efd579d1b98ba15d3194195c96fe7578de6dbd77695edfe13585709bfb16befb31b4ac9e1bc74edcab7f4bc0f691fe75749dd6dd76cf50386cf70c4794d5b3e3b2c2f5a1a52ea281946d117cf59efa974659bcef966939336f8e43a9f4fdc82867f383d73cb1bdabd1b5bc1c995a58b4c0fbde52ae28f8ea989bb21f60cc99f751ba18ebc1fb287565e95f6993ccb2aa4dfa1f47d7eb23db51b4c3f60463f27d60acd2f9f2af3775b5d55fe6c59f62fcc0a8839bb62bfdbe5236f781f7018f8bb6dd511b5d8ec7d8b6b1adb74fb5edf8ffbea1550e9fd75a8ff9e633f7b6463e1edfc91adbfd279b16bb2d3cae9ea34469b1dbe23b3e2d7a8eb21d3f6c5ae4b2ef439416ef597cc7a8452ddef7cca4c5bb161e57f7baa3b478d7e23b3e2d7a95677aae815aecb2f0b8baf710a585f8cb96f93d02e6b6463e1edfddab6df7c96c5aecb4f0b8ba6e8ed262a7c5777c5a74ed89f7e83269f18e8527fefb7399b578c7e23b3e2d7af7c17b7899b478dbc2e3ea996e94166f5b7cc71817a36df7726c5aecb0f0ecc8b1163b2cbe633c3fec69bbd766d362bb85c7c17dd78c5a6cb7f88e518b9178df359316db2c3cdb72acc5368beff8b4a8ee61bb276cd3e22d0b8fab7bc2515abc65f11d9f16237b2bdf5b1ba1c5560bcfd61c6bb1d5e23bc66ba8545c6c6984165b2c3c5b72acc5168beff8b4a8499d6b6d6e84169b2d3c9b73acc5668beff8b4284f1d533735428b4d169e4d39d66293c5778c7191ba9edcd8082d365a7836e6588b8d16df311e475271b1a1115a6cb0f06cc8b1161b2cbee3d3a23675ff697d23b4586fe1599f632dd65b7cc778cf251517eb1aa1c53a0bcfba1c6bb1cee23b3e2dbaa58ea96b1ba1c55a0bcfda1c6bb1d6e23b3e2d46a79e89ad6984166b2c3c6b72acc51a8bef18cf3b53edc5ea4668b1dac2b33ac75aacb6f88ef1bc3375ff625523b45865e15995632d56597cc7d876a6ce3b5736428b95169e9539d662a5c5778ce79d292dde6c84166f5a78deccb1166f5a7cc778de993a8ebcd1082ddeb0f0b81a03254a8b372cbe638c8b54dbb9a2115aacb0f0acc8b1162b2cbe63bcaf956a3b9737428be5161e57e3354469b1dce23bc6eb91d43dbe658dd062998567598eb55866f11de3b3a2d439f8d24668b1d4c2b334c75a2c05dffb62f79deecf2d3ea42fd6f98616c550e6948ee95fe98b15a5a3ac03fb95615d5e8fbd2ee97e654b22eaf23ad445ca9c0175691b3819a3a8bba3baa66266b15e97f44dffc0525729734ec7fab29d753e01dbe44358575fcbff652a32e6ab202ffaa93abf1a7f9d53b12a63c8c8f67dd5e2fb65608dc97757f45da493f8117b31e4fb74ac2f2be5440fd15ad8d53ef29ace23bbb9dc5263b95228f39aa5fe5541bcf57fd5e079d5604ebdf700712671e4a6ed4a33bd16a1d1f9a09194c13e7b1f38e231fb100a87f8536564fbb731ca601f4a297321b451d8af54ea9908beda6f52d56fb1a3fa892f59b7cc8bbf52b0ed0346b38e2a3e3e81be9f3256848c23a16c322e4437584f2fc3a6eadadb515dc597ac5be67b03a38c53d12bf78cc9c632f63418154f5f079ae1d81b32653a5ef4059e3e0e781cd533751caa30ead4dba8532994c1771b2b1cd4b308fccaba65be027cbbd8e6a8851c93cf31b4288632238cf3c7281d651d2a7e7b59ead2df715d64ddd22ef5cf81ef4ac3770fc3772268b89d8320f3fe5509ccfd1c30abf50e887fbde578de2631257e7a409d06820671d509d725e779030d6d8b213f0dcef3a49c9495e397b0ab58966d89ece6727d8de54aa14c7f4bfdab8278eb3fc0e0196030ab63f75d706ee7607f48c5407f8343e67b80760322b4eb0fda49193cfef574a45d3f8347e67b028f9ce354804dce15843f01ffef96036eb3ddabb0708b0dc789eb6961ec113f63ea5ca7a7c128f33d80516cfd80a7d29166e6b63ec7d0078fcb6d8c32b26c3194990dc7c684a5acdaef3a15d5d7aba5b6c7f6ee986ed35b3bd00bc7690c409fc0d0502661681bd48fe518274fbba07eacc62953eb268fbc73f40da3d38f1e05add8c0c4df224b355a800df32d2db6206838246531d86448ca56606b61c88243614a7919d2ce855ca887acbbd8e06c0b2c71fac6e13c65ca143a6d80c74528abd091213d75e8dc3279ecd4d1181fad0ccea6c48efa5fcb0ce5a2d6e56a3b98fb4415cc9b3158ecc87f4ba86f15cc8b3fb56d4a757ee2c851770f9c7ce7b4f1a3274c9d8242993b36e68b82861bc0fc8d12dcd54e87018015c6c6a195512f6c30e47fb261dac5cfd91dc7cc35b509c09f4ced40b7c31ce8a6d62f63df8e1a396edc75d3aac78d1d75e9b409a3a68ead9b805bb3ada15cd49696ffb7069bad89c7b26ac2660b976d63b1d9261c65b82dd8e4c87518d884a71dd85a425eca9b5bc649b87682f5cb2ea5fea7c469a52bde26a80f01391cab7655edbfeaf3b1ea34480d75ac8636569b530d5dacee18aaa189d557ecd4d0c36aa86135b4f009417ae8603554f0c9417a2860f5b58bb2203db4ef69417ae8de3382f4d0bc6701dfb781f9ec207ddaa586d6ed1ca487ce55b72ed5abebea336feadd7a75faae6e0ba8535e7589a74e3fd569a7babc50b72fd4ad2c754aa74e97d5a9a03a7d53972303b4d603c37461982e0ad3c561ba244c9786e9b2305d1ea62bc2746598ae0ad3d5611a14a66bc2746d98ae0bd3f561ba214c3786e9a6203dbcf3cd417af87535fcf3ad417a68e8db82f4b0d1b707e921a5ef08d2c34d8f0cd243518f0ad2c3548f0ed24358df19a487b71e1ba487c9bd3b480fb53b3e480fd7ab86c356c364abe1b3d530bf6a486035a4b01a6a580d4bac8630564320aba191ef0fd2432eab219b1f0ad2c33ecf08d323617a344c8f85e99b617a3c4c4f04e9e1c1d5b0e13383f430e36af8f139417ab8f279417a787335ecb91a0e5d0d93ae864f57c3aaab61ded5f0ef6a58f817c2f462985e0ad28f24d4a318f58842ddfe57b7a7d523a2d783f4adf36541fa11b77ae4afba40a82e21aa8bccaa20dd854a7529535dec549743d505537549555d74559765d5855b7569575dfcd52b0fea1510f54a8c7a4548bd32a55e2153afd4a9570cd56ba2eab54bf51ab17aad7a6f90be2dbe3f483f2a55b7c3d5a30175cb5cddbeff384cdf0ad231f99d307d374cdf0bd3f7c3f48330fd30480f6bac863b56c325aba195d530cc6ac8663594b31a0a5a0d1bfd49901e7a5a0d5dfddb203d24f6efc3f469983e0bd2c36b7f1ea63f86e98b30fd294c7f0ed35fc2f4d730fd2d4cff16a67f0fd37f84e9ef61fa4798fe19d40fb38d0dc909baf5d15730c1c8a953478f9f38b56c6a5dd9f869e3a68e9d38eebeb2e963a78e29abbb67f4e4da7175d371e16feb85658cf08193278fbcaf6cec849ad1f796d54d9b5a56575b565d376d424d8383f85ff442277dd5e3c89a9a6867fff57548ff4f139d1ea6db45197dfd8acc752b69d904418e6cca423d5b36ad4293f5114c2e756f4c9f07974d195737b5acbc6c42f8373cf0d64d1f5dd3a50cff37251479cad4b22953474e9e5a563bb96e7c59d72eb8de87db35a112ffddce0dcc9927344d9c4efa3b4b4d0ab15f9eda0405fef3d4a691b62efb1aa4edca9ae6b4acac09353cab290b5dd944c29bca22659932ad7aeae491a3a6462f7cebd759f88ea654734213ab7972c726383bbd290b0decd834c23b9ae26c5616ce82ff0f9c57cf6b845506009b2d6c6f00000028451f8b08000000000000ffed9d77741cc791c6679118164b1024c11ca04433015c2c12012630674a9464e5409004455a24419150b22c4bb224e79cb3e5749673ce675db4efce77bef3d96739fb9c6dc941f7cf3ddfbb7bcfefba67bb8c0fcd9935169a026bb035ef15b7a7b677ead7df54f70eba67874f054190098a5bb5b18b8273377abfcfbde69fded696e0b1f29c9c99947056a584b33a259c3529e1ac4d09675d4a3827a58473724a38a724c869d9aa82915bd2bc5319744d9a319b324deb53a0692e659a4e4b81a60d413ac6a8e929e16c4c09e78c9470ce4c09e7ac947036a58473764a38e7a484736e4a38e7a584737e4a3817a48473614a3817a58473714a3897a484b339259c17a484f3c294705e9412ce8b53c27949829c2b8173a97b7d867b5de65e97bbd715ee953eb3cabdb6b836d6b8fd5663ab2d9bb136efbd82b176631dc63abdf7ba8c751b5b63acc7bdd7ecdeeb35b6d6d83a63eb8d6d30b6d1e9b0c9d866635b8c6d35b6cdd876633b8ced34b6cbd86e637b8ced35b6cfd87e63971abbccd80163971bbbc2d895c69e69ec2a63571bbbc6d8b51ecb75c6ae377683b11b8ddd64ec6663078df51b3b64ecb0b123c6068c1d35768bb163c68e1b7b96b15b8d9d3076d2d8296383c64e1bbbcdd81963678d0d19bbddd81dc6ee347697b1bb3dcd9e6dec1e63cf3176afc7f95c63f719bbdfd803c69e67ec41630f197bd8d8f38dbdc0d80b8dbdc8d88b8dbdc4d84b8dbdccd8cb8dbdc2d82b8dbdcad8ab8dbdc6d86b8dbdced8eb8dbdc1d81b8dbdc9d89b8dbdc5d85b8dbdcdb1504778bbb177187bc4d83b8dbdcbd8bb8dbdc7d87b8dfd85b1f7197bd4d8fb8d7dc0d8078d7dc8d8878d7dc4d8478d7dccd8c78d7dc2d8278d7dcad8a78d7dc6d8678d7dced8e78d7dc1d8178dfda5b12f197bccd85f19fb6b637f63ec6f8dfd9db1bf37f665635f31f60fc6fed1d83f19fbaab17f36f62fc6bee669feafc6fecdd8d78dfdbbf37dc3bd7ed3d5a579b1ff30f62d577edcbd7edbbd7ec7bd7ed7fbccf78c7ddff3fdc0d80f3ddf8f8cfda72bffd8bdfec4bdfed4bdfeccbdfedcbdfec2bdfed2bdfecabdfedabd3ee15e9f74afbf71afbf75afbf73afbf77af4f19bbaca9589e1c0c6f7d41426354c7d1bc5d5321f197062337ab45b57b8f5e9b9dbfc6edd32b6957ebf66b3d7f9ddbaff38e33d9ed4ff6fc8d6ebfd1f3cf74fb333d7f93db6ff2fc73dcfe1ccf7fb1dbbf18fcd900e65c9ddffaaa9d2b033ecad72af0d53a5f35f8eae870e09be47cb5e0a3f35b07be29ce37097c539d6f32f8b2ce3785b43456ef7c7d4152b992efb7c7cd257d5cb70e352d79dec3f6b80d4cbcd393e71db0c76d64e0b5f931c31d6b3ae4cd4ce76b04df2ce79b013e3704fda9cf59df6ce79b05be39ced704beb9ce371b7cf39c6f0ef8e63bdf5cf02d70be79e05be87cf3c1b7c8f916806fb1f32d04df12e75b04be66e75b0cbe0b9c6f09f82e74be66f0d13d2e1780ef62e7bb107c9738df45e0a3b1f662f0d1b5e125ce67c789c919f88cf3d318157e86c667f02da3b1197ccb695c06df0a1a93c1b71262936f158c2be46b713e1aa3ec7bbdaedc1724d5270a619f589bf471cd91ed71d7277fdc70dd6e4330ac6b1fc4590b5a6d74e504ef0d6ac3d819671487fc3550de0575a91ee941df33c46ebf4fd6b9f2c6129febf53e97833aeb22dadf1724dbfef51ecf7a8fb916dacf93b3ed05cdd9516f65e7ecd550d7cf3dbae6998839bb17381872b64b7376d45bd9393b0075fddca3ebde8998b3d7010743cef6f3e46c21af395b9c230b82e8dca3bf7d2662ce1e038ee473b6537376f45bd939fb00d4f5738ffefe9d88397b0770249fb3ddfd7a6d30eaadec9c7d05d4f5738fe6622662ce3e041c0c393ba0e3eca8b7b273f66d50d7cf3d9a179c8839fb6ae0483e677b9872b65d733628ae77064174eed11cf544ccd9478023f99c3dacf3b3a3dfcaced9cf435d3ff768bd6422e6ec475cd9ae337cc3ad332c04df379d6f11f0269fdb473a9872bba0b95dbc0f2408a27394d6ee26626e3fe6ca368f1f877b0fc8f76de7bb007cdf71be0bc1f75de7bb08dac5d007fab50f8c7a2bbb0f7c1feafab94cebc813b10f7c1d381872f6b0e6eca8b7b273f609a8ebe71eddd3301173f647c0c190b3039ab3a3decaced93f405d3ff796b9f244cc59baafd45e2ffcd85d2fac00df4f9c6f25f87eea7cabc0f733e76b01dfcf9daf157cbf70bed5e0fba5f3e5c1f72be76b03dfaf9daf00be279caf1d7c4f3a5f07f87ee37c9de0fbadf37581ef77ced70dbedf3bdf1af03de57c3dce67d7bbe8deabaf3a9f3db7a4515f90ecb9a57b2ce9d8b4bf6a1c623778b11bc63176a317bb3122760b43ec2cc4a02de3edf741b98597279f0b46fefe8362ad4e3e56bb6d7b6b30fab6af069e3c43dbb31063343c79e0694b9e27bcd7b790fc71c373dcea699a8558add0ae7686766520161d9bf6295e0e7c387eb747307624cf58c8402c3a36ed770023f9f0fb84bed7a9ffd8efc3a599615e86be145e1361bc3ee0a0783550e7f7b386ebae706cf5f03e7eb7b6793ea6bc0cf38262d1b1699fe2d5437bdac69fb1305ac6bcc7c835466420161ddb8f8dfdbd65fc351bd579cd81ef3c8c4985b18e49f5c0361ed72971e75a4a6c8eefab0cc4a0b18d34a77835506776f570dd1d30ee32f4bf42b9d76f381e249fc7853cf6ebd1f0b4030f47df67eaaf79fcdeff63906cae757a5ab5795ae5a04e07e8d7c9a05fa9eb108aa7cccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaacccf299f1fe0b5cdfa47aab843092af003c1cf3fce1f3a3dcb1e8f8765de73bb0ae93fcba45218f6b96748fe172afcd3550e7c9cc30db0f603ddd5f1bc435cd55bcda8dea3e8bfae0dcb558ce35c4b875e0a8f5cbe6c462170e73adb7d967a8d8e790b57abaae8ad094e13e95119a663c4df13ec5951e8fcdd379d5c36c1c6b7fe5ae45a256544e726d0fef31e03d2fc5f18372a12a18397ee0f74c57e2b147ae61d27a799717bb06eafc4f66f8dcac81f7fb8273ef79b275babd63d36796c367bbbd6337b8cf12479d77fc56f82cd5f93f1853df5e15fc49338efb3f705c0ea0adb8f54119d7cd93ff1e2eaee3b797c1d3093c1ce30cd3f5461efb40d2ebf8dd9e5651d73154a70bf4eb66d02fea5a94f6299e322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb332cb67c6df8a126b16ea1584308ed3bd0fe17a063dff05d7a65e5a351c977b1d8ed69c56786dae813a5fab1a667ba52bd707e7deef10772e19d6f34a9e4b8a570fedc1b520aedf7377783c1d115a50b939b1d8c575fce4351e5ec76ff7742d4468cad55f718d1535c5fedae6f1e0da687d70eebd255938ce78dc3b149717140ffb5207f8a88cbf8fe638cff85de2dfd743f170fdfa51a76d43c075ee0b79ce7183d6e669adbe3da2ad54e7c330f67dd495f11e0ebc77e4b188f7692bb54e4dfab13ccb2e5f5cf7a567c0d1f9ed8d88bd0e58138add86b133ce280ef96ba0fca5aae1ba548ff420ad89ddf6117a2618b2fb9f6bf33e97833a3d11edef0b926d7fafc7d3eb31dbdcf904e4d963f0fdcf3526f5c468b41c34a23a781dc4754f9e3f46faf737e27d7b93bc3a78cd4275be026354dcfda351f71cae616a5fdc3d87140faf8d3b81d16fa37f9f67a5dfa7f5388c1749dfa7f538e410dea71578c75f01c727ae4941fc770bd5f99e777cff9a9c3e83f781519d1fc278d1e0ee59ac0fcebdfec67ba6c6e3efabb8fba4291e5ed760dffe736dc7be99f4f713e604b2603e519d5f79e7ac3b867b75c4679f8cf92c69d5e2caf8f78baf9fd5a1073ed397880ec53edfebb585f2ba07da4275fecbbb064cfebaa5780d987c5b475e93d038d011d156aaf3dfd0d7fe00d778749e70bcaaab3ef77dda4a5d03927eb6cde3fd7c608c2de1f9c0b5d5c375fde7fc92d6e53e1fb8cbfb9cc4e703ff2fe4591ddc87ce3556af8bd16805684475f0b741f43d82cff28dfa8ee1bab73fee3b26ea199438b637548f3f9b3faf16758d4075e8b3788d30cb3137389dfdbafe7c217d5f2679df30fe56a215e2e26f255a99f4cc836e7db08fd705e733769e2976dc33a7f3e3103bee99d3e311bbd18bdd388eb15573d55c92e60ccf440e7f7f86cf2cb55ba9eb5262c8c1e7aa52c0589d02c69a1430d6a680b12e058c9352c03839058c5352c03835058c59603c9fdfed0cfa14c6aa0fd7f92a75ad81b15b98b428e7ffef60febf544a5efb606c86bfe9422d5a82d16b817fe7713cfba1dcffeb8518f0ff2e989102c69929609c9502c6a61430ce4e01e39c1430ce4d01e3bc1430ce4f01e38214302e4c01e3a214302e4e01e392143036a780f18214305e9802c68b52c078710a182f4901e352654c8471252f6361ac8c9687e3fffc7b3affe718034f3eea9e53a6df9e94fdffad313f9fb46daccf8dc37b4b78ff4fb8a7f76c3b8e7b47ca7db65da9ff6f9589b1305646aefbd8f1773ca3e1c1df4546fdb68681b1305646aedfbfe06ff446c3d3059a754668c6c058182b23d7bd72e5decb89bf4deb8ad08c81b1305646aedf3c648391f737ff391efc1d447784660c8c85b13272dd979c8518a3e1e901cdd64468c6c058182b23d36fdb42cd7acae0c1df80f54468c6c058182ba3e559cba4596f193c6b41b3de08cd2431224fd2cfc9ee8d88c5f19bc172db4e0cc83825058c5353c088f749708c5fa5ee93e8e5d5a730567db8ce57a9fb243036c3ef63422df0f7107f4e8bf5bc3c25ef93c0d81b98b4c0dfabfc392d36000fc7ef67b21063343cc49083cfcd4801e3cc1430ce4a0163530a1867a780714e0a18e7a680715e0a18e7a78071410a1817a68071510a1817a78071490a18f16f55866bc5927fbf6c98e0b1e3fe5699e8b1e3fe2e99e8b135cf35cf2b21b6e6b9e67925c4d63cd73caf84d89ae79ae795105bf35cf3bc12626b9e6b9e57426ccd73cd7349b1d330c7af8c138f11799a93e3c963db31569f80b6f745f06498da8eb13609683b31a48d71630a18d7a68051752cde83381646cbb399896753193c9b81670b13cfe63278b600cfd6e479c29cda52060f31e4e0736b53c0b831058caaa3ea28895175ac1c1d955119955119cf07631ac670654c453e16c6ca6879b625cf136ab6b50c9e6da0197dae8d97b1305646cbb33d799e50b36d65f06c07cdb64568c6c058182ba3e5d9913c4fa8d9f63278768066db233463602c8c95d1f2ec4c9e27d46c47193c3b41b31d119a313016c6ca68797625cf136ab6b30c9e5da0d9ce08cd18180b6365b43cbb93e70935db5506cf6ed06c5784660c8c85b1325a9e3dc9f3849aed2e83670f68b63b423306c6c258192dcfdee47942cdf694c1b31734db13a119036361ac8c96675ff23ca1667bcbe0d9079aed8dd04c2ae3da14306e4c0123b38e85b1325a9efd4c3cfbcae0d90f3c9732f1ec2f83e752e0b92c799e30a72e2d83871872f0b9b52960dc980246d5517594c4a83a568e8ecaa88cca581e635f0a18f55c2ba3544686bfaf4afe86e6d2091ebbc18bdd5021b1e37e4333d1636b9e6b9e57426ccd73cdf34a88ad79ae795e09b135cf35cf2b21b6e6b9e67925c4d63cd73caf84d89ae79ae795105bf35cf3bc12626b9e6b9e57426ccd73cdf34a88ad79ae795e09b135cf35cf2b21b6e6b9e67925c4d63cd73caf84d89ae79ae795105bf35cf3bc12626b9e6b9e57426ccd73cdf34a88ad79ae795e09b135cf35cf2b21b6e6b9e67925c4d63cd73caf84d89ae79ae792621f483e76a1dc67cc1c001e8e67de30b5336f8f7bb93bd61f13d4cf6a7585a7d5a59e5639a87339e87705837e19884bc7a67d8a572ef333043033c52e4c33c79802eda7181b3d3d6cfc2b99da1e37d65f39c163c78df5133d76dc583fd1636b9e6b9e57426ccd73cdf34a88ad79ae792e2536966b83e1eb767afea93dc633e1fd8cc76ab71aa873d9a4e26b43a07d8823b6f621fdaea884d89ae79ae795105bf35cf3bc12626b9e6b9e57426ccd73cdf34a88ad79ae795e09b135cf35cf2b21b6e6b9bc3cc77ca81a079ec0e3094af06c10c6b35b18cf0e613c6b84f12c16c6d3298c67ae309e82309e19c278b60ae399228c67b9309e6a613c9b84f1e485f1ec15c6b34418cf0a613cf384f1cc14c63355184f8d309ecdc278560be3d9278c678f309e5e613c4b85f1f408e3d9268ca74b18cf7c613cedc2786609e359298c272b8ca755184fad309e9dc2785a84f12c13c6b35f18cf3a613c0b84f13409e3a917c69313c653278c67bd309e5dc278b60be3e916c6b350184f87309ed9c2785609e399268ca74118cf16613c9384f12c12c6334718cf74613c8dc278260be3198fe70d95c39311c0930dce7d265916de3f00be2aefb376bc6a6b1a7eff2ae7af82cf5cedcad511c7be0a7cf4dbf0ab233e8b3a5d056de973e5fcd3db429d30561fec53bc7ae0b85a08cf01613c9385f1340ae3992e8c678e309e45c2782609e3d9228ca74118cf34613cab84f1cc16c6d3218c67a1309e6e613cdb85f1ec12c6b35e184f9d309e9c309e7a613c4dc2781608e359278c67bf309e65c2785a84f1ec14c6532b8ca755184f5618cf4a613cb384f1b40be3992f8ca74b18cf36613c3dc278960ae3e915c6b34718cf3e613cab85f16c16c653238c67aa309e99c278e609e359218c6789309ebdc278f2c2783609e3a916c6b35c18cf14613c5b85f1cc10c65310c63357184fa7309ec5c278d608e3d9218c67b7309e0dc278aa227818feffcb9087ee5fa363d3fe0121b119ce43f8ff7e5ec3d4a66bddb1eadc71899fe2d5409debdc8581bd1f053f4b5cfefd8678efdcb5a0d1b54c6da1f391f1ce0f73ec02de57190043e0e91344f070dc8fcad4ce117998e0ff3f9bb75a5de769e59fbb1cd4b906f4bb8e41bfa8dcfe531f70af6964b63cf4dd41ac59a8b7410823f9aee4e509fbed8660e456aadf5e073c1c6318533bc3fe75bdd7a60d11ba531dccd5eb19da19d57768ff7a380f6963b63c9b5c9958b3506f931046f25dcbcb13f6af4dc1c8ad54ffba1e7838c61fa67686fdeb06af4d9b2274a73a98ab3730b433aaefd0fe0d701ed2c66c7936bb32b166a1de66218ce4bb8e97a7230b6da6ad54ffba017838c61fa67686fdeb46af4d9b2374a73a98ab3732b433aaefd0fe8d701e945999a3982d0ffdc68458b3506f8b1046f25dcfcad391cf429b692b358edd083c1ce33c93eee1387693d7a62d11ba531dccd59b18da19d57768ffa688d8cd41b25adc3c0a2d6e8ee0b9799cb5a078e5325f934266d559758e63569d55e73866d559758e63569d55e73866d559758e63569d5567bba9ceaab3eaac3a27c1ac3aabce71ccaab3ea1cc7ac3aabce71ccaab3ea1cc7ac3aabce71ccaab3ea1cc7ac3aabce71ccaab3ea1cc7ac3aabce71ccaab3ea1cc7ac3aabce71ccaab3ea1cc72c4167cb43cf8821d62cd4db2a84917c37f0f284bf0bda1a8cdc32de7e1f946f069e1b19f4616a67780ff941af4d5b2374a73ad8bf0e32b433aaefd0fe41380f07cb60be2985ccaaf3d8982d0f3d2b9658b3506f9b1046f2ddc8cb138e63db82915ba971ec20f0708cf34ced0cc7b17eaf4ddb2274a73ad8bffa19da19d577689fe229b332c7315b1efa3f6c88350bf5b60b6124dfcdac3c85f0f78ddb83915ba971ac1f780e26ce531cc718740fc7b1435e9bb647e84e7530570f31b433aaefd0fe21380fe530df944266d559758e63569d55e73866d559758e63569d55e73866d559758e63569d55e73866d559758e63569d55e73866d559758e63569d2b4767cb43ff7708b166a1de0e218ce43bc8cad31eae3bec08466e196fbf0fca8780a73f719ee2ba0383eee1bac361af4d3b2274a73ad8bf0e33b433aaefd0fe61380f139df9a614326b6e8c0fb3e68632c7316b6e28731cb3e68632c7316b6e28731cb3e68632c7316b6e28731cb3e68632c7316b6e28731cb3e68632c7316b6e28731cb3e68632c7316b6e28731cb3e68632c7316b6e28731cb384dcb03c3b5d9958b3506fa71046f2f5f3f284cf3dd8198cdc4addb77318780e31e8c3d4cef0be9d235e9b7646e84e75b07f1d61686754dfa1fd23701e945999a3982dcf2e5726d62cd4db2584917c877879c2716c5730722b358e1d011e8e719ea99de13836e0b5695784ee5407737580a19d517d87f607e03c28b33247315b9eddae4cac59a8b75b0823f90ef3f284e3d8ee60e4566a1c1b001e8e719ea99de13876d46bd3ee08dda90ee6ea51867646f51dda3f0ae7419995398ad9f2ec716562cd42bd3d4218c9778497a7908536d3566a1c3b0a3c1ce33c533bc371ec16af4d7b2274a73a98abb730b433aaefd0fe2d701ed2c66c79f6ba32b166a1de5e218ce41be0e509fbd7de60e456aa7fdd023c1ce30f533bc3fe75cc6bd3de08dda90ee6ea31867646f51dda3f06e7216dcc96679f2b136b16eaed13c248bea3bc3c61ffda178cdc4af5af63c0c331fe30b533ec5fc7bd36ed8bd09dea60ae1e67686754dfa1fde3701ed2c66c79f6bb32b166a1de7e218ce4c3ef8bfd4c3c398f2717a1c5448cdde0c56ea890d88d5eecc60a89ad79ae795e09b135cf35cf2b21b6e6b9e67925c4aed45c53cd2b53f3cc79d43c731e35cfa8e62235ff6372b13b715ca98258c798da895b1f94717e8eb635c278160be3e914c63357184f4118cf0c613c5384f12c17c6532d8c272f8c6789309e15c278e609e399298c67aa309e1a613cab85f1f40ae3592a8ca747184f97309ef9c278da85f1cc12c6b352184f56184fab309e5a613c2dc2789609e359278c6781309e26613cf5c27872c2780e08e3a913c6b35e184fb7309e85c2783a84f1cc16c6b34a18cf34613c0dc2782609e359248c678e309ee9c2781a85f14c16c69311c0930dcefd3d0afe9ea01a7c747fff7ef03dcb950f80af2a22061de738f868fe948e61c79b754de73254c1676e8de07a56443c8a736bc467c743778cd507fb14af1e386e15c23359184fa3309ee9c278e608e359248c6792309e06613cd384f1ac12c6335b184f87309e85c278ba85f1ac17c653278ce780309e9c309e7a613c4dc2781608e359278c6799309e16613cb5c2785a85f16485f1ac14c6334b184fbb309ef9c278ba84f1f408e3592a8ca75718cf6a613c35c278a60ae399298c679e309e15c2789608e3c90be3a916c6b35c18cf14613c3384f11484f1cc15c6d3298c67b1309e35c278aa22780e30f1c43d4fe18080d8763f0fbad82d0bef8fc7ef000f788cb47f0c18919778f24c3c71cfa0c80b886ddb4f7f4bd01a5c16dec7df7171e554de63a4fda89cc2fbd25633f1c43db763b580d8560b9abba47b00b2f03efe6e812ba7567b8cb41f95538dbc3ce1ff2dd1128cdc4add6b847d8ee31c32b5338ffd2fc16768443e8bbac5d30a9fa13a1ef7c9c78d07144f9995398ed9f2d0da05b1e2f7d978fcee6d348c51dfaf0c3ce1f8d81a8cdc4a8d8fc78087e3fb83a99de13876c26b536b84ee540773f504433ba3fa0eed9f8888dd1c24abc5c95168713282e7e4386b41f1ca653e904266093a5b9e55ae4cac59a8b74a0823f9f2bc3ce1f8b82a18b9951a1f4f020fc7f707533bc331e194d7a65511ba531dec5fa718da19d57768ff149c8772984fa49059751e1bb3e5a1396462cd42bd821046f21d63e529e4b3d066da4a8d63a78087639c67d23d1cc706bd36152274a73ad8bf0619da19d577687f10ce83322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb332cb66b63cf4db4662cd42bd76218ce43bc9ca535c77680f466ea5d61d068187635d8649f770dde1b4d7a6f608dda90ee6ea69867646f51dda3f0de7419995599995599995599995599995599995599995599995599995599995599965335b1e7ae636b166a15e871046f29de2e5097fb7d5118cdc4aad3b9c061e8e7519a67686eb0eb7796dea88d09dea60aedec6d0cea8be43fbb7c1795066658e62b63cf46c2b62cd42bd4e218ce41b64e529ae9f760623b752e3d86dc0c331ce33e91e8e6367bc367546e84e753057cf30b433aaefd0fe19380fe5309f4821b3eaac3ac731abceaa731cb3eaac3ac731abceaa731cb3eaac3ac731abceaa731cb3eaac3ac731abceaa731cb3eaac3ac731abce95a3b3e5a1ff738d58b350af4b0823f94eb3f2b487eb0e5dc1c8add4bac319e0e1589761d23d5c7738ebb5a92b4277aa83fdeb2c433ba3fa0eed9f85f330d1994fa4905973637c98353794398e59734399e398353794398e59734399e398353794398e59734399e398353794398e59734399e398353794398e59734399e398353794398e59734399e398353794398e59734399e39825e486e5e9766562cd42bd6e218ce4bb8d97277cee417730722b75dfce59e039c3a00f533bc3fb7686bc367547e84e75b07f0d31b433aaefd0fe109c076556e62866cbb3c69589350bf5d6086124df195e9e4216da4c5ba9716c087838c679a67686e3d8ed5e9bd644e84e7530576f67686754dfa1fddbe13ca48dd9f2f4b832b166a15e8f1046f2e1f7720f134fcee3c9456871be62dbfd5e57ae77af5978bf1718b9c6c31e8f91f631c79197787a99781a3c9e86082dce576cdbfe75ae3ccdbd66e1fd75c0c89553bd1e23ed47e55403f0ac63e269f4781a23b4385fb1ad16eb5d79ba7bcdc2fbeb81912ba7d6798cb41f95538dc0b39e89276e4c5a3f0eb1e3fad778c48ecb95f188ad9aabe6aab96acea979e63c6a9e398f9a675473519a335c4785f3bd14230006dcfaa08c7f2b705c7b32b5331ff5f7d87aaf4df8f718ce399cafbf37945999e39899e62d3ab25e6cd227f078681b62d6623ce74d7bbd36a561deb414f3891432abce6363b6b1ef483e7647d68b4dfa041e0f6d77306bc1d4ce703cb83388d698e2e5a00ee6e99d0cedcc405c3a36eddf09e7a11ce6132964569dc7c66c63df9578ece2f3e43136e913783cb4ddc5ac054f3b8be3c1dd41b4c6142f0775304fef66686706e2d2b169ff6e380fcaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaacccca2c9bd9c67e76e2b18bf3f7189bf4093c1eda9ecdac054f3b8bf3f7f704d11a53bc1cd4c1737e0f433b3310978e4dfbf7c0795066655666655666655666655666655666655666655666655666655666655666d9cc36f673928f1dfe1e0763933e81c743db7398b5606a67387f7f6f10ad31c5cb411d3ce7f732b4330371e9d8b47f2f9c076556e628661bfbb989c72eaee7616cd227f078687b2eb3163ced2c8e07f705d11a53bc1cd4c1737e1f433b3310978e4dfbf7c1792887f9440a995567d5398e5975569de3985567d5398e5975569de3985567d5398e5975569de3985567d5398e5975569de3985567d5398e5975ae1c9d6decfb138fdd1ecedf636cd227f07868bb9f590b9e7616e7ef1f08a235a67839a88379fa00433b3310978e4dfb14af12984fa4905973637c98353794398e59734399e398353794398e59734399e398353794398e59734399e398353794398e59734399e398353794398e59734399e398353794398e59734399e398353794398e59734399e39825e4868dfdbce46387bf67c7d8a44fe0f1d0f63c662d98da19defff26010ad31c5cb411dccd30719da9981b8746cda7f10ce83322b7314b38dfd50f2b10b592f36e913783cb43dc4ac05533bc3f1e0e1205a638a97833a78ce1f66686706e2d2b169ff61380f6963c6f397492e7678df26c5a872afd6f77c57ae06df0b5cb9067c2f74e55af0bdc895ebc0f762579e04be9740dbc8f752575e09be97b9f27af0bddc95d781ef15aedc0bbe57ba720ff85ee5ca43e07bb52bdf0ebed7b8f21de07bad2bdf09bed7b9f25de07bbd2bdf0dbe37b8f2b3c1f74657be077c6f72e5e780efcdae7c2ff8dee2cacf05df5b5df93ef0bdcd95ef07dfdb5df901f0bdc3959782ef9108df3b5df979e07b972b3f08be77bbf201f0bdc795a780efbdae3c157c7f01657a7d9f2bd783ef5157ce81effdae3c0d7c1f70e506f07dd095a783ef43aedc08be0fbbf20cf07dc4956782efa3ae3c0b7c1f73e526f07ddc956783ef13ae3c077c9f74e5b9e0fb942bcf03dfa75d793ef83ee3ca0bc0f759575e08becfb9f222f07dde951783ef0baebc047c5f74653cbf7fe9ca0f818fc69587c147e3caf3c147e3ca0bc047e3ca0bc147e3ca8bc047e3ca8bc147e3ca4bc04779f752f051debd0c7c94772f071fe5dd2bc04779f74af051debd0a7c9477af061fe5dd6bc04779f75af051debd0e7c9477af071fe5dd1bc04779f746f051debd097c94776f061fe5dd5bc04779f756f051debd0d7c94776f071fe5dd3bc04779f708f828efde093ecabb7781afd995df0dbe0b5cf93de0bbd095df0bbe8b5c19c7998b5df97de0bbc4951f051f8d85ef07df335cf903e05be6ca1f04df7257fe10f856b8f287c1b7d2953f02be55aefc51f0b5b8f2c7c0d7eaca1f07df6a57fe04f8f2aefc49f0b5b9f2a7c05770e54f83afdd953f03be0e57fe2cf83a5df973e0eb72e5cf83afdb95bf00be35aefc45f0d1f7388d33b63fdb7e493a9046d6476d6e8d680bf926435bfa8264afe928161d9bf6db8191ce4161fc190ba3656cf3182d4f2783669857b495fa9ba913783a187898da19fecdd4e5b5a9dd6b530eea3c03dad9c5d0ce0cc4a563d37e17c4e638e7a8459d3bee324f8b1aa853ebbed0ecf769291de918367f0b116de9616e0b1d9bc6a59e7188ddedc5ce7bb1713ca6ad54ffea06e6350cccf6b8bdc91f37ec5f6bddb128a7284e1edab40e3448aa4d183be38ce290bf06caf39b86eb523dd283bebf88dde6329d4b64f73fd7e97d2e07757a22dadf1724dbfe5e8fa7d763b6d7f40d4dc31c0cfd21cc811e8f83f6f3a05d6f8c763da01dd5c1efbf1626edd6783cb4df023c748dd3053eba56207ebcce6a1d076e7fdceb8ae0265f3730b644301692670caf755a3c46da2f0023f9d6004f379366feb95ee6e983dfcb93bc3af4d91aa8b31abe1bb311756dbf5b9a196e17fd0dfec720d931bd8e412f9c1f08409fc0d3903662981c0ccf2124c93335189e23383b3478a6ff9681cb07fa8f6400adc6c3c4d74c4433aac087e5ea085f108c9c0ac129599a0ac129d92a4f169c82a1faf64f29db2c9a6e1838797ce899a7064e1d3e73f7e9a181237b076f41ea5a8f1e49e35a80a4e8a36d72303c69d31724bb1853e7c52a953c93e17512bc4f75f24f6f6b636a67f8a537c56b539dd7a61cd4a985f7a630b4330371e9d8b43f252276820351a8c5d4516831358267ea386b8113dfe4c39e4aefe3e24995d716ecd1d8263fcf136d10055c0ac7cf3838fb9eedecb5ae319382e1934da3a7bda2b527c1ce98da6f2d3b236a6740ed10646738ed8ca6fd52b333967686d2ce48da19483be3686718ed8ca29d41b433867686b03928ce00da193f3bc36767f42e01b6af02affdabda7e43da19393b036767dcec9595bd02b05723f6eadb5e29dad90f7b8560ffb2b4b30cf6dbd65ec9d86f69fbcd6aaf14ed15a2bda2b757b876956a83b18d4eeb4dc6361bdb626cabb16dc6b61bdb616ca7b15dc6761bdb636cafb17dc6f61bbbd4d865417176fd72635718bbd2d8338d5d65ec6a63d718bbd6d875c6ae377683b11b8ddd64ec6663078df51b3b64ecb0b123c6068c1d35768bb163c68e1b7b96b15b83e21d3a278d9d323668ecb4b1db8c9d31763628ae98d91532bb226657c0ec8a975de1b22b5a7605cbae58d9152abb226557a0ee0f8a2b4c76a5c8ae0cd95501bb0a6067fded2cff0b83e22cbe9db57f49509c95b7b3f076d6ddceb2db59753b8b6e67cded2cb99d15b7b3e076d6dbce72db596d3b8b6d67aded2cb59d95b6b3d076d6d9ce323f12146791edacb19d25b6b3c27616d8cefada59de4783e22cae9db5b5b3b47656d6cec2da59573bcb6a6755ed2caa9d35b5b3a47656d4ce82da594f3bcb696735ed2ca69db5b4b3947656f24bc61e33f657c6fedad8df18fb5b637f67ecef8d7dd9d8578cfd83b17f34f64f41312fffd9d8bf18fb9ab17f35f66fc6be6eecdf8d7dc3d8378dfd87b16f197bdcd8b78d7dc7d8778d7dcfd8f78dfdc0d80f8dfdc8d87f1afbb1b19f18fba9b19f19fbb9b15f18fba5b15f19fbb5b1278c3d69ec37c67e6bec77c67e6feca96078750307913fb81d9a69ef1f1a1a38797aa87968b0f9e4ed27868e9f3e7177f39dc7878e350fde3170e6e889c13bf1c3ef73c3162d236c3a73a6ffeee6e3a78e0cdcd53c78fb50f3e0d1e64383b79f3a72163ff465f7a185e746ec3f72243ed8b7aa9e06e977c718f497ee73b440b3ab74db9e188b204f8de54333abc7d6a04bddb70efdf57e45f16ab7f9ec89c1a1e67cf329f36fff09f3998123adcdf8de5923f2d9a1e6b343fd67869a8f9e193cd9dcd68ac7bd76ca181a51d334860fb5368dbee5c1ff03c304b133250a0400", "privateFunctions": [ { "selector": { @@ -37,8 +37,8 @@ exports[`ContractClass creates a contract class from a contract compilation arti "isInternal": false } ], - "id": "0x2e00e9b3e778e864cfc790f18f232211f2bda1ee84aa5c4a05bf1b611d432483", + "id": "0x035bd6c2100ddfc79542bbeee9e8c506a3f17ee2f9dff1e25deff4a5277b5e68", "privateFunctionsRoot": "0x2dc1f38d7be98a8e72227d6f8aec393c60db813a1819c9c86b02a00cc18f6687", - "publicBytecodeCommitment": "0x008b8f64f2c814426b029f755f9fcf7320a4745cb014fdebcb30bdd6c5e64fb2" + "publicBytecodeCommitment": "0x19c6f3f069622a0e495b97bc2bc62989959e016b88acefecf98a2194ac1256b6" }" `; diff --git a/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap b/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap index a4c6a95fb82e..200b4dc53bcb 100644 --- a/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap +++ b/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap @@ -2,10 +2,10 @@ exports[`GasToken returns canonical protocol contract 1`] = ` { - "address": AztecAddress<0x0fbb005a23dac52e3c328b63834c2402ad4fb90e143cf73750af50f2a1e03646>, + "address": AztecAddress<0x2ced754038b131e7afe3f95263c4bf406403817dea3f2bbc45af5125a23df041>, "instance": { - "address": AztecAddress<0x0fbb005a23dac52e3c328b63834c2402ad4fb90e143cf73750af50f2a1e03646>, - "contractClassId": Fr<0x210658dedea30a0f6a675e0ad7e58d34b6c092c5248f81515391fbe3e1f38398>, + "address": AztecAddress<0x2ced754038b131e7afe3f95263c4bf406403817dea3f2bbc45af5125a23df041>, + "contractClassId": Fr<0x022f4fb4c9521c04fb71f2d1c221cf3f9a4fe7116f57e615cc8e878a91bf7de6>, "deployer": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, "initializationHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "portalContractAddress": EthAddress<0x0000000000000000000000000000000000000000>, @@ -19,10 +19,10 @@ exports[`GasToken returns canonical protocol contract 1`] = ` exports[`GasToken returns canonical protocol contract 2`] = ` { "artifactHash": Fr<0x18af4bb0ca6fe07d0ae6da493b2c7b1af038ee904721dbba9b6e571e6d495726>, - "id": Fr<0x210658dedea30a0f6a675e0ad7e58d34b6c092c5248f81515391fbe3e1f38398>, + "id": Fr<0x022f4fb4c9521c04fb71f2d1c221cf3f9a4fe7116f57e615cc8e878a91bf7de6>, "privateFunctions": [], "privateFunctionsRoot": Fr<0x15d28cad4c0736decea8997cb324cf0a0e0602f4d74472cd977bce2c8dd9923f>, - "publicBytecodeCommitment": Fr<0x01b2b2b29caee37af01f47a994f4182d3f456891d7f27b6f7eed0693934a05c5>, + "publicBytecodeCommitment": Fr<0x1626349ecd0025fad0d794b6c15423d679a77ef4319ac99cf98eec07b027c844>, "version": 1, } `;