From daef13e259e7c68d3fbc6341145506b46978ec4d Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Mon, 16 Dec 2024 13:45:45 -0700 Subject: [PATCH 1/3] feat: add event listeners --- Cargo.lock | 138 ++++ Cargo.toml | 14 + crates/blueprint-serde/CHANGELOG.md | 50 ++ crates/blueprint-serde/Cargo.toml | 28 + crates/blueprint-serde/src/de.rs | 344 ++++++++ crates/blueprint-serde/src/error.rs | 95 +++ crates/blueprint-serde/src/lib.rs | 149 ++++ crates/blueprint-serde/src/ser.rs | 351 ++++++++ crates/blueprint-serde/src/tests.rs | 764 ++++++++++++++++++ crates/contexts/src/tangle.rs | 8 +- crates/crypto/Cargo.toml | 3 + crates/crypto/tangle-pair-signer/Cargo.toml | 39 + crates/crypto/tangle-pair-signer/src/error.rs | 13 + crates/crypto/tangle-pair-signer/src/lib.rs | 4 + .../src/tangle_pair_signer.rs | 120 +++ crates/event-listeners/Cargo.toml | 24 + crates/event-listeners/core/Cargo.toml | 13 + .../core/src/exponential_backoff.rs | 128 +++ crates/event-listeners/core/src/lib.rs | 25 + crates/event-listeners/core/src/marker.rs | 7 + crates/event-listeners/core/src/testing.rs | 24 + crates/event-listeners/evm/Cargo.toml | 30 + crates/event-listeners/evm/src/contracts.rs | 119 +++ crates/event-listeners/evm/src/lib.rs | 13 + crates/event-listeners/periodic/Cargo.toml | 21 + crates/event-listeners/periodic/src/error.rs | 10 + crates/event-listeners/periodic/src/lib.rs | 2 + .../event-listeners/periodic/src/periodic.rs | 40 + crates/event-listeners/src/lib.rs | 14 + crates/event-listeners/tangle/Cargo.toml | 47 ++ crates/event-listeners/tangle/src/error.rs | 15 + crates/event-listeners/tangle/src/events.rs | 192 +++++ crates/event-listeners/tangle/src/lib.rs | 3 + crates/event-listeners/tangle/src/services.rs | 81 ++ crates/stores/Cargo.toml | 18 + crates/stores/local-database/Cargo.toml | 17 + crates/stores/local-database/src/lib.rs | 137 ++++ crates/stores/src/lib.rs | 2 + crates/utils/tangle/Cargo.toml | 12 +- crates/utils/tangle/src/lib.rs | 16 +- crates/utils/tangle/src/tx.rs | 51 ++ crates/utils/tangle/src/tx_progress.rs | 74 ++ 42 files changed, 3239 insertions(+), 16 deletions(-) create mode 100644 crates/blueprint-serde/CHANGELOG.md create mode 100644 crates/blueprint-serde/Cargo.toml create mode 100644 crates/blueprint-serde/src/de.rs create mode 100644 crates/blueprint-serde/src/error.rs create mode 100644 crates/blueprint-serde/src/lib.rs create mode 100644 crates/blueprint-serde/src/ser.rs create mode 100644 crates/blueprint-serde/src/tests.rs create mode 100644 crates/crypto/tangle-pair-signer/Cargo.toml create mode 100644 crates/crypto/tangle-pair-signer/src/error.rs create mode 100644 crates/crypto/tangle-pair-signer/src/lib.rs create mode 100644 crates/crypto/tangle-pair-signer/src/tangle_pair_signer.rs create mode 100644 crates/event-listeners/Cargo.toml create mode 100644 crates/event-listeners/core/Cargo.toml create mode 100644 crates/event-listeners/core/src/exponential_backoff.rs create mode 100644 crates/event-listeners/core/src/lib.rs create mode 100644 crates/event-listeners/core/src/marker.rs create mode 100644 crates/event-listeners/core/src/testing.rs create mode 100644 crates/event-listeners/evm/Cargo.toml create mode 100644 crates/event-listeners/evm/src/contracts.rs create mode 100644 crates/event-listeners/evm/src/lib.rs create mode 100644 crates/event-listeners/periodic/Cargo.toml create mode 100644 crates/event-listeners/periodic/src/error.rs create mode 100644 crates/event-listeners/periodic/src/lib.rs create mode 100644 crates/event-listeners/periodic/src/periodic.rs create mode 100644 crates/event-listeners/src/lib.rs create mode 100644 crates/event-listeners/tangle/Cargo.toml create mode 100644 crates/event-listeners/tangle/src/error.rs create mode 100644 crates/event-listeners/tangle/src/events.rs create mode 100644 crates/event-listeners/tangle/src/lib.rs create mode 100644 crates/event-listeners/tangle/src/services.rs create mode 100644 crates/stores/Cargo.toml create mode 100644 crates/stores/local-database/Cargo.toml create mode 100644 crates/stores/local-database/src/lib.rs create mode 100644 crates/stores/src/lib.rs create mode 100644 crates/utils/tangle/src/tx.rs create mode 100644 crates/utils/tangle/src/tx_progress.rs diff --git a/Cargo.lock b/Cargo.lock index 98c9193..969ed33 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4803,6 +4803,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "gadget-blueprint-serde" +version = "0.3.1" +dependencies = [ + "paste", + "serde", + "serde_bytes", + "serde_test", + "tangle-subxt", +] + [[package]] name = "gadget-client-eigenlayer" version = "0.1.0" @@ -4937,6 +4948,7 @@ dependencies = [ "gadget-crypto-k256", "gadget-crypto-sp-core", "gadget-crypto-sr25519", + "gadget-crypto-tangle-pair-signer", "sha2 0.10.8", "sha3", "thiserror 2.0.7", @@ -5036,6 +5048,25 @@ dependencies = [ "thiserror 2.0.7", ] +[[package]] +name = "gadget-crypto-tangle-pair-signer" +version = "0.1.0" +dependencies = [ + "alloy-primitives", + "alloy-signer-local", + "gadget-crypto-core", + "gadget-crypto-sp-core", + "gadget-std", + "k256", + "paste", + "serde", + "serde_json", + "sp-core 31.0.0", + "subxt", + "subxt-core", + "thiserror 2.0.7", +] + [[package]] name = "gadget-eigenlayer-bindings" version = "0.1.0" @@ -5059,6 +5090,81 @@ dependencies = [ "serde", ] +[[package]] +name = "gadget-event-listeners" +version = "0.1.0" +dependencies = [ + "gadget-event-listeners-core", + "gadget-event-listeners-evm", + "gadget-event-listeners-periodic", + "gadget-event-listeners-tangle", + "gadget-std", +] + +[[package]] +name = "gadget-event-listeners-core" +version = "0.1.0" +dependencies = [ + "async-trait", + "gadget-std", +] + +[[package]] +name = "gadget-event-listeners-evm" +version = "0.1.0" +dependencies = [ + "alloy-contract", + "alloy-network 0.5.4", + "alloy-provider", + "alloy-rpc-types", + "alloy-sol-types", + "alloy-transport", + "async-trait", + "gadget-event-listeners-core", + "gadget-logging", + "gadget-std", + "gadget-stores", + "thiserror 2.0.7", + "tokio", + "uuid 1.11.0", +] + +[[package]] +name = "gadget-event-listeners-periodic" +version = "0.1.0" +dependencies = [ + "async-trait", + "gadget-event-listeners-core", + "gadget-logging", + "gadget-std", + "thiserror 2.0.7", + "tokio", +] + +[[package]] +name = "gadget-event-listeners-tangle" +version = "0.1.0" +dependencies = [ + "async-trait", + "gadget-blueprint-serde", + "gadget-clients", + "gadget-contexts", + "gadget-crypto-tangle-pair-signer", + "gadget-event-listeners-core", + "gadget-keystore", + "gadget-logging", + "gadget-std", + "gadget-utils-tangle", + "parking_lot", + "serde", + "sp-core 31.0.0", + "subxt", + "subxt-core", + "tangle-subxt", + "thiserror 2.0.7", + "tokio", +] + [[package]] name = "gadget-keystore" version = "0.1.0" @@ -5159,6 +5265,22 @@ dependencies = [ "thiserror 2.0.7", ] +[[package]] +name = "gadget-store-local-database" +version = "0.1.0" +dependencies = [ + "gadget-std", + "serde", + "serde_json", +] + +[[package]] +name = "gadget-stores" +version = "0.1.0" +dependencies = [ + "gadget-store-local-database", +] + [[package]] name = "gadget-testing-utils" version = "0.1.0" @@ -5215,6 +5337,13 @@ dependencies = [ [[package]] name = "gadget-utils-tangle" version = "0.1.0" +dependencies = [ + "async-trait", + "gadget-logging", + "gadget-std", + "subxt", + "tracing", +] [[package]] name = "gcloud-sdk" @@ -9988,6 +10117,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_test" +version = "1.0.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f901ee573cab6b3060453d2d5f0bae4e6d628c23c0a962ff9b5f1d7c8d4f1ed" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" diff --git a/Cargo.toml b/Cargo.toml index 187cef5..6d5856c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ gadget-crypto-bls = { version = "0.1.0", path = "./crates/crypto/bls", default-f gadget-crypto-bn254 = { version = "0.1.0", path = "./crates/crypto/bn254", default-features = false } gadget-crypto-sp-core = { version = "0.1.0", path = "./crates/crypto/sp-core", default-features = false } gadget-crypto = { version = "0.1.0", path = "./crates/crypto", default-features = false } +gadget-crypto-tangle-pair-signer = { version = "0.1.0", path = "./crates/crypto/tangle-pair-signer", default-features = false } # Clients gadget-clients = { version = "0.1.0", path = "./crates/clients", default-features = false } @@ -44,8 +45,21 @@ gadget-client-eigenlayer = { version = "0.1.0", path = "./crates/clients/eigenla gadget-client-evm = { version = "0.1.0", path = "./crates/clients/evm", default-features = false } gadget-client-networking = { version = "0.1.0", path = "./crates/clients/networking", default-features = false } gadget-client-tangle = { version = "0.1.0", path = "./crates/clients/tangle", default-features = false } +gadget-contexts = { version = "0.1.0", path = "./crates/contexts", default-features = false } + +# Event listeners +gadget-event-listeners = { version = "0.1.0", path = "./crates/event-listeners", default-features = false } +gadget-event-listeners-core = { version = "0.1.0", path = "./crates/event-listeners/core", default-features = false } +gadget-event-listeners-evm = { version = "0.1.0", path = "./crates/event-listeners/evm", default-features = false } +gadget-event-listeners-periodic = { version = "0.1.0", path = "./crates/event-listeners/periodic", default-features = false } +gadget-event-listeners-tangle = { version = "0.1.0", path = "./crates/event-listeners/tangle", default-features = false } + +# Stores +gadget-stores = { version = "0.1.0", path = "./crates/stores", default-features = false } +gadget-store-local-database = { version = "0.1.0", path = "./crates/stores/local-database", default-features = false } # SDK +gadget-blueprint-serde = { version = "0.3.1", path = "./crates/blueprint-serde", default-features = false } gadget-config = { version = "0.1.0", path = "./crates/config", default-features = false } gadget-keystore = { version = "0.1.0", path = "./crates/keystore", default-features = false } gadget-logging = { version = "0.1.0", path = "./crates/logging", default-features = false } diff --git a/crates/blueprint-serde/CHANGELOG.md b/crates/blueprint-serde/CHANGELOG.md new file mode 100644 index 0000000..3639074 --- /dev/null +++ b/crates/blueprint-serde/CHANGELOG.md @@ -0,0 +1,50 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.3.1](https://github.com/tangle-network/gadget/compare/gadget-blueprint-serde-v0.3.0...gadget-blueprint-serde-v0.3.1) - 2024-12-11 + +### Other + +- update Cargo.toml dependencies + +## [0.3.0](https://github.com/tangle-network/gadget/compare/gadget-blueprint-serde-v0.2.0...gadget-blueprint-serde-v0.3.0) - 2024-11-29 + +### Fixed + +- *(gadget-blueprint-serde)* [**breaking**] handle bytes properly ([#500](https://github.com/tangle-network/gadget/pull/500)) + +## [0.2.0](https://github.com/tangle-network/gadget/compare/gadget-blueprint-serde-v0.1.1...gadget-blueprint-serde-v0.2.0) - 2024-11-16 + +### Added + +- *(gadget-blueprint-serde)* [**breaking**] change array/tuple serialization + +### Other + +- clippy + +## [0.1.1](https://github.com/tangle-network/gadget/compare/gadget-blueprint-serde-v0.1.0...gadget-blueprint-serde-v0.1.1) - 2024-11-08 + +### Added + +- *(gadget-blueprint-serde)* add crate docs ([#459](https://github.com/tangle-network/gadget/pull/459)) + +### Other + +- release ([#410](https://github.com/tangle-network/gadget/pull/410)) + +## [0.1.0](https://github.com/tangle-network/gadget/releases/tag/gadget-blueprint-serde-v0.1.0) - 2024-11-05 + +### Added + +- `blueprint-serde` crate ([#429](https://github.com/tangle-network/gadget/pull/429)) + +### Other + +- add description to crates ([#444](https://github.com/tangle-network/gadget/pull/444)) diff --git a/crates/blueprint-serde/Cargo.toml b/crates/blueprint-serde/Cargo.toml new file mode 100644 index 0000000..1ab9c64 --- /dev/null +++ b/crates/blueprint-serde/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "gadget-blueprint-serde" +version = "0.3.1" +description = "Tangle Blueprints serde integration" +authors.workspace = true +edition.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true + +[dependencies] +paste.workspace = true +serde.workspace = true +serde_bytes = { workspace = true, features = ["alloc"] } +tangle-subxt.workspace = true + +[dev-dependencies] +serde_test.workspace = true + +[lints] +workspace = true + +[features] +default = ["std"] +std = [ + "serde/std", + "serde_bytes/std" +] diff --git a/crates/blueprint-serde/src/de.rs b/crates/blueprint-serde/src/de.rs new file mode 100644 index 0000000..ffbd6cd --- /dev/null +++ b/crates/blueprint-serde/src/de.rs @@ -0,0 +1,344 @@ +use crate::error::{Error, Result, UnsupportedType}; +use crate::Field; +use alloc::collections::BTreeMap; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; +use serde::de::IntoDeserializer; +use serde::{de, forward_to_deserialize_any}; +use tangle_subxt::subxt_core::utils::AccountId32; +use tangle_subxt::tangle_testnet_runtime::api::runtime_types::bounded_collections::bounded_vec::BoundedVec; +use tangle_subxt::tangle_testnet_runtime::api::runtime_types::tangle_primitives::services::field::BoundedString; + +/// A deserializer for [`Field`] +/// +/// This is simply a wrapper over an owned `Field`, since it's an external type. +/// +/// See [`crate::from_field`]. +pub struct Deserializer(pub(crate) Field); + +impl<'de> de::Deserializer<'de> for Deserializer { + type Error = Error; + + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.0 { + Field::None => visitor.visit_none(), + Field::Bool(b) => visitor.visit_bool(b), + Field::Uint8(u) => visitor.visit_u8(u), + Field::Int8(i) => visitor.visit_i8(i), + Field::Uint16(u) => visitor.visit_u16(u), + Field::Int16(i) => visitor.visit_i16(i), + Field::Uint32(u) => visitor.visit_u32(u), + Field::Int32(i) => visitor.visit_i32(i), + Field::Uint64(u) => visitor.visit_u64(u), + Field::Int64(i) => visitor.visit_i64(i), + Field::String(s) => { + let s = String::from_utf8(s.0 .0)?; + visitor.visit_string(s) + } + Field::Bytes(b) => { + // Unless `deserialize_bytes` is explicitly called, assume a sequence is desired + de::value::SeqDeserializer::new(b.0.into_iter()).deserialize_any(visitor) + } + Field::Array(seq) | Field::List(seq) => visit_seq(seq.0, visitor), + Field::Struct(_, fields) => visit_struct(*fields, visitor), + Field::AccountId(a) => visitor.visit_string(a.to_string()), + } + } + + fn deserialize_f32(self, _visitor: V) -> Result + where + V: de::Visitor<'de>, + { + Err(Error::UnsupportedType(UnsupportedType::f32)) + } + + fn deserialize_f64(self, _visitor: V) -> Result + where + V: de::Visitor<'de>, + { + Err(Error::UnsupportedType(UnsupportedType::f64)) + } + + fn deserialize_char(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + let string; + match self.0 { + Field::String(bound_string) => string = String::from_utf8(bound_string.0 .0)?, + _ => return Err(self.invalid_type(&visitor)), + }; + + let mut chars = string.chars(); + let Some(ch) = chars.next() else { + return Err(Error::BadCharLength(0)); + }; + + if chars.next().is_some() { + return Err(Error::BadCharLength(chars.count().saturating_add(2))); + } + + visitor.visit_char(ch) + } + + fn deserialize_str(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_string(visitor) + } + + fn deserialize_option(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.0 { + Field::None => visitor.visit_none(), + _ => visitor.visit_some(self), + } + } + + fn deserialize_unit(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.0 { + Field::None => visitor.visit_unit(), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_unit_struct(self, _name: &'static str, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.deserialize_unit(visitor) + } + + fn deserialize_newtype_struct(self, _name: &'static str, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + fn deserialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + match self.0 { + Field::Struct(_, fields) => { + let mut values = Vec::with_capacity(fields.0.len()); + for (_, field) in fields.0 { + values.push(field); + } + + visit_seq(values, visitor) + } + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_map(self, _visitor: V) -> Result + where + V: de::Visitor<'de>, + { + Err(Error::UnsupportedType(UnsupportedType::Map)) + } + + fn deserialize_enum( + self, + _name: &'static str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + // Only accept unit variants + match self.0 { + Field::String(bound_string) => { + visitor.visit_enum(String::from_utf8(bound_string.0 .0)?.into_deserializer()) + } + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_ignored_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + drop(self); + visitor.visit_unit() + } + + forward_to_deserialize_any! { + bool u8 u16 u32 u64 i8 i16 i32 i64 string + bytes byte_buf seq struct identifier tuple + } +} + +impl Deserializer { + #[cold] + fn invalid_type(&self, exp: &dyn de::Expected) -> E + where + E: de::Error, + { + de::Error::invalid_type(self.unexpected(), exp) + } + + #[cold] + fn unexpected(&self) -> de::Unexpected<'_> { + match &self.0 { + Field::None => de::Unexpected::Unit, + Field::Bool(b) => de::Unexpected::Bool(*b), + + Field::Uint8(u) => de::Unexpected::Unsigned(u64::from(*u)), + Field::Uint16(u) => de::Unexpected::Unsigned(u64::from(*u)), + Field::Uint32(u) => de::Unexpected::Unsigned(u64::from(*u)), + Field::Uint64(u) => de::Unexpected::Unsigned(*u), + + Field::Int8(i) => de::Unexpected::Signed(i64::from(*i)), + Field::Int16(i) => de::Unexpected::Signed(i64::from(*i)), + Field::Int32(i) => de::Unexpected::Signed(i64::from(*i)), + Field::Int64(i) => de::Unexpected::Signed(*i), + + Field::String(s) => de::Unexpected::Str(core::str::from_utf8(&s.0 .0).unwrap_or("")), + Field::Bytes(b) => de::Unexpected::Bytes(b.0.as_slice()), + Field::Array(_) | Field::List(_) => de::Unexpected::Seq, + Field::Struct(_, _) => de::Unexpected::Other("Struct"), + Field::AccountId(_) => de::Unexpected::Other("AccountId"), + } + } +} + +struct StructDeserializer { + iter: > as IntoIterator>::IntoIter, + field: Option>, +} + +impl StructDeserializer { + fn new(map: BTreeMap>) -> Self { + StructDeserializer { + iter: map.into_iter(), + field: None, + } + } +} + +impl<'de> de::MapAccess<'de> for StructDeserializer { + type Error = Error; + + fn next_key_seed(&mut self, seed: K) -> Result> + where + K: de::DeserializeSeed<'de>, + { + match self.iter.next() { + Some((key, field)) => { + self.field = Some(field); + seed.deserialize(key.into_deserializer()).map(Some) + } + None => Ok(None), + } + } + + fn next_value_seed(&mut self, seed: V) -> Result + where + V: de::DeserializeSeed<'de>, + { + match self.field.take() { + Some(field) => seed.deserialize(Deserializer(field)), + None => Err(serde::de::Error::custom("value is missing")), + } + } + + fn size_hint(&self) -> Option { + match self.iter.size_hint() { + (lower, Some(upper)) if lower == upper => Some(upper), + _ => None, + } + } +} + +fn visit_struct<'de, V>( + serialized_fields: BoundedVec<(BoundedString, Field)>, + visitor: V, +) -> Result +where + V: de::Visitor<'de>, +{ + let mut fields = BTreeMap::new(); + for (name, value) in serialized_fields.0 { + let name = String::from_utf8(name.0 .0)?; + fields.insert(name, value); + } + + let len = fields.len(); + let mut de = StructDeserializer::new(fields); + let seq = visitor.visit_map(&mut de)?; + let remaining = de.iter.len(); + if remaining == 0 { + Ok(seq) + } else { + Err(de::Error::invalid_length(len, &"fewer elements in struct")) + } +} + +struct SeqDeserializer { + iter: alloc::vec::IntoIter>, +} + +impl SeqDeserializer { + fn new(vec: Vec>) -> Self { + SeqDeserializer { + iter: vec.into_iter(), + } + } +} + +impl<'de> de::SeqAccess<'de> for SeqDeserializer { + type Error = Error; + + fn next_element_seed(&mut self, seed: T) -> Result> + where + T: de::DeserializeSeed<'de>, + { + match self.iter.next() { + Some(field) => seed.deserialize(Deserializer(field)).map(Some), + None => Ok(None), + } + } + + fn size_hint(&self) -> Option { + match self.iter.size_hint() { + (lower, Some(upper)) if lower == upper => Some(upper), + _ => None, + } + } +} + +fn visit_seq<'de, V>(seq: Vec>, visitor: V) -> Result +where + V: de::Visitor<'de>, +{ + let len = seq.len(); + let mut de = SeqDeserializer::new(seq); + let seq = visitor.visit_seq(&mut de)?; + let remaining = de.iter.len(); + if remaining == 0 { + Ok(seq) + } else { + Err(de::Error::invalid_length( + len, + &"fewer elements in sequence", + )) + } +} diff --git a/crates/blueprint-serde/src/error.rs b/crates/blueprint-serde/src/error.rs new file mode 100644 index 0000000..943ddfa --- /dev/null +++ b/crates/blueprint-serde/src/error.rs @@ -0,0 +1,95 @@ +use alloc::string::{String, ToString}; +use core::fmt::Display; +use core::fmt::Formatter; +use serde::{de, ser}; + +pub type Result = core::result::Result; + +/// Types that cannot be represented as a [`Field`](crate::Field) +/// +/// Attempting to de/serialize any of these types will cause an error. +#[derive(Debug)] +#[allow(non_camel_case_types)] +pub enum UnsupportedType { + f32, + f64, + Map, + /// Any enum that is not a simple unit enum + /// + /// ## Valid + /// + /// ```rust + /// enum Foo { + /// Bar, + /// Baz, + /// } + /// ``` + /// + /// ## Invalid + /// + /// ```rust + /// enum Foo { + /// Bar(String), + /// } + /// ``` + /// + /// Or + /// + /// ```rust + /// enum Foo { + /// Baz { a: String }, + /// } + /// ``` + NonUnitEnum, +} + +#[derive(Debug)] +pub enum Error { + UnsupportedType(UnsupportedType), + /// Attempting to deserialize a [`char`] from a [`Field::String`](crate::Field::String) + BadCharLength(usize), + HeterogeneousTuple, + FromUtf8Error(alloc::string::FromUtf8Error), + Other(String), +} + +impl ser::Error for Error { + fn custom(msg: T) -> Self { + Error::Other(msg.to_string()) + } +} + +impl de::Error for Error { + fn custom(msg: T) -> Self { + Error::Other(msg.to_string()) + } +} + +impl From for Error { + fn from(err: alloc::string::FromUtf8Error) -> Self { + Error::FromUtf8Error(err) + } +} + +impl Display for Error { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + Error::UnsupportedType(unsupported_type) => { + write!(f, "Type `{:?}` unsupported", unsupported_type) + } + Error::BadCharLength(len) => { + write!(f, "String contains {len} characters, expected 1") + } + Error::HeterogeneousTuple => { + write!( + f, + "Attempted to serialize heterogeneous tuple, not currently supported" + ) + } + Error::FromUtf8Error(e) => write!(f, "{e}"), + Error::Other(msg) => write!(f, "{}", msg), + } + } +} + +impl core::error::Error for Error {} diff --git a/crates/blueprint-serde/src/lib.rs b/crates/blueprint-serde/src/lib.rs new file mode 100644 index 0000000..53270c8 --- /dev/null +++ b/crates/blueprint-serde/src/lib.rs @@ -0,0 +1,149 @@ +//! Compatibility crate for using the [Serde](https://docs.rs/serde) serialization frame with data from [`tangle_subxt`](https://docs.rs/tangle_subxt) +//! +//! This crate provides two primary functions: +//! +//! * [`to_field`] - Convert a [`Serialize`] type to a [`Field`] +//! * [`from_field`] - Convert a [`Field`] to a [`DeserializeOwned`] type +//! +//! # Examples +//! +//! ```rust +//! use gadget_blueprint_serde::{new_bounded_string, BoundedVec, Field}; +//! use serde::{Deserialize, Serialize}; +//! +//! #[derive(PartialEq, Debug, Serialize, Deserialize)] +//! struct Person { +//! name: String, +//! age: u8, +//! } +//! +//! let person = Person { +//! name: String::from("John"), +//! age: 40, +//! }; +//! +//! let expected = Field::Struct( +//! new_bounded_string("Person"), +//! Box::new(BoundedVec(vec![ +//! ( +//! new_bounded_string("name"), +//! Field::String(new_bounded_string("John")), +//! ), +//! (new_bounded_string("age"), Field::Uint8(40)), +//! ])), +//! ); +//! +//! // Convert our `Serialize` type to a `tangle_subxt::Field` +//! let field = gadget_blueprint_serde::to_field(&person).unwrap(); +//! assert_eq!(expected, field); +//! +//! // Convert our `tangle_subxt::Field` back to a `Person` +//! let person_deserialized: Person = gadget_blueprint_serde::from_field(field).unwrap(); +//! assert_eq!(person, person_deserialized); +//! ``` + +#![cfg_attr(feature = "std", no_std)] + +mod de; +pub mod error; +mod ser; +#[cfg(test)] +mod tests; + +extern crate alloc; + +use serde::Serialize; +use serde::de::DeserializeOwned; +use tangle_subxt::subxt_core::utils::AccountId32; +pub use tangle_subxt::tangle_testnet_runtime::api::runtime_types::tangle_primitives::services::field::Field; +pub use tangle_subxt::tangle_testnet_runtime::api::runtime_types::bounded_collections::bounded_vec::BoundedVec; +pub use ser::new_bounded_string; +pub use serde_bytes::ByteBuf; +use error::Result; + +/// Derive a [`Field`] from an instance of type `S` +/// +/// # Errors +/// +/// * Attempting to serialize an [`UnsupportedType`](error::UnsupportedType) +/// +/// # Examples +/// +/// ```rust +/// use gadget_blueprint_serde::{new_bounded_string, BoundedVec, Field}; +/// use serde::Serialize; +/// +/// #[derive(Serialize)] +/// struct Person { +/// name: String, +/// age: u8, +/// } +/// +/// let person = Person { +/// name: String::from("John"), +/// age: 40, +/// }; +/// +/// let expected = Field::Struct( +/// new_bounded_string("Person"), +/// Box::new(BoundedVec(vec![ +/// ( +/// new_bounded_string("name"), +/// Field::String(new_bounded_string("John")), +/// ), +/// (new_bounded_string("age"), Field::Uint8(40)), +/// ])), +/// ); +/// +/// let field = gadget_blueprint_serde::to_field(person).unwrap(); +/// assert_eq!(expected, field); +/// ``` +pub fn to_field(value: S) -> Result> +where + S: Serialize, +{ + let mut ser = ser::Serializer; + value.serialize(&mut ser) +} + +/// Derive an instance of type `D` from a [`Field`] +/// +/// # Errors +/// +/// * Attempting to deserialize an [`UnsupportedType`](error::UnsupportedType) +/// * Attempting to deserialize non UTF-8 bytes into a [`String`](alloc::string::String) +/// * Any type mismatch (e.g. attempting to deserialize [`Field::Int8`] into a [`char`]). +/// +/// # Examples +/// +/// ```rust +/// use gadget_blueprint_serde::{new_bounded_string, BoundedVec, Field}; +/// use serde::Deserialize; +/// +/// #[derive(Deserialize, Debug)] +/// struct Person { +/// name: String, +/// age: u8, +/// } +/// +/// let field = Field::Struct( +/// new_bounded_string("Person"), +/// Box::new(BoundedVec(vec![ +/// ( +/// new_bounded_string("name"), +/// Field::String(new_bounded_string("John")), +/// ), +/// (new_bounded_string("age"), Field::Uint8(40)), +/// ])), +/// ); +/// +/// let person: Person = gadget_blueprint_serde::from_field(field).unwrap(); +/// println!("{:#?}", person); +/// ``` +pub fn from_field(field: Field) -> Result +where + D: DeserializeOwned, +{ + let de = de::Deserializer(field); + D::deserialize(de) +} diff --git a/crates/blueprint-serde/src/ser.rs b/crates/blueprint-serde/src/ser.rs new file mode 100644 index 0000000..5099b3d --- /dev/null +++ b/crates/blueprint-serde/src/ser.rs @@ -0,0 +1,351 @@ +use crate::error::{Result, UnsupportedType}; +use crate::Field; +use alloc::boxed::Box; +use alloc::format; +use alloc::string::String; +use alloc::vec::Vec; +use serde::ser; +use serde::Serialize; +use tangle_subxt::subxt_core::utils::AccountId32; +use tangle_subxt::tangle_testnet_runtime::api::runtime_types::bounded_collections::bounded_vec::BoundedVec; +use tangle_subxt::tangle_testnet_runtime::api::runtime_types::tangle_primitives::services::field::BoundedString; + +/// A serializer for [`Field`] +/// +/// See [`crate::into_field`]. +pub struct Serializer; + +impl<'a> serde::Serializer for &'a mut Serializer { + type Ok = Field; + type Error = crate::error::Error; + type SerializeSeq = SerializeSeq<'a>; + type SerializeTuple = Self::SerializeSeq; + type SerializeTupleStruct = SerializeTupleStruct<'a>; + type SerializeTupleVariant = ser::Impossible; + type SerializeMap = ser::Impossible; + type SerializeStruct = SerializeStruct<'a>; + type SerializeStructVariant = ser::Impossible; + + fn serialize_bool(self, v: bool) -> Result { + Ok(Field::Bool(v)) + } + + fn serialize_i8(self, v: i8) -> Result { + Ok(Field::Int8(v)) + } + + fn serialize_i16(self, v: i16) -> Result { + Ok(Field::Int16(v)) + } + + fn serialize_i32(self, v: i32) -> Result { + Ok(Field::Int32(v)) + } + + fn serialize_i64(self, v: i64) -> Result { + Ok(Field::Int64(v)) + } + + fn serialize_u8(self, v: u8) -> Result { + Ok(Field::Uint8(v)) + } + + fn serialize_u16(self, v: u16) -> Result { + Ok(Field::Uint16(v)) + } + + fn serialize_u32(self, v: u32) -> Result { + Ok(Field::Uint32(v)) + } + + fn serialize_u64(self, v: u64) -> Result { + Ok(Field::Uint64(v)) + } + + fn serialize_f32(self, _v: f32) -> Result { + Err(Self::Error::UnsupportedType(UnsupportedType::f32)) + } + + fn serialize_f64(self, _v: f64) -> Result { + Err(Self::Error::UnsupportedType(UnsupportedType::f64)) + } + + fn serialize_char(self, v: char) -> Result { + Ok(Field::String(new_bounded_string(v))) + } + + fn serialize_str(self, v: &str) -> Result { + Ok(Field::String(new_bounded_string(v))) + } + + fn serialize_bytes(self, v: &[u8]) -> Result { + Ok(Field::Bytes(BoundedVec(v.into()))) + } + + fn serialize_none(self) -> Result { + self.serialize_unit() + } + + fn serialize_some(self, value: &T) -> Result + where + T: ?Sized + Serialize, + { + value.serialize(self) + } + + fn serialize_unit(self) -> Result { + Ok(Field::None) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result { + self.serialize_unit() + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result { + Ok(Field::String(new_bounded_string(variant))) + } + + fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result + where + T: ?Sized + Serialize, + { + value.serialize(self) + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _value: &T, + ) -> Result + where + T: ?Sized + Serialize, + { + Err(Self::Error::UnsupportedType(UnsupportedType::NonUnitEnum)) + } + + fn serialize_seq(self, len: Option) -> Result { + let vec; + match len { + Some(len) => vec = Vec::with_capacity(len), + None => vec = Vec::new(), + } + + Ok(SerializeSeq { ser: self, vec }) + } + + fn serialize_tuple(self, len: usize) -> Result { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_struct( + self, + name: &'static str, + len: usize, + ) -> Result { + let ser = SerializeTupleStruct { + ser: self, + name, + fields: Vec::with_capacity(len), + }; + Ok(ser) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Err(Self::Error::UnsupportedType(UnsupportedType::NonUnitEnum)) + } + + fn serialize_map(self, _len: Option) -> Result { + Err(Self::Error::UnsupportedType(UnsupportedType::Map)) + } + + fn serialize_struct(self, name: &'static str, len: usize) -> Result { + let ser = SerializeStruct { + ser: self, + name, + fields: Vec::with_capacity(len), + }; + Ok(ser) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Err(Self::Error::UnsupportedType(UnsupportedType::NonUnitEnum)) + } + + fn is_human_readable(&self) -> bool { + false + } +} + +pub struct SerializeSeq<'a> { + ser: &'a mut Serializer, + vec: Vec>, +} + +impl SerializeSeq<'_> { + fn is_homogeneous(&self) -> bool { + if self.vec.is_empty() { + return true; + } + + macro_rules! homogeneous_check { + ($($field:pat),+ $(,)?) => { + paste::paste! { + match &self.vec[0] { + $($field => { self.vec.iter().all(|f| matches!(f, $field)) },)+ + Field::Struct(name, fields) => { + self.vec.iter().all(|f| { + match f { + Field::Struct(n, f) => { + n == name && fields == f + }, + _ => false, + } + }) + } + } + } + } + } + + homogeneous_check!( + Field::None, + Field::Bool(_), + Field::Uint8(_), + Field::Int8(_), + Field::Uint16(_), + Field::Int16(_), + Field::Uint32(_), + Field::Int32(_), + Field::Uint64(_), + Field::Int64(_), + Field::String(_), + Field::Bytes(_), + Field::Array(_), + Field::List(_), + Field::AccountId(_), + ) + } +} + +impl ser::SerializeSeq for SerializeSeq<'_> { + type Ok = Field; + type Error = crate::error::Error; + + fn serialize_element(&mut self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + let value = value.serialize(&mut *self.ser)?; + self.vec.push(value); + Ok(()) + } + + fn end(self) -> Result { + Ok(Field::List(BoundedVec(self.vec))) + } +} + +impl ser::SerializeTuple for SerializeSeq<'_> { + type Ok = Field; + type Error = crate::error::Error; + + #[inline] + fn serialize_element(&mut self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + as ser::SerializeSeq>::serialize_element(self, value) + } + + #[inline] + fn end(self) -> Result { + if self.is_homogeneous() { + return Ok(Field::Array(BoundedVec(self.vec))); + } + + Err(crate::error::Error::HeterogeneousTuple) + } +} + +pub struct SerializeTupleStruct<'a> { + ser: &'a mut Serializer, + name: &'a str, + fields: Vec<(BoundedString, Field)>, +} + +impl ser::SerializeTupleStruct for SerializeTupleStruct<'_> { + type Ok = Field; + type Error = crate::error::Error; + + fn serialize_field(&mut self, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + let field_value = value.serialize(&mut *self.ser)?; + let field_name = format!("field_{}", self.fields.len()); + self.fields + .push((new_bounded_string(field_name), field_value)); + Ok(()) + } + + fn end(self) -> Result { + Ok(Field::Struct( + new_bounded_string(self.name), + Box::new(BoundedVec(self.fields)), + )) + } +} + +pub struct SerializeStruct<'a> { + ser: &'a mut Serializer, + name: &'a str, + fields: Vec<(BoundedString, Field)>, +} + +impl ser::SerializeStruct for SerializeStruct<'_> { + type Ok = Field; + type Error = crate::error::Error; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> + where + T: ?Sized + Serialize, + { + let field_value = value.serialize(&mut *self.ser)?; + self.fields.push((new_bounded_string(key), field_value)); + Ok(()) + } + + fn end(self) -> Result { + Ok(Field::Struct( + new_bounded_string(self.name), + Box::new(BoundedVec(self.fields)), + )) + } +} + +pub fn new_bounded_string(s: S) -> BoundedString +where + S: Into, +{ + let s = s.into(); + BoundedString(BoundedVec(s.into_bytes())) +} diff --git a/crates/blueprint-serde/src/tests.rs b/crates/blueprint-serde/src/tests.rs new file mode 100644 index 0000000..200c01f --- /dev/null +++ b/crates/blueprint-serde/src/tests.rs @@ -0,0 +1,764 @@ +use crate::from_field; +use crate::ser::new_bounded_string; +use crate::to_field; +use crate::Field; +use alloc::boxed::Box; +use alloc::string::String; +use alloc::vec; +use serde::{Deserialize, Serialize}; +use serde_test::{assert_de_tokens, assert_ser_tokens, Token}; +use tangle_subxt::subxt_core::utils::AccountId32; +use tangle_subxt::tangle_testnet_runtime::api::runtime_types::bounded_collections::bounded_vec::BoundedVec; + +mod structs { + use super::*; + + #[derive(Serialize, Deserialize, Debug, PartialEq)] + struct Person { + name: String, + age: u8, + } + + impl Default for Person { + fn default() -> Self { + Person { + name: String::from("John"), + age: 40, + } + } + } + + impl Person { + fn as_field(&self) -> Field { + let struct_fields = vec![ + ( + new_bounded_string("name"), + Field::String(new_bounded_string(&self.name)), + ), + (new_bounded_string("age"), Field::Uint8(self.age)), + ]; + + Field::Struct( + new_bounded_string("Person"), + Box::new(BoundedVec(struct_fields)), + ) + } + } + + #[test] + fn test_ser_struct_valid() { + let person = Person::default(); + + assert_ser_tokens( + &person, + &[ + Token::Struct { + name: "Person", + len: 2, + }, + Token::Str("name"), + Token::Str("John"), + Token::Str("age"), + Token::U8(40), + Token::StructEnd, + ], + ); + + let field = to_field(&person).unwrap(); + assert_eq!(field, person.as_field()); + } + + #[test] + fn test_de_struct_valid() { + let person = Person::default(); + + assert_de_tokens( + &person, + &[ + Token::Struct { + name: "Person", + len: 2, + }, + Token::Str("name"), + Token::Str("John"), + Token::Str("age"), + Token::U8(40), + Token::StructEnd, + ], + ); + + let person_de: Person = from_field(person.as_field()).unwrap(); + assert_eq!(person_de, person); + } + + #[derive(Serialize, Deserialize, Debug, PartialEq)] + struct PersonWithFriend { + name: String, + age: u8, + friend: Person, + } + + impl Default for PersonWithFriend { + fn default() -> Self { + PersonWithFriend { + name: String::from("Matthew"), + age: 37, + friend: Person::default(), + } + } + } + + impl PersonWithFriend { + fn as_field(&self) -> Field { + let friend_fields = vec![ + ( + new_bounded_string("name"), + Field::String(new_bounded_string(Person::default().name)), + ), + ( + new_bounded_string("age"), + Field::Uint8(Person::default().age), + ), + ]; + + let person_fields = vec![ + ( + new_bounded_string("name"), + Field::String(new_bounded_string(&self.name)), + ), + (new_bounded_string("age"), Field::Uint8(self.age)), + ( + new_bounded_string("friend"), + Field::Struct( + new_bounded_string("Person"), + Box::new(BoundedVec(friend_fields)), + ), + ), + ]; + + Field::Struct( + new_bounded_string("PersonWithFriend"), + Box::new(BoundedVec(person_fields)), + ) + } + } + + #[test] + fn test_ser_struct_nested() { + let person_with_friend = PersonWithFriend::default(); + + assert_ser_tokens( + &person_with_friend, + &[ + Token::Struct { + name: "PersonWithFriend", + len: 3, + }, + Token::Str("name"), + Token::Str("Matthew"), + Token::Str("age"), + Token::U8(37), + Token::Str("friend"), + Token::Struct { + name: "Person", + len: 2, + }, + Token::Str("name"), + Token::Str("John"), + Token::Str("age"), + Token::U8(40), + Token::StructEnd, + Token::StructEnd, + ], + ); + + let field = to_field(&person_with_friend).unwrap(); + assert_eq!(field, person_with_friend.as_field()); + } + + #[test] + fn test_de_struct_nested() { + let person_with_friend = PersonWithFriend::default(); + + assert_de_tokens( + &person_with_friend, + &[ + Token::Struct { + name: "PersonWithFriend", + len: 3, + }, + Token::Str("name"), + Token::Str("Matthew"), + Token::Str("age"), + Token::U8(37), + Token::Str("friend"), + Token::Struct { + name: "Person", + len: 2, + }, + Token::Str("name"), + Token::Str("John"), + Token::Str("age"), + Token::U8(40), + Token::StructEnd, + Token::StructEnd, + ], + ); + + let person_with_friend_de: PersonWithFriend = + from_field(person_with_friend.as_field()).unwrap(); + assert_eq!(person_with_friend_de, person_with_friend); + } + + #[derive(Serialize, Deserialize, Debug, PartialEq)] + struct PersonTuple(String, u8); + + impl Default for PersonTuple { + fn default() -> Self { + let person = Person::default(); + PersonTuple(person.name, person.age) + } + } + + impl PersonTuple { + fn as_field(&self) -> Field { + let fields = vec![ + ( + new_bounded_string("field_0"), + Field::String(new_bounded_string(self.0.clone())), + ), + (new_bounded_string("field_1"), Field::Uint8(self.1)), + ]; + + Field::Struct( + new_bounded_string("PersonTuple"), + Box::new(BoundedVec(fields)), + ) + } + } + + #[test] + fn test_ser_struct_tuple() { + let person_tuple = PersonTuple::default(); + + assert_ser_tokens( + &person_tuple, + &[ + Token::TupleStruct { + name: "PersonTuple", + len: 2, + }, + Token::Str("John"), + Token::U8(40), + Token::TupleStructEnd, + ], + ); + + let field = to_field(&person_tuple).unwrap(); + assert_eq!(field, person_tuple.as_field()); + } + + #[test] + fn test_de_struct_tuple() { + let person_tuple = PersonTuple::default(); + + assert_de_tokens( + &person_tuple, + &[ + Token::TupleStruct { + name: "PersonTuple", + len: 2, + }, + Token::Str("John"), + Token::U8(40), + Token::TupleStructEnd, + ], + ); + + let person_tuple_de: PersonTuple = from_field(person_tuple.as_field()).unwrap(); + assert_eq!(person_tuple_de, person_tuple); + } +} + +mod enums { + use super::*; + use serde::{Deserialize, Serialize}; + use serde_test::{assert_ser_tokens, Token}; + + #[derive(Serialize, Deserialize, Debug, PartialEq, Default)] + enum Availability { + Available, + #[default] + NotAvailable, + } + + impl Availability { + fn as_field(&self) -> Field { + match self { + Availability::Available => Field::String(new_bounded_string("Available")), + Availability::NotAvailable => Field::String(new_bounded_string("NotAvailable")), + } + } + } + + #[test] + fn test_ser_enum() { + let availability = Availability::default(); + + assert_ser_tokens( + &availability, + &[ + Token::Enum { + name: "Availability", + }, + Token::Str("NotAvailable"), + Token::Unit, + ], + ); + + let field = to_field(&availability).unwrap(); + assert_eq!(field, availability.as_field()); + } + + #[test] + fn test_de_enum() { + let availability = Availability::default(); + + assert_de_tokens( + &availability, + &[ + Token::Enum { + name: "Availability", + }, + Token::UnitVariant { + name: "Availability", + variant: "NotAvailable", + }, + ], + ); + + let availability_de: Availability = from_field(availability.as_field()).unwrap(); + assert_eq!(availability_de, availability); + } + + #[derive(Serialize, Deserialize, Debug, PartialEq)] + enum InvalidAvailability { + Available { days: u8 }, + NotAvailable(String), + } + + impl Default for InvalidAvailability { + fn default() -> Self { + Self::Available { days: 5 } + } + } + + #[test] + fn test_ser_invalid_enum() { + let invalid_availability = InvalidAvailability::default(); + + assert_ser_tokens( + &invalid_availability, + &[ + Token::StructVariant { + name: "InvalidAvailability", + variant: "Available", + len: 1, + }, + Token::Str("days"), + Token::U8(5), + Token::StructVariantEnd, + ], + ); + + let err = to_field(&invalid_availability).unwrap_err(); + assert!(matches!(err, crate::error::Error::UnsupportedType(_))); + } + + #[test] + fn test_de_invalid_enum() { + let invalid_availability = InvalidAvailability::default(); + + assert_ser_tokens( + &invalid_availability, + &[ + Token::StructVariant { + name: "InvalidAvailability", + variant: "Available", + len: 1, + }, + Token::Str("days"), + Token::U8(5), + Token::StructVariantEnd, + ], + ); + + let _ = from_field::(Field::String(new_bounded_string("Available"))) + .expect_err("should fail"); + } +} + +mod primitives { + use super::*; + + macro_rules! test_primitive { + ($($t:ty => $val:literal, $token:path, $field:path);+ $(;)?) => { + $( + paste::paste! { + #[test] + fn []() { + let val: $t = $val; + + assert_ser_tokens( + &val, + &[ + $token($val) + ], + ); + + let field = to_field(&val).unwrap(); + assert_eq!(field, $field(val)); + } + + #[test] + fn []() { + let val: $t = $val; + + assert_de_tokens( + &val, + &[ + $token($val) + ], + ); + + let val_de: $t = from_field($field(val)).unwrap(); + assert_eq!(val_de, val); + } + } + )+ + }; + } + + test_primitive!( + bool => true, Token::Bool, Field::Bool; + u8 => 0, Token::U8, Field::Uint8; + i8 => 0, Token::I8, Field::Int8; + u16 => 0, Token::U16, Field::Uint16; + i16 => 0, Token::I16, Field::Int16; + u32 => 0, Token::U32, Field::Uint32; + i32 => 0, Token::I32, Field::Int32; + u64 => 0, Token::U64, Field::Uint64; + i64 => 0, Token::I64, Field::Int64; + ); +} + +mod sequences { + use super::*; + use alloc::vec::Vec; + + fn expected_empty_bytes_field() -> Field { + Field::Bytes(BoundedVec(Vec::new())) + } + + #[test] + fn test_ser_bytes_empty() { + let bytes: serde_bytes::ByteBuf = serde_bytes::ByteBuf::from(Vec::new()); + + assert_ser_tokens(&bytes, &[Token::Bytes(&[])]); + + let field = to_field(&bytes).unwrap(); + assert_eq!(field, expected_empty_bytes_field()); + } + + #[test] + fn test_de_bytes_empty() { + let bytes: serde_bytes::ByteBuf = serde_bytes::ByteBuf::from(Vec::new()); + + assert_de_tokens(&bytes, &[Token::Bytes(&[])]); + + let bytes_de: serde_bytes::ByteBuf = from_field(expected_empty_bytes_field()).unwrap(); + assert_eq!(bytes, bytes_de); + } + + #[test] + fn test_de_bytes_seq_empty() { + let bytes: Vec = Vec::new(); + + assert_de_tokens(&bytes, &[Token::Seq { len: Some(0) }, Token::SeqEnd]); + + let bytes_de: Vec = from_field(expected_empty_bytes_field()).unwrap(); + assert_eq!(bytes, bytes_de); + } + + fn expected_bytes_field() -> Field { + Field::Bytes(BoundedVec(vec![1, 2, 3])) + } + + #[test] + fn test_ser_bytes() { + let bytes: serde_bytes::ByteBuf = serde_bytes::ByteBuf::from(vec![1, 2, 3]); + + assert_ser_tokens(&bytes, &[Token::Bytes(&[1, 2, 3])]); + + let field = to_field(&bytes).unwrap(); + assert_eq!(field, expected_bytes_field()); + } + + #[test] + fn test_de_bytes() { + let bytes: serde_bytes::ByteBuf = serde_bytes::ByteBuf::from(vec![1, 2, 3]); + + assert_de_tokens(&bytes, &[Token::Bytes(&[1, 2, 3])]); + + let bytes_de: serde_bytes::ByteBuf = from_field(expected_bytes_field()).unwrap(); + assert_eq!(bytes, bytes_de); + } + + #[test] + fn test_de_bytes_seq() { + let bytes: Vec = vec![1, 2, 3]; + + assert_de_tokens( + &bytes, + &[ + Token::Seq { len: Some(3) }, + Token::U8(1), + Token::U8(2), + Token::U8(3), + Token::SeqEnd, + ], + ); + + let bytes_de: Vec = from_field(expected_bytes_field()).unwrap(); + assert_eq!(bytes, bytes_de); + } + + fn expected_vec_field() -> Field { + Field::List(BoundedVec(vec![ + Field::Uint32(1), + Field::Uint32(2), + Field::Uint32(3), + ])) + } + + #[test] + fn test_ser_vec() { + let vec: Vec = vec![1, 2, 3]; + + assert_ser_tokens( + &vec, + &[ + Token::Seq { len: Some(3) }, + Token::U32(1), + Token::U32(2), + Token::U32(3), + Token::SeqEnd, + ], + ); + + let field = to_field(&vec).unwrap(); + assert_eq!(field, expected_vec_field()); + } + + #[test] + fn test_de_vec() { + let vec: Vec = vec![1, 2, 3]; + + assert_de_tokens( + &vec, + &[ + Token::Seq { len: Some(3) }, + Token::U32(1), + Token::U32(2), + Token::U32(3), + Token::SeqEnd, + ], + ); + + let vec_de: Vec = from_field(expected_vec_field()).unwrap(); + assert_eq!(vec, vec_de); + } + + fn expected_array_field() -> Field { + Field::Array(BoundedVec(vec![ + Field::Uint32(1), + Field::Uint32(2), + Field::Uint32(3), + ])) + } + + #[test] + fn test_ser_array() { + let array: [u32; 3] = [1, 2, 3]; + + assert_ser_tokens( + &array, + &[ + Token::Tuple { len: 3 }, + Token::U32(1), + Token::U32(2), + Token::U32(3), + Token::TupleEnd, + ], + ); + + let field = to_field(array).unwrap(); + assert_eq!(field, expected_array_field()); + } + + #[test] + fn test_de_array() { + let array: [u32; 3] = [1, 2, 3]; + + assert_de_tokens( + &array, + &[ + Token::Tuple { len: 3 }, + Token::U32(1), + Token::U32(2), + Token::U32(3), + Token::TupleEnd, + ], + ); + + let array_de: [u32; 3] = from_field(expected_array_field()).unwrap(); + assert_eq!(array, array_de); + } + + fn expected_same_type_field() -> Field { + Field::Array(BoundedVec(vec![ + Field::Uint32(1u32), + Field::Uint32(2u32), + Field::Uint32(3u32), + ])) + } + + #[test] + fn test_ser_tuple_same_type() { + let tuple: (u32, u32, u32) = (1, 2, 3); + + assert_ser_tokens( + &tuple, + &[ + Token::Tuple { len: 3 }, + Token::U32(1), + Token::U32(2), + Token::U32(3), + Token::TupleEnd, + ], + ); + + let field = to_field(tuple).unwrap(); + assert_eq!(field, expected_same_type_field()); + } + + #[test] + fn test_de_tuple_same_type() { + let tuple: (u32, u32, u32) = (1, 2, 3); + + assert_de_tokens( + &tuple, + &[ + Token::Tuple { len: 3 }, + Token::U32(1), + Token::U32(2), + Token::U32(3), + Token::TupleEnd, + ], + ); + + let tuple_de: (u32, u32, u32) = from_field(expected_same_type_field()).unwrap(); + assert_eq!(tuple, tuple_de); + } + + fn expected_different_type_field() -> Field { + Field::Array(BoundedVec(vec![ + Field::Uint32(1u32), + Field::Uint16(2u16), + Field::Uint8(3u8), + ])) + } + + #[test] + #[should_panic = "HeterogeneousTuple"] // TODO: Support heterogeneous tuples + fn test_ser_tuple_different_type() { + let tuple: (u32, u16, u8) = (1, 2, 3); + + assert_ser_tokens( + &tuple, + &[ + Token::Tuple { len: 3 }, + Token::U32(1), + Token::U16(2), + Token::U8(3), + Token::TupleEnd, + ], + ); + + let field = to_field(tuple).unwrap(); + assert_eq!(field, expected_different_type_field()); + } + + #[test] + fn test_de_tuple_different_type() { + let tuple: (u32, u16, u8) = (1, 2, 3); + + assert_de_tokens( + &tuple, + &[ + Token::Tuple { len: 3 }, + Token::U32(1), + Token::U16(2), + Token::U8(3), + Token::TupleEnd, + ], + ); + + let tuple_de: (u32, u16, u8) = from_field(expected_different_type_field()).unwrap(); + assert_eq!(tuple, tuple_de); + } +} + +mod accountid32 { + use super::*; + use core::str::FromStr; + + fn expected_accountid32_field() -> Field { + Field::AccountId( + AccountId32::from_str("12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU").unwrap(), + ) + } + + #[test] + #[should_panic = "assertion `left == right` failed"] // TODO: No way to differentiate, AccountId32 is serialized as a string. + fn test_ser_accountid32() { + let account_id: AccountId32 = + AccountId32::from_str("12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU").unwrap(); + + assert_ser_tokens( + &account_id, + &[Token::Str( + "5DfhGyQdFobKM8NsWvEeAKk5EQQgYe9AydgJ7rMB6E1EqRzV", + )], + ); + + let field = to_field(account_id).unwrap(); + assert_eq!(field, expected_accountid32_field()); + } + + #[test] + fn test_de_accountid32() { + let account_id: AccountId32 = + AccountId32::from_str("12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU").unwrap(); + + assert_de_tokens( + &account_id, + &[Token::Str( + "5DfhGyQdFobKM8NsWvEeAKk5EQQgYe9AydgJ7rMB6E1EqRzV", + )], + ); + + let account_id_de: AccountId32 = from_field(expected_accountid32_field()).unwrap(); + assert_eq!(account_id, account_id_de); + } +} diff --git a/crates/contexts/src/tangle.rs b/crates/contexts/src/tangle.rs index d169e09..97047a9 100644 --- a/crates/contexts/src/tangle.rs +++ b/crates/contexts/src/tangle.rs @@ -1,5 +1,11 @@ /// `TangleContext` trait provides access to the Tangle client from the context. -pub trait TangleContext { +pub trait TangleClientContext { /// Returns the Tangle client instance fn client(&self) -> gadget_client_tangle::runtime::TangleClient; + + fn get_call_id(&mut self) -> &mut Option; + + fn set_call_id(&mut self, call_id: u64) { + *self.get_call_id() = Some(call_id); + } } diff --git a/crates/crypto/Cargo.toml b/crates/crypto/Cargo.toml index 5b4489e..170a519 100644 --- a/crates/crypto/Cargo.toml +++ b/crates/crypto/Cargo.toml @@ -11,6 +11,7 @@ gadget-crypto-ed25519 = { path = "ed25519", optional = true } gadget-crypto-bls = { path = "bls", optional = true } gadget-crypto-bn254 = { path = "bn254", optional = true } gadget-crypto-sp-core = { path = "sp-core", optional = true } +gadget-crypto-tangle-pair-signer = { workspace = true, optional = true } sha2 = { workspace = true, optional = true } sha3 = { workspace = true, optional = true } thiserror = { workspace = true } @@ -25,6 +26,7 @@ std = [ "gadget-crypto-bls?/std", "gadget-crypto-bn254?/std", "gadget-crypto-sp-core?/std", + "gadget-crypto-tangle-pair-signer?/std", ] k256 = ["gadget-crypto-k256", "gadget-crypto-core/k256"] sr25519-schnorrkel = ["gadget-crypto-sr25519", "gadget-crypto-core/sr25519-schnorrkel"] @@ -33,5 +35,6 @@ bls = ["gadget-crypto-bls", "gadget-crypto-core/bls"] bn254 = ["gadget-crypto-bn254", "gadget-crypto-core/bn254"] sp-core = ["gadget-crypto-sp-core", "gadget-crypto-core/tangle"] sp-core-bls = ["gadget-crypto-sp-core/bls", "gadget-crypto-core/tangle"] +tangle-pair-signer = ["gadget-crypto-tangle-pair-signer"] hashing = ["sha2", "sha3"] \ No newline at end of file diff --git a/crates/crypto/tangle-pair-signer/Cargo.toml b/crates/crypto/tangle-pair-signer/Cargo.toml new file mode 100644 index 0000000..7f23d60 --- /dev/null +++ b/crates/crypto/tangle-pair-signer/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "gadget-crypto-tangle-pair-signer" +version = "0.1.0" +edition = "2021" + +[dependencies] +gadget-std = { workspace = true } +gadget-crypto-core = { workspace = true, features = ["tangle"] } +gadget-crypto-sp-core = { workspace = true } +k256 = { workspace = true, optional = true } +sp-core = { workspace = true, features = ["full_crypto"] } +paste = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true, features = ["alloc"] } +subxt = { workspace = true } +subxt-core = { workspace = true } +thiserror = { workspace = true } + +alloy-primitives = { workspace = true, optional = true } +alloy-signer-local = { workspace = true, optional = true } + +[features] +default = ["std", "evm"] +std = [ + "gadget-crypto-core/std", + "gadget-crypto-sp-core/std", + "gadget-std/std", + "serde/std", + "serde_json/std", + "sp-core/std", + "subxt/native", + "subxt/substrate-compat", + "subxt-core/std", +] +evm = [ + "alloy-primitives", + "alloy-signer-local", + "k256", +] \ No newline at end of file diff --git a/crates/crypto/tangle-pair-signer/src/error.rs b/crates/crypto/tangle-pair-signer/src/error.rs new file mode 100644 index 0000000..8a47f53 --- /dev/null +++ b/crates/crypto/tangle-pair-signer/src/error.rs @@ -0,0 +1,13 @@ +use gadget_crypto_sp_core::error::SecretStringErrorWrapper; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum TanglePairSignerError { + #[error("Invalid secret string: {0}")] + SecretStringError(SecretStringErrorWrapper), + #[cfg(feature = "evm")] + #[error("Ecdsa k256 error: {0}")] + EcdsaError(#[from] k256::ecdsa::Error), +} + +pub type Result = gadget_std::result::Result; diff --git a/crates/crypto/tangle-pair-signer/src/lib.rs b/crates/crypto/tangle-pair-signer/src/lib.rs new file mode 100644 index 0000000..facad72 --- /dev/null +++ b/crates/crypto/tangle-pair-signer/src/lib.rs @@ -0,0 +1,4 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +pub mod error; +pub mod tangle_pair_signer; diff --git a/crates/crypto/tangle-pair-signer/src/tangle_pair_signer.rs b/crates/crypto/tangle-pair-signer/src/tangle_pair_signer.rs new file mode 100644 index 0000000..3778686 --- /dev/null +++ b/crates/crypto/tangle-pair-signer/src/tangle_pair_signer.rs @@ -0,0 +1,120 @@ +use gadget_std::vec::Vec; +use sp_core::crypto::DeriveError; +use sp_core::crypto::SecretStringError; +use sp_core::DeriveJunction; +use subxt::PolkadotConfig; +use subxt_core::{ + tx::signer::{PairSigner, Signer}, + utils::{AccountId32, MultiAddress, MultiSignature}, +}; + +#[derive(Clone, Debug)] +pub struct TanglePairSigner { + pub(crate) pair: subxt::tx::PairSigner, +} + +impl sp_core::crypto::CryptoType for TanglePairSigner { + type Pair = Pair; +} + +impl TanglePairSigner +where + ::Signature: Into, + subxt::ext::sp_runtime::MultiSigner: From<::Public>, +{ + pub fn new(pair: Pair) -> Self { + TanglePairSigner { + pair: PairSigner::new(pair), + } + } + + pub fn into_inner(self) -> PairSigner { + self.pair + } + + pub fn signer(&self) -> &Pair { + self.pair.signer() + } +} + +impl Signer for TanglePairSigner +where + Pair: sp_core::Pair, + Pair::Signature: Into, +{ + fn account_id(&self) -> AccountId32 { + self.pair.account_id() + } + + fn address(&self) -> MultiAddress { + self.pair.address() + } + + fn sign(&self, signer_payload: &[u8]) -> MultiSignature { + self.pair.sign(signer_payload) + } +} + +impl sp_core::Pair for TanglePairSigner +where + ::Signature: Into, + subxt::ext::sp_runtime::MultiSigner: From<::Public>, +{ + type Public = Pair::Public; + type Seed = Pair::Seed; + type Signature = Pair::Signature; + + fn derive>( + &self, + path: Iter, + seed: Option, + ) -> Result<(Self, Option), DeriveError> { + Pair::derive(self.pair.signer(), path, seed).map(|(pair, seed)| { + ( + TanglePairSigner { + pair: PairSigner::new(pair), + }, + seed, + ) + }) + } + + fn from_seed_slice(seed: &[u8]) -> Result { + Pair::from_seed_slice(seed).map(|pair| TanglePairSigner { + pair: PairSigner::new(pair), + }) + } + + fn sign(&self, message: &[u8]) -> Self::Signature { + Pair::sign(self.pair.signer(), message) + } + + fn verify>(sig: &Self::Signature, message: M, pubkey: &Self::Public) -> bool { + Pair::verify(sig, message, pubkey) + } + + fn public(&self) -> Self::Public { + Pair::public(self.pair.signer()) + } + + fn to_raw_vec(&self) -> Vec { + Pair::to_raw_vec(self.pair.signer()) + } +} + +#[cfg(feature = "evm")] +impl TanglePairSigner { + /// Returns the alloy-compatible key for the ECDSA key pair. + pub fn alloy_key( + &self, + ) -> crate::error::Result> { + let k256_ecdsa_secret_key = self.pair.signer().seed(); + let res = alloy_signer_local::LocalSigner::from_slice(&k256_ecdsa_secret_key)?; + Ok(res) + } + + /// Returns the Alloy Address for the ECDSA key pair. + pub fn alloy_address(&self) -> crate::error::Result { + Ok(self.alloy_key()?.address()) + } +} diff --git a/crates/event-listeners/Cargo.toml b/crates/event-listeners/Cargo.toml new file mode 100644 index 0000000..7d744a1 --- /dev/null +++ b/crates/event-listeners/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "gadget-event-listeners" +version = "0.1.0" +edition = "2021" + +[dependencies] +gadget-std = { workspace = true } +gadget-event-listeners-evm = { workspace = true, optional = true } +gadget-event-listeners-core = { workspace = true } +gadget-event-listeners-periodic = { workspace = true, optional = true } +gadget-event-listeners-tangle = { workspace = true, optional = true } + +[features] +default = ["std", "evm", "periodic", "tangle"] +std = [ + "gadget-std/std", + "gadget-event-listeners-core/std", + "gadget-event-listeners-evm?/std", + "gadget-event-listeners-periodic?/std", + "gadget-event-listeners-tangle?/std", +] +evm = ["gadget-event-listeners-evm"] +periodic = ["gadget-event-listeners-periodic"] +tangle = ["gadget-event-listeners-tangle"] \ No newline at end of file diff --git a/crates/event-listeners/core/Cargo.toml b/crates/event-listeners/core/Cargo.toml new file mode 100644 index 0000000..3309c09 --- /dev/null +++ b/crates/event-listeners/core/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "gadget-event-listeners-core" +version = "0.1.0" +edition = "2021" + +[dependencies] +gadget-std = { workspace = true } +async-trait = { workspace = true } + +[features] +default = ["std"] +std = ["gadget-std/std"] +testing = [] \ No newline at end of file diff --git a/crates/event-listeners/core/src/exponential_backoff.rs b/crates/event-listeners/core/src/exponential_backoff.rs new file mode 100644 index 0000000..06dbe6d --- /dev/null +++ b/crates/event-listeners/core/src/exponential_backoff.rs @@ -0,0 +1,128 @@ +use gadget_std::iter::Iterator; +use gadget_std::time::Duration; +use gadget_std::u64::MAX as U64_MAX; + +/// A retry strategy driven by exponential back-off. +/// +/// The power corresponds to the number of past attempts. +#[derive(Debug, Clone)] +pub struct ExponentialBackoff { + current: u64, + base: u64, + factor: u64, + max_delay: Option, +} + +impl ExponentialBackoff { + /// Constructs a new exponential back-off strategy, + /// given a base duration in milliseconds. + /// + /// The resulting duration is calculated by taking the base to the `n`-th power, + /// where `n` denotes the number of past attempts. + pub fn from_millis(base: u64) -> ExponentialBackoff { + ExponentialBackoff { + current: base, + base: base, + factor: 1u64, + max_delay: None, + } + } + + /// A multiplicative factor that will be applied to the retry delay. + /// + /// For example, using a factor of `1000` will make each delay in units of seconds. + /// + /// Default factor is `1`. + pub fn factor(mut self, factor: u64) -> ExponentialBackoff { + self.factor = factor; + self + } + + /// Apply a maximum delay. No retry delay will be longer than this `Duration`. + pub fn max_delay(mut self, duration: Duration) -> ExponentialBackoff { + self.max_delay = Some(duration); + self + } +} + +impl Iterator for ExponentialBackoff { + type Item = Duration; + + fn next(&mut self) -> Option { + // set delay duration by applying factor + let duration = if let Some(duration) = self.current.checked_mul(self.factor) { + Duration::from_millis(duration) + } else { + Duration::from_millis(U64_MAX) + }; + + // check if we reached max delay + if let Some(ref max_delay) = self.max_delay { + if duration > *max_delay { + return Some(*max_delay); + } + } + + if let Some(next) = self.current.checked_mul(self.base) { + self.current = next; + } else { + self.current = U64_MAX; + } + + Some(duration) + } +} + +#[test] +fn returns_some_exponential_base_10() { + let mut s = ExponentialBackoff::from_millis(10); + + assert_eq!(s.next(), Some(Duration::from_millis(10))); + assert_eq!(s.next(), Some(Duration::from_millis(100))); + assert_eq!(s.next(), Some(Duration::from_millis(1000))); +} + +#[test] +fn returns_some_exponential_base_2() { + let mut s = ExponentialBackoff::from_millis(2); + + assert_eq!(s.next(), Some(Duration::from_millis(2))); + assert_eq!(s.next(), Some(Duration::from_millis(4))); + assert_eq!(s.next(), Some(Duration::from_millis(8))); +} + +#[test] +fn saturates_at_maximum_value() { + let mut s = ExponentialBackoff::from_millis(U64_MAX - 1); + + assert_eq!(s.next(), Some(Duration::from_millis(U64_MAX - 1))); + assert_eq!(s.next(), Some(Duration::from_millis(U64_MAX))); + assert_eq!(s.next(), Some(Duration::from_millis(U64_MAX))); +} + +#[test] +fn can_use_factor_to_get_seconds() { + let factor = 1000; + let mut s = ExponentialBackoff::from_millis(2).factor(factor); + + assert_eq!(s.next(), Some(Duration::from_secs(2))); + assert_eq!(s.next(), Some(Duration::from_secs(4))); + assert_eq!(s.next(), Some(Duration::from_secs(8))); +} + +#[test] +fn stops_increasing_at_max_delay() { + let mut s = ExponentialBackoff::from_millis(2).max_delay(Duration::from_millis(4)); + + assert_eq!(s.next(), Some(Duration::from_millis(2))); + assert_eq!(s.next(), Some(Duration::from_millis(4))); + assert_eq!(s.next(), Some(Duration::from_millis(4))); +} + +#[test] +fn returns_max_when_max_less_than_base() { + let mut s = ExponentialBackoff::from_millis(20).max_delay(Duration::from_millis(10)); + + assert_eq!(s.next(), Some(Duration::from_millis(10))); + assert_eq!(s.next(), Some(Duration::from_millis(10))); +} diff --git a/crates/event-listeners/core/src/lib.rs b/crates/event-listeners/core/src/lib.rs new file mode 100644 index 0000000..e874ae6 --- /dev/null +++ b/crates/event-listeners/core/src/lib.rs @@ -0,0 +1,25 @@ +pub mod exponential_backoff; +pub mod marker; + +#[cfg(feature = "testing")] +pub mod testing; + +use async_trait::async_trait; +use exponential_backoff::ExponentialBackoff; +use gadget_std::iter::Take; + +/// The [`EventListener`] trait defines the interface for event listeners. +#[async_trait] +pub trait EventListener: Send + 'static { + type Error: gadget_std::error::Error + Send + Sync + 'static; + async fn new(context: &Ctx) -> Result + where + Self: Sized; + + /// Obtains the next event to be processed by the event listener. + async fn next_event(&mut self) -> Option; +} + +pub fn get_exponential_backoff() -> Take { + ExponentialBackoff::from_millis(2).factor(1000).take(N) +} diff --git a/crates/event-listeners/core/src/marker.rs b/crates/event-listeners/core/src/marker.rs new file mode 100644 index 0000000..5876bd7 --- /dev/null +++ b/crates/event-listeners/core/src/marker.rs @@ -0,0 +1,7 @@ +//! Marker Types +//! +//! These marker type are for internal use only. The help to differentiate between different +//! types of event listeners for the [`JobBuilder`](crate::job_runner::JobBuilder). +//! These are auto implemented for the respective event listeners in the macro code. +pub trait IsTangle {} +pub trait IsEvm {} diff --git a/crates/event-listeners/core/src/testing.rs b/crates/event-listeners/core/src/testing.rs new file mode 100644 index 0000000..9b426ba --- /dev/null +++ b/crates/event-listeners/core/src/testing.rs @@ -0,0 +1,24 @@ +use crate::EventListener; +use async_trait::async_trait; + +/// Only useful for testing job syntax, not running jobs. +/// This event listener will never return an event. +pub struct PendingEventListener(gadget_std::marker::PhantomData<(T, Ctx)>); + +#[async_trait] +impl EventListener + for PendingEventListener +{ + type Error = std::io::Error; + + async fn new(_context: &Ctx) -> Result + where + Self: Sized, + { + Ok(Self(gadget_std::marker::PhantomData)) + } + + async fn next_event(&mut self) -> Option { + futures::future::pending().await + } +} diff --git a/crates/event-listeners/evm/Cargo.toml b/crates/event-listeners/evm/Cargo.toml new file mode 100644 index 0000000..f40f775 --- /dev/null +++ b/crates/event-listeners/evm/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "gadget-event-listeners-evm" +version = "0.1.0" +edition = "2021" + +[dependencies] +gadget-std = { workspace = true } +gadget-event-listeners-core = { workspace = true } +gadget-logging = { workspace = true } +gadget-stores = { workspace = true, features = ["local"] } +alloy-contract = { workspace = true } +alloy-network = { workspace = true } +alloy-provider = { workspace = true } +alloy-rpc-types = { workspace = true, features = ["eth"] } +alloy-sol-types = { workspace = true } +alloy-transport = { workspace = true } +async-trait = { workspace = true } +thiserror = { workspace = true } +tokio = { workspace = true } +uuid = { workspace = true, features = ["v4"] } + +[features] +default = ["std"] +std = [ + "gadget-std/std", + "gadget-event-listeners-core/std", + "gadget-logging/std", + "gadget-stores/std", + "tokio/full", +] \ No newline at end of file diff --git a/crates/event-listeners/evm/src/contracts.rs b/crates/event-listeners/evm/src/contracts.rs new file mode 100644 index 0000000..0d34e5d --- /dev/null +++ b/crates/event-listeners/evm/src/contracts.rs @@ -0,0 +1,119 @@ +use crate::Result; +use alloy_contract::ContractInstance; +use alloy_contract::Event; +use alloy_network::Ethereum; +use alloy_provider::Provider; +use alloy_provider::RootProvider; +use alloy_rpc_types::{BlockNumberOrTag, Filter}; +use alloy_sol_types::SolEvent; +use alloy_transport::BoxTransport; +use gadget_event_listeners_core::EventListener; +use gadget_std::collections::VecDeque; +use gadget_std::time::Duration; +use gadget_stores::local_database::LocalDatabase; +use uuid::Uuid; + +pub type AlloyRootProvider = RootProvider; +pub type AlloyContractInstance = ContractInstance; + +pub struct EvmContractEventListener { + instance: AlloyContractInstance, + chain_id: u64, + local_db: LocalDatabase, + should_cooldown: bool, + enqueued_events: VecDeque<(E, alloy_rpc_types::Log)>, +} + +#[async_trait::async_trait] +impl + EventListener<(E, alloy_rpc_types::Log), AlloyContractInstance> + for EvmContractEventListener +{ + type Error = crate::EvmEventListenerError; + + async fn new(context: &AlloyContractInstance) -> Result + where + Self: Sized, + { + let provider = context.provider().root(); + // Add more detailed error handling and logging + let chain_id = provider.get_chain_id().await?; + + let local_db = LocalDatabase::open(format!("./db/{}", Uuid::new_v4())); + Ok(Self { + chain_id, + should_cooldown: false, + enqueued_events: VecDeque::new(), + local_db, + instance: context.clone(), + }) + } + + async fn next_event(&mut self) -> Option<(E, alloy_rpc_types::Log)> { + if let Some(event) = self.enqueued_events.pop_front() { + return Some(event); + } + + if self.should_cooldown { + tokio::time::sleep(Duration::from_millis(5000)).await; + self.should_cooldown = false; + } + + let contract = &self.instance; + let step = 100; + let target_block_number: u64 = contract + .provider() + .get_block_number() + .await + .unwrap_or_default(); + + let block = self + .local_db + .get(&format!("LAST_BLOCK_NUMBER_{}", contract.address())) + .unwrap_or(0); + + let should_cooldown = block >= target_block_number; + if should_cooldown { + self.should_cooldown = true; + return self.next_event().await; + } + + let dest_block = core::cmp::min(block + step, target_block_number); + + // Query events + let events_filter = Event::new(contract.provider(), Filter::new()) + .address(*contract.address()) + .from_block(BlockNumberOrTag::Number(block + 1)) + .to_block(BlockNumberOrTag::Number(dest_block)) + .event_signature(E::SIGNATURE_HASH); + + gadget_logging::info!("Querying events for filter, address: {}, from_block: {}, to_block: {}, event_signature: {}", contract.address(), block + 1, dest_block, E::SIGNATURE_HASH); + match events_filter.query().await { + Ok(events) => { + let events = events.into_iter().collect::>(); + self.local_db.set( + &format!("LAST_BLOCK_NUMBER_{}", contract.address()), + dest_block, + ); + + self.local_db.set( + &format!("TARGET_BLOCK_{}", contract.address()), + target_block_number, + ); + + if events.is_empty() { + self.should_cooldown = true; + return self.next_event().await; + } + + self.enqueued_events = events; + + self.next_event().await + } + Err(e) => { + gadget_logging::error!(?e, %self.chain_id, "Error while querying events"); + None + } + } + } +} diff --git a/crates/event-listeners/evm/src/lib.rs b/crates/event-listeners/evm/src/lib.rs new file mode 100644 index 0000000..d4dfdba --- /dev/null +++ b/crates/event-listeners/evm/src/lib.rs @@ -0,0 +1,13 @@ +use thiserror::Error; + +pub mod contracts; + +#[derive(Debug, Error)] +pub enum EvmEventListenerError { + #[error("Client error: {0}")] + Client(String), + #[error("Transport error: {0}")] + TransportError(#[from] alloy_transport::RpcError), +} + +pub type Result = gadget_std::result::Result; diff --git a/crates/event-listeners/periodic/Cargo.toml b/crates/event-listeners/periodic/Cargo.toml new file mode 100644 index 0000000..27ad8e6 --- /dev/null +++ b/crates/event-listeners/periodic/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "gadget-event-listeners-periodic" +version = "0.1.0" +edition = "2021" + +[dependencies] +gadget-std = { workspace = true } +gadget-event-listeners-core = { workspace = true } +gadget-logging = { workspace = true } +async-trait = { workspace = true } +thiserror = { workspace = true } +tokio = { workspace = true } + +[features] +default = ["std"] +std = [ + "gadget-std/std", + "gadget-event-listeners-core/std", + "gadget-logging/std", + "tokio/full", +] \ No newline at end of file diff --git a/crates/event-listeners/periodic/src/error.rs b/crates/event-listeners/periodic/src/error.rs new file mode 100644 index 0000000..f62cbf3 --- /dev/null +++ b/crates/event-listeners/periodic/src/error.rs @@ -0,0 +1,10 @@ +use gadget_std::string::String; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum PeriodicEventListenerError { + #[error("Inner listener error: {0}")] + InnerListener(String), +} + +pub type Result = gadget_std::result::Result; diff --git a/crates/event-listeners/periodic/src/lib.rs b/crates/event-listeners/periodic/src/lib.rs new file mode 100644 index 0000000..71ade14 --- /dev/null +++ b/crates/event-listeners/periodic/src/lib.rs @@ -0,0 +1,2 @@ +pub mod error; +pub mod periodic; diff --git a/crates/event-listeners/periodic/src/periodic.rs b/crates/event-listeners/periodic/src/periodic.rs new file mode 100644 index 0000000..d301e3e --- /dev/null +++ b/crates/event-listeners/periodic/src/periodic.rs @@ -0,0 +1,40 @@ +use crate::error::{PeriodicEventListenerError, Result}; +use async_trait::async_trait; +use gadget_event_listeners_core::EventListener; +use gadget_std::time::Duration; + +#[derive(Default)] +pub struct PeriodicEventListener { + listener: T, + _pd: gadget_std::marker::PhantomData<(Event, Ctx)>, +} + +#[async_trait] +impl< + const MSEC: usize, + T: EventListener, + Ctx: Send + Sync + 'static, + Event: Send + Sync + 'static, + > EventListener for PeriodicEventListener +{ + type Error = PeriodicEventListenerError; + + async fn new(context: &Ctx) -> Result + where + Self: Sized, + { + let listener = T::new(context) + .await + .map_err(|e| PeriodicEventListenerError::InnerListener(e.to_string()))?; + Ok(Self { + listener, + _pd: gadget_std::marker::PhantomData, + }) + } + + async fn next_event(&mut self) -> Option { + let interval = Duration::from_millis(MSEC as u64); + tokio::time::sleep(interval).await; + self.listener.next_event().await + } +} diff --git a/crates/event-listeners/src/lib.rs b/crates/event-listeners/src/lib.rs new file mode 100644 index 0000000..b93cf3f --- /dev/null +++ b/crates/event-listeners/src/lib.rs @@ -0,0 +1,14 @@ +pub fn add(left: u64, right: u64) -> u64 { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} diff --git a/crates/event-listeners/tangle/Cargo.toml b/crates/event-listeners/tangle/Cargo.toml new file mode 100644 index 0000000..2b5c404 --- /dev/null +++ b/crates/event-listeners/tangle/Cargo.toml @@ -0,0 +1,47 @@ +[package] +name = "gadget-event-listeners-tangle" +version = "0.1.0" +edition = "2021" + +[dependencies] +gadget-blueprint-serde = { workspace = true } +gadget-clients = { workspace = true, features = ["tangle"] } +gadget-contexts = { workspace = true, features = ["tangle", "keystore"] } +gadget-crypto-tangle-pair-signer = { workspace = true } +gadget-event-listeners-core = { workspace = true } +gadget-keystore = { workspace = true } +gadget-logging = { workspace = true } +gadget-std = { workspace = true } +gadget-utils-tangle = { workspace = true } +async-trait = { workspace = true } +parking_lot = { workspace = true } +serde = { workspace = true, features = ["derive"] } +sp-core = { workspace = true } +subxt = { workspace = true } +subxt-core = { workspace = true } +tangle-subxt = { workspace = true } +thiserror = { workspace = true } +tokio = { workspace = true } + +[features] +default = ["std"] +std = [ + "gadget-blueprint-serde/std", + "gadget-clients/std", + "gadget-contexts/std", + "gadget-crypto-tangle-pair-signer/std", + "gadget-event-listeners-core/std", + "gadget-logging/std", + "gadget-std/std", + "gadget-utils-tangle/std", + "serde/std", + "sp-core/std", + "subxt/native", + "subxt-core/std", + "tangle-subxt/std", + "tokio/full", +] +no_std = [ + "gadget-utils-tangle/no_std", + "subxt/web", +] \ No newline at end of file diff --git a/crates/event-listeners/tangle/src/error.rs b/crates/event-listeners/tangle/src/error.rs new file mode 100644 index 0000000..c7f7a34 --- /dev/null +++ b/crates/event-listeners/tangle/src/error.rs @@ -0,0 +1,15 @@ +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum TangleEventListenerError { + #[error("Subxt error: {0}")] + SubxtError(#[from] subxt::Error), + #[error("Skip preprocessed type")] + SkipPreProcessedType, + #[error("Blueprint serde error: {0}")] + BlueprintSerde(#[from] gadget_blueprint_serde::error::Error), + #[error("Client error: {0}")] + Client(String), +} + +pub type Result = gadget_std::result::Result; diff --git a/crates/event-listeners/tangle/src/events.rs b/crates/event-listeners/tangle/src/events.rs new file mode 100644 index 0000000..7e9e288 --- /dev/null +++ b/crates/event-listeners/tangle/src/events.rs @@ -0,0 +1,192 @@ +use crate::error::{Result, TangleEventListenerError}; +use async_trait::async_trait; +use gadget_clients::tangle::runtime::{TangleClient, TangleConfig}; +use gadget_crypto_tangle_pair_signer::tangle_pair_signer::TanglePairSigner; +use gadget_event_listeners_core::marker::IsTangle; +use gadget_event_listeners_core::EventListener; +use gadget_std::collections::VecDeque; +use gadget_std::sync::atomic::{AtomicBool, Ordering}; +use gadget_std::sync::Arc; +use subxt::backend::StreamOfResults; +use subxt_core::events::{EventDetails, StaticEvent}; +use subxt_core::utils::AccountId32; +use tangle_subxt::tangle_testnet_runtime::api::runtime_types::tangle_primitives::services::field::Field; +use tangle_subxt::tangle_testnet_runtime::api::services::calls::types::call::{Job, ServiceId}; +use tangle_subxt::tangle_testnet_runtime::api::services::events::job_called; +use tangle_subxt::tangle_testnet_runtime::api::services::events::job_called::CallId; +use tokio::sync::Mutex; + +pub struct TangleEventListener { + current_block: Option, + job_id: Job, + service_id: ServiceId, + listener: Mutex>>, + context: C, + signer: TanglePairSigner, + client: TangleClient, + has_stopped: Arc, + stopper_tx: Arc>>>, + enqueued_events: VecDeque, +} + +pub type BlockNumber = u32; + +#[derive(Clone)] +pub struct TangleListenerInput { + pub client: TangleClient, + pub job_id: Job, + pub service_id: ServiceId, + pub signer: TanglePairSigner, + pub context: C, +} + +/// Emitted by the [`TangleEventListener`] when a new event is received. +/// +/// Root events are preferred to be used as the E, as then the application can +/// sort through a series of events to find the ones it is interested in for +/// pre-processing. +#[derive(Clone)] +pub struct TangleEvent { + pub evt: E::Output, + pub context: C, + pub call_id: Option, + pub args: job_called::Args, + pub block_number: BlockNumber, + pub signer: TanglePairSigner, + pub client: TangleClient, + pub job_id: Job, + pub service_id: ServiceId, + pub stopper: Arc>>>, +} + +impl TangleEvent { + /// Stops the event listener + pub fn stop(&self) -> bool { + let mut lock = self.stopper.lock(); + if let Some(tx) = lock.take() { + tx.send(()).is_ok() + } else { + false + } + } +} + +pub trait EventMatcher: Send + 'static { + type Output: Send + 'static; + fn try_decode(event: EventDetails) -> Option; +} + +impl EventMatcher for T { + type Output = T; + fn try_decode(event: EventDetails) -> Option { + event.as_event::().ok().flatten() + } +} + +#[derive(Copy, Clone)] +pub struct AllEvents; + +impl EventMatcher for AllEvents { + type Output = EventDetails; + fn try_decode(event: EventDetails) -> Option { + Some(event) + } +} + +impl IsTangle for TangleEventListener {} + +pub trait ThreadSafeCloneable: Clone + Send + Sync + 'static {} +impl ThreadSafeCloneable for T {} + +#[async_trait] +impl + EventListener, TangleListenerInput> for TangleEventListener +{ + type Error = TangleEventListenerError; + + async fn new(context: &TangleListenerInput) -> Result + where + Self: Sized, + { + let TangleListenerInput { + client, + job_id, + service_id, + context, + signer, + } = context; + + let listener = Mutex::new(client.blocks().subscribe_finalized().await?); + + let (tx, rx) = tokio::sync::oneshot::channel(); + let has_stopped = Arc::new(AtomicBool::new(false)); + + let has_stopped_clone = has_stopped.clone(); + + let background_task = async move { + let _ = rx.await; + has_stopped_clone.store(true, Ordering::SeqCst); + }; + + drop(tokio::task::spawn(background_task)); + + Ok(Self { + listener, + current_block: None, + job_id: *job_id, + service_id: *service_id, + context: context.clone(), + client: client.clone(), + signer: signer.clone(), + stopper_tx: Arc::new(parking_lot::Mutex::new(Some(tx))), + has_stopped, + enqueued_events: VecDeque::new(), + }) + } + + async fn next_event(&mut self) -> Option> { + loop { + if self.has_stopped.load(Ordering::SeqCst) { + return None; + } + + if let Some(evt) = self.enqueued_events.pop_front() { + return Some(TangleEvent { + evt, + context: self.context.clone(), + signer: self.signer.clone(), + call_id: None, + stopper: self.stopper_tx.clone(), + args: vec![], + block_number: self.current_block?, + client: self.client.clone(), + job_id: self.job_id, + service_id: self.service_id, + }); + } + + let next_events = self.listener.get_mut().next().await?.ok()?; + let block_number = next_events.number(); + self.current_block = Some(block_number); + + let events = next_events + .events() + .await + .ok()? + .iter() + .filter_map(|r| r.ok().and_then(E::try_decode)) + .collect::>(); + + gadget_logging::debug!("Found {} possible events ...", events.len()); + self.enqueued_events = events; + } + } +} + +pub struct TangleResult { + pub results: R, + pub service_id: ServiceId, + pub call_id: job_called::CallId, + pub client: TangleClient, + pub signer: TanglePairSigner, +} diff --git a/crates/event-listeners/tangle/src/lib.rs b/crates/event-listeners/tangle/src/lib.rs new file mode 100644 index 0000000..920f079 --- /dev/null +++ b/crates/event-listeners/tangle/src/lib.rs @@ -0,0 +1,3 @@ +pub mod error; +pub mod events; +pub mod services; diff --git a/crates/event-listeners/tangle/src/services.rs b/crates/event-listeners/tangle/src/services.rs new file mode 100644 index 0000000..f18dfe9 --- /dev/null +++ b/crates/event-listeners/tangle/src/services.rs @@ -0,0 +1,81 @@ +use crate::error::{Result, TangleEventListenerError}; +use crate::events::{EventMatcher, TangleEvent, TangleResult}; +use gadget_contexts::tangle::TangleClientContext; +use std::any::Any; +use tangle_subxt::tangle_testnet_runtime::api; +use tangle_subxt::tangle_testnet_runtime::api::services::events::{JobCalled, JobResultSubmitted}; + +pub async fn services_pre_processor>( + event: TangleEvent, +) -> Result> { + let TangleEvent { + evt, + mut context, + block_number, + signer, + client, + job_id, + service_id, + stopper, + .. + } = event; + let boxed_item = Box::new(evt) as Box; + + let (event_job_id, event_service_id, event_call_id, args) = + if let Some(res) = boxed_item.downcast_ref::() { + (res.job, res.service_id, res.call_id, res.args.clone()) + } else if let Some(res) = boxed_item.downcast_ref::() { + (res.job, res.service_id, res.call_id, vec![]) + } else { + return Err(TangleEventListenerError::SkipPreProcessedType); + }; + + gadget_logging::info!("Pre-processing event for service-id/job-id = {service_id}/{job_id} ..."); + + if event_job_id == job_id && event_service_id == service_id { + gadget_logging::info!( + "Found actionable event for service-id/job-id = {event_service_id}/{event_job_id} ..." + ); + // Set the call ID that way the user can access it in the job function + context.set_call_id(event_call_id); + return Ok(TangleEvent { + evt: *boxed_item.downcast().unwrap(), + context, + call_id: Some(event_call_id), + args, + block_number, + signer, + client, + job_id: event_job_id, + service_id: event_service_id, + stopper, + }); + } + + Err(TangleEventListenerError::SkipPreProcessedType) +} + +/// By default, the tangle post-processor takes in a job result and submits the result on-chain +pub async fn services_post_processor( + TangleResult { + results, + service_id, + call_id, + client, + signer, + }: TangleResult, +) -> Result<()> { + gadget_logging::info!( + "Submitting result on-chain for service {service_id} call_id {call_id} ..." + ); + let response = api::tx().services().submit_result( + service_id, + call_id, + vec![gadget_blueprint_serde::to_field(results)?], + ); + let _ = gadget_utils_tangle::tx::send(&client, &signer, &response) + .await + .map_err(|err| TangleEventListenerError::Client(err.to_string()))?; + gadget_logging::info!("Submitted result on-chain"); + Ok(()) +} diff --git a/crates/stores/Cargo.toml b/crates/stores/Cargo.toml new file mode 100644 index 0000000..9646ef5 --- /dev/null +++ b/crates/stores/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "gadget-stores" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true + +[dependencies] +gadget-store-local-database = { workspace = true, optional = true } + +[features] +default = ["std", "local"] +std = [ + "gadget-store-local-database?/std", +] +local = ["gadget-store-local-database"] \ No newline at end of file diff --git a/crates/stores/local-database/Cargo.toml b/crates/stores/local-database/Cargo.toml new file mode 100644 index 0000000..aeabc8d --- /dev/null +++ b/crates/stores/local-database/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "gadget-store-local-database" +version = "0.1.0" +edition = "2021" + +[dependencies] +gadget-std = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } + +[features] +default = ["std"] +std = [ + "gadget-std/std", + "serde/std", + "serde_json/std", +] \ No newline at end of file diff --git a/crates/stores/local-database/src/lib.rs b/crates/stores/local-database/src/lib.rs new file mode 100644 index 0000000..59472e1 --- /dev/null +++ b/crates/stores/local-database/src/lib.rs @@ -0,0 +1,137 @@ +use serde::{de::DeserializeOwned, Serialize}; +use std::collections::HashMap; +use std::fs; +use std::path::{Path, PathBuf}; +use std::sync::Mutex; + +/// A local database for storing key-value pairs. +/// +/// The database is stored in a JSON file, which is updated every time a key-value pair is added or updated. +/// +/// # Example +/// +/// ```no_run +/// use gadget_sdk::store::LocalDatabase; +/// +/// let db = LocalDatabase::::open("data.json"); +/// +/// db.set("key", 42); +/// assert_eq!(db.get("key"), Some(42)); +/// ``` +#[derive(Debug)] +pub struct LocalDatabase { + path: PathBuf, + data: Mutex>, +} + +impl LocalDatabase +where + T: Serialize + DeserializeOwned + Clone + Default, +{ + /// Reads a `LocalDatabase` from the given path. + /// + /// If the file does not exist, an empty database is created. + /// + /// # Example + /// + /// ```no_run + /// use gadget_sdk::store::LocalDatabase; + /// + /// let db = LocalDatabase::::open("data.json"); + /// assert!(db.is_empty()); + /// ``` + #[must_use] + pub fn open>(path: P) -> Self { + let path = path.as_ref(); + let parent_dir = path.parent().expect("Failed to get parent directory"); + + // Create the parent directory if it doesn't exist + fs::create_dir_all(parent_dir).expect("Failed to create parent directory"); + + let data = if path.exists() { + let content = fs::read_to_string(path).expect("Failed to read the file"); + serde_json::from_str(&content).unwrap_or_default() + } else { + HashMap::new() + }; + + Self { + path: path.to_owned(), + data: Mutex::new(data), + } + } + + /// Returns the number of key-value pairs in the database. + /// + /// # Example + /// + /// ```no_run + /// use gadget_sdk::store::LocalDatabase; + /// + /// let db = LocalDatabase::::open("data.json"); + /// assert_eq!(db.len(), 0); + /// + /// db.set("key", 42); + /// assert_eq!(db.len(), 1); + /// ``` + pub fn len(&self) -> usize { + let data = self.data.lock().unwrap(); + data.len() + } + + /// Checks if the database is empty. + /// + /// # Example + /// + /// ```no_run + /// use gadget_sdk::store::LocalDatabase; + /// + /// let db = LocalDatabase::::open("data.json"); + /// assert!(db.is_empty()); + /// + /// db.set("key", 42); + /// assert!(!db.is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { + let data = self.data.lock().unwrap(); + data.is_empty() + } + + /// Adds or updates a key-value pair in the database. + /// + /// # Example + /// + /// ```no_run + /// use gadget_sdk::store::LocalDatabase; + /// + /// let db = LocalDatabase::::open("data.json"); + /// + /// db.set("key", 42); + /// assert_eq!(db.get("key"), Some(42)); + /// ``` + pub fn set(&self, key: &str, value: T) { + let mut data = self.data.lock().unwrap(); + let _old = data.insert(key.to_string(), value); + + // Save the data while the lock is held + let json_string = serde_json::to_string(&*data).expect("Failed to serialize data to JSON"); + fs::write(&self.path, json_string).expect("Failed to write to the file"); + } + + /// Retrieves a value associated with the given key. + /// + /// # Example + /// + /// ```no_run + /// use gadget_sdk::store::LocalDatabase; + /// + /// let db = LocalDatabase::::open("data.json"); + /// + /// db.set("key", 42); + /// assert_eq!(db.get("key"), Some(42)); + /// ``` + pub fn get(&self, key: &str) -> Option { + let data = self.data.lock().unwrap(); + data.get(key).cloned() + } +} diff --git a/crates/stores/src/lib.rs b/crates/stores/src/lib.rs new file mode 100644 index 0000000..42a3a07 --- /dev/null +++ b/crates/stores/src/lib.rs @@ -0,0 +1,2 @@ +#[cfg(feature = "local")] +pub use gadget_store_local_database as local_database; diff --git a/crates/utils/tangle/Cargo.toml b/crates/utils/tangle/Cargo.toml index 8d2049f..fa28fe7 100644 --- a/crates/utils/tangle/Cargo.toml +++ b/crates/utils/tangle/Cargo.toml @@ -8,7 +8,17 @@ homepage.workspace = true repository.workspace = true [dependencies] +async-trait = { workspace = true } +gadget-std = { workspace = true } +gadget-logging = { workspace = true } +subxt = { workspace = true } +tracing = { workspace = true, features = ["attributes"] } [features] default = ["std"] -std = [] \ No newline at end of file +std = [ + "gadget-std/std", + "gadget-logging/std", + "subxt/native", +] +no_std = ["subxt/web"] \ No newline at end of file diff --git a/crates/utils/tangle/src/lib.rs b/crates/utils/tangle/src/lib.rs index b93cf3f..618ca4c 100644 --- a/crates/utils/tangle/src/lib.rs +++ b/crates/utils/tangle/src/lib.rs @@ -1,14 +1,2 @@ -pub fn add(left: u64, right: u64) -> u64 { - left + right -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} +pub mod tx; +pub mod tx_progress; diff --git a/crates/utils/tangle/src/tx.rs b/crates/utils/tangle/src/tx.rs new file mode 100644 index 0000000..1cdc1ac --- /dev/null +++ b/crates/utils/tangle/src/tx.rs @@ -0,0 +1,51 @@ +/// Send a transaction to the Tangle network. +/// +/// # Errors +/// +/// Returns a [`subxt::Error`] if the transaction fails. +#[tracing::instrument(skip_all)] +pub async fn send( + client: &subxt::OnlineClient, + signer: &S, + xt: &X, +) -> Result, subxt::Error> +where + T: subxt::Config, + S: subxt::tx::Signer, + X: subxt::tx::Payload, + >::Params: Default, +{ + if let Some(details) = xt.validation_details() { + gadget_logging::debug!("Calling {}.{}", details.pallet_name, details.call_name); + } + + gadget_logging::debug!("Waiting for the transaction to be included in a finalized block"); + let progress = client + .tx() + .sign_and_submit_then_watch_default(xt, signer) + .await?; + + #[cfg(not(test))] + { + gadget_logging::debug!("Waiting for finalized success ..."); + let result = progress.wait_for_finalized_success().await?; + gadget_logging::debug!( + "Transaction with hash: {:?} has been finalized", + result.extrinsic_hash() + ); + Ok(result) + } + #[cfg(test)] + { + // In tests, we don't wait for the transaction to be finalized. + // This is because the test environment we will be using instant sealing. + // Instead, we just wait for the transaction to be included in a block. + gadget_logging::debug!("Waiting for in block success ..."); + let result = progress.wait_for_in_block_success().await?; + gadget_logging::debug!( + "Transaction with hash: {:?} has been included in a block", + result.extrinsic_hash() + ); + Ok(result) + } +} diff --git a/crates/utils/tangle/src/tx_progress.rs b/crates/utils/tangle/src/tx_progress.rs new file mode 100644 index 0000000..289b4fd --- /dev/null +++ b/crates/utils/tangle/src/tx_progress.rs @@ -0,0 +1,74 @@ +use subxt::{ + client::OnlineClientT, + error::TransactionError, + tx::{TxInBlock, TxStatus}, +}; + +/// Extension trait for transaction progress handling. +/// +/// This trait provides additional methods for handling the progress of a transaction, +/// such as waiting for the transaction to be included in a block successfully. +/// +/// # Type Parameters +/// +/// - `T`: The configuration type for the Substrate runtime. +/// - `C`: The client type that implements the `OnlineClientT` trait. +#[async_trait::async_trait] +pub trait TxProgressExt { + /// Wait for the transaction to be in block, and return a [`TxInBlock`] + /// instance when it is, or an error if there was a problem waiting for finalization. + /// + /// **Note:** consumes `self`. If you'd like to perform multiple actions as the state of the + /// transaction progresses, use [`TxProgress::next()`] instead. + /// + /// **Note:** transaction statuses like `Invalid`/`Usurped`/`Dropped` indicate with some + /// probability that the transaction will not make it into a block but there is no guarantee + /// that this is true. In those cases the stream is closed however, so you currently have no way to find + /// out if they finally made it into a block or not. + async fn wait_for_in_block(mut self) -> Result, subxt::Error>; + + /// Wait for the transaction to be finalized, and for the transaction events to indicate + /// that the transaction was successful. Returns the events associated with the transaction, + /// as well as a couple of other details (block hash and extrinsic hash). + /// + /// **Note:** consumes self. If you'd like to perform multiple actions as progress is made, + /// use [`TxProgress::next()`] instead. + /// + /// **Note:** transaction statuses like `Invalid`/`Usurped`/`Dropped` indicate with some + /// probability that the transaction will not make it into a block but there is no guarantee + /// that this is true. In those cases the stream is closed however, so you currently have no way to find + /// out if they finally made it into a block or not. + async fn wait_for_in_block_success( + self, + ) -> Result, subxt::Error>; +} + +#[async_trait::async_trait] +impl> TxProgressExt for subxt::tx::TxProgress { + async fn wait_for_in_block(mut self) -> Result, subxt::Error> { + while let Some(status) = self.next().await { + match status? { + // In Block! Return. + TxStatus::InBestBlock(s) => return Ok(s), + // Error scenarios; return the error. + TxStatus::Error { message } => return Err(TransactionError::Error(message).into()), + TxStatus::Invalid { message } => { + return Err(TransactionError::Invalid(message).into()) + } + TxStatus::Dropped { message } => { + return Err(TransactionError::Dropped(message).into()) + } + // Ignore and wait for next status event: + _ => continue, + } + } + Err(subxt::error::RpcError::SubscriptionDropped.into()) + } + + async fn wait_for_in_block_success( + self, + ) -> Result, subxt::Error> { + let evs = self.wait_for_in_block().await?.wait_for_success().await?; + Ok(evs) + } +} From e20b07c2d74f8441c85e18ea1f1160c5b91a794e Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Mon, 16 Dec 2024 17:33:06 -0700 Subject: [PATCH 2/3] chore: add ci --- .github/workflows/build-setup.yml | 7 ++ .github/workflows/ci.yml | 128 +++++++++++++++++++++++++ Cargo.lock | 1 + crates/event-listeners/core/Cargo.toml | 6 +- crates/event-listeners/core/src/lib.rs | 7 ++ 5 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/build-setup.yml create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/build-setup.yml b/.github/workflows/build-setup.yml new file mode 100644 index 0000000..5af4396 --- /dev/null +++ b/.github/workflows/build-setup.yml @@ -0,0 +1,7 @@ +# This file is used to install the Foundry toolchain and verify the installation. + +- name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + +- name: Verify Forge installation + run: forge --version diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c80a61a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,128 @@ +name: CI + +on: + pull_request: + branches: [main] + push: + branches: [main] + workflow_dispatch: + +concurrency: + group: rust-validation-${{ github.head_ref }} + cancel-in-progress: true + +env: + RUST_BACKTRACE: full + RUST_LOG: "gadget=trace" + CARGO_TERM_COLOR: always + +jobs: + formatting: + name: Rustfmt + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v2 + + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + components: rustfmt + + - name: Check Formatting + run: cargo fmt -- --check + + linting: + timeout-minutes: 120 + name: cargo clippy + runs-on: macos-latest + steps: + - name: checkout code + uses: actions/checkout@v2 + + - name: Install Foundry + run: | + curl -L https://foundry.paradigm.xyz | bash + source /Users/runner/.bashrc + foundryup + + - name: Add Foundry to PATH + run: echo "${HOME}/.foundry/bin" >> $GITHUB_PATH + + - name: Verify Forge installation + run: forge --version + + - name: install rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + + - uses: swatinem/rust-cache@v2 + with: + cache-on-failure: "true" + + - name: install protobuf + run: brew install protobuf + + - name: Run Clippy + run: cargo clippy --tests --examples -- -D warnings + + testing: + timeout-minutes: 90 + name: cargo test + runs-on: macos-14 + strategy: + matrix: + package: + [ + gadget-blueprint-serde, + gadget-clients, + gadget-contexts, + gadget-crypto, + gadget-crypto-core, + gadget-crypto-sp-core, + gadget-crypto-ed25519, + gadget-crypto-bls, + gadget-crypto-k256, + gadget-crypto-sr25519, + gadget-crypto-tangle-pair-signer, + gadget-event-listeners-core, + gadget-event-listeners-evm, + gadget-event-listeners-periodic, + gadget-event-listeners-tangle, + gadget-keystore, + gadget-logging, + gadget-std, + gadget-utils-tangle, + ] + steps: + - name: checkout code + uses: actions/checkout@v2 + + - name: install rust + uses: dtolnay/rust-toolchain@nightly + with: + toolchain: stable + + - uses: swatinem/rust-cache@v2 + with: + cache-on-failure: "true" + + - name: install protobuf + run: brew install protobuf gmp + + - name: Set Relevant M1 env vars + run: | + export LIBRARY_PATH=$LIBRARY_PATH:/opt/homebrew/lib + export INCLUDE_PATH=$INCLUDE_PATH:/opt/homebrew/include + + - name: install cargo-nextest + run: cargo install cargo-nextest --locked + + - name: tests + run: cargo nextest run --nocapture --package ${{ matrix.package }} ${{ matrix.package == 'gadget-sdk' && '--features getrandom,std' || '' }} + + # TODO: nextest doesn't support doc tests yet (https://github.com/nextest-rs/nextest/issues/16) + - name: doc tests + run: cargo test --package ${{ matrix.package }} --doc diff --git a/Cargo.lock b/Cargo.lock index 969ed33..fbe20c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5107,6 +5107,7 @@ version = "0.1.0" dependencies = [ "async-trait", "gadget-std", + "tokio", ] [[package]] diff --git a/crates/event-listeners/core/Cargo.toml b/crates/event-listeners/core/Cargo.toml index 3309c09..bc6a6bf 100644 --- a/crates/event-listeners/core/Cargo.toml +++ b/crates/event-listeners/core/Cargo.toml @@ -6,8 +6,12 @@ edition = "2021" [dependencies] gadget-std = { workspace = true } async-trait = { workspace = true } +tokio = { workspace = true } [features] default = ["std"] -std = ["gadget-std/std"] +std = [ + "gadget-std/std", + "tokio/full", +] testing = [] \ No newline at end of file diff --git a/crates/event-listeners/core/src/lib.rs b/crates/event-listeners/core/src/lib.rs index e874ae6..f617a59 100644 --- a/crates/event-listeners/core/src/lib.rs +++ b/crates/event-listeners/core/src/lib.rs @@ -23,3 +23,10 @@ pub trait EventListener: Send + 'static pub fn get_exponential_backoff() -> Take { ExponentialBackoff::from_millis(2).factor(1000).take(N) } + +#[async_trait] +pub trait InitializableEventHandler { + async fn init_event_handler( + &self, + ) -> Option>>; +} From e0796390d2cf0f95cb30f300652c4ec504f60b8b Mon Sep 17 00:00:00 2001 From: drewstone Date: Tue, 17 Dec 2024 08:54:32 -0700 Subject: [PATCH 3/3] chore: test instrumented client and others (#9) * chore: test instrumented client * chore: test config * chore: replace bytes with list * chore: work on eigenlayer client test * chore: update p2p client --- Cargo.lock | 10 + crates/benchmarking/src/lib.rs | 6 +- crates/blueprint-serde/src/ser.rs | 4 +- crates/blueprint-serde/src/tests.rs | 8 +- crates/clients/eigenlayer/Cargo.toml | 9 + crates/clients/eigenlayer/src/eigenlayer.rs | 94 +-- crates/clients/eigenlayer/src/lib.rs | 111 +++ crates/clients/evm/Cargo.toml | 5 + crates/clients/evm/src/instrumented_client.rs | 157 ++-- crates/clients/networking/Cargo.toml | 6 +- crates/clients/networking/src/error.rs | 4 +- crates/clients/networking/src/p2p.rs | 65 +- crates/config/Cargo.toml | 32 +- crates/config/src/context_config.rs | 2 +- crates/config/src/lib.rs | 158 +++- crates/config/src/protocol.rs | 2 +- crates/networking/Cargo.toml | 13 +- crates/networking/src/channels.rs | 779 ------------------ crates/networking/src/lib.rs | 12 +- crates/networking/src/networking.rs | 37 +- crates/stores/local-database/Cargo.toml | 5 +- crates/stores/local-database/src/lib.rs | 154 +++- crates/testing-utils/anvil/data/state.json | 533 ++++++++++++ crates/testing-utils/anvil/src/anvil.rs | 5 +- crates/testing-utils/anvil/src/lib.rs | 3 + 25 files changed, 1244 insertions(+), 970 deletions(-) delete mode 100644 crates/networking/src/channels.rs create mode 100644 crates/testing-utils/anvil/data/state.json diff --git a/Cargo.lock b/Cargo.lock index fbe20c4..7e7dcfd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4822,10 +4822,13 @@ dependencies = [ "alloy-network 0.5.4", "alloy-primitives", "alloy-provider", + "alloy-pubsub", "alloy-transport", "eigensdk", + "gadget-anvil-utils", "gadget-config", "gadget-std", + "gadget-utils-evm", "num-bigint", "thiserror 2.0.7", "tokio", @@ -4847,12 +4850,15 @@ dependencies = [ "alloy-rpc-client", "alloy-rpc-types", "alloy-rpc-types-eth 0.5.4", + "alloy-signer-local", "alloy-transport", "alloy-transport-http", "async-trait", + "gadget-anvil-utils", "gadget-logging", "gadget-rpc-calls", "gadget-std", + "gadget-utils-evm", "hex", "serde", "serde_json", @@ -4868,6 +4874,7 @@ dependencies = [ "async-trait", "gadget-config", "gadget-crypto", + "gadget-logging", "gadget-networking", "gadget-std", "libp2p", @@ -4913,6 +4920,7 @@ version = "0.1.0" dependencies = [ "alloy-primitives", "clap", + "gadget-config", "gadget-std", "libp2p", "lock_api", @@ -5246,6 +5254,7 @@ dependencies = [ "thiserror 2.0.7", "tokio", "tracing", + "tracing-subscriber 0.3.19", ] [[package]] @@ -5273,6 +5282,7 @@ dependencies = [ "gadget-std", "serde", "serde_json", + "tempfile", ] [[package]] diff --git a/crates/benchmarking/src/lib.rs b/crates/benchmarking/src/lib.rs index 9544856..239966e 100644 --- a/crates/benchmarking/src/lib.rs +++ b/crates/benchmarking/src/lib.rs @@ -59,7 +59,7 @@ impl Bencher { /// # Examples /// /// ``` - /// use gadget_sdk::benchmark::{Bencher, TokioRuntime}; + /// use gadget_benchmarking::{Bencher, TokioRuntime}; /// /// const THREADS: usize = 4; /// @@ -78,7 +78,7 @@ impl Bencher { /// # Examples /// /// ```no_run - /// use gadget_sdk::benchmark::{Bencher, TokioRuntime}; + /// use gadget_benchmarking::{Bencher, TokioRuntime}; /// /// const THREADS: usize = 4; /// @@ -99,7 +99,7 @@ impl Bencher { /// # Examples /// /// ```no_run - /// use gadget_sdk::benchmark::{Bencher, TokioRuntime}; + /// use gadget_benchmarking::{Bencher, TokioRuntime}; /// const THREADS: usize = 4; /// /// let bencher = Bencher::new(THREADS, TokioRuntime); diff --git a/crates/blueprint-serde/src/ser.rs b/crates/blueprint-serde/src/ser.rs index 5099b3d..eb25986 100644 --- a/crates/blueprint-serde/src/ser.rs +++ b/crates/blueprint-serde/src/ser.rs @@ -79,7 +79,9 @@ impl<'a> serde::Serializer for &'a mut Serializer { } fn serialize_bytes(self, v: &[u8]) -> Result { - Ok(Field::Bytes(BoundedVec(v.into()))) + Ok(Field::List(BoundedVec( + v.iter().map(|b| Field::Uint8(*b)).collect(), + ))) } fn serialize_none(self) -> Result { diff --git a/crates/blueprint-serde/src/tests.rs b/crates/blueprint-serde/src/tests.rs index 200c01f..83a67fd 100644 --- a/crates/blueprint-serde/src/tests.rs +++ b/crates/blueprint-serde/src/tests.rs @@ -457,7 +457,7 @@ mod sequences { use alloc::vec::Vec; fn expected_empty_bytes_field() -> Field { - Field::Bytes(BoundedVec(Vec::new())) + Field::List(BoundedVec(Vec::new())) } #[test] @@ -491,7 +491,11 @@ mod sequences { } fn expected_bytes_field() -> Field { - Field::Bytes(BoundedVec(vec![1, 2, 3])) + Field::List(BoundedVec(vec![ + Field::Uint8(1), + Field::Uint8(2), + Field::Uint8(3), + ])) } #[test] diff --git a/crates/clients/eigenlayer/Cargo.toml b/crates/clients/eigenlayer/Cargo.toml index 751e797..30450b3 100644 --- a/crates/clients/eigenlayer/Cargo.toml +++ b/crates/clients/eigenlayer/Cargo.toml @@ -6,10 +6,12 @@ edition = "2021" [dependencies] gadget-config = { workspace = true, features = ["eigenlayer"] } gadget-std = { workspace = true } +gadget-utils-evm = { workspace = true } alloy-contract = { workspace = true } alloy-network = { workspace = true } alloy-primitives = { workspace = true } alloy-provider = { workspace = true } +alloy-pubsub = { workspace = true } alloy-transport = { workspace = true } eigensdk = { workspace = true, features = [ "client-avsregistry", @@ -27,11 +29,18 @@ tokio = { workspace = true } tokio-util = { workspace = true } url = { workspace = true } +[dev-dependencies] +gadget-anvil-utils = { workspace = true } +gadget-utils-evm = { workspace = true } +alloy-primitives = { workspace = true } +tokio = { workspace = true, features = ["full"] } + [features] default = ["std"] std = [ "gadget-config/std", "gadget-std/std", + "gadget-utils-evm/std", "tokio/full", "url/std", ] \ No newline at end of file diff --git a/crates/clients/eigenlayer/src/eigenlayer.rs b/crates/clients/eigenlayer/src/eigenlayer.rs index d7d6ae8..cce9bd4 100644 --- a/crates/clients/eigenlayer/src/eigenlayer.rs +++ b/crates/clients/eigenlayer/src/eigenlayer.rs @@ -1,10 +1,12 @@ use crate::error::{EigenlayerClientError, Result}; use alloy_primitives::{Address, Bytes}; use alloy_provider::{Provider, ProviderBuilder, RootProvider}; +use alloy_pubsub::PubSubFrontend; use alloy_transport::BoxTransport; -use eigensdk::client_avsregistry::reader::AvsRegistryReader; +use eigensdk::{client_avsregistry::reader::AvsRegistryReader, utils::get_ws_provider}; use gadget_config::GadgetConfiguration; use gadget_std::collections::HashMap; +use gadget_utils_evm::{get_provider_http, get_wallet_provider_http}; use num_bigint::BigInt; /// Client that provides access to EigenLayer utility functions through the use of the [`GadgetConfiguration`]. @@ -17,18 +19,8 @@ impl EigenlayerClient { /// /// # Returns /// - [`The HTTP provider`](RootProvider) - pub fn get_provider_http(&self) -> Result> { - let http_endpoint = self.config.http_rpc_endpoint.clone(); - let http_endpoint = http_endpoint - .parse() - .map_err(|e| gadget_std::io::Error::new(gadget_std::io::ErrorKind::InvalidInput, e))?; - let provider = ProviderBuilder::new() - .with_recommended_fillers() - .on_http(http_endpoint) - .root() - .clone() - .boxed(); - Ok(provider) + pub fn get_provider_http(&self) -> RootProvider { + get_provider_http(&self.config.http_rpc_endpoint) } /// Get the provider for this client's http endpoint with the specified [`Wallet`](EthereumWallet) @@ -38,34 +30,18 @@ impl EigenlayerClient { pub fn get_wallet_provider_http( &self, wallet: alloy_network::EthereumWallet, - ) -> Result> { - let http_endpoint = self.config.http_rpc_endpoint.clone(); - let http_endpoint = http_endpoint.parse()?; - let provider = ProviderBuilder::new() - .with_recommended_fillers() - .wallet(wallet) - .on_http(http_endpoint) - .root() - .clone() - .boxed(); - Ok(provider) + ) -> RootProvider { + get_wallet_provider_http(&self.config.http_rpc_endpoint, wallet) } /// Get the provider for this client's websocket endpoint /// /// # Returns /// - [`The WS provider`](RootProvider) - pub async fn get_provider_ws(&self) -> Result> { - let ws_endpoint = self.config.ws_rpc_endpoint.clone(); - let provider = ProviderBuilder::new() - .with_recommended_fillers() - .on_ws(alloy_provider::WsConnect::new(ws_endpoint)) + pub async fn get_provider_ws(&self) -> Result> { + get_ws_provider(&self.config.ws_rpc_endpoint) .await - .unwrap() - .root() - .clone() - .boxed(); - Ok(provider) + .map_err(Into::into) } /// Get the slasher address from the `DelegationManager` contract @@ -76,7 +52,7 @@ impl EigenlayerClient { /// # Errors /// - [`Error::AlloyContract`] - If the call to the contract fails (i.e. the contract doesn't exist at the given address) pub async fn get_slasher_address(&self, delegation_manager_addr: Address) -> Result
{ - let provider = self.get_provider_http()?; + let provider = self.get_provider_http(); let delegation_manager = eigensdk::utils::delegationmanager::DelegationManager::DelegationManagerInstance::new( delegation_manager_addr, @@ -91,7 +67,7 @@ impl EigenlayerClient { } /// Provides a reader for the AVS registry. - async fn avs_registry_reader( + pub async fn avs_registry_reader( &self, ) -> Result { let http_rpc_endpoint = self.config.http_rpc_endpoint.clone(); @@ -109,7 +85,7 @@ impl EigenlayerClient { } /// Provides a writer for the AVS registry. - async fn avs_registry_writer( + pub async fn avs_registry_writer( &self, private_key: String, ) -> Result { @@ -129,7 +105,7 @@ impl EigenlayerClient { } /// Provides an operator info service. - async fn operator_info_service_in_memory( + pub async fn operator_info_service_in_memory( &self, ) -> Result<( eigensdk::services_operatorsinfo::operatorsinfo_inmemory::OperatorInfoServiceInMemory, @@ -150,7 +126,7 @@ impl EigenlayerClient { } /// Provides an AVS registry service chain caller. - async fn avs_registry_service_chain_caller_in_memory( + pub async fn avs_registry_service_chain_caller_in_memory( &self, ) -> Result< eigensdk::services_avsregistry::chaincaller::AvsRegistryServiceChainCaller< @@ -163,7 +139,7 @@ impl EigenlayerClient { let cancellation_token = tokio_util::sync::CancellationToken::new(); let token_clone = cancellation_token.clone(); - let provider = self.get_provider_http()?; + let provider = self.get_provider_http(); let current_block = provider.get_block_number().await?; let operator_info_clone = operator_info_service.clone(); @@ -182,7 +158,7 @@ impl EigenlayerClient { } /// Provides a BLS aggregation service. - async fn bls_aggregation_service_in_memory(&self) -> Result Result, ) -> Result> { @@ -223,7 +199,7 @@ impl EigenlayerClient { } /// Get an Operator by ID. - async fn get_operator_by_id(&self, operator_id: [u8; 32]) -> Result
{ + pub async fn get_operator_by_id(&self, operator_id: [u8; 32]) -> Result
{ self.avs_registry_reader() .await? .get_operator_from_id(operator_id) @@ -232,13 +208,13 @@ impl EigenlayerClient { } /// Get an Operator stake history. - async fn get_operator_stake_history( + pub async fn get_operator_stake_history( &self, operator_id: alloy_primitives::FixedBytes<32>, quorum_number: u8, ) -> Result> { let contract_addresses = self.config.protocol_settings.eigenlayer()?; - let provider = self.get_provider_http()?; + let provider = self.get_provider_http(); let registry_coordinator = eigensdk::utils::registrycoordinator::RegistryCoordinator::new( contract_addresses.registry_coordinator_address, provider.clone(), @@ -254,14 +230,14 @@ impl EigenlayerClient { } /// Get an Operator stake update at a given index. - async fn get_operator_stake_update_at_index( + pub async fn get_operator_stake_update_at_index( &self, quorum_number: u8, operator_id: alloy_primitives::FixedBytes<32>, index: alloy_primitives::U256, ) -> Result { let contract_addresses = self.config.protocol_settings.eigenlayer()?; - let provider = self.get_provider_http()?; + let provider = self.get_provider_http(); let registry_coordinator = eigensdk::utils::registrycoordinator::RegistryCoordinator::new( contract_addresses.registry_coordinator_address, provider.clone(), @@ -277,14 +253,14 @@ impl EigenlayerClient { } /// Get an Operator's stake at a given block number. - async fn get_operator_stake_at_block_number( + pub async fn get_operator_stake_at_block_number( &self, operator_id: alloy_primitives::FixedBytes<32>, quorum_number: u8, block_number: u32, ) -> Result> { let contract_addresses = self.config.protocol_settings.eigenlayer()?; - let provider = self.get_provider_http()?; + let provider = self.get_provider_http(); let registry_coordinator = eigensdk::utils::registrycoordinator::RegistryCoordinator::new( contract_addresses.registry_coordinator_address, provider.clone(), @@ -300,7 +276,7 @@ impl EigenlayerClient { } /// Get an Operator's [`details`](OperatorDetails). - async fn get_operator_details( + pub async fn get_operator_details( &self, operator_addr: Address, ) -> Result { @@ -320,13 +296,13 @@ impl EigenlayerClient { } /// Get an Operator's latest stake update. - async fn get_latest_stake_update( + pub async fn get_latest_stake_update( &self, operator_id: alloy_primitives::FixedBytes<32>, quorum_number: u8, ) -> Result { let contract_addresses = self.config.protocol_settings.eigenlayer()?; - let provider = self.get_provider_http()?; + let provider = self.get_provider_http(); let registry_coordinator = eigensdk::utils::registrycoordinator::RegistryCoordinator::new( contract_addresses.registry_coordinator_address, provider.clone(), @@ -342,7 +318,7 @@ impl EigenlayerClient { } /// Get an Operator's ID as [`FixedBytes`] from its [`Address`]. - async fn get_operator_id( + pub async fn get_operator_id( &self, operator_addr: Address, ) -> Result> { @@ -354,7 +330,7 @@ impl EigenlayerClient { } /// Get the total stake at a given block number from a given index. - async fn get_total_stake_at_block_number_from_index( + pub async fn get_total_stake_at_block_number_from_index( &self, quorum_number: u8, block_number: u32, @@ -362,7 +338,7 @@ impl EigenlayerClient { ) -> Result> { use alloy_provider::Provider as _; let contract_addresses = self.config.protocol_settings.eigenlayer()?; - let provider = self.get_provider_http()?; + let provider = self.get_provider_http(); let registry_coordinator = eigensdk::utils::registrycoordinator::RegistryCoordinator::new( contract_addresses.registry_coordinator_address, provider.clone(), @@ -379,12 +355,12 @@ impl EigenlayerClient { } /// Get the total stake history length of a given quorum. - async fn get_total_stake_history_length( + pub async fn get_total_stake_history_length( &self, quorum_number: u8, ) -> Result { let contract_addresses = self.config.protocol_settings.eigenlayer()?; - let provider = self.get_provider_http()?; + let provider = self.get_provider_http(); let registry_coordinator = eigensdk::utils::registrycoordinator::RegistryCoordinator::new( contract_addresses.registry_coordinator_address, provider.clone(), @@ -400,7 +376,7 @@ impl EigenlayerClient { } /// Provides the public keys of existing registered operators within the provided block range. - async fn query_existing_registered_operator_pub_keys( + pub async fn query_existing_registered_operator_pub_keys( &self, start_block: u64, to_block: u64, diff --git a/crates/clients/eigenlayer/src/lib.rs b/crates/clients/eigenlayer/src/lib.rs index cd045d0..181771d 100644 --- a/crates/clients/eigenlayer/src/lib.rs +++ b/crates/clients/eigenlayer/src/lib.rs @@ -1,2 +1,113 @@ pub mod eigenlayer; pub mod error; + +#[cfg(test)] +mod tests { + use super::*; + use alloy_primitives::{address, U256}; + use alloy_provider::Provider; + use eigenlayer::EigenlayerClient; + use gadget_anvil_utils::{start_anvil_container, ANVIL_STATE_PATH}; + use gadget_config::{ + load, + protocol::{EigenlayerContractAddresses, Protocol, ProtocolSettings}, + supported_chains::SupportedChains, + ContextConfig, GadgetCLICoreSettings, GadgetConfiguration, + }; + + async fn setup_test_environment() -> (String, String, GadgetConfiguration) { + let (_container, http_endpoint, ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + + // Create test configuration + let context_config = ContextConfig::create_eigenlayer_config( + http_endpoint.parse().unwrap(), + ws_endpoint.parse().unwrap(), + String::new(), + None, + SupportedChains::LocalTestnet, + EigenlayerContractAddresses::default(), + ); + let config = load(context_config).unwrap(); + + (http_endpoint, ws_endpoint, config) + } + + #[tokio::test] + async fn test_get_provider_http() { + let (_, _, config) = setup_test_environment().await; + let client = EigenlayerClient { config }; + let provider = client.get_provider_http(); + assert!(provider.get_block_number().await.is_ok()); + } + + #[tokio::test] + async fn test_get_provider_ws() { + let (_, _, config) = setup_test_environment().await; + let client = EigenlayerClient { config }; + let provider = client.get_provider_ws().await.unwrap(); + assert!(provider.get_block_number().await.is_ok()); + } + + #[tokio::test] + async fn test_get_slasher_address() { + let (_, _, config) = setup_test_environment().await; + let client = EigenlayerClient { config }; + let delegation_manager_addr = address!("dc64a140aa3e981100a9beca4e685f962f0cf6c9"); + let result = client.get_slasher_address(delegation_manager_addr).await; + assert!(result.is_err()); // Will error since contract doesn't exist in test environment + } + + #[tokio::test] + async fn test_avs_registry_reader() { + let (_, _, config) = setup_test_environment().await; + let client = EigenlayerClient { config }; + let result = client.avs_registry_reader().await; + assert!(result.is_ok()); + } + + #[tokio::test] + async fn test_avs_registry_writer() { + let (_, _, config) = setup_test_environment().await; + let client = EigenlayerClient { config }; + let private_key = "0000000000000000000000000000000000000000000000000000000000000001"; + let result = client.avs_registry_writer(private_key.to_string()).await; + assert!(result.is_ok()); + } + + #[tokio::test] + async fn test_operator_info_service() { + let (_, _, config) = setup_test_environment().await; + let client = EigenlayerClient { config }; + let result = client.operator_info_service_in_memory().await; + assert!(result.is_ok()); + } + + #[tokio::test] + async fn test_get_operator_stake_in_quorums() { + let (_, _, config) = setup_test_environment().await; + let client = EigenlayerClient { config }; + let result = client + .get_operator_stake_in_quorums_at_block(1, vec![1, 2].into()) + .await; + assert!(result.is_ok()); + } + + #[tokio::test] + async fn test_get_operator_id() { + let (_, _, config) = setup_test_environment().await; + let client = EigenlayerClient { config }; + let operator_addr = address!("f39fd6e51aad88f6f4ce6ab8827279cfffb92266"); + let result = client.get_operator_id(operator_addr).await; + assert!(result.is_ok()); + } + + #[tokio::test] + async fn test_get_operator_details() { + let (_, _, config) = setup_test_environment().await; + let client = EigenlayerClient { config }; + let operator_addr = address!("f39fd6e51aad88f6f4ce6ab8827279cfffb92266"); + let result = client.get_operator_details(operator_addr).await; + assert!(result.is_err()); // Will error since contract doesn't exist in test environment + } +} diff --git a/crates/clients/evm/Cargo.toml b/crates/clients/evm/Cargo.toml index fedde91..16dc673 100644 --- a/crates/clients/evm/Cargo.toml +++ b/crates/clients/evm/Cargo.toml @@ -31,6 +31,11 @@ tokio = { workspace = true } gadget-logging = { workspace = true } gadget-rpc-calls = { workspace = true } +[dev-dependencies] +gadget-utils-evm = { workspace = true } +gadget-anvil-utils = { workspace = true } +alloy-signer-local = { workspace = true } + [features] default = ["std"] std = [ diff --git a/crates/clients/evm/src/instrumented_client.rs b/crates/clients/evm/src/instrumented_client.rs index 662ddbb..99e0eb7 100644 --- a/crates/clients/evm/src/instrumented_client.rs +++ b/crates/clients/evm/src/instrumented_client.rs @@ -809,20 +809,19 @@ mod tests { use alloy_rpc_types::eth::{ pubsub::SubscriptionResult, BlockId, BlockNumberOrTag, BlockTransactionsKind, }; - use alloy_rpc_types::{BlockNumberOrTag, BlockTransactionsKind}; - use eigen_signer::signer::Config; - use eigen_testing_utils::anvil::start_anvil_container; - use eigen_testing_utils::transaction::wait_transaction; - use eigen_utils::get_provider; + use alloy_signer_local::PrivateKeySigner; + use gadget_anvil_utils::{start_anvil_container, wait_transaction, ANVIL_STATE_PATH}; + use gadget_utils_evm::get_provider_http; use tokio; #[tokio::test] async fn test_suggest_gas_tip_cap() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); let fee_per_gas = instrumented_client.suggest_gas_tip_cap().await.unwrap(); - let expected_fee_per_gas = get_provider(&http_endpoint) + let expected_fee_per_gas = get_provider_http(&http_endpoint) .get_max_priority_fee_per_gas() .await .unwrap(); @@ -831,8 +830,9 @@ mod tests { #[tokio::test] async fn test_gas_price() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); let gas_price = instrumented_client.suggest_gas_price().await.unwrap(); @@ -842,8 +842,9 @@ mod tests { #[tokio::test] async fn test_sync_status() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); let sync_status = instrumented_client.sync_progress().await.unwrap(); @@ -853,8 +854,9 @@ mod tests { #[tokio::test] async fn test_chain_id() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); @@ -866,8 +868,9 @@ mod tests { #[tokio::test] async fn test_balance_at() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); let address = provider.get_accounts().await.unwrap()[0]; @@ -883,7 +886,8 @@ mod tests { #[tokio::test] async fn test_subscribe_new_head() { - let (_container, _http_endpoint, ws_endpoint) = start_anvil_container().await; + let (_container, _http_endpoint, ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; let instrumented_client = InstrumentedClient::new_ws(&ws_endpoint).await.unwrap(); let subscription: TransportResult> = @@ -893,8 +897,9 @@ mod tests { #[tokio::test] async fn test_subscribe_filter_logs() { - let (_container, http_endpoint, ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new_ws(&ws_endpoint).await.unwrap(); let address = provider.clone().get_accounts().await.unwrap()[0]; @@ -908,14 +913,15 @@ mod tests { #[tokio::test] async fn test_block_by_hash() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); // get the hash from the last block let hash = provider - .get_block(BlockId::latest(), BlockTransactionsKind::Hashes) + .get_block(BlockId::latest(), BlockTransactionsKind::Hashes.into()) .await .unwrap() .unwrap() @@ -923,7 +929,7 @@ mod tests { .hash; let expected_block = provider - .get_block_by_hash(hash, BlockTransactionsKind::Full) + .get_block_by_hash(hash, BlockTransactionsKind::Full.into()) .await .unwrap(); let block = instrumented_client.block_by_hash(hash).await.unwrap(); @@ -933,14 +939,15 @@ mod tests { #[tokio::test] async fn test_block_by_number() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); let block_number = 1; let expected_block = provider - .get_block_by_number(block_number.into(), BlockTransactionsKind::Full) + .get_block_by_number(block_number.into(), BlockTransactionsKind::Full.into()) .await .unwrap(); let block = instrumented_client @@ -953,13 +960,14 @@ mod tests { #[tokio::test] async fn test_transaction_count() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); let block = provider - .get_block(BlockId::latest(), BlockTransactionsKind::Hashes) + .get_block(BlockId::latest(), BlockTransactionsKind::Hashes.into()) .await .unwrap() .unwrap(); @@ -980,8 +988,10 @@ mod tests { /// * `transaction_receipt` /// * `transaction_in_block` #[tokio::test] + #[ignore] async fn test_transaction_methods() { - let (_container, rpc_url, _ws_endpoint) = start_anvil_container().await; + let (_container, rpc_url, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; let instrumented_client = InstrumentedClient::new(&rpc_url).await.unwrap(); // build the transaction @@ -998,8 +1008,7 @@ mod tests { let private_key_hex = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80".to_string(); - let config = Config::PrivateKey(private_key_hex); - let signer = Config::signer_from_config(config).unwrap(); + let signer: PrivateKeySigner = private_key_hex.parse().unwrap(); let signature = signer.sign_transaction_sync(&mut tx).unwrap(); let signed_tx = tx.into_signed(signature); let tx: TxEnvelope = TxEnvelope::from(signed_tx); @@ -1032,8 +1041,9 @@ mod tests { #[tokio::test] async fn test_estimate_gas() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); let accounts = provider.get_accounts().await.unwrap(); @@ -1060,8 +1070,9 @@ mod tests { #[tokio::test] async fn test_call_contract_and_pending_call_contract() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); @@ -1103,8 +1114,9 @@ mod tests { #[tokio::test] async fn test_filter_logs() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); let address = provider.clone().get_accounts().await.unwrap()[0]; @@ -1118,8 +1130,9 @@ mod tests { #[tokio::test] async fn test_storage_at() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); @@ -1140,8 +1153,9 @@ mod tests { #[tokio::test] async fn test_block_number() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); @@ -1153,8 +1167,9 @@ mod tests { #[tokio::test] async fn test_code_at() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); let address = provider.get_accounts().await.unwrap()[0]; @@ -1170,8 +1185,9 @@ mod tests { #[tokio::test] async fn test_fee_history() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); let block_count = 4; @@ -1192,19 +1208,20 @@ mod tests { #[tokio::test] async fn test_header_by_hash() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); let hash = provider - .get_block(BlockId::latest(), BlockTransactionsKind::Hashes) + .get_block(BlockId::latest(), BlockTransactionsKind::Hashes.into()) .await .unwrap() .unwrap() .header .hash; let expected_header = provider - .get_block_by_hash(hash, BlockTransactionsKind::Hashes) + .get_block_by_hash(hash, BlockTransactionsKind::Hashes.into()) .await .unwrap() .unwrap() @@ -1216,8 +1233,9 @@ mod tests { #[tokio::test] async fn test_header_by_number() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); let block_number = BlockNumberOrTag::Earliest; @@ -1228,7 +1246,7 @@ mod tests { .unwrap(); let expected_header = provider - .get_block_by_number(block_number, BlockTransactionsKind::Hashes) + .get_block_by_number(block_number, BlockTransactionsKind::Hashes.into()) .await .unwrap() .unwrap() @@ -1239,8 +1257,9 @@ mod tests { #[tokio::test] async fn test_nonce_at() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); let address = provider.get_accounts().await.unwrap()[0]; @@ -1256,8 +1275,9 @@ mod tests { #[tokio::test] async fn test_pending_balance_at() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); let address = provider.get_accounts().await.unwrap()[0]; @@ -1274,8 +1294,9 @@ mod tests { #[tokio::test] async fn test_pending_code_at() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); let address = provider.get_accounts().await.unwrap()[0]; @@ -1289,8 +1310,9 @@ mod tests { #[tokio::test] async fn test_pending_nonce_at() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); let address = provider.get_accounts().await.unwrap()[0]; @@ -1304,8 +1326,9 @@ mod tests { #[tokio::test] async fn test_pending_storage_at() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); let address = provider.get_accounts().await.unwrap()[0]; @@ -1324,13 +1347,17 @@ mod tests { #[tokio::test] async fn test_pending_transaction_count() { - let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await; - let provider = get_provider(&http_endpoint); + let (_container, http_endpoint, _ws_endpoint) = + start_anvil_container(ANVIL_STATE_PATH, false).await; + let provider = get_provider_http(&http_endpoint); let instrumented_client = InstrumentedClient::new(&http_endpoint).await.unwrap(); let expected_transaction_count: u64 = provider - .get_block_by_number(BlockNumberOrTag::Pending, BlockTransactionsKind::Hashes) + .get_block_by_number( + BlockNumberOrTag::Pending, + BlockTransactionsKind::Hashes.into(), + ) .await .unwrap() .unwrap() diff --git a/crates/clients/networking/Cargo.toml b/crates/clients/networking/Cargo.toml index abf1c29..95c1ada 100644 --- a/crates/clients/networking/Cargo.toml +++ b/crates/clients/networking/Cargo.toml @@ -5,9 +5,10 @@ edition = "2021" [dependencies] async-trait = { workspace = true } -gadget-config = { workspace = true } +gadget-config = { workspace = true, features = ["networking"] } gadget-crypto = { workspace = true, features = ["k256"] } -gadget-networking = { workspace = true } +gadget-logging = { workspace = true } +gadget-networking = { workspace = true, features = ["round-based-compat"]} gadget-std = { workspace = true } libp2p = { workspace = true } proc-macro2 = { workspace = true } @@ -20,6 +21,7 @@ default = ["std"] std = [ "gadget-config/std", "gadget-crypto/std", + "gadget-logging/std", "gadget-networking/std", "gadget-std/std", "serde/std", diff --git a/crates/clients/networking/src/error.rs b/crates/clients/networking/src/error.rs index b12e69b..5f4c51d 100644 --- a/crates/clients/networking/src/error.rs +++ b/crates/clients/networking/src/error.rs @@ -9,8 +9,8 @@ pub enum NetworkError { Transport(String), #[error("Protocol error: {0}")] Protocol(String), - #[error("Connection error: {0}")] - Connection(String), + #[error("Configuration error: {0}")] + Configuration(String), } pub type Result = gadget_std::result::Result; diff --git a/crates/clients/networking/src/p2p.rs b/crates/clients/networking/src/p2p.rs index 37b5cb6..934d5c4 100644 --- a/crates/clients/networking/src/p2p.rs +++ b/crates/clients/networking/src/p2p.rs @@ -1,15 +1,21 @@ -use crate::error::Result; +use crate::error::{NetworkError, Result}; use gadget_config::GadgetConfiguration; -use gadget_crypto::k256_crypto::K256VerifyingKey; +use gadget_crypto::k256_crypto::{K256SigningKey, K256VerifyingKey}; +use gadget_networking::gossip::GossipHandle; use gadget_networking::round_based_compat::NetworkDeliveryWrapper; +use gadget_networking::setup::NetworkConfig; use gadget_networking::{networking::NetworkMultiplexer, round_based}; use gadget_std::collections::BTreeMap; +use gadget_std::net::IpAddr; use gadget_std::sync::Arc; use round_based::PartyIndex; pub struct P2PClient { name: proc_macro2::Ident, pub config: GadgetConfiguration, + pub target_addr: IpAddr, + pub target_port: u16, + pub my_ecdsa_key: K256SigningKey, } impl P2PClient { @@ -22,7 +28,60 @@ impl P2PClient { } } - /// Creates a network delivery wrapper for MPC communication + pub fn libp2p_identity(&self, ed25519_seed: Vec) -> Result { + let mut seed_bytes = ed25519_seed; + let keypair = libp2p::identity::Keypair::ed25519_from_bytes(&mut seed_bytes) + .map_err(|err| NetworkError::Configuration(err.to_string()))?; + Ok(keypair) + } + + /// Returns a new `NetworkConfig` for the current environment. + pub fn libp2p_network_config>( + &self, + network_name: T, + ed25519_seed: Vec, + ) -> Result { + let network_identity = self.libp2p_identity(ed25519_seed)?; + let network_config = NetworkConfig::new_service_network( + network_identity, + self.my_ecdsa_key.clone(), + self.config.bootnodes.clone(), + self.target_port, + network_name, + ); + + Ok(network_config) + } + + /// Starts the P2P network and returns the gossip handle + pub fn start_p2p_network>( + &self, + network_name: T, + ed25519_seed: Vec, + ) -> Result { + let network_config = self.libp2p_network_config(network_name, ed25519_seed)?; + match gadget_networking::setup::start_p2p_network(network_config) { + Ok(handle) => Ok(handle), + Err(err) => { + gadget_logging::error!("Failed to start network: {}", err.to_string()); + Err(NetworkError::Protocol(format!( + "Failed to start network: {err}" + ))) + } + } + } + + /// Creates a network multiplexer backend + fn create_network_multiplexer>( + &self, + network_name: T, + ed25519_seed: Vec, + ) -> Result> { + let handle = self.start_p2p_network(network_name, ed25519_seed)?; + Ok(Arc::new(NetworkMultiplexer::new(handle))) + } + + /// Creates a network delivery wrapper fn create_network_delivery_wrapper( &self, mux: Arc, diff --git a/crates/config/Cargo.toml b/crates/config/Cargo.toml index 252772d..40eb45d 100644 --- a/crates/config/Cargo.toml +++ b/crates/config/Cargo.toml @@ -12,27 +12,39 @@ gadget-std = { workspace = true } lock_api = { workspace = true } parking_lot = { workspace = true } serde = { workspace = true, features = ["derive"] } -serde_json = { workspace = true, optional = true } +serde_json = { workspace = true, features = ["alloc"], optional = true } thiserror = { workspace = true } tracing = { workspace = true } url = { workspace = true, features = ["serde"] } # Optional dependencies (feature-gated) libp2p = { workspace = true, optional = true } -alloy-primitives = { workspace = true, optional = true } +alloy-primitives = { workspace = true, features = ["serde"], optional = true } -[features] -default = ["std", "tangle"] -std = ["gadget-std/std", "serde_json"] -# Core feature groups -keystore = [] -networking = ["dep:libp2p"] +[dev-dependencies] +alloy-primitives = { workspace = true, features = ["serde"] } +gadget-config = { path = ".", features = ["std", "eigenlayer", "symbiotic", "tangle", "networking"] } +gadget-std = { workspace = true, features = ["std"] } +libp2p = { workspace = true } -# Protocol-specific features -tangle = [] +[features] +default = ["std"] +std = [ + "alloy-primitives/std", + "clap/std", + "gadget-std/std", + "serde/std", + "serde_json/std", +] eigenlayer = ["dep:alloy-primitives"] symbiotic = ["dep:alloy-primitives"] +tangle = [] +networking = ["libp2p"] + +# Core feature groups +keystore = [] # Testing features test-utils = ["std"] + diff --git a/crates/config/src/context_config.rs b/crates/config/src/context_config.rs index 5eca404..3d4d6f7 100644 --- a/crates/config/src/context_config.rs +++ b/crates/config/src/context_config.rs @@ -443,7 +443,7 @@ impl ContextConfig { keystore_uri: String, keystore_password: Option, chain: SupportedChains, - symbiotic_contract_addresses: SymbioticContractAddresses, + symbiotic_contract_addresses: crate::protocol::SymbioticContractAddresses, ) -> Self { Self::create_config_with_defaults( http_rpc_url, diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index 49a61c7..bd18f1f 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -81,6 +81,7 @@ pub struct GadgetConfiguration { pub http_rpc_endpoint: String, /// WS RPC endpoint for host restaking network (Tangle / Ethereum (Eigenlayer or Symbiotic)). pub ws_rpc_endpoint: String, + /// The keystore URI for the gadget pub keystore_uri: String, /// Data directory exclusively for this gadget @@ -199,17 +200,19 @@ fn load_inner(config: ContextConfig) -> Result { #[cfg(feature = "symbiotic")] { ProtocolSettings::from_symbiotic(crate::protocol::SymbioticContractAddresses { - operator_registry: operator_registry + operator_registry_address: operator_registry + .ok_or(Error::MissingSymbioticContractAddresses)?, + network_registry_address: network_registry .ok_or(Error::MissingSymbioticContractAddresses)?, - network_registry: network_registry + base_delegator_address: base_delegator .ok_or(Error::MissingSymbioticContractAddresses)?, - base_delegator: base_delegator.ok_or(Error::MissingSymbioticContractAddresses)?, - network_opt_in_service: network_opt_in_service + network_opt_in_service_address: network_opt_in_service .ok_or(Error::MissingSymbioticContractAddresses)?, - vault_opt_in_service: vault_opt_in_service + vault_opt_in_service_address: vault_opt_in_service + .ok_or(Error::MissingSymbioticContractAddresses)?, + slasher_address: slasher.ok_or(Error::MissingSymbioticContractAddresses)?, + veto_slasher_address: veto_slasher .ok_or(Error::MissingSymbioticContractAddresses)?, - slasher: slasher.ok_or(Error::MissingSymbioticContractAddresses)?, - veto_slasher: veto_slasher.ok_or(Error::MissingSymbioticContractAddresses)?, }) } #[cfg(not(feature = "symbiotic"))] @@ -239,10 +242,151 @@ fn load_inner(config: ContextConfig) -> Result { #[cfg(test)] mod tests { use super::*; + use crate::protocol::{Protocol, ProtocolSettings}; #[test] fn verify_cli() { use clap::CommandFactory; ContextConfig::command().debug_assert(); } + + #[test] + fn test_default_configuration() { + let config = GadgetConfiguration::default(); + assert!(config.http_rpc_endpoint.is_empty()); + assert!(config.ws_rpc_endpoint.is_empty()); + assert!(config.keystore_uri.is_empty()); + assert!(config.data_dir.is_none()); + assert!(!config.test_mode); + assert_eq!(config.protocol, Protocol::default()); + } + + // Test Eigenlayer configuration when feature is enabled + #[cfg(feature = "eigenlayer")] + mod eigenlayer_tests { + use alloy_primitives::address; + + use super::*; + use crate::protocol::EigenlayerContractAddresses; + + #[test] + fn test_eigenlayer_configuration() { + let addresses = EigenlayerContractAddresses::default(); + + let settings = ProtocolSettings::from_eigenlayer(addresses.clone()); + assert!(matches!(settings, ProtocolSettings::Eigenlayer(_))); + if let ProtocolSettings::Eigenlayer(addrs) = settings { + assert_eq!( + addrs.registry_coordinator_address, + addresses.registry_coordinator_address + ); + assert_eq!( + addrs.operator_state_retriever_address, + addresses.operator_state_retriever_address + ); + assert_eq!( + addrs.delegation_manager_address, + addresses.delegation_manager_address + ); + assert_eq!( + addrs.service_manager_address, + addresses.service_manager_address + ); + assert_eq!( + addrs.stake_registry_address, + addresses.stake_registry_address + ); + assert_eq!( + addrs.strategy_manager_address, + addresses.strategy_manager_address + ); + assert_eq!(addrs.avs_directory_address, addresses.avs_directory_address); + } + } + } + + // Test Symbiotic configuration when feature is enabled + #[cfg(feature = "symbiotic")] + mod symbiotic_tests { + use alloy_primitives::address; + + use super::*; + use crate::protocol::SymbioticContractAddresses; + + #[test] + fn test_symbiotic_configuration() { + let addresses = SymbioticContractAddresses { + operator_registry_address: address!("8431e038b88ba5945ce8bf41e4af1374f3fb6e4c"), + network_registry_address: address!("4f4495243837681061c4743b74b3eedf548d56a5"), + base_delegator_address: address!("2279b7a0a67db372996a5fab50d91eaa73d2ebe6"), + network_opt_in_service_address: address!( + "610178da211fef7d417bc0e6fed39f05609ad788" + ), + vault_opt_in_service_address: address!("8a791620dd6260079bf849dc5567adc3f2fdc318"), + slasher_address: address!("f9e5b5c6a4b5b9c1d4e8f7a3b2e1d0c9a8b7f6e5"), + veto_slasher_address: address!("a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"), + }; + + let settings = ProtocolSettings::from_symbiotic(addresses.clone()); + assert!(matches!(settings, ProtocolSettings::Symbiotic(_))); + if let ProtocolSettings::Symbiotic(addrs) = settings { + assert_eq!( + addrs.operator_registry_address, + addresses.operator_registry_address + ); + assert_eq!( + addrs.network_registry_address, + addresses.network_registry_address + ); + assert_eq!( + addrs.base_delegator_address, + addresses.base_delegator_address + ); + assert_eq!( + addrs.network_opt_in_service_address, + addresses.network_opt_in_service_address + ); + assert_eq!( + addrs.vault_opt_in_service_address, + addresses.vault_opt_in_service_address + ); + assert_eq!(addrs.slasher_address, addresses.slasher_address); + assert_eq!(addrs.veto_slasher_address, addresses.veto_slasher_address); + } + } + } + + #[test] + fn test_configuration_validation() { + // Test RPC endpoint validation + let config = GadgetConfiguration { + http_rpc_endpoint: "invalid-url".to_string(), + ..Default::default() + }; + assert!(validate_rpc_endpoint(&config.http_rpc_endpoint).is_err()); + + // Test keystore URI validation + let config = GadgetConfiguration { + keystore_uri: "invalid-uri".to_string(), + ..Default::default() + }; + assert!(validate_keystore_uri(&config.keystore_uri).is_err()); + } + + // Helper functions for tests + fn validate_rpc_endpoint(endpoint: &str) -> Result<(), Error> { + if !endpoint.starts_with("http://") && !endpoint.starts_with("https://") { + return Err(Error::BadRpcConnection( + "Invalid RPC URL format".to_string(), + )); + } + Ok(()) + } + + fn validate_keystore_uri(uri: &str) -> Result<(), Error> { + if !uri.starts_with("file://") { + return Err(Error::UnsupportedKeystoreUri(uri.to_string())); + } + Ok(()) + } } diff --git a/crates/config/src/protocol.rs b/crates/config/src/protocol.rs index c0a0bca..8aaad9b 100644 --- a/crates/config/src/protocol.rs +++ b/crates/config/src/protocol.rs @@ -5,7 +5,7 @@ use core::fmt::Debug; use serde::{Deserialize, Serialize}; /// The protocol on which a gadget will be executed. -#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize)] +#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] #[cfg_attr( feature = "std", derive(clap::ValueEnum), diff --git a/crates/networking/Cargo.toml b/crates/networking/Cargo.toml index 0804d4f..f6f0ceb 100644 --- a/crates/networking/Cargo.toml +++ b/crates/networking/Cargo.toml @@ -36,7 +36,7 @@ gadget-crypto = { workspace = true, features = ["k256", "hashing"] } k256 = { workspace = true } # Round-based protocol support -round-based = { workspace = true } +round-based = { workspace = true, optional = true } [target.'cfg(not(target_family = "wasm"))'.dependencies.libp2p] workspace = true @@ -60,6 +60,9 @@ features = [ "autonat", ] +[dev-dependencies] +tracing-subscriber = { workspace = true } + [features] default = ["std"] std = [ @@ -71,8 +74,8 @@ std = [ "tokio/full", "serde/std", "serde_json/std", - "round-based/std", + "round-based?/std", ] - -[lints] -workspace = true +round-based-compat = [ + "round-based", +] \ No newline at end of file diff --git a/crates/networking/src/channels.rs b/crates/networking/src/channels.rs deleted file mode 100644 index 4a0c9af..0000000 --- a/crates/networking/src/channels.rs +++ /dev/null @@ -1,779 +0,0 @@ -use crate::networking::{ - deserialize, IdentifierInfo, Network, NetworkMultiplexer, ProtocolMessage, -}; -use crate::Error; -use futures::StreamExt; -use gadget_crypto::k256_crypto::K256VerifyingKey; -use gadget_std::collections::HashMap; -use gadget_std::sync::Arc; -use round_based::{Incoming, MessageDestination, MessageType, MsgId, Outgoing, PartyIndex}; -use serde::de::DeserializeOwned; -use serde::{Deserialize, Serialize}; -use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender}; - -/// Unique identifier for an involved party -/// -/// This is used to identify both senders and receivers in message transmission. -pub type UserID = u16; - -/// Represent a message transmitting between parties on wire -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] -pub struct Msg { - /// Index of the sender - /// - /// Lies in range `[1; n]` where `n` is number of parties involved in computation - pub sender: UserID, - /// Index of receiver - /// - /// `None` indicates that it's broadcast message. Receiver index, if set, lies in range `[1; n]` - /// where `n` is number of parties involved in computation - pub receiver: Option, - /// Message body - pub body: B, -} - -impl Msg { - /// Applies closure to message body - pub fn map_body(self, f: F) -> Msg - where - F: FnOnce(B) -> T, - { - Msg { - sender: self.sender, - receiver: self.receiver, - body: f(self.body), - } - } -} - -#[cfg(feature = "std")] -#[allow(clippy::too_many_arguments, clippy::let_underscore_future)] -pub fn create_job_manager_to_async_protocol_channel_split< - N: Network, - C1: Serialize + DeserializeOwned + MaybeSenderReceiver + Send + 'static, - C2: Serialize + DeserializeOwned + MaybeSenderReceiver + Send + 'static, ->( - mut rx_gadget: UnboundedReceiver, - identifier_info: IdentifierInfo, - user_id_mapping: Arc>, - my_account_id: K256VerifyingKey, - network: N, -) -> ( - futures::channel::mpsc::UnboundedSender, - futures::channel::mpsc::UnboundedReceiver>, - UnboundedSender, - UnboundedReceiver, -) { - let (tx_to_async_proto_1, rx_for_async_proto_1) = futures::channel::mpsc::unbounded(); - let (tx_to_async_proto_2, rx_for_async_proto_2) = tokio::sync::mpsc::unbounded_channel(); - // Take the messages from the gadget and send them to the async protocol - let _ = tokio::task::spawn(async move { - while let Some(msg) = rx_gadget.recv().await { - match deserialize::>(&msg.payload[..]) { - Ok(msg) => match msg { - MultiplexedChannelMessage::Channel1(msg) => { - if tx_to_async_proto_1.unbounded_send(Ok(msg)).is_err() { - gadget_logging::error!("Failed to send message to C1 protocol"); - } - } - MultiplexedChannelMessage::Channel2(msg) => { - if tx_to_async_proto_2.send(msg).is_err() { - gadget_logging::error!("Failed to send message to C2 protocol"); - } - } - - _ => { - unreachable!("We only have two channels") - } - }, - Err(err) => { - gadget_logging::error!("Failed to deserialize message: {err:?}"); - } - } - } - }); - - let (tx_to_outbound_1, mut rx_to_outbound_1) = futures::channel::mpsc::unbounded::(); - let (tx_to_outbound_2, mut rx_to_outbound_2) = tokio::sync::mpsc::unbounded_channel::(); - let multiplexed_network = NetworkMultiplexer::new(network); - let network = multiplexed_network.multiplex(identifier_info); - let user_id_mapping_clone = user_id_mapping.clone(); - let my_user_id = user_id_mapping - .iter() - .find_map(|(user_id, account_id)| { - if *account_id == my_account_id { - Some(*user_id) - } else { - None - } - }) - .expect("Failed to find my user id"); - - // Take the messages the async protocol sends to the outbound channel and send them to the gadget - let _ = tokio::task::spawn(async move { - let network = &network; - let channel_1_task = async move { - while let Some(msg) = rx_to_outbound_1.next().await { - if let Err(err) = wrap_message_and_forward_to_network::<_, C1, C2, (), _>( - msg, - network, - &user_id_mapping, - my_user_id, - identifier_info, - MultiplexedChannelMessage::Channel1, - ) - .await - { - gadget_logging::error!("Failed to send message to outbound: {err:?}"); - } - } - }; - - let channel_2_task = async move { - while let Some(msg) = rx_to_outbound_2.recv().await { - if let Err(err) = wrap_message_and_forward_to_network::<_, C1, C2, (), _>( - msg, - network, - &user_id_mapping_clone, - my_user_id, - identifier_info, - MultiplexedChannelMessage::Channel2, - ) - .await - { - gadget_logging::error!("Failed to send message to outbound: {err:?}"); - } - } - }; - - tokio::join!(channel_1_task, channel_2_task); - }); - - ( - tx_to_outbound_1, - rx_for_async_proto_1, - tx_to_outbound_2, - rx_for_async_proto_2, - ) -} - -impl MaybeSenderReceiver for Msg { - fn maybe_sender(&self) -> MaybeSender { - MaybeSender::SomeoneElse(self.sender) - } - - fn maybe_receiver(&self) -> MaybeReceiver { - match self.receiver { - None => MaybeReceiver::Broadcast, - Some(i) => MaybeReceiver::P2P(i), - } - } -} - -#[derive(Serialize, Deserialize, Debug)] -pub enum MultiplexedChannelMessage { - Channel1(C1), - Channel2(C2), - Channel3(C3), -} - -/// All possible senders of a message -#[derive(Debug, Default, Serialize, Deserialize, Copy, Clone)] -pub enum MaybeSender { - /// We are the sender of the message - Myself, - /// The sender is someone else - /// it could also be us, double check the [`UserID`] - SomeoneElse(UserID), - /// The sender is unknown. - #[default] - Unknown, -} - -impl MaybeSender { - /// Returns `true` if the maybe sender is [`Myself`]. - /// - /// [`Myself`]: MaybeSender::Myself - #[must_use] - pub fn is_myself(&self) -> bool { - matches!(self, Self::Myself) - } - - /// Returns `true` if the maybe sender is [`Myself`]. - /// Or if the sender is [`SomeoneElse`] but the [`UserID`] is the same as `my_user_id` - /// - /// [`Myself`]: MaybeSender::Myself - /// [`SomeoneElse`]: MaybeSender::SomeoneElse - #[must_use] - pub fn is_myself_check(&self, my_user_id: UserID) -> bool { - match self { - Self::Myself => true, - Self::SomeoneElse(id) if (*id == my_user_id) => true, - _ => false, - } - } - - /// Returns `true` if the maybe sender is [`SomeoneElse`]. - /// - /// [`SomeoneElse`]: MaybeSender::SomeoneElse - #[must_use] - pub fn is_someone_else(&self) -> bool { - matches!(self, Self::SomeoneElse(..)) - } - - /// Returns `true` if the maybe sender is [`Unknown`]. - /// - /// [`Unknown`]: MaybeSender::Unknown - #[must_use] - pub fn is_unknown(&self) -> bool { - matches!(self, Self::Unknown) - } - - /// Returns the sender as [`UserID`] if it is knwon. - #[must_use] - pub fn as_user_id(&self) -> Option { - match self { - Self::Myself => None, - Self::SomeoneElse(id) => Some(*id), - Self::Unknown => None, - } - } -} - -#[derive(Debug, Default, Serialize, Deserialize, Copy, Clone)] -pub enum MaybeReceiver { - /// The message is broadcasted to everyone - Broadcast, - /// The message is sent to a specific party - P2P(UserID), - /// The receiver is us. - Myself, - /// The receiver is unknown. - #[default] - Unknown, -} - -impl MaybeReceiver { - /// Returns `true` if the maybe receiver is [`Broadcast`]. - /// - /// [`Broadcast`]: MaybeReceiver::Broadcast - #[must_use] - pub fn is_broadcast(&self) -> bool { - matches!(self, Self::Broadcast) - } - - /// Returns `true` if the maybe receiver is [`P2P`]. - /// - /// [`P2P`]: MaybeReceiver::P2P - #[must_use] - pub fn is_p2p(&self) -> bool { - matches!(self, Self::P2P(..)) - } - - /// Returns `true` if the maybe receiver is [`Myself`]. - /// - /// [`Myself`]: MaybeReceiver::Myself - #[must_use] - pub fn is_myself(&self) -> bool { - matches!(self, Self::Myself) - } - - /// Returns `true` if the maybe receiver is [`Myself`] - /// Or if the receiver is [`P2P`] but the [`UserID`] is the same as `my_user_id` - /// - /// [`Myself`]: MaybeReceiver::Myself - /// [`P2P`]: MaybeReceiver::P2P - #[must_use] - pub fn is_myself_check(&self, my_user_id: UserID) -> bool { - match self { - Self::Myself => true, - Self::P2P(id) if (*id == my_user_id) => true, - _ => false, - } - } - - /// Returns `true` if the maybe receiver is [`Unknown`]. - /// - /// [`Unknown`]: MaybeReceiver::Unknown - #[must_use] - pub fn is_unknown(&self) -> bool { - matches!(self, Self::Unknown) - } - - /// Returns the receiver as [`UserID`] if it is known. - #[must_use] - pub fn as_user_id(&self) -> Option { - match self { - Self::Broadcast => None, - Self::P2P(id) => Some(*id), - Self::Myself => None, - Self::Unknown => None, - } - } -} - -pub trait InnerMessage { - type Inner: Serialize + DeserializeOwned + Send + 'static; - fn inner_message(self) -> Self::Inner; -} - -pub trait InnerMessageFromInbound: Sized + InnerMessage { - fn from_inbound( - id: MsgId, - sender: PartyIndex, - msg_type: MessageType, - msg: ::Inner, - ) -> Self; -} - -impl InnerMessage for Outgoing { - type Inner = M; - - fn inner_message(self) -> Self::Inner { - self.msg - } -} - -impl InnerMessage for Incoming { - type Inner = M; - - fn inner_message(self) -> Self::Inner { - self.msg - } -} - -/// A Simple trait to extract the sender and the receiver from a message -pub trait MaybeSenderReceiver { - fn maybe_sender(&self) -> MaybeSender; - fn maybe_receiver(&self) -> MaybeReceiver; -} - -impl MaybeSenderReceiver for Outgoing { - fn maybe_sender(&self) -> MaybeSender { - MaybeSender::Myself - } - - fn maybe_receiver(&self) -> MaybeReceiver { - match self.recipient { - MessageDestination::AllParties => MaybeReceiver::Broadcast, - MessageDestination::OneParty(i) => MaybeReceiver::P2P(i), - } - } -} - -impl MaybeSenderReceiver for Incoming { - fn maybe_sender(&self) -> MaybeSender { - MaybeSender::SomeoneElse(self.sender) - } - - fn maybe_receiver(&self) -> MaybeReceiver { - match self.msg_type { - MessageType::Broadcast => MaybeReceiver::Broadcast, - MessageType::P2P => MaybeReceiver::Myself, - } - } -} - -impl InnerMessageFromInbound for Incoming { - fn from_inbound( - id: MsgId, - sender: PartyIndex, - msg_type: MessageType, - msg: ::Inner, - ) -> Self { - Incoming { - id, - sender, - msg_type, - msg, - } - } -} - -impl MaybeSenderReceiver for () { - fn maybe_sender(&self) -> MaybeSender { - MaybeSender::Unknown - } - - fn maybe_receiver(&self) -> MaybeReceiver { - MaybeReceiver::Unknown - } -} - -pub type DuplexedChannel = ( - futures::channel::mpsc::UnboundedSender, - futures::channel::mpsc::UnboundedReceiver>, - futures::channel::mpsc::UnboundedSender, - futures::channel::mpsc::UnboundedReceiver, -); - -#[cfg(feature = "std")] -#[allow(clippy::too_many_arguments, clippy::let_underscore_future)] -pub fn create_job_manager_to_async_protocol_channel_split_io< - N: Network, - C2: Serialize + DeserializeOwned + MaybeSenderReceiver + Send + 'static, - O: InnerMessage + MaybeSenderReceiver + Send + 'static, - I: InnerMessage + InnerMessageFromInbound + MaybeSenderReceiver + Send + 'static, ->( - mut rx_gadget: UnboundedReceiver, - identifier_info: IdentifierInfo, - user_id_mapping: Arc>, - my_account_id: K256VerifyingKey, - network: N, - i: UserID, -) -> DuplexedChannel { - let (tx_to_async_proto_1, rx_for_async_proto_1) = futures::channel::mpsc::unbounded(); - let (tx_to_async_proto_2, rx_for_async_proto_2) = futures::channel::mpsc::unbounded(); - let mapping_clone = user_id_mapping.clone(); - - let my_user_id = user_id_mapping - .iter() - .find_map(|(user_id, account_id)| { - if *account_id == my_account_id { - Some(*user_id) - } else { - None - } - }) - .expect("Failed to find my user id"); - - if my_user_id != i { - gadget_logging::error!("My user id is not equal to i: {} != {}", my_user_id, i); - } - - // Take the messages from the gadget and send them to the async protocol - let _ = tokio::task::spawn(async move { - let mut id = 0; - while let Some(msg_orig) = rx_gadget.recv().await { - if msg_orig.payload.is_empty() { - gadget_logging::warn!( - "Received empty message from Peer {:?}", - msg_orig.sender.user_id - ); - continue; - } - - match deserialize::>(&msg_orig.payload[..]) { - Ok(msg) => match msg { - MultiplexedChannelMessage::Channel1(msg) => { - gadget_logging::trace!("Received message count: {id}", id = id + 1); - gadget_logging::trace!( - "Received message from {:?} as {:?}", - msg_orig.sender.user_id, - msg_orig.recipient - ); - let msg_type = if let Some(to) = msg_orig.recipient { - if let Some(to_account_id) = mapping_clone.get(&to.user_id) { - if *to_account_id != my_account_id { - gadget_logging::error!("Invalid message received"); - continue; - } - } else { - gadget_logging::error!( - "Invalid message received (`to` not found in mapping)" - ); - continue; - } - - MessageType::P2P - } else { - MessageType::Broadcast - }; - - let incoming = I::from_inbound(id, msg_orig.sender.user_id, msg_type, msg); - - if tx_to_async_proto_1.unbounded_send(Ok(incoming)).is_err() { - gadget_logging::error!("Failed to send Incoming message to protocol"); - } - - id += 1; - } - MultiplexedChannelMessage::Channel2(msg) => { - if tx_to_async_proto_2.unbounded_send(msg).is_err() { - gadget_logging::error!("Failed to send C2 message to protocol"); - } - } - _ => { - unreachable!("We only have two channels") - } - }, - Err(err) => { - gadget_logging::error!("Failed to deserialize message: {err:?}"); - } - } - } - }); - - let (tx_to_outbound_1, mut rx_to_outbound_1) = futures::channel::mpsc::unbounded::(); - let (tx_to_outbound_2, mut rx_to_outbound_2) = futures::channel::mpsc::unbounded::(); - let multiplexed_network = NetworkMultiplexer::new(network); - let network = multiplexed_network.multiplex(identifier_info); - let user_id_mapping_clone = user_id_mapping.clone(); - - // Take the messages from the async protocol and send them to the gadget - let _ = tokio::task::spawn(async move { - let network = &network; - let channel_1_task = async move { - while let Some(msg) = rx_to_outbound_1.next().await { - if let Err(err) = wrap_message_and_forward_to_network::<_, O::Inner, C2, (), _>( - msg, - network, - &user_id_mapping, - my_user_id, - identifier_info, - |m| MultiplexedChannelMessage::Channel1(m.inner_message()), - ) - .await - { - gadget_logging::error!("Failed to send message to outbound: {err:?}"); - } - } - - gadget_logging::trace!("Channel 1 outgoing task closing") - }; - - let channel_2_task = async move { - while let Some(msg) = rx_to_outbound_2.next().await { - if let Err(err) = wrap_message_and_forward_to_network::<_, O::Inner, C2, (), _>( - msg, - network, - &user_id_mapping_clone, - my_user_id, - identifier_info, - |m| MultiplexedChannelMessage::Channel2(m), - ) - .await - { - gadget_logging::error!("Failed to send message to outbound: {err:?}"); - } - } - - gadget_logging::trace!("Channel 2 outgoing task closing") - }; - - tokio::join!(channel_1_task, channel_2_task); - }); - - ( - tx_to_outbound_1, - rx_for_async_proto_1, - tx_to_outbound_2, - rx_for_async_proto_2, - ) -} - -pub type TriplexedChannel = ( - futures::channel::mpsc::UnboundedSender, - futures::channel::mpsc::UnboundedReceiver>, - futures::channel::mpsc::UnboundedSender, - futures::channel::mpsc::UnboundedReceiver>, - futures::channel::mpsc::UnboundedSender, - futures::channel::mpsc::UnboundedReceiver, -); - -#[cfg(feature = "std")] -#[allow(clippy::too_many_arguments, clippy::let_underscore_future)] -pub fn create_job_manager_to_async_protocol_channel_split_io_triplex< - N: Network + 'static, - C3: Serialize + DeserializeOwned + MaybeSenderReceiver + Send + 'static, - O1: InnerMessage + MaybeSenderReceiver + Send + 'static, - I1: InnerMessage + InnerMessageFromInbound + MaybeSenderReceiver + Send + 'static, - O2: InnerMessage + MaybeSenderReceiver + Send + 'static, - I2: InnerMessage + InnerMessageFromInbound + MaybeSenderReceiver + Send + 'static, ->( - mut rx_gadget: UnboundedReceiver, - identifier_info: IdentifierInfo, - user_id_mapping: Arc>, - my_account_id: K256VerifyingKey, - network: N, -) -> TriplexedChannel { - let (tx_to_async_proto_1, rx_for_async_proto_1) = futures::channel::mpsc::unbounded(); - let (tx_to_async_proto_2, rx_for_async_proto_2) = futures::channel::mpsc::unbounded(); - let (tx_to_async_proto_3, rx_for_async_proto_3) = futures::channel::mpsc::unbounded(); - - // Take the messages from the gadget and send them to the async protocol - let _ = tokio::task::spawn(async move { - let mut id = 0; - while let Some(msg_orig) = rx_gadget.recv().await { - if msg_orig.payload.is_empty() { - gadget_logging::warn!( - "Received empty message from Peer {:?}", - msg_orig.sender.user_id - ); - continue; - } - - match deserialize::>( - &msg_orig.payload[..], - ) { - Ok(msg) => match msg { - MultiplexedChannelMessage::Channel1(msg) => { - let msg_type = if msg_orig.recipient.is_some() { - MessageType::P2P - } else { - MessageType::Broadcast - }; - - let incoming = I1::from_inbound(id, msg_orig.sender.user_id, msg_type, msg); - - if tx_to_async_proto_1.unbounded_send(Ok(incoming)).is_err() { - gadget_logging::error!("Failed to send Incoming message to protocol"); - } - - id += 1; - } - MultiplexedChannelMessage::Channel2(msg) => { - let msg_type = if msg_orig.recipient.is_some() { - MessageType::P2P - } else { - MessageType::Broadcast - }; - - let incoming = I2::from_inbound(id, msg_orig.sender.user_id, msg_type, msg); - - if tx_to_async_proto_2.unbounded_send(Ok(incoming)).is_err() { - gadget_logging::error!("Failed to send Incoming message to protocol"); - } - - id += 1; - } - MultiplexedChannelMessage::Channel3(msg) => { - if tx_to_async_proto_3.unbounded_send(msg).is_err() { - gadget_logging::error!("Failed to send C2 message to protocol"); - } - } - }, - - Err(err) => { - gadget_logging::error!("Failed to deserialize message: {err:?}"); - } - } - } - }); - - let (tx_to_outbound_1, mut rx_to_outbound_1) = futures::channel::mpsc::unbounded::(); - let (tx_to_outbound_2, mut rx_to_outbound_2) = futures::channel::mpsc::unbounded::(); - let (tx_to_outbound_3, mut rx_to_outbound_3) = futures::channel::mpsc::unbounded::(); - - let my_user_id = user_id_mapping - .iter() - .find_map(|(user_id, account_id)| { - if *account_id == my_account_id { - Some(*user_id) - } else { - None - } - }) - .expect("Failed to find my user id"); - // Take the messages from the async protocol and send them to the gadget - let _ = tokio::task::spawn(async move { - let user_id_mapping = &user_id_mapping; - let network = &network; - let task0 = async move { - while let Some(msg) = rx_to_outbound_1.next().await { - if let Err(err) = - wrap_message_and_forward_to_network::<_, O1::Inner, O2::Inner, C3, _>( - msg, - network, - user_id_mapping, - my_user_id, - identifier_info, - |m| MultiplexedChannelMessage::Channel1(m.inner_message()), - ) - .await - { - gadget_logging::error!("Failed to send message to outbound: {err:?}"); - } - } - }; - - let task1 = async move { - while let Some(msg) = rx_to_outbound_2.next().await { - if let Err(err) = - wrap_message_and_forward_to_network::<_, O1::Inner, O2::Inner, C3, _>( - msg, - network, - user_id_mapping, - my_user_id, - identifier_info, - |m| MultiplexedChannelMessage::Channel2(m.inner_message()), - ) - .await - { - gadget_logging::error!("Failed to send message to outbound: {err:?}"); - } - } - }; - - let task2 = async move { - while let Some(msg) = rx_to_outbound_3.next().await { - if let Err(err) = - wrap_message_and_forward_to_network::<_, O1::Inner, O2::Inner, C3, _>( - msg, - network, - user_id_mapping, - my_user_id, - identifier_info, - |m| MultiplexedChannelMessage::Channel3(m), - ) - .await - { - gadget_logging::error!("Failed to send message to outbound: {err:?}"); - } - } - }; - - tokio::join!(task0, task1, task2); - }); - - ( - tx_to_outbound_1, - rx_for_async_proto_1, - tx_to_outbound_2, - rx_for_async_proto_2, - tx_to_outbound_3, - rx_for_async_proto_3, - ) -} - -#[allow(clippy::too_many_arguments)] -#[cfg(feature = "std")] -async fn wrap_message_and_forward_to_network< - N: Network, - C1: Serialize, - C2: Serialize, - C3: Serialize, - M, ->( - msg: M, - network: &N, - user_id_mapping: &HashMap, - my_user_id: UserID, - identifier_info: IdentifierInfo, - splitter: impl FnOnce(M) -> MultiplexedChannelMessage, -) -> Result<(), Error> -where - M: MaybeSenderReceiver + Send + 'static, -{ - let from = msg.maybe_sender(); - let to = msg.maybe_receiver(); - gadget_logging::trace!("Sending message from {:?} to {:?}", from, to); - - let from_account_id = user_id_mapping - .get(&from.as_user_id().unwrap_or(my_user_id)) - .cloned(); - let to_account_id = to - .as_user_id() - .and_then(|to| user_id_mapping.get(&to).cloned()); - - let msg = N::build_protocol_message( - identifier_info, - my_user_id, - to.as_user_id(), - &splitter(msg), - from_account_id, - to_account_id, - ); - - network.send_message(msg).await -} diff --git a/crates/networking/src/lib.rs b/crates/networking/src/lib.rs index be84460..8a57dff 100644 --- a/crates/networking/src/lib.rs +++ b/crates/networking/src/lib.rs @@ -1,19 +1,23 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] -pub mod channels; pub mod gossip; pub mod handlers; pub mod messaging; pub mod networking; +#[cfg(feature = "round-based-compat")] pub mod round_based_compat; - -pub use round_based; - pub mod setup; use gadget_std::string::String; +/// Re-exported networking crates +#[cfg(feature = "round-based-compat")] +pub use round_based; + +/// Unique identifier for a party +pub type UserID = u16; + #[derive(Debug, thiserror::Error)] pub enum Error { #[error("Network error: {0}")] diff --git a/crates/networking/src/networking.rs b/crates/networking/src/networking.rs index 409b39d..cc47ad6 100644 --- a/crates/networking/src/networking.rs +++ b/crates/networking/src/networking.rs @@ -1,5 +1,5 @@ -use crate::channels::UserID; use crate::Error; +use crate::UserID; use async_trait::async_trait; use dashmap::DashMap; use futures::{Stream, StreamExt}; @@ -520,11 +520,15 @@ pub fn serialize(object: &impl Serialize) -> Result, serde_json::Error> #[cfg(test)] mod tests { use super::*; + use crate::gossip::GossipHandle; use futures::{stream, StreamExt}; + use gadget_crypto::{ + hashing::sha2_256, + k256_crypto::{K256Ecdsa, K256SigningKey}, + KeyType, + }; use gadget_std::collections::BTreeMap; - use gossip::GossipHandle; use serde::{Deserialize, Serialize}; - use sp_core::Pair; const TOPIC: &str = "/gadget/test/1.0.0"; @@ -816,23 +820,24 @@ mod tests { Ok(()) } - fn node_with_id() -> (gossip::GossipHandle, ecdsa::Pair) { + fn node_with_id() -> (crate::gossip::GossipHandle, K256SigningKey) { let identity = libp2p::identity::Keypair::generate_ed25519(); - let ecdsa_key = sp_core::ecdsa::Pair::generate().0; + let ecdsa_key = K256Ecdsa::generate_with_seed(None).unwrap(); let bind_port = 0; - let handle = setup::start_p2p_network(setup::NetworkConfig::new_service_network( - identity, - ecdsa_key.clone(), - Default::default(), - bind_port, - TOPIC, - )) - .unwrap(); + let handle = + crate::setup::start_p2p_network(crate::setup::NetworkConfig::new_service_network( + identity, + ecdsa_key.clone(), + Default::default(), + bind_port, + TOPIC, + )) + .unwrap(); (handle, ecdsa_key) } - fn node() -> gossip::GossipHandle { + fn node() -> crate::gossip::GossipHandle { node_with_id().0 } @@ -849,8 +854,8 @@ mod tests { let (network0, network1) = (networks.remove(0), networks.remove(0)); - let public0 = id0.public(); - let public1 = id1.public(); + let public0 = id0.verifying_key(); + let public1 = id1.verifying_key(); let multiplexer0 = NetworkMultiplexer::new(network0); let multiplexer1 = NetworkMultiplexer::new(network1); diff --git a/crates/stores/local-database/Cargo.toml b/crates/stores/local-database/Cargo.toml index aeabc8d..00ade8c 100644 --- a/crates/stores/local-database/Cargo.toml +++ b/crates/stores/local-database/Cargo.toml @@ -14,4 +14,7 @@ std = [ "gadget-std/std", "serde/std", "serde_json/std", -] \ No newline at end of file +] + +[dev-dependencies] +tempfile = "3.8" \ No newline at end of file diff --git a/crates/stores/local-database/src/lib.rs b/crates/stores/local-database/src/lib.rs index 59472e1..0854259 100644 --- a/crates/stores/local-database/src/lib.rs +++ b/crates/stores/local-database/src/lib.rs @@ -11,7 +11,7 @@ use std::sync::Mutex; /// # Example /// /// ```no_run -/// use gadget_sdk::store::LocalDatabase; +/// use gadget_store_local_database::LocalDatabase; /// /// let db = LocalDatabase::::open("data.json"); /// @@ -35,7 +35,7 @@ where /// # Example /// /// ```no_run - /// use gadget_sdk::store::LocalDatabase; + /// use gadget_store_local_database::LocalDatabase; /// /// let db = LocalDatabase::::open("data.json"); /// assert!(db.is_empty()); @@ -52,7 +52,12 @@ where let content = fs::read_to_string(path).expect("Failed to read the file"); serde_json::from_str(&content).unwrap_or_default() } else { - HashMap::new() + // Create an empty file with default empty JSON object + let empty_data = HashMap::new(); + let json_string = + serde_json::to_string(&empty_data).expect("Failed to serialize empty data to JSON"); + fs::write(path, json_string).expect("Failed to write empty file"); + empty_data }; Self { @@ -66,7 +71,7 @@ where /// # Example /// /// ```no_run - /// use gadget_sdk::store::LocalDatabase; + /// use gadget_store_local_database::LocalDatabase; /// /// let db = LocalDatabase::::open("data.json"); /// assert_eq!(db.len(), 0); @@ -84,7 +89,7 @@ where /// # Example /// /// ```no_run - /// use gadget_sdk::store::LocalDatabase; + /// use gadget_store_local_database::LocalDatabase; /// /// let db = LocalDatabase::::open("data.json"); /// assert!(db.is_empty()); @@ -102,7 +107,7 @@ where /// # Example /// /// ```no_run - /// use gadget_sdk::store::LocalDatabase; + /// use gadget_store_local_database::LocalDatabase; /// /// let db = LocalDatabase::::open("data.json"); /// @@ -123,7 +128,7 @@ where /// # Example /// /// ```no_run - /// use gadget_sdk::store::LocalDatabase; + /// use gadget_store_local_database::LocalDatabase; /// /// let db = LocalDatabase::::open("data.json"); /// @@ -135,3 +140,138 @@ where data.get(key).cloned() } } + +#[cfg(test)] +mod tests { + use super::*; + use serde::{Deserialize, Serialize}; + use std::fs; + use tempfile::tempdir; + + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)] + struct TestStruct { + field1: String, + field2: i32, + } + + #[test] + fn test_create_new_database() { + let dir = tempdir().unwrap(); + let db_path = dir.path().join("test.json"); + + let db = LocalDatabase::::open(&db_path); + assert!(db.is_empty()); + assert_eq!(db.len(), 0); + assert!(db_path.exists()); + } + + #[test] + fn test_set_and_get() { + let dir = tempdir().unwrap(); + let db_path = dir.path().join("test.json"); + + let db = LocalDatabase::::open(&db_path); + db.set("key1", 42); + db.set("key2", 100); + + assert_eq!(db.get("key1"), Some(42)); + assert_eq!(db.get("key2"), Some(100)); + assert_eq!(db.get("nonexistent"), None); + assert_eq!(db.len(), 2); + } + + #[test] + fn test_complex_type() { + let dir = tempdir().unwrap(); + let db_path = dir.path().join("test.json"); + + let db = LocalDatabase::::open(&db_path); + + let test_struct = TestStruct { + field1: "test".to_string(), + field2: 42, + }; + + db.set("key1", test_struct.clone()); + assert_eq!(db.get("key1"), Some(test_struct)); + } + + #[test] + fn test_persistence() { + let dir = tempdir().unwrap(); + let db_path = dir.path().join("test.json"); + + // Write data + { + let db = LocalDatabase::::open(&db_path); + db.set("key1", 42); + db.set("key2", 100); + } + + // Read data in new instance + { + let db = LocalDatabase::::open(&db_path); + assert_eq!(db.get("key1"), Some(42)); + assert_eq!(db.get("key2"), Some(100)); + assert_eq!(db.len(), 2); + } + } + + #[test] + fn test_overwrite() { + let dir = tempdir().unwrap(); + let db_path = dir.path().join("test.json"); + + let db = LocalDatabase::::open(&db_path); + db.set("key1", 42); + assert_eq!(db.get("key1"), Some(42)); + + db.set("key1", 100); + assert_eq!(db.get("key1"), Some(100)); + assert_eq!(db.len(), 1); + } + + #[test] + fn test_invalid_json() { + let dir = tempdir().unwrap(); + let db_path = dir.path().join("test.json"); + + // Write invalid JSON + fs::write(&db_path, "{invalid_json}").unwrap(); + + // Should create empty database when JSON is invalid + let db = LocalDatabase::::open(&db_path); + assert!(db.is_empty()); + } + + #[test] + fn test_concurrent_access() { + use std::sync::Arc; + use std::thread; + + let dir = tempdir().unwrap(); + let db_path = dir.path().join("test.json"); + + let db = Arc::new(LocalDatabase::::open(&db_path)); + let mut handles = vec![]; + + // Spawn multiple threads to write to the database + for i in 0..10 { + let db_clone = Arc::clone(&db); + let handle = thread::spawn(move || { + db_clone.set(&format!("key{}", i), i as u32); + }); + handles.push(handle); + } + + // Wait for all threads to complete + for handle in handles { + handle.join().unwrap(); + } + + assert_eq!(db.len(), 10); + for i in 0..10 { + assert_eq!(db.get(&format!("key{}", i)), Some(i as u32)); + } + } +} diff --git a/crates/testing-utils/anvil/data/state.json b/crates/testing-utils/anvil/data/state.json new file mode 100644 index 0000000..7a834b4 --- /dev/null +++ b/crates/testing-utils/anvil/data/state.json @@ -0,0 +1,533 @@ +{ + "accounts": { + "0x0000000000000000000000000000000000000000": { + "nonce": 0, + "balance": "0x367632a", + "code": "0x", + "storage": {} + }, + "0x0165878a594ca255338adfa4d48449f69242eb8f": { + "nonce": 1, + "balance": "0x0", + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106f1565b610118565b61005b61009336600461070c565b61015f565b3480156100a457600080fd5b506100ad6101d0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106f1565b61020b565b3480156100f557600080fd5b506100ad610235565b61010661029b565b61011661011161033a565b610344565b565b610120610368565b6001600160a01b0316336001600160a01b03161415610157576101548160405180602001604052806000815250600061039b565b50565b6101546100fe565b610167610368565b6001600160a01b0316336001600160a01b031614156101c8576101c38383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001925061039b915050565b505050565b6101c36100fe565b60006101da610368565b6001600160a01b0316336001600160a01b03161415610200576101fb61033a565b905090565b6102086100fe565b90565b610213610368565b6001600160a01b0316336001600160a01b0316141561015757610154816103c6565b600061023f610368565b6001600160a01b0316336001600160a01b03161415610200576101fb610368565b6060610285838360405180606001604052806027815260200161080b6027913961041a565b9392505050565b6001600160a01b03163b151590565b6102a3610368565b6001600160a01b0316336001600160a01b031614156101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101fb6104f7565b3660008037600080366000845af43d6000803e808015610363573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103a48361051f565b6000825111806103b15750805b156101c3576103c08383610260565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103ef610368565b604080516001600160a01b03928316815291841660208301520160405180910390a16101548161055f565b60606001600160a01b0384163b6104825760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610331565b600080856001600160a01b03168560405161049d91906107bb565b600060405180830381855af49150503d80600081146104d8576040519150601f19603f3d011682016040523d82523d6000602084013e6104dd565b606091505b50915091506104ed828286610608565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61038c565b61052881610641565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105c45760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610331565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60608315610617575081610285565b8251156106275782518084602001fd5b8160405162461bcd60e51b815260040161033191906107d7565b6001600160a01b0381163b6106ae5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610331565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105e7565b80356001600160a01b03811681146106ec57600080fd5b919050565b60006020828403121561070357600080fd5b610285826106d5565b60008060006040848603121561072157600080fd5b61072a846106d5565b9250602084013567ffffffffffffffff8082111561074757600080fd5b818601915086601f83011261075b57600080fd5b81358181111561076a57600080fd5b87602082850101111561077c57600080fd5b6020830194508093505050509250925092565b60005b838110156107aa578181015183820152602001610792565b838111156103c05750506000910152565b600082516107cd81846020870161078f565b9190910192915050565b60208152600082518060208401526107f681604085016020870161078f565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212208c7daa35c73cc3931155de6fec176061a18c7828634d7222e2c3c877ecc7552c64736f6c634300080c0033", + "storage": { + "0x0": "0x1", + "0x33": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x65": "0x9fe46736679d2d9a65f0992f2272de9f3c7fa6e0", + "0x66": "0x0", + "0x97": "0x94af000f6f71feb2b8401e668d95fd208038580e89d240930f90ba827aa34858", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x9a676e781a523b5d0c0e43731313a708cb607508", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512" + } + }, + "0x09635f643e140090a9a8dcd712ed6285858cebef": { + "nonce": 1, + "balance": "0x0", + "code": "0x6080604052348015600f57600080fd5b506004361060285760003560e01c8063c298557814602d575b600080fd5b600060405190815260200160405180910390f3fea264697066735822122007c80e3ab75b64ab2851d22a863601e8064735da0ba4040cde0990cb0528b7c064736f6c634300080c0033", + "storage": {} + }, + "0x0b306bf915c4d645ff596e518faf3f9669b97016": { + "nonce": 1, + "balance": "0x0", + "code": "0x608060405234801561001057600080fd5b50600436106101f05760003560e01c80637cf72bba1161010f578063d98128c0116100a2578063e921d4fa11610071578063e921d4fa146103c6578063f2fde38b1461044c578063f73b7519146102a9578063fabc1cbc1461045f57600080fd5b8063d98128c014610430578063da16e29b14610322578063df5cf723146102ba578063e58398361461043e57600080fd5b80638da5cb5b116100de5780638da5cb5b146103b5578063a49db732146103c6578063c747075b146103da578063d7b7fa13146103ee57600080fd5b80637cf72bba146103465780638105e04314610354578063855fcc4a1461036b578063886f1195146103a257600080fd5b806339b70e38116101875780636f0c2f74116101565780636f0c2f7414610322578063715018a614610330578063723e59c7146103385780637259a45c1461024257600080fd5b806339b70e38146102ba578063595c6a67146102d55780635ac86ab7146102dd5780635c975abb1461031057600080fd5b80631794bb3c116101c35780631794bb3c1461022f5780631874e5ae14610242578063282670fc1461027257806338c8ee64146102a957600080fd5b80630ffabbce146101f557806310d67a2f14610209578063136439dd1461021c578063175d3205146101f5575b600080fd5b610207610203366004610b25565b5050565b005b610207610217366004610b5a565b610472565b61020761022a366004610b7e565b61052b565b61020761023d366004610b97565b505050565b610258610250366004610b25565b600092915050565b60405163ffffffff90911681526020015b60405180910390f35b610285610280366004610bd8565b61066a565b60408051825163ffffffff9081168252602093840151169281019290925201610269565b6102076102b7366004610b5a565b50565b60005b6040516001600160a01b039091168152602001610269565b610207610685565b6103006102eb366004610c04565b606654600160ff9092169190911b9081161490565b6040519015158152602001610269565b6066545b604051908152602001610269565b610258610250366004610c27565b61020761074c565b610314610250366004610b25565b610207610203366004610c60565b610300610362366004610cd5565b60009392505050565b610385610379366004610c27565b60008060009250925092565b604080519315158452602084019290925290820152606001610269565b6065546102bd906001600160a01b031681565b6033546001600160a01b03166102bd565b6103146103d4366004610b5a565b50600090565b6102076103e8366004610d13565b50505050565b6104016103fc366004610c27565b610760565b60408051825163ffffffff90811682526020808501518216908301529282015190921690820152606001610269565b610300610250366004610c27565b6103006103d4366004610b5a565b61020761045a366004610b5a565b610782565b61020761046d366004610b7e565b6107f8565b606560009054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e99190610d60565b6001600160a01b0316336001600160a01b0316146105225760405162461bcd60e51b815260040161051990610d7d565b60405180910390fd5b6102b781610954565b60655460405163237dfb4760e11b81523360048201526001600160a01b03909116906346fbf68e90602401602060405180830381865afa158015610573573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105979190610dc7565b6105b35760405162461bcd60e51b815260040161051990610de9565b6066548181161461062c5760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e70617573653a20696e76616c696420617474656d70742060448201527f746f20756e70617573652066756e6374696f6e616c69747900000000000000006064820152608401610519565b606681905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d906020015b60405180910390a250565b60408051808201909152600080825260208201525b92915050565b60655460405163237dfb4760e11b81523360048201526001600160a01b03909116906346fbf68e90602401602060405180830381865afa1580156106cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f19190610dc7565b61070d5760405162461bcd60e51b815260040161051990610de9565b600019606681905560405190815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a2565b610754610a4b565b61075e6000610aa5565b565b604080516060810182526000808252602082018190529181019190915261067f565b61078a610a4b565b6001600160a01b0381166107ef5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610519565b6102b781610aa5565b606560009054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561084b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086f9190610d60565b6001600160a01b0316336001600160a01b03161461089f5760405162461bcd60e51b815260040161051990610d7d565b60665419811960665419161461091d5760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e756e70617573653a20696e76616c696420617474656d7060448201527f7420746f2070617573652066756e6374696f6e616c69747900000000000000006064820152608401610519565b606681905560405181815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c9060200161065f565b6001600160a01b0381166109e25760405162461bcd60e51b815260206004820152604960248201527f5061757361626c652e5f73657450617573657252656769737472793a206e657760448201527f50617573657252656769737472792063616e6e6f7420626520746865207a65726064820152686f206164647265737360b81b608482015260a401610519565b606554604080516001600160a01b03928316815291831660208301527f6e9fcd539896fca60e8b0f01dd580233e48a6b0f7df013b89ba7f565869acdb6910160405180910390a1606580546001600160a01b0319166001600160a01b0392909216919091179055565b6033546001600160a01b0316331461075e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610519565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b03811681146102b757600080fd5b803563ffffffff81168114610b2057600080fd5b919050565b60008060408385031215610b3857600080fd5b8235610b4381610af7565b9150610b5160208401610b0c565b90509250929050565b600060208284031215610b6c57600080fd5b8135610b7781610af7565b9392505050565b600060208284031215610b9057600080fd5b5035919050565b600080600060608486031215610bac57600080fd5b8335610bb781610af7565b92506020840135610bc781610af7565b929592945050506040919091013590565b60008060408385031215610beb57600080fd5b8235610bf681610af7565b946020939093013593505050565b600060208284031215610c1657600080fd5b813560ff81168114610b7757600080fd5b60008060408385031215610c3a57600080fd5b8235610c4581610af7565b91506020830135610c5581610af7565b809150509250929050565b60008060208385031215610c7357600080fd5b823567ffffffffffffffff80821115610c8b57600080fd5b818501915085601f830112610c9f57600080fd5b813581811115610cae57600080fd5b8660208260051b8501011115610cc357600080fd5b60209290920196919550909350505050565b600080600060608486031215610cea57600080fd5b8335610cf581610af7565b9250610d0360208501610b0c565b9150604084013590509250925092565b60008060008060808587031215610d2957600080fd5b8435610d3481610af7565b9350610d4260208601610b0c565b9250610d5060408601610b0c565b9396929550929360600135925050565b600060208284031215610d7257600080fd5b8151610b7781610af7565b6020808252602a908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526939903ab73830bab9b2b960b11b606082015260800190565b600060208284031215610dd957600080fd5b81518015158114610b7757600080fd5b60208082526028908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526739903830bab9b2b960c11b60608201526080019056fea26469706673582212208298e2bea1b15e9d0b71a258e4425ada0f91f0b73975e73ef506ba14eb2081c264736f6c634300080c0033", + "storage": {} + }, + "0x0dcd1bf9a1b36ce34237eeafef220932846bcd82": { + "nonce": 1, + "balance": "0x0", + "code": "0x608060405234801561001057600080fd5b50600436106102065760003560e01c80638da5cb5b1161011a578063c6656702116100ad578063df5cf7231161007c578063df5cf72314610515578063e7a050aa1461053c578063f2fde38b1461054f578063f698da2514610562578063fabc1cbc1461056a57600080fd5b8063c6656702146104c9578063cbc2bd62146104dc578063cf756fdf146104ef578063df5b35471461050257600080fd5b8063b1344271116100e9578063b134427114610469578063b5d8b5b814610490578063c4623ea1146104a3578063c608c7f3146104b657600080fd5b80638da5cb5b1461040157806394f649dd14610412578063967fc0d2146104335780639b4da03d1461044657600080fd5b80635ac86ab71161019d5780637a7e0d921161016c5780637a7e0d92146103675780637ecebe0014610392578063886f1195146103b25780638b8aac3c146103c55780638c80d4e5146103ee57600080fd5b80635ac86ab7146103015780635c975abb14610334578063663c1de41461033c578063715018a61461035f57600080fd5b80634665bcda116101d95780634665bcda1461028057806348825e94146102bf5780634e5a4263146102e6578063595c6a67146102f957600080fd5b806310d67a2f1461020b578063136439dd1461022057806320606b701461023357806332e89ace1461026d575b600080fd5b61021e6102193660046129e8565b61057d565b005b61021e61022e366004612a05565b610639565b61025a7f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6040519081526020015b60405180910390f35b61025a61027b366004612a34565b610778565b6102a77f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe681565b6040516001600160a01b039091168152602001610264565b61025a7f4337f82d142e41f2a8c10547cd8c859bddb92262a61058e77842e24d9dea922481565b61021e6102f4366004612b3d565b610a66565b61021e610a9e565b61032461030f366004612b76565b609854600160ff9092169190911b9081161490565b6040519015158152602001610264565b60985461025a565b61032461034a3660046129e8565b60d16020526000908152604090205460ff1681565b61021e610b65565b61025a610375366004612b99565b60cd60209081526000928352604080842090915290825290205481565b61025a6103a03660046129e8565b60ca6020526000908152604090205481565b6097546102a7906001600160a01b031681565b61025a6103d33660046129e8565b6001600160a01b0316600090815260ce602052604090205490565b61021e6103fc366004612bc7565b610b79565b6033546001600160a01b03166102a7565b6104256104203660046129e8565b610bd2565b604051610264929190612c08565b60cb546102a7906001600160a01b031681565b6103246104543660046129e8565b60d36020526000908152604090205460ff1681565b6102a77f000000000000000000000000a513e6e4b8f2a923d98304ec87f64353c4d5c85381565b61021e61049e366004612cd1565b610d52565b61021e6104b1366004612d13565b610ec6565b61021e6104c4366004612d64565b610f1a565b61021e6104d73660046129e8565b610fd2565b6102a76104ea366004612db7565b610fe3565b61021e6104fd366004612d13565b61101b565b61021e610510366004612de3565b61114f565b6102a77f000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c981565b61025a61054a366004612bc7565b611378565b61021e61055d3660046129e8565b611441565b61025a6114b7565b61021e610578366004612a05565b6114f5565b609760009054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f49190612e4f565b6001600160a01b0316336001600160a01b03161461062d5760405162461bcd60e51b815260040161062490612e6c565b60405180910390fd5b61063681611651565b50565b60975460405163237dfb4760e11b81523360048201526001600160a01b03909116906346fbf68e90602401602060405180830381865afa158015610681573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a59190612eb6565b6106c15760405162461bcd60e51b815260040161062490612ed3565b6098548181161461073a5760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e70617573653a20696e76616c696420617474656d70742060448201527f746f20756e70617573652066756e6374696f6e616c69747900000000000000006064820152608401610624565b609881905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d906020015b60405180910390a250565b6098546000908190600190811614156107cf5760405162461bcd60e51b815260206004820152601960248201527814185d5cd8589b194e881a5b99195e081a5cc81c185d5cd959603a1b6044820152606401610624565b600260655414156108225760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610624565b60026065556001600160a01b038816600090815260d3602052604090205460ff16156108c95760405162461bcd60e51b815260206004820152604a60248201527f53747261746567794d616e616765722e6465706f736974496e746f537472617460448201527f656779576974685369676e61747572653a207468697264207472616e736665726064820152691cc8191a5cd8589b195960b21b608482015260a401610624565b4284101561094b5760405162461bcd60e51b815260206004820152604360248201527f53747261746567794d616e616765722e6465706f736974496e746f537472617460448201527f656779576974685369676e61747572653a207369676e617475726520657870696064820152621c995960ea1b608482015260a401610624565b6001600160a01b03858116600081815260ca602090815260408083205481517f4337f82d142e41f2a8c10547cd8c859bddb92262a61058e77842e24d9dea922493810193909352908201939093528b84166060820152928a16608084015260a0830189905260c0830182905260e0830187905290916101000160408051601f1981840301815291815281516020928301206001600160a01b038a16600090815260ca9093529082206001850190559150610a036114b7565b60405161190160f01b6020820152602281019190915260428101839052606201604051602081830303815290604052805190602001209050610a46888288611748565b610a52888c8c8c611907565b60016065559b9a5050505050505050505050565b60cb546001600160a01b03163314610a905760405162461bcd60e51b815260040161062490612f1b565b610a9a8282611ad6565b5050565b60975460405163237dfb4760e11b81523360048201526001600160a01b03909116906346fbf68e90602401602060405180830381865afa158015610ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0a9190612eb6565b610b265760405162461bcd60e51b815260040161062490612ed3565b600019609881905560405190815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a2565b610b6d611b44565b610b776000611b9e565b565b336001600160a01b037f000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c91614610bc15760405162461bcd60e51b815260040161062490612f85565b610bcc838383611bf0565b50505050565b6001600160a01b038116600090815260ce60205260408120546060918291908167ffffffffffffffff811115610c0a57610c0a612a1e565b604051908082528060200260200182016040528015610c33578160200160208202803683370190505b50905060005b82811015610cc4576001600160a01b038616600090815260cd6020908152604080832060ce9092528220805491929184908110610c7857610c78612fe3565b60009182526020808320909101546001600160a01b031683528201929092526040019020548251839083908110610cb157610cb1612fe3565b6020908102919091010152600101610c39565b5060ce6000866001600160a01b03166001600160a01b031681526020019081526020016000208181805480602002602001604051908101604052809291908181526020018280548015610d4057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610d22575b50505050509150935093505050915091565b60cb546001600160a01b03163314610d7c5760405162461bcd60e51b815260040161062490612f1b565b8060005b81811015610bcc5760d16000858584818110610d9e57610d9e612fe3565b9050602002016020810190610db391906129e8565b6001600160a01b0316815260208101919091526040016000205460ff1615610ebe57600060d16000868685818110610ded57610ded612fe3565b9050602002016020810190610e0291906129e8565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790557f4074413b4b443e4e58019f2855a8765113358c7c72e39509c6af45fc0f5ba030848483818110610e5d57610e5d612fe3565b9050602002016020810190610e7291906129e8565b6040516001600160a01b03909116815260200160405180910390a1610ebe848483818110610ea257610ea2612fe3565b9050602002016020810190610eb791906129e8565b6000611ad6565b600101610d80565b336001600160a01b037f000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c91614610f0e5760405162461bcd60e51b815260040161062490612f85565b610bcc84848484611d4c565b336001600160a01b037f000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c91614610f625760405162461bcd60e51b815260040161062490612f85565b604051636ce5768960e11b81526001600160a01b03858116600483015282811660248301526044820184905284169063d9caed1290606401600060405180830381600087803b158015610fb457600080fd5b505af1158015610fc8573d6000803e3d6000fd5b5050505050505050565b610fda611b44565b61063681611fd9565b60ce6020528160005260406000208181548110610fff57600080fd5b6000918252602090912001546001600160a01b03169150829050565b600054610100900460ff161580801561103b5750600054600160ff909116105b806110555750303b158015611055575060005460ff166001145b6110b85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610624565b6000805460ff1916600117905580156110db576000805461ff0019166101001790555b6110e3612042565b60c9556110f083836120d9565b6110f985611b9e565b61110284611fd9565b8015611148576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b60cb546001600160a01b031633146111795760405162461bcd60e51b815260040161062490612f1b565b8281146112025760405162461bcd60e51b815260206004820152604b60248201527f53747261746567794d616e616765722e61646453747261746567696573546f4460448201527f65706f73697457686974656c6973743a206172726179206c656e67746873206460648201526a0de40dcdee840dac2e8c6d60ab1b608482015260a401610624565b8260005b818110156113705760d1600087878481811061122457611224612fe3565b905060200201602081019061123991906129e8565b6001600160a01b0316815260208101919091526040016000205460ff1661136857600160d1600088888581811061127257611272612fe3565b905060200201602081019061128791906129e8565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790557f0c35b17d91c96eb2751cd456e1252f42a386e524ef9ff26ecc9950859fdc04fe8686838181106112e2576112e2612fe3565b90506020020160208101906112f791906129e8565b6040516001600160a01b03909116815260200160405180910390a161136886868381811061132757611327612fe3565b905060200201602081019061133c91906129e8565b85858481811061134e5761134e612fe3565b90506020020160208101906113639190612ff9565b611ad6565b600101611206565b505050505050565b6098546000908190600190811614156113cf5760405162461bcd60e51b815260206004820152601960248201527814185d5cd8589b194e881a5b99195e081a5cc81c185d5cd959603a1b6044820152606401610624565b600260655414156114225760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610624565b600260655561143333868686611907565b600160655595945050505050565b611449611b44565b6001600160a01b0381166114ae5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610624565b61063681611b9e565b60007f0000000000000000000000000000000000000000000000000000000000007a694614156114e8575060c95490565b6114f0612042565b905090565b609760009054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611548573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156c9190612e4f565b6001600160a01b0316336001600160a01b03161461159c5760405162461bcd60e51b815260040161062490612e6c565b60985419811960985419161461161a5760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e756e70617573653a20696e76616c696420617474656d7060448201527f7420746f2070617573652066756e6374696f6e616c69747900000000000000006064820152608401610624565b609881905560405181815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c9060200161076d565b6001600160a01b0381166116df5760405162461bcd60e51b815260206004820152604960248201527f5061757361626c652e5f73657450617573657252656769737472793a206e657760448201527f50617573657252656769737472792063616e6e6f7420626520746865207a65726064820152686f206164647265737360b81b608482015260a401610624565b609754604080516001600160a01b03928316815291831660208301527f6e9fcd539896fca60e8b0f01dd580233e48a6b0f7df013b89ba7f565869acdb6910160405180910390a1609780546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0383163b1561186757604051630b135d3f60e11b808252906001600160a01b03851690631626ba7e90611788908690869060040161306e565b602060405180830381865afa1580156117a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c99190613087565b6001600160e01b031916146118625760405162461bcd60e51b815260206004820152605360248201527f454950313237315369676e61747572655574696c732e636865636b5369676e6160448201527f747572655f454950313237313a2045524331323731207369676e6174757265206064820152721d995c9a599a58d85d1a5bdb8819985a5b1959606a1b608482015260a401610624565b505050565b826001600160a01b031661187b83836121bf565b6001600160a01b0316146118625760405162461bcd60e51b815260206004820152604760248201527f454950313237315369676e61747572655574696c732e636865636b5369676e6160448201527f747572655f454950313237313a207369676e6174757265206e6f742066726f6d6064820152661039b4b3b732b960c91b608482015260a401610624565b6001600160a01b038316600090815260d16020526040812054849060ff166119ad5760405162461bcd60e51b815260206004820152604d60248201527f53747261746567794d616e616765722e6f6e6c7953747261746567696573576860448201527f6974656c6973746564466f724465706f7369743a207374726174656779206e6f60648201526c1d081dda1a5d195b1a5cdd1959609a1b608482015260a401610624565b6119c26001600160a01b0385163387866121e3565b6040516311f9fbc960e21b81526001600160a01b038581166004830152602482018590528616906347e7ef24906044016020604051808303816000875af1158015611a11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3591906130b1565b9150611a4386858785611d4c565b604051631452b9d760e11b81526001600160a01b0387811660048301528681166024830152604482018490527f000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c916906328a573ae90606401600060405180830381600087803b158015611ab557600080fd5b505af1158015611ac9573d6000803e3d6000fd5b5050505050949350505050565b604080516001600160a01b038416815282151560208201527f77d930df4937793473a95024d87a98fd2ccb9e92d3c2463b3dacd65d3e6a5786910160405180910390a16001600160a01b0391909116600090815260d360205260409020805460ff1916911515919091179055565b6033546001600160a01b03163314610b775760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610624565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600081611c655760405162461bcd60e51b815260206004820152603e60248201527f53747261746567794d616e616765722e5f72656d6f76655368617265733a207360448201527f68617265416d6f756e742073686f756c64206e6f74206265207a65726f2100006064820152608401610624565b6001600160a01b03808516600090815260cd602090815260408083209387168352929052205480831115611cf75760405162461bcd60e51b815260206004820152603360248201527f53747261746567794d616e616765722e5f72656d6f76655368617265733a20736044820152720d0c2e4ca82dadeeadce840e8dede40d0d2ced606b1b6064820152608401610624565b6001600160a01b03808616600090815260cd602090815260408083209388168352929052208382039081905590831415611d3f57611d35858561223d565b6001915050611d45565b60009150505b9392505050565b6001600160a01b038416611dc85760405162461bcd60e51b815260206004820152603960248201527f53747261746567794d616e616765722e5f6164645368617265733a207374616b60448201527f65722063616e6e6f74206265207a65726f2061646472657373000000000000006064820152608401610624565b80611e345760405162461bcd60e51b815260206004820152603660248201527f53747261746567794d616e616765722e5f6164645368617265733a207368617260448201527565732073686f756c64206e6f74206265207a65726f2160501b6064820152608401610624565b6001600160a01b03808516600090815260cd6020908152604080832093861683529290522054611f45576001600160a01b038416600090815260ce602090815260409091205410611f065760405162461bcd60e51b815260206004820152605060248201527f53747261746567794d616e616765722e5f6164645368617265733a206465706f60448201527f73697420776f756c6420657863656564204d41585f5354414b45525f5354524160648201526f0a88a8eb2be9892a6a8be988a9c8ea8960831b608482015260a401610624565b6001600160a01b03848116600090815260ce602090815260408220805460018101825590835291200180546001600160a01b0319169184169190911790555b6001600160a01b03808516600090815260cd6020908152604080832093861683529290529081208054839290611f7c9084906130e0565b9091555050604080516001600160a01b03868116825285811660208301528416818301526060810183905290517f7cfff908a4b583f36430b25d75964c458d8ede8a99bd61be750e97ee1b2f3a969181900360800190a150505050565b60cb54604080516001600160a01b03928316815291831660208301527f4264275e593955ff9d6146a51a4525f6ddace2e81db9391abcc9d1ca48047d29910160405180910390a160cb80546001600160a01b0319166001600160a01b0392909216919091179055565b604080518082018252600a81526922b4b3b2b72630bcb2b960b11b60209182015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527f71b625cfad44bac63b13dba07f2e1d6084ee04b6f8752101ece6126d584ee6ea81840152466060820152306080808301919091528351808303909101815260a0909101909252815191012090565b6097546001600160a01b03161580156120fa57506001600160a01b03821615155b61217c5760405162461bcd60e51b815260206004820152604760248201527f5061757361626c652e5f696e697469616c697a655061757365723a205f696e6960448201527f7469616c697a6550617573657228292063616e206f6e6c792062652063616c6c6064820152666564206f6e636560c81b608482015260a401610624565b609881905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a2610a9a82611651565b60008060006121ce858561242f565b915091506121db8161249f565b509392505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052610bcc90859061265a565b6001600160a01b038216600090815260ce6020526040812054905b81811015612358576001600160a01b03848116600090815260ce602052604090208054918516918390811061228f5761228f612fe3565b6000918252602090912001546001600160a01b03161415612350576001600160a01b038416600090815260ce6020526040902080546122d0906001906130f8565b815481106122e0576122e0612fe3565b60009182526020808320909101546001600160a01b03878116845260ce909252604090922080549190921691908390811061231d5761231d612fe3565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550612358565b600101612258565b818114156123e05760405162461bcd60e51b815260206004820152604960248201527f53747261746567794d616e616765722e5f72656d6f766553747261746567794660448201527f726f6d5374616b657253747261746567794c6973743a207374726174656779206064820152681b9bdd08199bdd5b9960ba1b608482015260a401610624565b6001600160a01b038416600090815260ce602052604090208054806124075761240761310f565b600082815260209020810160001990810180546001600160a01b031916905501905550505050565b6000808251604114156124665760208301516040840151606085015160001a61245a8782858561272c565b94509450505050612498565b8251604014156124905760208301516040840151612485868383612819565b935093505050612498565b506000905060025b9250929050565b60008160048111156124b3576124b3613125565b14156124bc5750565b60018160048111156124d0576124d0613125565b141561251e5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610624565b600281600481111561253257612532613125565b14156125805760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610624565b600381600481111561259457612594613125565b14156125ed5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610624565b600481600481111561260157612601613125565b14156106365760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610624565b60006126af826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166128529092919063ffffffff16565b80519091501561186257808060200190518101906126cd9190612eb6565b6118625760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610624565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156127635750600090506003612810565b8460ff16601b1415801561277b57508460ff16601c14155b1561278c5750600090506004612810565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156127e0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661280957600060019250925050612810565b9150600090505b94509492505050565b6000806001600160ff1b0383168161283660ff86901c601b6130e0565b90506128448782888561272c565b935093505050935093915050565b60606128618484600085612869565b949350505050565b6060824710156128ca5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610624565b6001600160a01b0385163b6129215760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610624565b600080866001600160a01b0316858760405161293d919061313b565b60006040518083038185875af1925050503d806000811461297a576040519150601f19603f3d011682016040523d82523d6000602084013e61297f565b606091505b509150915061298f82828661299a565b979650505050505050565b606083156129a9575081611d45565b8251156129b95782518084602001fd5b8160405162461bcd60e51b81526004016106249190613157565b6001600160a01b038116811461063657600080fd5b6000602082840312156129fa57600080fd5b8135611d45816129d3565b600060208284031215612a1757600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060c08789031215612a4d57600080fd5b8635612a58816129d3565b95506020870135612a68816129d3565b9450604087013593506060870135612a7f816129d3565b92506080870135915060a087013567ffffffffffffffff80821115612aa357600080fd5b818901915089601f830112612ab757600080fd5b813581811115612ac957612ac9612a1e565b604051601f8201601f19908116603f01168101908382118183101715612af157612af1612a1e565b816040528281528c6020848701011115612b0a57600080fd5b8260208601602083013760006020848301015280955050505050509295509295509295565b801515811461063657600080fd5b60008060408385031215612b5057600080fd5b8235612b5b816129d3565b91506020830135612b6b81612b2f565b809150509250929050565b600060208284031215612b8857600080fd5b813560ff81168114611d4557600080fd5b60008060408385031215612bac57600080fd5b8235612bb7816129d3565b91506020830135612b6b816129d3565b600080600060608486031215612bdc57600080fd5b8335612be7816129d3565b92506020840135612bf7816129d3565b929592945050506040919091013590565b604080825283519082018190526000906020906060840190828701845b82811015612c4a5781516001600160a01b031684529284019290840190600101612c25565b5050508381038285015284518082528583019183019060005b81811015612c7f57835183529284019291840191600101612c63565b5090979650505050505050565b60008083601f840112612c9e57600080fd5b50813567ffffffffffffffff811115612cb657600080fd5b6020830191508360208260051b850101111561249857600080fd5b60008060208385031215612ce457600080fd5b823567ffffffffffffffff811115612cfb57600080fd5b612d0785828601612c8c565b90969095509350505050565b60008060008060808587031215612d2957600080fd5b8435612d34816129d3565b93506020850135612d44816129d3565b92506040850135612d54816129d3565b9396929550929360600135925050565b60008060008060808587031215612d7a57600080fd5b8435612d85816129d3565b93506020850135612d95816129d3565b9250604085013591506060850135612dac816129d3565b939692955090935050565b60008060408385031215612dca57600080fd5b8235612dd5816129d3565b946020939093013593505050565b60008060008060408587031215612df957600080fd5b843567ffffffffffffffff80821115612e1157600080fd5b612e1d88838901612c8c565b90965094506020870135915080821115612e3657600080fd5b50612e4387828801612c8c565b95989497509550505050565b600060208284031215612e6157600080fd5b8151611d45816129d3565b6020808252602a908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526939903ab73830bab9b2b960b11b606082015260800190565b600060208284031215612ec857600080fd5b8151611d4581612b2f565b60208082526028908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526739903830bab9b2b960c11b606082015260800190565b60208082526044908201527f53747261746567794d616e616765722e6f6e6c7953747261746567795768697460408201527f656c69737465723a206e6f742074686520737472617465677957686974656c6960608201526339ba32b960e11b608082015260a00190565b602080825260409082018190527f53747261746567794d616e616765722e6f6e6c7944656c65676174696f6e4d61908201527f6e616765723a206e6f74207468652044656c65676174696f6e4d616e61676572606082015260800190565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561300b57600080fd5b8135611d4581612b2f565b60005b83811015613031578181015183820152602001613019565b83811115610bcc5750506000910152565b6000815180845261305a816020860160208601613016565b601f01601f19169290920160200192915050565b8281526040602082015260006128616040830184613042565b60006020828403121561309957600080fd5b81516001600160e01b031981168114611d4557600080fd5b6000602082840312156130c357600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b600082198211156130f3576130f36130ca565b500190565b60008282101561310a5761310a6130ca565b500390565b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b6000825161314d818460208701613016565b9190910192915050565b602081526000611d45602083018461304256fea2646970667358221220ac5d735b508ba27b0932a9dab2cacd43280d9e99b8844fcb7c2e20a9e5a8a63664736f6c634300080c0033", + "storage": { "0x0": "0xff" } + }, + "0x14dc79964da2c08b23698b3d3cc7ca32193d9955": { + "nonce": 5, + "balance": "0x21ea4a7ec9e3e2d636c", + "code": "0x", + "storage": {} + }, + "0x15d34aaf54267db7d7c367839aaf71a00a2c6a65": { + "nonce": 5, + "balance": "0x21ea4a7ec52a397b31d", + "code": "0x", + "storage": {} + }, + "0x1613beb3b2c4f22ee086b2b38c1476a3ce7f78e8": { + "nonce": 1, + "balance": "0x0", + "code": "0x608060405234801561001057600080fd5b50600436106100625760003560e01c806331b36bd9146100675780633563b0d1146100905780634d2b57fe146100b05780634f739f74146100d05780635c155662146100f0578063cefdc1d414610110575b600080fd5b61007a6100753660046113fa565b610131565b60405161008791906114e8565b60405180910390f35b6100a361009e366004611524565b61024d565b604051610087919061167f565b6100c36100be3660046116f8565b6106e3565b6040516100879190611747565b6100e36100de3660046117df565b6107f8565b60405161008791906118d7565b6101036100fe366004611992565b610f22565b60405161008791906119f5565b61012361011e366004611a2d565b6110ea565b604051610087929190611a64565b606081516001600160401b0381111561014c5761014c611391565b604051908082528060200260200182016040528015610175578160200160208202803683370190505b50905060005b825181101561024657836001600160a01b03166313542a4e8483815181106101a5576101a5611a85565b60200260200101516040518263ffffffff1660e01b81526004016101d891906001600160a01b0391909116815260200190565b602060405180830381865afa1580156101f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102199190611a9b565b82828151811061022b5761022b611a85565b602090810291909101015261023f81611aca565b905061017b565b5092915050565b60606000846001600160a01b031663683048356040518163ffffffff1660e01b8152600401602060405180830381865afa15801561028f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b39190611ae5565b90506000856001600160a01b0316639e9923c26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103199190611ae5565b90506000866001600160a01b0316635df459466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561035b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037f9190611ae5565b9050600086516001600160401b0381111561039c5761039c611391565b6040519080825280602002602001820160405280156103cf57816020015b60608152602001906001900390816103ba5790505b50905060005b87518110156106d75760008882815181106103f2576103f2611a85565b0160200151604051638902624560e01b815260f89190911c6004820181905263ffffffff8a16602483015291506000906001600160a01b03871690638902624590604401600060405180830381865afa158015610453573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261047b9190810190611b02565b905080516001600160401b0381111561049657610496611391565b6040519080825280602002602001820160405280156104e157816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816104b45790505b508484815181106104f4576104f4611a85565b602002602001018190525060005b81518110156106c1576040518060600160405280876001600160a01b03166347b314e885858151811061053757610537611a85565b60200260200101516040518263ffffffff1660e01b815260040161055d91815260200190565b602060405180830381865afa15801561057a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061059e9190611ae5565b6001600160a01b031681526020018383815181106105be576105be611a85565b60200260200101518152602001896001600160a01b031663fa28c6278585815181106105ec576105ec611a85565b60209081029190910101516040516001600160e01b031960e084901b168152600481019190915260ff8816602482015263ffffffff8f166044820152606401602060405180830381865afa158015610648573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066c9190611b92565b6001600160601b031681525085858151811061068a5761068a611a85565b602002602001015182815181106106a3576106a3611a85565b602002602001018190525080806106b990611aca565b915050610502565b50505080806106cf90611aca565b9150506103d5565b50979650505050505050565b606081516001600160401b038111156106fe576106fe611391565b604051908082528060200260200182016040528015610727578160200160208202803683370190505b50905060005b825181101561024657836001600160a01b031663296bb06484838151811061075757610757611a85565b60200260200101516040518263ffffffff1660e01b815260040161077d91815260200190565b602060405180830381865afa15801561079a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107be9190611ae5565b8282815181106107d0576107d0611a85565b6001600160a01b03909216602092830291909101909101526107f181611aca565b905061072d565b6108236040518060800160405280606081526020016060815260200160608152602001606081525090565b6000876001600160a01b031663683048356040518163ffffffff1660e01b8152600401602060405180830381865afa158015610863573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108879190611ae5565b90506108b46040518060800160405280606081526020016060815260200160608152602001606081525090565b6040516361c8a12f60e11b81526001600160a01b038a169063c391425e906108e4908b9089908990600401611bbb565b600060405180830381865afa158015610901573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109299190810190611c05565b81526040516340e03a8160e11b81526001600160a01b038316906381c075029061095b908b908b908b90600401611cbc565b600060405180830381865afa158015610978573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109a09190810190611c05565b6040820152856001600160401b038111156109bd576109bd611391565b6040519080825280602002602001820160405280156109f057816020015b60608152602001906001900390816109db5790505b50606082015260005b60ff8116871115610e33576000856001600160401b03811115610a1e57610a1e611391565b604051908082528060200260200182016040528015610a47578160200160208202803683370190505b5083606001518360ff1681518110610a6157610a61611a85565b602002602001018190525060005b86811015610d335760008c6001600160a01b03166304ec63518a8a85818110610a9a57610a9a611a85565b905060200201358e88600001518681518110610ab857610ab8611a85565b60200260200101516040518463ffffffff1660e01b8152600401610af59392919092835263ffffffff918216602084015216604082015260600190565b602060405180830381865afa158015610b12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b369190611ce5565b90506001600160c01b038116610bde5760405162461bcd60e51b815260206004820152605c60248201527f4f70657261746f7253746174655265747269657665722e676574436865636b5360448201527f69676e617475726573496e64696365733a206f70657261746f72206d7573742060648201527f6265207265676973746572656420617420626c6f636b6e756d62657200000000608482015260a40160405180910390fd5b8a8a8560ff16818110610bf357610bf3611a85565b6001600160c01b03841692013560f81c9190911c600190811614159050610d2057856001600160a01b031663dd9846b98a8a85818110610c3557610c35611a85565b905060200201358d8d8860ff16818110610c5157610c51611a85565b6040516001600160e01b031960e087901b1681526004810194909452919091013560f81c60248301525063ffffffff8f166044820152606401602060405180830381865afa158015610ca7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccb9190611d0e565b85606001518560ff1681518110610ce457610ce4611a85565b60200260200101518481518110610cfd57610cfd611a85565b63ffffffff9092166020928302919091019091015282610d1c81611aca565b9350505b5080610d2b81611aca565b915050610a6f565b506000816001600160401b03811115610d4e57610d4e611391565b604051908082528060200260200182016040528015610d77578160200160208202803683370190505b50905060005b82811015610df85784606001518460ff1681518110610d9e57610d9e611a85565b60200260200101518181518110610db757610db7611a85565b6020026020010151828281518110610dd157610dd1611a85565b63ffffffff9092166020928302919091019091015280610df081611aca565b915050610d7d565b508084606001518460ff1681518110610e1357610e13611a85565b602002602001018190525050508080610e2b90611d2b565b9150506109f9565b506000896001600160a01b0316635df459466040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e989190611ae5565b60405163354952a360e21b81529091506001600160a01b0382169063d5254a8c90610ecb908b908b908e90600401611d4b565b600060405180830381865afa158015610ee8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f109190810190611c05565b60208301525098975050505050505050565b60606000846001600160a01b031663c391425e84866040518363ffffffff1660e01b8152600401610f54929190611d75565b600060405180830381865afa158015610f71573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f999190810190611c05565b9050600084516001600160401b03811115610fb657610fb6611391565b604051908082528060200260200182016040528015610fdf578160200160208202803683370190505b50905060005b85518110156110e057866001600160a01b03166304ec635187838151811061100f5761100f611a85565b60200260200101518786858151811061102a5761102a611a85565b60200260200101516040518463ffffffff1660e01b81526004016110679392919092835263ffffffff918216602084015216604082015260600190565b602060405180830381865afa158015611084573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110a89190611ce5565b6001600160c01b03168282815181106110c3576110c3611a85565b6020908102919091010152806110d881611aca565b915050610fe5565b5095945050505050565b604080516001808252818301909252600091606091839160208083019080368337019050509050848160008151811061112557611125611a85565b60209081029190910101526040516361c8a12f60e11b81526000906001600160a01b0388169063c391425e906111619088908690600401611d75565b600060405180830381865afa15801561117e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111a69190810190611c05565b6000815181106111b8576111b8611a85565b60209081029190910101516040516304ec635160e01b81526004810188905263ffffffff87811660248301529091166044820181905291506000906001600160a01b038916906304ec635190606401602060405180830381865afa158015611224573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112489190611ce5565b6001600160c01b03169050600061125e8261127c565b90508161126c8a838a61024d565b9550955050505050935093915050565b606060008061128a84611348565b61ffff166001600160401b038111156112a5576112a5611391565b6040519080825280601f01601f1916602001820160405280156112cf576020820181803683370190505b5090506000805b8251821080156112e7575061010081105b1561133e576001811b93508584161561132e578060f81b83838151811061131057611310611a85565b60200101906001600160f81b031916908160001a9053508160010191505b61133781611aca565b90506112d6565b5090949350505050565b6000805b82156113735761135d600184611d94565b909216918061136b81611dab565b91505061134c565b92915050565b6001600160a01b038116811461138e57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156113cf576113cf611391565b604052919050565b60006001600160401b038211156113f0576113f0611391565b5060051b60200190565b6000806040838503121561140d57600080fd5b823561141881611379565b91506020838101356001600160401b0381111561143457600080fd5b8401601f8101861361144557600080fd5b8035611458611453826113d7565b6113a7565b81815260059190911b8201830190838101908883111561147757600080fd5b928401925b8284101561149e57833561148f81611379565b8252928401929084019061147c565b80955050505050509250929050565b600081518084526020808501945080840160005b838110156114dd578151875295820195908201906001016114c1565b509495945050505050565b6020815260006114fb60208301846114ad565b9392505050565b63ffffffff8116811461138e57600080fd5b803561151f81611502565b919050565b60008060006060848603121561153957600080fd5b833561154481611379565b92506020848101356001600160401b038082111561156157600080fd5b818701915087601f83011261157557600080fd5b81358181111561158757611587611391565b611599601f8201601f191685016113a7565b915080825288848285010111156115af57600080fd5b80848401858401376000848284010152508094505050506115d260408501611514565b90509250925092565b600081518084526020808501808196508360051b810191508286016000805b86811015611671578385038a52825180518087529087019087870190845b8181101561165c57835180516001600160a01b031684528a8101518b8501526040908101516001600160601b03169084015292890192606090920191600101611618565b50509a87019a955050918501916001016115fa565b509298975050505050505050565b6020815260006114fb60208301846115db565b600082601f8301126116a357600080fd5b813560206116b3611453836113d7565b82815260059290921b840181019181810190868411156116d257600080fd5b8286015b848110156116ed57803583529183019183016116d6565b509695505050505050565b6000806040838503121561170b57600080fd5b823561171681611379565b915060208301356001600160401b0381111561173157600080fd5b61173d85828601611692565b9150509250929050565b6020808252825182820181905260009190848201906040850190845b818110156117885783516001600160a01b031683529284019291840191600101611763565b50909695505050505050565b60008083601f8401126117a657600080fd5b5081356001600160401b038111156117bd57600080fd5b6020830191508360208260051b85010111156117d857600080fd5b9250929050565b600080600080600080608087890312156117f857600080fd5b863561180381611379565b9550602087013561181381611502565b945060408701356001600160401b038082111561182f57600080fd5b818901915089601f83011261184357600080fd5b81358181111561185257600080fd5b8a602082850101111561186457600080fd5b60208301965080955050606089013591508082111561188257600080fd5b5061188f89828a01611794565b979a9699509497509295939492505050565b600081518084526020808501945080840160005b838110156114dd57815163ffffffff16875295820195908201906001016118b5565b6000602080835283516080828501526118f360a08501826118a1565b905081850151601f198086840301604087015261191083836118a1565b9250604087015191508086840301606087015261192d83836118a1565b60608801518782038301608089015280518083529194508501925084840190600581901b8501860160005b8281101561198457848783030184526119728287516118a1565b95880195938801939150600101611958565b509998505050505050505050565b6000806000606084860312156119a757600080fd5b83356119b281611379565b925060208401356001600160401b038111156119cd57600080fd5b6119d986828701611692565b92505060408401356119ea81611502565b809150509250925092565b6020808252825182820181905260009190848201906040850190845b8181101561178857835183529284019291840191600101611a11565b600080600060608486031215611a4257600080fd5b8335611a4d81611379565b92506020840135915060408401356119ea81611502565b828152604060208201526000611a7d60408301846115db565b949350505050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611aad57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000600019821415611ade57611ade611ab4565b5060010190565b600060208284031215611af757600080fd5b81516114fb81611379565b60006020808385031215611b1557600080fd5b82516001600160401b03811115611b2b57600080fd5b8301601f81018513611b3c57600080fd5b8051611b4a611453826113d7565b81815260059190911b82018301908381019087831115611b6957600080fd5b928401925b82841015611b8757835182529284019290840190611b6e565b979650505050505050565b600060208284031215611ba457600080fd5b81516001600160601b03811681146114fb57600080fd5b63ffffffff84168152604060208201819052810182905260006001600160fb1b03831115611be857600080fd5b8260051b8085606085013760009201606001918252509392505050565b60006020808385031215611c1857600080fd5b82516001600160401b03811115611c2e57600080fd5b8301601f81018513611c3f57600080fd5b8051611c4d611453826113d7565b81815260059190911b82018301908381019087831115611c6c57600080fd5b928401925b82841015611b87578351611c8481611502565b82529284019290840190611c71565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b63ffffffff84168152604060208201526000611cdc604083018486611c93565b95945050505050565b600060208284031215611cf757600080fd5b81516001600160c01b03811681146114fb57600080fd5b600060208284031215611d2057600080fd5b81516114fb81611502565b600060ff821660ff811415611d4257611d42611ab4565b60010192915050565b604081526000611d5f604083018587611c93565b905063ffffffff83166020830152949350505050565b63ffffffff83168152604060208201526000611a7d60408301846114ad565b600082821015611da657611da6611ab4565b500390565b600061ffff80831681811415611dc357611dc3611ab4565b600101939250505056fea2646970667358221220f132d612dc5ee69696c54481af5080643164710364aba06230c3a62cc008321664736f6c634300080c0033", + "storage": {} + }, + "0x2279b7a0a67db372996a5fab50d91eaa73d2ebe6": { + "nonce": 1, + "balance": "0x0", + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106f1565b610118565b61005b61009336600461070c565b61015f565b3480156100a457600080fd5b506100ad6101d0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106f1565b61020b565b3480156100f557600080fd5b506100ad610235565b61010661029b565b61011661011161033a565b610344565b565b610120610368565b6001600160a01b0316336001600160a01b03161415610157576101548160405180602001604052806000815250600061039b565b50565b6101546100fe565b610167610368565b6001600160a01b0316336001600160a01b031614156101c8576101c38383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001925061039b915050565b505050565b6101c36100fe565b60006101da610368565b6001600160a01b0316336001600160a01b03161415610200576101fb61033a565b905090565b6102086100fe565b90565b610213610368565b6001600160a01b0316336001600160a01b0316141561015757610154816103c6565b600061023f610368565b6001600160a01b0316336001600160a01b03161415610200576101fb610368565b6060610285838360405180606001604052806027815260200161080b6027913961041a565b9392505050565b6001600160a01b03163b151590565b6102a3610368565b6001600160a01b0316336001600160a01b031614156101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101fb6104f7565b3660008037600080366000845af43d6000803e808015610363573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103a48361051f565b6000825111806103b15750805b156101c3576103c08383610260565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103ef610368565b604080516001600160a01b03928316815291841660208301520160405180910390a16101548161055f565b60606001600160a01b0384163b6104825760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610331565b600080856001600160a01b03168560405161049d91906107bb565b600060405180830381855af49150503d80600081146104d8576040519150601f19603f3d011682016040523d82523d6000602084013e6104dd565b606091505b50915091506104ed828286610608565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61038c565b61052881610641565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105c45760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610331565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60608315610617575081610285565b8251156106275782518084602001fd5b8160405162461bcd60e51b815260040161033191906107d7565b6001600160a01b0381163b6106ae5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610331565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105e7565b80356001600160a01b03811681146106ec57600080fd5b919050565b60006020828403121561070357600080fd5b610285826106d5565b60008060006040848603121561072157600080fd5b61072a846106d5565b9250602084013567ffffffffffffffff8082111561074757600080fd5b818601915086601f83011261075b57600080fd5b81358181111561076a57600080fd5b87602082850101111561077c57600080fd5b6020830194508093505050509250925092565b60005b838110156107aa578181015183820152602001610792565b838111156103c05750506000910152565b600082516107cd81846020870161078f565b9190910192915050565b60208152600082518060208401526107f681604085016020870161078f565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212208c7daa35c73cc3931155de6fec176061a18c7828634d7222e2c3c877ecc7552c64736f6c634300080c0033", + "storage": { + "0x0": "0x1", + "0x33": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x65": "0x9fe46736679d2d9a65f0992f2272de9f3c7fa6e0", + "0x66": "0x1e", + "0x97": "0x0", + "0x100b92d405499c3de7f4a1e8085709adcf550341c269b620c70ea9255439afcd": "0x0", + "0x1393a1d70b9b844090bd72cf75acdf0f029e51c7f20dc19f709114e90291f857": "0x0", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x959922be3caee4b8cd9a407cc3ac1c251c2007b1", + "0x386ca4caf6b5d029b6056a7ab8ca7941f9c6f68fcf59a75e75818295fb25dee7": "0x0", + "0x4bd1a248598516933914f7c6a6034a5ceb25277f3805df0b4c6bc6d58e8df63b": "0x0", + "0x5198c4d0ef0d0dff50c7cdf0b0c169a8058deb467803638255c839040d6cffb6": "0x0", + "0x7252638e9537b92a07e7971413facd0d1d32e075f171550c9098ff9a973b94ab": "0x0", + "0xb03c1d8a8855206d8f1a60ef13fe8ca0133e544612372e0bf9492485fffa4665": "0x0", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512", + "0xbbed94ee43ad8dc25c0f280657be25eac161dcc66395523da10db7015bc63ae2": "0x0", + "0xcf12883c0efa64ef4a106bff64685433c1d7aa1316b9289d7b2e1186b1f32f47": "0x0", + "0xd217710a0c414a0f43791db2b6df0b24fa10e2744800f58caf0c33ca34de7572": "0x0" + } + }, + "0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f": { + "nonce": 5, + "balance": "0x21ea4a7eca90e2b826c", + "code": "0x", + "storage": {} + }, + "0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc": { + "nonce": 5, + "balance": "0x21ea4a7ebceeeeaa174", + "code": "0x", + "storage": {} + }, + "0x4e59b44847b379578588920ca78fbf26c0b4956c": { + "nonce": 0, + "balance": "0x0", + "code": "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3", + "storage": {} + }, + "0x5fbdb2315678afecb367f032d93f642f64180aa3": { + "nonce": 1, + "balance": "0x0", + "code": "0x608060405234801561001057600080fd5b506004361061007d5760003560e01c80637fafbbdd1161005b5780637fafbbdd146100ee5780638736381a1461011d5780638c5b838514610134578063acd5baa21461018057600080fd5b80633ca6bb92146100825780636842109e146100ab5780637f3c2c28146100d9575b600080fd5b610095610090366004610458565b610193565b6040516100a29190610495565b60405180910390f35b6100be6100b936600461056b565b61022d565b604080519384526020840192909252908201526060016100a2565b6100ec6100e73660046105b0565b6102a2565b005b6100be6100fc366004610458565b60036020526000908152604090208054600182015460029092015490919083565b61012660025481565b6040519081526020016100a2565b61016861014236600461060e565b80516020818301810180516000825292820191909301209152546001600160a01b031681565b6040516001600160a01b0390911681526020016100a2565b6100ec61018e36600461064b565b61039a565b600160205260009081526040902080546101ac9061069f565b80601f01602080910402602001604051908101604052809291908181526020018280546101d89061069f565b80156102255780601f106101fa57610100808354040283529160200191610225565b820191906000526020600020905b81548152906001019060200180831161020857829003601f168201915b505050505081565b60008060008060036000878760405160200161024a9291906106d9565b60408051601f1981840301815291815281516020928301208352828201939093529082016000208251606081018452815480825260018301549382018490526002909201549301839052955093509150509250925092565b60006001600160a01b03166000836040516102bd91906106fb565b908152604051908190036020019020546001600160a01b0316146103275760405162461bcd60e51b815260206004820152601b60248201527f636f6e747261637420616c726561647920726567697374657265640000000000604482015260640160405180910390fd5b8060008360405161033891906106fb565b908152604080516020928190038301902080546001600160a01b0319166001600160a01b03949094169390931790925560025460009081526001909152206103808382610768565b506002805490600061039183610828565b91905055505050565b6003600085856040516020016103b19291906106d9565b604051602081830303815290604052805190602001208152602001908152602001600020600001546000146103e557600080fd5b604051806060016040528083815260200182815260200184815250600360008660405160200161041591906106fb565b60408051601f1981840301815291815281516020928301208352828201939093529082016000208351815590830151600182015591015160029091015550505050565b60006020828403121561046a57600080fd5b5035919050565b60005b8381101561048c578181015183820152602001610474565b50506000910152565b60208152600082518060208401526104b4816040850160208701610471565b601f01601f19169190910160400192915050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126104ef57600080fd5b813567ffffffffffffffff8082111561050a5761050a6104c8565b604051601f8301601f19908116603f01168101908282118183101715610532576105326104c8565b8160405283815286602085880101111561054b57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806040838503121561057e57600080fd5b823567ffffffffffffffff81111561059557600080fd5b6105a1858286016104de565b95602094909401359450505050565b600080604083850312156105c357600080fd5b823567ffffffffffffffff8111156105da57600080fd5b6105e6858286016104de565b92505060208301356001600160a01b038116811461060357600080fd5b809150509250929050565b60006020828403121561062057600080fd5b813567ffffffffffffffff81111561063757600080fd5b610643848285016104de565b949350505050565b6000806000806080858703121561066157600080fd5b843567ffffffffffffffff81111561067857600080fd5b610684878288016104de565b97602087013597506040870135966060013595509350505050565b600181811c908216806106b357607f821691505b6020821081036106d357634e487b7160e01b600052602260045260246000fd5b50919050565b600083516106eb818460208801610471565b9190910191825250602001919050565b6000825161070d818460208701610471565b9190910192915050565b601f821115610763576000816000526020600020601f850160051c810160208610156107405750805b601f850160051c820191505b8181101561075f5782815560010161074c565b5050505b505050565b815167ffffffffffffffff811115610782576107826104c8565b61079681610790845461069f565b84610717565b602080601f8311600181146107cb57600084156107b35750858301515b600019600386901b1c1916600185901b17855561075f565b600085815260208120601f198616915b828110156107fa578886015182559484019460019091019084016107db565b50858210156108185787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006001820161084857634e487b7160e01b600052601160045260246000fd5b506001019056fea264697066735822122004027db4bb76b44cb36fd812ce5d5b0a1b62fe652f80ec1cd0847649d2a2481464736f6c63430008180033", + "storage": { + "0x2": "0x9", + "0x1ac01cd1d863ce91fd19968ed0966f665d1e74d4837b0642c6cc45d0e9a1eea1": "0x0", + "0x1d4fbd750626f890eee906436e87fbba37637233c10ea6caa3959400bb5b6c6f": "0x0", + "0x1dc0aa43789912179e9a099ab0ba9cc68d8a5852aa0ff2aa357efbf46459f74b": "0x0", + "0x2530796d58628e4b3dd5db0d44433a0207a8da65e806a6815a2fa87fb24a7616": "0x1613beb3b2c4f22ee086b2b38c1476a3ce7f78e8", + "0x2ecd4187ae81f0488e18cc7fc9f0070ee223a52ecf4ca360654d9688d2b2feb3": "0x0", + "0x33fc4c28cf24fc3e342f1bc2c1753688c4fd257556b0061e8df5036fa539571d": "0x0", + "0x3541db3943a49e9bc08c1091fc723e702de969ac54841075428b35d17630b7d5": "0x0", + "0x3a5720db255dda4fc759dc6846d1f13051d9df3ecde134a0df275ca6069b829e": "0x165878a594ca255338adfa4d48449f69242eb8f", + "0x3e471b463d7129b02a5741cedb20b3761facec90c88a50dbf102af19ccdcfc58": "0x0", + "0x4672d66bd6b31e5b6046861ca0a16ff960e9cc36c315df13d4a2228868bce69c": "0x46", + "0x4672d66bd6b31e5b6046861ca0a16ff960e9cc36c315df13d4a2228868bce69d": "0x66828f7e", + "0x4672d66bd6b31e5b6046861ca0a16ff960e9cc36c315df13d4a2228868bce69e": "0x9", + "0x4db57451e2a8fd1712043520adfae22d5f9123e7cdc211ef2ea3c2f9f9432973": "0xc5a5c42992decbae36851359345fe25997f5c42d", + "0x4db623e5c4870b62d3fc9b4e8f893a1a77627d75ab45d9ff7e56ba19564af99b": "0x65726332304d6f636b5374726174656779000000000000000000000000000022", + "0x5a105ec97f363ec5586f506ef8e1fad389d2a0275fbef6322a78e21c0640504f": "0x67d269191c92caf3cd7723f116c85e6e9bf55933", + "0x5a697185bf6c4949aa9db15abf55574283a1917552d92045ce6b6aa3ae2ce655": "0x0", + "0x5b103892d785e903f72f2e72dfbd4a6e4f97ba9259586f91f2f7f2140e1bafd1": "0x7969c5ed335650692bc04293b07f5bf2e7a673c0", + "0x6b9fa4028d289b8b6d2a277760003772949eab3a19ca2c925bba93ffcb45fbbe": "0x0", + "0x6f540b3dcecc09b9a7da8a5bee1990cfc365872023a32192184152402a4692af": "0x0", + "0x740d9b4b7e6aa00c0f83bbb2a6b69e31e052c085af83872857478f7443c89d2a": "0x0", + "0x788a408b6fa94f32351ea2075021dffa8b99053510e67501f7e7353362805a16": "0x5fc8d32690cc91d4c39d9d3abcbd16989f875707", + "0x7d7a00081084405c16f2177997c404187cea4c4ffff0763bc31376d83c0e775f": "0x0", + "0x7dfe757ecd65cbd7922a9c0161e935dd7fdbcc0e999689c7d31633896b1fc60b": "0x6d6f636b417673536572766963654d616e61676572000000000000000000002a", + "0x8f331abe73332f95a25873e8b430885974c0409691f89d643119a11623a7924a": "0x64656c65676174696f6e4d616e61676572000000000000000000000000000022", + "0x9cacc91fad1b99c6b087374aaa48bb94777e3102189d594a093c4c5f1e8b0d06": "0x0", + "0xa27c2064c2cf377dbc02a9fc15a4b3ebeb0a0a09e278b15d7483c648bf58fe02": "0x14", + "0xa27c2064c2cf377dbc02a9fc15a4b3ebeb0a0a09e278b15d7483c648bf58fe03": "0x66828f4c", + "0xa27c2064c2cf377dbc02a9fc15a4b3ebeb0a0a09e278b15d7483c648bf58fe04": "0x9", + "0xa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49": "0x50726f787941646d696e00000000000000000000000000000000000000000014", + "0xaec042747de4dbfef4a318a36b979f05c565af1ba593f4159410715096300a21": "0xdc64a140aa3e981100a9beca4e685f962f0cf6c9", + "0xb0a80c8d3e2ea008739ebc08d92bd4d4a31cf98733c48067387e95601416765b": "0x0", + "0xb63de4c312985e039bc7cb922ff579b44d7f7a17a7495b9741d200b83002bf61": "0x0", + "0xc0f8c423799470410dad8e36ca3a91d3b1665450672348a739573f7b4cc8d053": "0x0", + "0xcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f": "0x4176734469726563746f72790000000000000000000000000000000000000018", + "0xce9564d5566850c1c2acf303dce3294f5714e28233b3d7c1992639555159f420": "0x0", + "0xd5e72402f9a8f9cf95a213bd1a09c160fe8e7b60c977f837b69f08d8fa56fc80": "0x0", + "0xd6b8b93bd8854fe813bf2c494a9d7862d1d948777f4a5bfdf1b066693ed94d83": "0xc3e53f4d16ae77db1c982e75a937b9f60fe63690", + "0xd9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330f": "0x656967656e6c6179657250617573657252656700000000000000000000000026", + "0xdc686ec4a0ff239c70e7c7c36e8f853eced3bc8618f48d2b816da2a74311237e": "0x73747261746567794d616e61676572000000000000000000000000000000001e", + "0xe18688d5851aa433ab67f12fb752c9493897b8d0378a5c622e5ae1ab2bf46b48": "0x0", + "0xe2689cd4a84e23ad2f564004f1c9013e9589d260bde6380aba3ca7e09e4df40c": "0x6d6f636b4176734f70657261746f72537461746552657472696576657200003a", + "0xe5be96bc9e75e510e7e079217ca03d7f8929a58282d4b289ea2bf40a87239628": "0x0", + "0xedc95719e9a3b28dd8e80877cb5880a9be7de1a13fc8b05e7999683b6b567643": "0x6d6f636b4176735265676973747279436f6f7264696e61746f72000000000034", + "0xf758e63a2b9a4c05f7403796fd178fa961b296e08733a8a64a7f7852bacf58a9": "0x9fe46736679d2d9a65f0992f2272de9f3c7fa6e0" + } + }, + "0x5fc8d32690cc91d4c39d9d3abcbd16989f875707": { + "nonce": 1, + "balance": "0x0", + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106f1565b610118565b61005b61009336600461070c565b61015f565b3480156100a457600080fd5b506100ad6101d0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106f1565b61020b565b3480156100f557600080fd5b506100ad610235565b61010661029b565b61011661011161033a565b610344565b565b610120610368565b6001600160a01b0316336001600160a01b03161415610157576101548160405180602001604052806000815250600061039b565b50565b6101546100fe565b610167610368565b6001600160a01b0316336001600160a01b031614156101c8576101c38383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001925061039b915050565b505050565b6101c36100fe565b60006101da610368565b6001600160a01b0316336001600160a01b03161415610200576101fb61033a565b905090565b6102086100fe565b90565b610213610368565b6001600160a01b0316336001600160a01b0316141561015757610154816103c6565b600061023f610368565b6001600160a01b0316336001600160a01b03161415610200576101fb610368565b6060610285838360405180606001604052806027815260200161080b6027913961041a565b9392505050565b6001600160a01b03163b151590565b6102a3610368565b6001600160a01b0316336001600160a01b031614156101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101fb6104f7565b3660008037600080366000845af43d6000803e808015610363573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103a48361051f565b6000825111806103b15750805b156101c3576103c08383610260565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103ef610368565b604080516001600160a01b03928316815291841660208301520160405180910390a16101548161055f565b60606001600160a01b0384163b6104825760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610331565b600080856001600160a01b03168560405161049d91906107bb565b600060405180830381855af49150503d80600081146104d8576040519150601f19603f3d011682016040523d82523d6000602084013e6104dd565b606091505b50915091506104ed828286610608565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61038c565b61052881610641565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105c45760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610331565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60608315610617575081610285565b8251156106275782518084602001fd5b8160405162461bcd60e51b815260040161033191906107d7565b6001600160a01b0381163b6106ae5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610331565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105e7565b80356001600160a01b03811681146106ec57600080fd5b919050565b60006020828403121561070357600080fd5b610285826106d5565b60008060006040848603121561072157600080fd5b61072a846106d5565b9250602084013567ffffffffffffffff8082111561074757600080fd5b818601915086601f83011261075b57600080fd5b81358181111561076a57600080fd5b87602082850101111561077c57600080fd5b6020830194508093505050509250925092565b60005b838110156107aa578181015183820152602001610792565b838111156103c05750506000910152565b600082516107cd81846020870161078f565b9190910192915050565b60208152600082518060208401526107f681604085016020870161078f565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212208c7daa35c73cc3931155de6fec176061a18c7828634d7222e2c3c877ecc7552c64736f6c634300080c0033", + "storage": { + "0x0": "0x1", + "0x33": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x65": "0x1", + "0x97": "0x9fe46736679d2d9a65f0992f2272de9f3c7fa6e0", + "0x98": "0x0", + "0xc9": "0x5bc5b424ff8db9bd8202cae3beb193c946b905d8ebddb990e36a723af40eb1c4", + "0xcb": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x17f7bbf439f69d31f7875a9b76fee55189df010c3ef81139a25f323068dda036": "0x1", + "0x1d54343aeb2a2d1054e02d93239c1dfa56e846cd848b1a974864628044024f87": "0x1", + "0x1f9eab9ee4192c6980c47dd29a704c1b177904fde01342b51b4030eab81f6249": "0x8042ae896b8e68bb", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0xdcd1bf9a1b36ce34237eeafef220932846bcd82", + "0x3de0abadbf6143887067e867d71d14d316fc83e1b3e43ef44558da3dd1984e05": "0x216714fd5b83698d", + "0x40c535a4a45fe852ec21338d6d42cad9fee16d07e36d750fd65ed1532316fc0b": "0x7969c5ed335650692bc04293b07f5bf2e7a673c0", + "0x4e0a51fd26771cc8e0118fc4993101067175e0a0f075985f71179b6265938f3c": "0x7969c5ed335650692bc04293b07f5bf2e7a673c0", + "0x5087c3127cba8feb0d570b7023ffa135d112fd9ddd6388e127b1057490654f68": "0x7969c5ed335650692bc04293b07f5bf2e7a673c0", + "0x7651a69f68b14174b46b2e090e43a66341d2f5d8e23e5bfdd60ea605d68ddc16": "0x1", + "0x8651ae832af017f5c542de1feed040f8a8a823bef9570884e9fefb0ebca34d7a": "0x7969c5ed335650692bc04293b07f5bf2e7a673c0", + "0x885b88a26973a0d995f339abf302191f6bd9c3f1c35f60e215917de873148ff1": "0x7969c5ed335650692bc04293b07f5bf2e7a673c0", + "0x8930e19288724c621237253fbdd986656e1e7792cd3dad28cfe83008d0033f26": "0x5d9f943ccb6a86b8", + "0x8b00a5b15f9a43717ddbcdd5b26c7ea8911909780ad51be2022c6e5b68ba60f0": "0x0", + "0x912145a7a45c64ddf5252326741e68d9219372b020d9024fd92881173cd19941": "0x1", + "0x96bffa00e85f8d42b9876c68a96c56c24c5c0d7b029b4f82cd607f9cfb7471e7": "0x32d96cba53cf0152", + "0x9e32a4740ce9aa7ef70d6241eec7918faa34b925ad3a355ab1dedbd3f795d33b": "0x122c6ab631ff0891", + "0x9f61c4c704364042590b062d4c0303438abcae7078fffa9922a0c19a53eed85e": "0x32a862794ae172cb", + "0xa1192d72203a4d5c8bf19f4fe0386f9b28ba31dd74483b0993a14945357a7bc4": "0x7969c5ed335650692bc04293b07f5bf2e7a673c0", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512", + "0xbc3510822c4351b3f0f548d60d83924819a8ca41ce84280c2762ffdbaeace4d8": "0x1", + "0xbdca4bf0cbefb63c16dc0613270620f0f029d6f1ac149e6656d3603e77d3bd7f": "0x1", + "0xc42e9c55b8ec54de36b5ea3f4e6928ff5078c8636397bc2b7b4a30c52cb7c059": "0x1", + "0xc4c08b2806611c44f3e759ce7d419bee04a964a5bb7e6df6acb31e9219ca1ac2": "0x7c6d1175e13d2753", + "0xc96438d4eb7b6bb4a9d5ce753d7e425a1be9ba3a9ab7a69824bf839636c71400": "0x7969c5ed335650692bc04293b07f5bf2e7a673c0", + "0xcc7738880c31a966acbc9e0cd61dd2699639da0c0fb4e38057de466e213ddd58": "0x7969c5ed335650692bc04293b07f5bf2e7a673c0", + "0xd0094af1e3bff4f1d2089c45849ae33285fe58b04e5f5e763ebd2d7de527f726": "0x86759309fd1fd327", + "0xd61592b22ff7bb8bd5419c99fa1878381ea0b14179e0369bb10f1fb0c9fcd99d": "0x1", + "0xd665a624157dc289bfdd8947da4621fe6a701cb3f2545c41043f553e0004c8f5": "0x1c712bd73fa1ed3c", + "0xd89c0d424ea7a762d99e0cb828dbf68c9bb0386a1aef182e84cfccde20323bf1": "0x7969c5ed335650692bc04293b07f5bf2e7a673c0", + "0xd8bf6fcb47f5c0c80fe11ec4e2e24f7990882d3dc412e1272ac8b8238bd96c67": "0x1", + "0xd938c877f88d172c33ab2a16a045dbe62dec079d3d2845475da670e3ffa8e805": "0x19aa30cbbe932840", + "0xde836558c1295fd28e954047a87eebcc99290e066b5f270dc2671f2a00c7acd3": "0x1", + "0xe0ef8e67489800538a09c05946ac0b5706b16e8d57dd3dd5af9933bf83ab2d4d": "0x7969c5ed335650692bc04293b07f5bf2e7a673c0", + "0xf1ba70b4177fbda7ecf4396f125335ba00168b662fccf58afb30e8efbd430817": "0x1" + } + }, + "0x610178da211fef7d417bc0e6fed39f05609ad788": { + "nonce": 1, + "balance": "0x0", + "code": "0x6080604052600436106101855760003560e01c806374cdd798116100d1578063c49074421161008a578063e251ef5211610064578063e251ef5214610563578063e2c8344514610583578063f2882461146105a3578063fe80b087146105d757600080fd5b8063c490744214610503578063c4d66de814610523578063dda3346c1461054357600080fd5b806374cdd7981461044057806387e0d289146104745780639b4e46341461049b578063a50600f4146104ae578063b522538a146104ce578063baa7145a146104ee57600080fd5b806334bea20a1161013e57806358eaee791161011857806358eaee791461038f5780635d3f65b6146103bc5780636fcd0e53146103dc5780637439841f1461040957600080fd5b806334bea20a146103005780633f65cf191461033b5780634665bcda1461035b57600080fd5b80630b18ff66146101db5780630cd4649e146102185780631a5057be1461022f5780631d905d5c146102635780633106ab53146102af5780633474aa16146102e057600080fd5b366101d657346037600082825461019c9190614c9f565b90915550506040513481527f6fdd3dbdb173299608c0aa9f368735857c8842b581f8389238bf05bd04b3bf499060200160405180910390a1005b600080fd5b3480156101e757600080fd5b506033546101fb906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561022457600080fd5b5061022d6105fb565b005b34801561023b57600080fd5b506101fb7f0000000000000000000000008a791620dd6260079bf849dc5567adc3f2fdc31881565b34801561026f57600080fd5b506102977f000000000000000000000000000000000000000000000000000000077359400081565b6040516001600160401b03909116815260200161020f565b3480156102bb57600080fd5b506034546102d090600160401b900460ff1681565b604051901515815260200161020f565b3480156102ec57600080fd5b50603454610297906001600160401b031681565b34801561030c57600080fd5b506102d061031b366004614cdc565b603560209081526000928352604080842090915290825290205460ff1681565b34801561034757600080fd5b5061022d610356366004614d6f565b610764565b34801561036757600080fd5b506101fb7f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe681565b34801561039b57600080fd5b506103af6103aa366004614e80565b610caf565b60405161020f9190614ef9565b3480156103c857600080fd5b50603854610297906001600160401b031681565b3480156103e857600080fd5b506103fc6103f7366004614f07565b610d14565b60405161020f9190614f20565b34801561041557600080fd5b506103af610424366004614f07565b600090815260366020526040902054600160c01b900460ff1690565b34801561044c57600080fd5b506101fb7f00000000000000000000000000000000219ab540356cbb839cbe05303d7705fa81565b34801561048057600080fd5b5060335461029790600160a01b90046001600160401b031681565b61022d6104a9366004614f68565b610dc1565b3480156104ba57600080fd5b5061022d6104c9366004614fdb565b610f6e565b3480156104da57600080fd5b506103fc6104e9366004614e80565b611304565b3480156104fa57600080fd5b5061022d6113f7565b34801561050f57600080fd5b5061022d61051e366004615085565b611462565b34801561052f57600080fd5b5061022d61053e3660046150b1565b61169f565b34801561054f57600080fd5b5061022d61055e3660046151cb565b611877565b34801561056f57600080fd5b5061022d61057e36600461529c565b611a4a565b34801561058f57600080fd5b5061022d61059e366004615085565b611e15565b3480156105af57600080fd5b506102977f000000000000000000000000000000000000000000000000000000006059f46081565b3480156105e357600080fd5b506105ed60375481565b60405190815260200161020f565b604051635ac86ab760e01b8152600260048201819052907f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe66001600160a01b031690635ac86ab790602401602060405180830381865afa158015610663573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106879190615397565b156106ad5760405162461bcd60e51b81526004016106a4906153b9565b60405180910390fd5b6033546001600160a01b031633146106d75760405162461bcd60e51b81526004016106a490615416565b603454600160401b900460ff16156107015760405162461bcd60e51b81526004016106a49061545e565b6034805460ff60401b1916600160401b179055603354610729906001600160a01b0316611ff8565b6033546040516001600160a01b03909116907fca8dfc8c5e0a67a74501c072a3325f685259bebbae7cfd230ab85198a78b70cd90600090a250565b6033546001600160a01b0316331461078e5760405162461bcd60e51b81526004016106a490615416565b604051635ac86ab760e01b8152600260048201819052907f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe66001600160a01b031690635ac86ab790602401602060405180830381865afa1580156107f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061081a9190615397565b156108375760405162461bcd60e51b81526004016106a4906153b9565b603454600160401b900460ff166108af5760405162461bcd60e51b815260206004820152603660248201527f456967656e506f642e686173456e61626c656452657374616b696e673a2072656044820152751cdd185ada5b99c81a5cc81b9bdd08195b98589b195960521b60648201526084016106a4565b85841480156108bd57508382145b61094d5760405162461bcd60e51b815260206004820152605560248201527f456967656e506f642e7665726966795769746864726177616c43726564656e7460448201527f69616c733a2076616c696461746f72496e646963657320616e642070726f6f666064820152740e640daeae6e840c4ca40e6c2daca40d8cadccee8d605b1b608482015260a4016106a4565b603354600160a01b90046001600160401b031615806109a2575060335461098c9061098790600160a01b90046001600160401b031661202c565b612116565b6001600160401b0316896001600160401b031610155b610a2e5760405162461bcd60e51b815260206004820152605160248201527f456967656e506f642e7665726966795769746864726177616c43726564656e7460448201527f69616c733a2070726f6f66206d75737420626520696e207468652065706f63686064820152701030b33a32b91030b1ba34bb30ba34b7b760791b608482015260a4016106a4565b42610a44613f486001600160401b038c16614c9f565b1015610acd5760405162461bcd60e51b815260206004820152604c60248201527f456967656e506f642e7665726966795769746864726177616c43726564656e7460448201527f69616c733a207370656369666965642074696d657374616d7020697320746f6f60648201526b0819985c881a5b881c185cdd60a21b608482015260a4016106a4565b60405163d1c64cc960e01b81526001600160401b038a166004820152610b76907f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe66001600160a01b03169063d1c64cc990602401602060405180830381865afa158015610b3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6291906154ad565b8935610b7160208c018c6154c6565b612163565b6000805b87811015610c1a57610bfc8b8b358b8b85818110610b9a57610b9a61550c565b9050602002016020810190610baf9190615522565b8a8a86818110610bc157610bc161550c565b9050602002810190610bd391906154c6565b8a8a88818110610be557610be561550c565b9050602002810190610bf79190615549565b6122f1565b610c069083614c9f565b915080610c1281615592565b915050610b7a565b5060335460405163030b147160e61b81526001600160a01b039182166004820152602481018390527f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe69091169063c2c51c40906044015b600060405180830381600087803b158015610c8b57600080fd5b505af1158015610c9f573d6000803e3d6000fd5b5050505050505050505050505050565b600080610cf184848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506127ab92505050565b600090815260366020526040902054600160c01b900460ff169150505b92915050565b610d3c6040805160808101825260008082526020820181905291810182905290606082015290565b600082815260366020908152604091829020825160808101845281546001600160401b038082168352600160401b8204811694830194909452600160801b810490931693810193909352906060830190600160c01b900460ff166002811115610da757610da7614ec1565b6002811115610db857610db8614ec1565b90525092915050565b336001600160a01b037f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe61614610e095760405162461bcd60e51b81526004016106a4906155ad565b346801bc16d674ec80000014610e955760405162461bcd60e51b8152602060048201526044602482018190527f456967656e506f642e7374616b653a206d75737420696e697469616c6c792073908201527f74616b6520666f7220616e792076616c696461746f72207769746820333220656064820152633a3432b960e11b608482015260a4016106a4565b7f00000000000000000000000000000000219ab540356cbb839cbe05303d7705fa6001600160a01b031663228951186801bc16d674ec8000008787610ed86128a5565b8888886040518863ffffffff1660e01b8152600401610efc9695949392919061567f565b6000604051808303818588803b158015610f1557600080fd5b505af1158015610f29573d6000803e3d6000fd5b50505050507f606865b7934a25d4aed43f6cdb426403353fa4b3009c4d228407474581b01e238585604051610f5f9291906156ce565b60405180910390a15050505050565b604051635ac86ab760e01b8152600360048201819052907f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe66001600160a01b031690635ac86ab790602401602060405180830381865afa158015610fd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ffa9190615397565b156110175760405162461bcd60e51b81526004016106a4906153b9565b868414801561102557508382145b6110ae5760405162461bcd60e51b815260206004820152604e60248201527f456967656e506f642e76657269667942616c616e6365557064617465733a207660448201527f616c696461746f72496e646963657320616e642070726f6f6673206d7573742060648201526d0c4ca40e6c2daca40d8cadccee8d60931b608482015260a4016106a4565b426110c4613f486001600160401b038c16614c9f565b10156111465760405162461bcd60e51b815260206004820152604560248201527f456967656e506f642e76657269667942616c616e6365557064617465733a207360448201527f70656369666965642074696d657374616d7020697320746f6f2066617220696e606482015264081c185cdd60da1b608482015260a4016106a4565b60405163d1c64cc960e01b81526001600160401b038a1660048201526111ea907f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe66001600160a01b03169063d1c64cc990602401602060405180830381865afa1580156111b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111db91906154ad565b8735610b7160208a018a6154c6565b6000805b8881101561128e576112708b8b8b8481811061120c5761120c61550c565b90506020020160208101906112219190615522565b8a358a8a868181106112355761123561550c565b905060200281019061124791906154c6565b8a8a888181106112595761125961550c565b905060200281019061126b9190615549565b6128ea565b61127a90836156e2565b91508061128681615592565b9150506111ee565b506033546001600160a01b037f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe681169163c2c51c4091166112d3633b9aca0085615723565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401610c71565b61132c6040805160808101825260008082526020820181905291810182905290606082015290565b6036600061136f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506127ab92505050565b81526020808201929092526040908101600020815160808101835281546001600160401b038082168352600160401b8204811695830195909552600160801b81049094169281019290925290916060830190600160c01b900460ff1660028111156113dc576113dc614ec1565b60028111156113ed576113ed614ec1565b9052509392505050565b6033546001600160a01b031633146114215760405162461bcd60e51b81526004016106a490615416565b603454600160401b900460ff161561144b5760405162461bcd60e51b81526004016106a49061545e565b603354611460906001600160a01b0316611ff8565b565b336001600160a01b037f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe616146114aa5760405162461bcd60e51b81526004016106a4906155ad565b6114b8633b9aca00826157be565b156115425760405162461bcd60e51b815260206004820152604e60248201527f456967656e506f642e776974686472617752657374616b6564426561636f6e4360448201527f6861696e4554483a20616d6f756e74576569206d75737420626520612077686f60648201526d1b194811ddd95a48185b5bdd5b9d60921b608482015260a4016106a4565b6000611552633b9aca00836157d2565b6034549091506001600160401b03908116908216111561160b5760405162461bcd60e51b815260206004820152606260248201527f456967656e506f642e776974686472617752657374616b6564426561636f6e4360448201527f6861696e4554483a20616d6f756e74477765692065786365656473207769746860648201527f6472617761626c6552657374616b6564457865637574696f6e4c617965724777608482015261656960f01b60a482015260c4016106a4565b603480548291906000906116299084906001600160401b03166157e6565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550826001600160a01b03167f8947fd2ce07ef9cc302c4e8f0461015615d91ce851564839e91cc804c2f49d8e8360405161168891815260200190565b60405180910390a261169a8383612dc8565b505050565b600054610100900460ff16158080156116bf5750600054600160ff909116105b806116d95750303b1580156116d9575060005460ff166001145b61173c5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016106a4565b6000805460ff19166001179055801561175f576000805461ff0019166101001790555b6001600160a01b0382166117d25760405162461bcd60e51b815260206004820152603460248201527f456967656e506f642e696e697469616c697a653a20706f644f776e65722063616044820152736e6e6f74206265207a65726f206164647265737360601b60648201526084016106a4565b603380546001600160a01b0384166001600160a01b031990911681179091556034805460ff60401b1916600160401b1790556040517fca8dfc8c5e0a67a74501c072a3325f685259bebbae7cfd230ab85198a78b70cd90600090a28015611873576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6033546001600160a01b031633146118a15760405162461bcd60e51b81526004016106a490615416565b604051635ac86ab760e01b8152600560048201819052907f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe66001600160a01b031690635ac86ab790602401602060405180830381865afa158015611909573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061192d9190615397565b1561194a5760405162461bcd60e51b81526004016106a4906153b9565b82518451146119d55760405162461bcd60e51b815260206004820152604b60248201527f456967656e506f642e7265636f766572546f6b656e733a20746f6b656e4c697360448201527f7420616e6420616d6f756e7473546f5769746864726177206d7573742062652060648201526a0e6c2daca40d8cadccee8d60ab1b608482015260a4016106a4565b60005b8451811015611a4357611a31838583815181106119f7576119f761550c565b6020026020010151878481518110611a1157611a1161550c565b60200260200101516001600160a01b0316612dd29092919063ffffffff16565b80611a3b81615592565b9150506119d8565b5050505050565b604051635ac86ab760e01b81526004808201819052907f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe66001600160a01b031690635ac86ab790602401602060405180830381865afa158015611ab1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad59190615397565b15611af25760405162461bcd60e51b81526004016106a4906153b9565b8386148015611b0057508588145b8015611b0b57508782145b611b7f576040805162461bcd60e51b81526020600482015260248101919091527f456967656e506f642e766572696679416e6450726f636573735769746864726160448201527f77616c733a20696e70757473206d7573742062652073616d65206c656e67746860648201526084016106a4565b60405163d1c64cc960e01b81526001600160401b038c166004820152611c23907f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe66001600160a01b03169063d1c64cc990602401602060405180830381865afa158015611bf0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c1491906154ad565b8b35610b7160208e018e6154c6565b604080518082019091526000808252602082015260005b83811015611d23576000611cde8d358d8d85818110611c5b57611c5b61550c565b9050602002810190611c6d919061580e565b8c8c86818110611c7f57611c7f61550c565b9050602002810190611c9191906154c6565b8c8c88818110611ca357611ca361550c565b9050602002810190611cb59190615549565b8c8c8a818110611cc757611cc761550c565b9050602002810190611cd99190615549565b612e24565b80518451919250908490611cf3908390614c9f565b9052506020808201519084018051611d0c9083906156e2565b905250819050611d1b81615592565b915050611c3a565b50805115611d52576033548151611d52916001600160a01b031690611d4d90633b9aca009061582f565b61339c565b602081015115611e075760335460208201516001600160a01b037f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe681169263c2c51c4092911690611da890633b9aca0090615723565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015611dee57600080fd5b505af1158015611e02573d6000803e3d6000fd5b505050505b505050505050505050505050565b6033546001600160a01b03163314611e3f5760405162461bcd60e51b81526004016106a490615416565b604051635ac86ab760e01b8152600560048201819052907f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe66001600160a01b031690635ac86ab790602401602060405180830381865afa158015611ea7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ecb9190615397565b15611ee85760405162461bcd60e51b81526004016106a4906153b9565b603754821115611f995760405162461bcd60e51b815260206004820152606a60248201527f456967656e506f642e77697468647261776e6f6e426561636f6e436861696e4560448201527f544842616c616e63655765693a20616d6f756e74546f5769746864726177206960648201527f732067726561746572207468616e206e6f6e426561636f6e436861696e45544860848201526942616c616e636557656960b01b60a482015260c4016106a4565b8160376000828254611fab919061584e565b90915550506040518281526001600160a01b038416907f30420aacd028abb3c1fd03aba253ae725d6ddd52d16c9ac4cb5742cd43f530969060200160405180910390a261169a838361339c565b6033805467ffffffffffffffff60a01b19164263ffffffff16600160a01b021790556000603755612029814761339c565b50565b60007f000000000000000000000000000000000000000000000000000000006059f4606001600160401b0316826001600160401b031610156120d65760405162461bcd60e51b815260206004820152603760248201527f456967656e506f642e5f74696d657374616d70546f45706f63683a2074696d6560448201527f7374616d70206973206265666f72652067656e6573697300000000000000000060648201526084016106a4565b6120e2600c6020615865565b61210c7f000000000000000000000000000000000000000000000000000000006059f460846157e6565b610d0e9190615894565b6000612124600c6020615865565b61212f8360016158ba565b6121399190615865565b610d0e907f000000000000000000000000000000000000000000000000000000006059f4606158ba565b61216f6003602061582f565b81146121ff5760405162461bcd60e51b815260206004820152605360248201527f426561636f6e436861696e50726f6f66732e7665726966795374617465526f6f60448201527f74416761696e73744c6174657374426c6f636b526f6f743a2050726f6f6620686064820152720c2e640d2dcc6dee4e4cac6e840d8cadccee8d606b1b608482015260a4016106a4565b61224482828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508892508791506003905061342a565b6122eb5760405162461bcd60e51b815260206004820152606660248201527f426561636f6e436861696e50726f6f66732e7665726966795374617465526f6f60448201527f74416761696e73744c6174657374426c6f636b526f6f743a20496e76616c696460648201527f206c617465737420626c6f636b2068656164657220726f6f74206d65726b6c6560848201526510383937b7b360d11b60a482015260c4016106a4565b50505050565b60008061233084848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061344292505050565b6000818152603660209081526040808320815160808101835281546001600160401b038082168352600160401b8204811695830195909552600160801b8104909416928101929092529394509192906060830190600160c01b900460ff16600281111561239f5761239f614ec1565b60028111156123b0576123b0614ec1565b90525090506000816060015160028111156123cd576123cd614ec1565b146124765760405162461bcd60e51b815260206004820152606760248201527f456967656e506f642e766572696679436f72726563745769746864726177616c60448201527f43726564656e7469616c733a2056616c696461746f72206d757374206265206960648201527f6e61637469766520746f2070726f7665207769746864726177616c2063726564608482015266656e7469616c7360c81b60a482015260c4016106a4565b61247e6128a5565b612487906158e5565b6124c386868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061346692505050565b1461254a5760405162461bcd60e51b815260206004820152604b60248201527f456967656e506f642e766572696679436f72726563745769746864726177616c60448201527f43726564656e7469616c733a2050726f6f66206973206e6f7420666f7220746860648201526a1a5cc8115a59d95b941bd960aa1b608482015260a4016106a4565b600061258886868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061347b92505050565b90506125988a87878b8b8e6134a0565b603980549060006125a883615592565b90915550506001606083015264ffffffffff891682526001600160401b038b811660408401527f00000000000000000000000000000000000000000000000000000007735940008116908216111561262e576001600160401b037f000000000000000000000000000000000000000000000000000000077359400016602083015261263e565b6001600160401b03811660208301525b6000838152603660209081526040918290208451815492860151938601516001600160401b03908116600160801b0267ffffffffffffffff60801b19958216600160401b026001600160801b0319909516919092161792909217928316821781556060850151859391929091839160ff60c01b191668ffffffffffffffffff60801b1990911617600160c01b8360028111156126dc576126dc614ec1565b02179055505060405164ffffffffff8b1681527f2d0800bbc377ea54a08c5db6a87aafff5e3e9c8fead0eda110e40e0c10441449915060200160405180910390a17f0e5fac175b83177cc047381e030d8fb3b42b37bd1c025e22c280facad62c32df898c84602001516040516127779392919064ffffffffff9390931683526001600160401b03918216602084015216604082015260600190565b60405180910390a1633b9aca0082602001516001600160401b031661279c919061582f565b9b9a5050505050505050505050565b600081516030146128345760405162461bcd60e51b815260206004820152604760248201527f456967656e506f642e5f63616c63756c61746556616c696461746f725075626b60448201527f657948617368206d75737420626520612034382d6279746520424c53207075626064820152666c6963206b657960c81b608482015260a4016106a4565b60405160029061284b908490600090602001615909565b60408051601f198184030181529082905261286591615938565b602060405180830381855afa158015612882573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610d0e91906154ad565b60408051600160f81b60208201526000602182015230606090811b6bffffffffffffffffffffffff1916602c8301529101604051602081830303815290604052905090565b60008061292984848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061347b92505050565b9050600061296985858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061344292505050565b6000818152603660209081526040808320815160808101835281546001600160401b038082168352600160401b8204811695830195909552600160801b8104909416928101929092529394509192906060830190600160c01b900460ff1660028111156129d8576129d8614ec1565b60028111156129e9576129e9614ec1565b8152505090508a6001600160401b031681604001516001600160401b031610612aa05760405162461bcd60e51b815260206004820152605c60248201527f456967656e506f642e76657269667942616c616e63655570646174653a20566160448201527f6c696461746f72732062616c616e63652068617320616c72656164792062656560648201527f6e207570646174656420666f7220746869732074696d657374616d7000000000608482015260a4016106a4565b600181606001516002811115612ab857612ab8614ec1565b14612b205760405162461bcd60e51b815260206004820152603260248201527f456967656e506f642e76657269667942616c616e63655570646174653a2056616044820152716c696461746f72206e6f742061637469766560701b60648201526084016106a4565b612b298b61202c565b6001600160401b0316612b6e8787808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506136f792505050565b6001600160401b031611612c11576000836001600160401b031611612c115760405162461bcd60e51b815260206004820152604d60248201527f456967656e506f642e76657269667942616c616e63655570646174653a20766160448201527f6c696461746f7220697320776974686472617761626c6520627574206861732060648201526c3737ba103bb4ba34323930bbb760991b608482015260a4016106a4565b612c1f8987878b8b8f6134a0565b602081015160006001600160401b037f000000000000000000000000000000000000000000000000000000077359400081169086161115612c8157507f0000000000000000000000000000000000000000000000000000000773594000612c84565b50835b6001600160401b0380821660208086019182528f831660408088019182526000898152603690935290912086518154935192518516600160801b0267ffffffffffffffff60801b19938616600160401b026001600160801b031990951691909516179290921790811683178255606086015186939091839160ff60c01b191668ffffffffffffffffff60801b1990911617600160c01b836002811115612d2c57612d2c614ec1565b0217905550905050816001600160401b0316816001600160401b031614612db8577f0e5fac175b83177cc047381e030d8fb3b42b37bd1c025e22c280facad62c32df8c8e83604051612da39392919064ffffffffff9390931683526001600160401b03918216602084015216604082015260600190565b60405180910390a1612db5818361370f565b95505b5050505050979650505050505050565b611873828261372e565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261169a908490613847565b6040805180820190915260008082526020820152612e49612e44896159b9565b613919565b6033546001600160401b03600160a01b90910481169082161015612f0b5760405162461bcd60e51b815260206004820152606760248201527f456967656e506f642e70726f6f664973466f7256616c696454696d657374616d60448201527f703a20626561636f6e20636861696e2070726f6f66206d75737420626520617460648201527f206f72206166746572206d6f7374526563656e745769746864726177616c546960848201526606d657374616d760cc1b60a482015260c4016106a4565b6000612f19612e448b6159b9565b90506000612f5988888080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061344292505050565b905060008082815260366020526040902054600160c01b900460ff166002811115612f8657612f86614ec1565b141561303d5760405162461bcd60e51b815260206004820152607460248201527f456967656e506f642e5f766572696679416e6450726f6365737357697468647260448201527f6177616c3a2056616c696461746f72206e657665722070726f76656e20746f2060648201527f68617665207769746864726177616c2063726564656e7469616c7320706f696e6084820152731d1959081d1bc81d1a1a5cc818dbdb9d1c9858dd60621b60a482015260c4016106a4565b60008181526035602090815260408083206001600160401b038616845290915290205460ff16156130fc5760405162461bcd60e51b815260206004820152605b60248201527f456967656e506f642e5f766572696679416e6450726f6365737357697468647260448201527f6177616c3a207769746864726177616c2068617320616c72656164792062656560648201527f6e2070726f76656e20666f7220746869732074696d657374616d700000000000608482015260a4016106a4565b6001603560008381526020019081526020016000206000846001600160401b03166001600160401b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055506131d98c87878e7f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe66001600160a01b03166344e71c806040518163ffffffff1660e01b8152600401602060405180830381865afa1580156131b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131d49190615af5565b613929565b600061321787878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061434a92505050565b90506132278d8a8a8e8e866134a0565b600061326588888080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061436292505050565b90506132a38a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506136f792505050565b6001600160401b03166132bd6132b88f6159b9565b61437a565b6001600160401b03161061337557603354600084815260366020908152604091829020825160808101845281546001600160401b038082168352600160401b8204811694830194909452600160801b81049093169381019390935261336a93869388938a936001600160a01b03909316928892916060830190600160c01b900460ff16600281111561335157613351614ec1565b600281111561336257613362614ec1565b90525061438c565b95505050505061338f565b60335461336a90839086906001600160a01b0316846145ca565b5098975050505050505050565b603354604051633036cd5360e21b81526001600160a01b03918216600482015283821660248201527f0000000000000000000000008a791620dd6260079bf849dc5567adc3f2fdc3189091169063c0db354c9083906044016000604051808303818588803b15801561340d57600080fd5b505af1158015613421573d6000803e3d6000fd5b50505050505050565b6000836134388685856146a8565b1495945050505050565b6000816000815181106134575761345761550c565b60200260200101519050919050565b6000816001815181106134575761345761550c565b6000610d0e826002815181106134935761349361550c565b60200260200101516147f4565b6134ac60036002615bf6565b84146135375760405162461bcd60e51b815260206004820152604e60248201527f426561636f6e436861696e50726f6f66732e76657269667956616c696461746f60448201527f724669656c64733a2056616c696461746f72206669656c64732068617320696e60648201526d0c6dee4e4cac6e840d8cadccee8d60931b608482015260a4016106a4565b600561354560286001614c9f565b61354f9190614c9f565b61355a90602061582f565b82146135da5760405162461bcd60e51b815260206004820152604360248201527f426561636f6e436861696e50726f6f66732e76657269667956616c696461746f60448201527f724669656c64733a2050726f6f662068617320696e636f7272656374206c656e6064820152620cee8d60eb1b608482015260a4016106a4565b600064ffffffffff82166135f060286001614c9f565b600b901b179050600061363587878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061485b92505050565b905061367b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c925085915086905061342a565b6136ed5760405162461bcd60e51b815260206004820152603d60248201527f426561636f6e436861696e50726f6f66732e76657269667956616c696461746f60448201527f724669656c64733a20496e76616c6964206d65726b6c652070726f6f6600000060648201526084016106a4565b5050505050505050565b6000610d0e826007815181106134935761349361550c565b60006137276001600160401b03808416908516615c02565b9392505050565b8047101561377e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016106a4565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146137cb576040519150601f19603f3d011682016040523d82523d6000602084013e6137d0565b606091505b505090508061169a5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016106a4565b600061389c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614b089092919063ffffffff16565b80519091501561169a57808060200190518101906138ba9190615397565b61169a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016106a4565b6000610d0e8261014001516147f4565b613934600280615bf6565b83146139a85760405162461bcd60e51b81526020600482015260496024820152600080516020615c8983398151915260448201527f616c3a207769746864726177616c4669656c64732068617320696e636f7272656064820152680c6e840d8cadccee8d60bb1b608482015260a4016106a4565b6139b4600d6002615bf6565b6139c460c0840160a08501615c41565b6001600160401b031610613a2e5760405162461bcd60e51b815260206004820152603f6024820152600080516020615c8983398151915260448201527f616c3a20626c6f636b526f6f74496e64657820697320746f6f206c617267650060648201526084016106a4565b613a3a60046002615bf6565b613a4b610100840160e08501615c41565b6001600160401b031610613ab7576040805162461bcd60e51b8152602060048201526024810191909152600080516020615c8983398151915260448201527f616c3a207769746864726177616c496e64657820697320746f6f206c6172676560648201526084016106a4565b613ac360186002615bf6565b613ad360e0840160c08501615c41565b6001600160401b031610613b4d5760405162461bcd60e51b81526020600482015260476024820152600080516020615c8983398151915260448201527f616c3a20686973746f726963616c53756d6d617279496e64657820697320746f6064820152666f206c6172676560c81b608482015260a4016106a4565b60006001600160401b038216613b65612e44856159b9565b6001600160401b031610613b7a576005613b7d565b60045b9050613b8a600482614c9f565b613b95906001614c9f565b613ba090602061582f565b613baa84806154c6565b905014613c1e5760405162461bcd60e51b81526020600482015260486024820152600080516020615c8983398151915260448201527f616c3a207769746864726177616c50726f6f662068617320696e636f727265636064820152670e840d8cadccee8d60c31b608482015260a4016106a4565b613c2a60046003614c9f565b613c3590602061582f565b613c4260408501856154c6565b905014613cbc5760405162461bcd60e51b815260206004820152604e6024820152600080516020615c8983398151915260448201527f616c3a20657865637574696f6e5061796c6f616450726f6f662068617320696e60648201526d0c6dee4e4cac6e840d8cadccee8d60931b608482015260a4016106a4565b613cc86003602061582f565b613cd560208501856154c6565b905014613d435760405162461bcd60e51b81526020600482015260426024820152600080516020615c8983398151915260448201527f616c3a20736c6f7450726f6f662068617320696e636f7272656374206c656e676064820152610e8d60f31b608482015260a4016106a4565b613d4e81602061582f565b613d5b60608501856154c6565b905014613dce5760405162461bcd60e51b81526020600482015260476024820152600080516020615c8983398151915260448201527f616c3a2074696d657374616d7050726f6f662068617320696e636f7272656374606482015266040d8cadccee8d60cb1b608482015260a4016106a4565b600d613ddc60186001614c9f565b613de7906005614c9f565b613df2906001614c9f565b613dfc9190614c9f565b613e0790602061582f565b613e1460808501856154c6565b905014613e9d5760405162461bcd60e51b81526020600482015260586024820152600080516020615c8983398151915260448201527f616c3a20686973746f726963616c53756d6d617279426c6f636b526f6f74507260648201527f6f6f662068617320696e636f7272656374206c656e6774680000000000000000608482015260a4016106a4565b6000613eaf60c0850160a08601615c41565b6001600160401b03166000613ec6600d6001614c9f565b613ed660e0880160c08901615c41565b6001600160401b0316901b600d613eef60186001614c9f565b613efa906001614c9f565b613f049190614c9f565b601b901b1717179050613f5f613f1d60808601866154c6565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b925050506101008701358461342a565b613fd25760405162461bcd60e51b815260206004820152604a6024820152600080516020615c8983398151915260448201527f616c3a20496e76616c696420686973746f726963616c73756d6d617279206d656064820152693935b63290383937b7b360b11b608482015260a4016106a4565b614029613fe260208601866154c6565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506101008a013593506101208a01359250905061342a565b6140895760405162461bcd60e51b815260206004820152603d6024820152600080516020615c8983398151915260448201527f616c3a20496e76616c696420736c6f74206d65726b6c652070726f6f6600000060648201526084016106a4565b60496140e161409b60408701876154c6565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050506101008701356101608801358461342a565b6141535760405162461bcd60e51b81526020600482015260496024820152600080516020615c8983398151915260448201527f616c3a20496e76616c696420657865637574696f6e5061796c6f6164206d657260648201526835b63290383937b7b360b91b608482015260a4016106a4565b506141ab61416460608601866154c6565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505050610160860135610140870135600961342a565b6142165760405162461bcd60e51b81526020600482015260426024820152600080516020615c8983398151915260448201527f616c3a20496e76616c69642074696d657374616d70206d65726b6c652070726f60648201526137b360f11b608482015260a4016106a4565b6000614229610100860160e08701615c41565b6001600160401b031661423e60046001614c9f565b600e901b179050600061428388888080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061485b92505050565b90506142d361429287806154c6565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505050610160880135838561342a565b61433f5760405162461bcd60e51b81526020600482015260436024820152600080516020615c8983398151915260448201527f616c3a20496e76616c6964207769746864726177616c206d65726b6c6520707260648201526237b7b360e91b608482015260a4016106a4565b505050505050505050565b6000610d0e826001815181106134935761349361550c565b6000610d0e826003815181106134935761349361550c565b6000602061210c8361012001516147f4565b604080518082019091526000808252602082015260007f00000000000000000000000000000000000000000000000000000007735940006001600160401b0316846001600160401b0316111561440357507f0000000000000000000000000000000000000000000000000000000773594000614406565b50825b604080518082019091526000808252602082015261442482866157e6565b6001600160401b039081168252603480548492600091614446918591166158ba565b92506101000a8154816001600160401b0302191690836001600160401b0316021790555061447882856020015161370f565b602082015260028460600151600281111561449557614495614ec1565b146144b757603980549060006144aa83615c5e565b9091555050600260608501525b600060208086018281528a83526036909152604091829020865181549251938801516001600160401b03908116600160801b0267ffffffffffffffff60801b19958216600160401b026001600160801b0319909516929091169190911792909217928316821781556060870151879391929091839160ff60c01b191668ffffffffffffffffff60801b1990911617600160c01b83600281111561455c5761455c614ec1565b0217905550506040805164ffffffffff8c1681526001600160401b038a8116602083015288168183015290516001600160a01b03891692507fb76a93bb649ece524688f1a01d184e0bbebcda58eae80c28a898bec3fb5a09639181900360600190a298975050505050505050565b60408051808201909152600080825260208201526040805164ffffffffff871681526001600160401b0380871660208301528416918101919091526001600160a01b038416907f8a7335714231dbd551aaba6314f4a97a14c201e53a3e25e1140325cdf67d7a4e9060600160405180910390a26038805483919060009061465b9084906001600160401b03166158ba565b92506101000a8154816001600160401b0302191690836001600160401b031602179055506040518060400160405280836001600160401b0316815260200160008152509050949350505050565b600083516000141580156146c75750602084516146c591906157be565b155b6147565760405162461bcd60e51b815260206004820152605460248201527f4d65726b6c652e70726f63657373496e636c7573696f6e50726f6f665368613260448201527f35363a2070726f6f66206c656e6774682073686f756c642062652061206e6f6e60648201527316bd32b9379036bab63a34b836329037b310199960611b608482015260a4016106a4565b604080516020808201909252848152905b855181116147ea5761477a6002856157be565b6147ad578151600052808601516020526020826040600060026107d05a03fa6147a257600080fd5b6002840493506147d8565b8086015160005281516020526020826040600060026107d05a03fa6147d157600080fd5b6002840493505b6147e3602082614c9f565b9050614767565b5051949350505050565b60f881901c60e882901c61ff00161760d882901c62ff0000161760c882901c63ff000000161764ff0000000060b883901c161765ff000000000060a883901c161766ff000000000000609883901c161767ff0000000000000060889290921c919091161790565b6000806002835161486c91906157d2565b90506000816001600160401b03811115614888576148886150ce565b6040519080825280602002602001820160405280156148b1578160200160208202803683370190505b50905060005b828110156149b8576002856148cc838361582f565b815181106148dc576148dc61550c565b6020026020010151868360026148f2919061582f565b6148fd906001614c9f565b8151811061490d5761490d61550c565b602002602001015160405160200161492f929190918252602082015260400190565b60408051601f198184030181529082905261494991615938565b602060405180830381855afa158015614966573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061498991906154ad565b82828151811061499b5761499b61550c565b6020908102919091010152806149b081615592565b9150506148b7565b506149c46002836157d2565b91505b8115614ae45760005b82811015614ad1576002826149e5838361582f565b815181106149f5576149f561550c565b602002602001015183836002614a0b919061582f565b614a16906001614c9f565b81518110614a2657614a2661550c565b6020026020010151604051602001614a48929190918252602082015260400190565b60408051601f1981840301815290829052614a6291615938565b602060405180830381855afa158015614a7f573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190614aa291906154ad565b828281518110614ab457614ab461550c565b602090810291909101015280614ac981615592565b9150506149d0565b50614add6002836157d2565b91506149c7565b80600081518110614af757614af761550c565b602002602001015192505050919050565b6060614b178484600085614b1f565b949350505050565b606082471015614b805760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016106a4565b6001600160a01b0385163b614bd75760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106a4565b600080866001600160a01b03168587604051614bf39190615938565b60006040518083038185875af1925050503d8060008114614c30576040519150601f19603f3d011682016040523d82523d6000602084013e614c35565b606091505b5091509150614c45828286614c50565b979650505050505050565b60608315614c5f575081613727565b825115614c6f5782518084602001fd5b8160405162461bcd60e51b81526004016106a49190615c75565b634e487b7160e01b600052601160045260246000fd5b60008219821115614cb257614cb2614c89565b500190565b6001600160401b038116811461202957600080fd5b8035614cd781614cb7565b919050565b60008060408385031215614cef57600080fd5b823591506020830135614d0181614cb7565b809150509250929050565b600060408284031215614d1e57600080fd5b50919050565b60008083601f840112614d3657600080fd5b5081356001600160401b03811115614d4d57600080fd5b6020830191508360208260051b8501011115614d6857600080fd5b9250929050565b60008060008060008060008060a0898b031215614d8b57600080fd5b8835614d9681614cb7565b975060208901356001600160401b0380821115614db257600080fd5b614dbe8c838d01614d0c565b985060408b0135915080821115614dd457600080fd5b614de08c838d01614d24565b909850965060608b0135915080821115614df957600080fd5b614e058c838d01614d24565b909650945060808b0135915080821115614e1e57600080fd5b50614e2b8b828c01614d24565b999c989b5096995094979396929594505050565b60008083601f840112614e5157600080fd5b5081356001600160401b03811115614e6857600080fd5b602083019150836020828501011115614d6857600080fd5b60008060208385031215614e9357600080fd5b82356001600160401b03811115614ea957600080fd5b614eb585828601614e3f565b90969095509350505050565b634e487b7160e01b600052602160045260246000fd5b60038110614ef557634e487b7160e01b600052602160045260246000fd5b9052565b60208101610d0e8284614ed7565b600060208284031215614f1957600080fd5b5035919050565b60006080820190506001600160401b03808451168352806020850151166020840152806040850151166040840152506060830151614f616060840182614ed7565b5092915050565b600080600080600060608688031215614f8057600080fd5b85356001600160401b0380821115614f9757600080fd5b614fa389838a01614e3f565b90975095506020880135915080821115614fbc57600080fd5b50614fc988828901614e3f565b96999598509660400135949350505050565b60008060008060008060008060a0898b031215614ff757600080fd5b883561500281614cb7565b975060208901356001600160401b038082111561501e57600080fd5b61502a8c838d01614d24565b909950975060408b013591508082111561504357600080fd5b61504f8c838d01614d0c565b965060608b0135915080821115614df957600080fd5b6001600160a01b038116811461202957600080fd5b8035614cd781615065565b6000806040838503121561509857600080fd5b82356150a381615065565b946020939093013593505050565b6000602082840312156150c357600080fd5b813561372781615065565b634e487b7160e01b600052604160045260246000fd5b60405161018081016001600160401b0381118282101715615107576151076150ce565b60405290565b604051601f8201601f191681016001600160401b0381118282101715615135576151356150ce565b604052919050565b60006001600160401b03821115615156576151566150ce565b5060051b60200190565b600082601f83011261517157600080fd5b813560206151866151818361513d565b61510d565b82815260059290921b840181019181810190868411156151a557600080fd5b8286015b848110156151c057803583529183019183016151a9565b509695505050505050565b6000806000606084860312156151e057600080fd5b83356001600160401b03808211156151f757600080fd5b818601915086601f83011261520b57600080fd5b8135602061521b6151818361513d565b82815260059290921b8401810191818101908a84111561523a57600080fd5b948201945b8386101561526157853561525281615065565b8252948201949082019061523f565b9750508701359250508082111561527757600080fd5b5061528486828701615160565b9250506152936040850161507a565b90509250925092565b60008060008060008060008060008060c08b8d0312156152bb57600080fd5b6152c48b614ccc565b995060208b01356001600160401b03808211156152e057600080fd5b6152ec8e838f01614d0c565b9a5060408d013591508082111561530257600080fd5b61530e8e838f01614d24565b909a50985060608d013591508082111561532757600080fd5b6153338e838f01614d24565b909850965060808d013591508082111561534c57600080fd5b6153588e838f01614d24565b909650945060a08d013591508082111561537157600080fd5b5061537e8d828e01614d24565b915080935050809150509295989b9194979a5092959850565b6000602082840312156153a957600080fd5b8151801515811461372757600080fd5b6020808252603e908201527f456967656e506f642e6f6e6c795768656e4e6f745061757365643a20696e646560408201527f782069732070617573656420696e20456967656e506f644d616e616765720000606082015260800190565b60208082526028908201527f456967656e506f642e6f6e6c79456967656e506f644f776e65723a206e6f74206040820152673837b227bbb732b960c11b606082015260800190565b6020808252602f908201527f456967656e506f642e6861734e6576657252657374616b65643a20726573746160408201526e1ada5b99c81a5cc8195b98589b1959608a1b606082015260800190565b6000602082840312156154bf57600080fd5b5051919050565b6000808335601e198436030181126154dd57600080fd5b8301803591506001600160401b038211156154f757600080fd5b602001915036819003821315614d6857600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561553457600080fd5b813564ffffffffff8116811461372757600080fd5b6000808335601e1984360301811261556057600080fd5b8301803591506001600160401b0382111561557a57600080fd5b6020019150600581901b3603821315614d6857600080fd5b60006000198214156155a6576155a6614c89565b5060010190565b60208082526031908201527f456967656e506f642e6f6e6c79456967656e506f644d616e616765723a206e6f6040820152703a1032b4b3b2b72837b226b0b730b3b2b960791b606082015260800190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60005b8381101561564257818101518382015260200161562a565b838111156122eb5750506000910152565b6000815180845261566b816020860160208601615627565b601f01601f19169290920160200192915050565b60808152600061569360808301888a6155fe565b82810360208401526156a58188615653565b905082810360408401526156ba8186886155fe565b915050826060830152979650505050505050565b602081526000614b176020830184866155fe565b600080821280156001600160ff1b038490038513161561570457615704614c89565b600160ff1b839003841281161561571d5761571d614c89565b50500190565b60006001600160ff1b038184138284138082168684048611161561574957615749614c89565b600160ff1b600087128281168783058912161561576857615768614c89565b6000871292508782058712848416161561578457615784614c89565b8785058712818416161561579a5761579a614c89565b505050929093029392505050565b634e487b7160e01b600052601260045260246000fd5b6000826157cd576157cd6157a8565b500690565b6000826157e1576157e16157a8565b500490565b60006001600160401b038381169083168181101561580657615806614c89565b039392505050565b6000823561017e1983360301811261582557600080fd5b9190910192915050565b600081600019048311821515161561584957615849614c89565b500290565b60008282101561586057615860614c89565b500390565b60006001600160401b038083168185168183048111821515161561588b5761588b614c89565b02949350505050565b60006001600160401b03808416806158ae576158ae6157a8565b92169190910492915050565b60006001600160401b038083168185168083038211156158dc576158dc614c89565b01949350505050565b80516020808301519190811015614d1e5760001960209190910360031b1b16919050565b6000835161591b818460208801615627565b6001600160801b0319939093169190920190815260100192915050565b60008251615825818460208701615627565b600082601f83011261595b57600080fd5b81356001600160401b03811115615974576159746150ce565b615987601f8201601f191660200161510d565b81815284602083860101111561599c57600080fd5b816020850160208301376000918101602001919091529392505050565b600061018082360312156159cc57600080fd5b6159d46150e4565b82356001600160401b03808211156159eb57600080fd5b6159f73683870161594a565b83526020850135915080821115615a0d57600080fd5b615a193683870161594a565b60208401526040850135915080821115615a3257600080fd5b615a3e3683870161594a565b60408401526060850135915080821115615a5757600080fd5b615a633683870161594a565b60608401526080850135915080821115615a7c57600080fd5b50615a893682860161594a565b608083015250615a9b60a08401614ccc565b60a0820152615aac60c08401614ccc565b60c0820152615abd60e08401614ccc565b60e082015261010083810135908201526101208084013590820152610140808401359082015261016092830135928101929092525090565b600060208284031215615b0757600080fd5b815161372781614cb7565b600181815b80851115615b4d578160001904821115615b3357615b33614c89565b80851615615b4057918102915b93841c9390800290615b17565b509250929050565b600082615b6457506001610d0e565b81615b7157506000610d0e565b8160018114615b875760028114615b9157615bad565b6001915050610d0e565b60ff841115615ba257615ba2614c89565b50506001821b610d0e565b5060208310610133831016604e8410600b8410161715615bd0575081810a610d0e565b615bda8383615b12565b8060001904821115615bee57615bee614c89565b029392505050565b60006137278383615b55565b60008083128015600160ff1b850184121615615c2057615c20614c89565b6001600160ff1b0384018313811615615c3b57615c3b614c89565b50500390565b600060208284031215615c5357600080fd5b813561372781614cb7565b600081615c6d57615c6d614c89565b506000190190565b602081526000613727602083018461565356fe426561636f6e436861696e50726f6f66732e7665726966795769746864726177a264697066735822122051b2333b4222c7e0d27536f488f9f9e519598db2925adfc70eedf9fddb9d4d5864736f6c634300080c0033", + "storage": { "0x0": "0xff" } + }, + "0x67d269191c92caf3cd7723f116c85e6e9bf55933": { + "nonce": 1, + "balance": "0x0", + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106f1565b610118565b61005b61009336600461070c565b61015f565b3480156100a457600080fd5b506100ad6101d0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106f1565b61020b565b3480156100f557600080fd5b506100ad610235565b61010661029b565b61011661011161033a565b610344565b565b610120610368565b6001600160a01b0316336001600160a01b03161415610157576101548160405180602001604052806000815250600061039b565b50565b6101546100fe565b610167610368565b6001600160a01b0316336001600160a01b031614156101c8576101c38383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001925061039b915050565b505050565b6101c36100fe565b60006101da610368565b6001600160a01b0316336001600160a01b03161415610200576101fb61033a565b905090565b6102086100fe565b90565b610213610368565b6001600160a01b0316336001600160a01b0316141561015757610154816103c6565b600061023f610368565b6001600160a01b0316336001600160a01b03161415610200576101fb610368565b6060610285838360405180606001604052806027815260200161080b6027913961041a565b9392505050565b6001600160a01b03163b151590565b6102a3610368565b6001600160a01b0316336001600160a01b031614156101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101fb6104f7565b3660008037600080366000845af43d6000803e808015610363573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103a48361051f565b6000825111806103b15750805b156101c3576103c08383610260565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103ef610368565b604080516001600160a01b03928316815291841660208301520160405180910390a16101548161055f565b60606001600160a01b0384163b6104825760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610331565b600080856001600160a01b03168560405161049d91906107bb565b600060405180830381855af49150503d80600081146104d8576040519150601f19603f3d011682016040523d82523d6000602084013e6104dd565b606091505b50915091506104ed828286610608565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61038c565b61052881610641565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105c45760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610331565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60608315610617575081610285565b8251156106275782518084602001fd5b8160405162461bcd60e51b815260040161033191906107d7565b6001600160a01b0381163b6106ae5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610331565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105e7565b80356001600160a01b03811681146106ec57600080fd5b919050565b60006020828403121561070357600080fd5b610285826106d5565b60008060006040848603121561072157600080fd5b61072a846106d5565b9250602084013567ffffffffffffffff8082111561074757600080fd5b818601915086601f83011261075b57600080fd5b81358181111561076a57600080fd5b87602082850101111561077c57600080fd5b6020830194508093505050509250925092565b60005b838110156107aa578181015183820152602001610792565b838111156103c05750506000910152565b600082516107cd81846020870161078f565b9190910192915050565b60208152600082518060208401526107f681604085016020870161078f565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212201336548e393b6bf33c1e3380011fea84db160f673ebc8828297c6c2b86153c4664736f6c634300080c0033", + "storage": { + "0x0": "0x1", + "0x33": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x65": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x8f86403a4de0bb5791fa46b8e795c547942fe4cf", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0xc5a5c42992decbae36851359345fe25997f5c42d" + } + }, + "0x70997970c51812dc3a010c7d01b50e0d17dc79c8": { + "nonce": 5, + "balance": "0x21ea4a7eb450e5cbbe6", + "code": "0x", + "storage": {} + }, + "0x70e0ba845a1a0f2da3359c97e0285013525ffc49": { + "nonce": 1, + "balance": "0x0", + "code": "0x608060405234801561001057600080fd5b50600436106101e55760003560e01c80639f3ccf651161010f578063c8294c56116100a2578063f2be94ae11610071578063f2be94ae1461054b578063f851e1981461055e578063fa28c62714610571578063ff694a771461058457600080fd5b8063c8294c56146104d6578063d5eccc05146104e9578063dd9846b9146104fc578063df5cf7231461052457600080fd5b8063bc9a40c3116100de578063bc9a40c314610474578063bd29b8cd14610487578063c46778a51461049a578063c601527d146104c357600080fd5b80639f3ccf65146103ee578063ac6bfb0314610401578063adc804da14610421578063b6904b781461046157600080fd5b80634bd26e091161018757806366acfefe1161015657806366acfefe1461034a5780636d14a987146103755780637c172347146103b457806381c07502146103ce57600080fd5b80634bd26e09146102e55780635401ed27146103155780635e5a6775146103285780635f1f2d771461033757600080fd5b806320b66298116101c357806320b662981461026c57806325504777146102815780632cd95940146102a25780633ca5a5f5146102c257600080fd5b80630491b41c146101ea57806308732461146102205780631f9b74e014610241575b600080fd5b61020d6101f8366004612803565b60ff1660009081526001602052604090205490565b6040519081526020015b60405180910390f35b61023361022e36600461281e565b610597565b604051610217929190612848565b61025461024f36600461287f565b6105e0565b6040516001600160601b039091168152602001610217565b61027f61027a3660046128fa565b610602565b005b61029461028f3660046129bb565b610860565b604051610217929190612a5a565b6102b56102b0366004612a7f565b610a78565b6040516102179190612aab565b61020d6102d0366004612803565b60ff1660009081526003602052604090205490565b61020d6102f3366004612a7f565b600091825260026020908152604080842060ff93909316845291905290205490565b610254610323366004612a7f565b610b17565b61020d670de0b6b3a764000081565b61027f610345366004612bb4565b610b30565b61035d6103583660046129bb565b610e78565b6040516001600160c01b039091168152602001610217565b61039c7f000000000000000000000000c3e53f4d16ae77db1c982e75a937b9f60fe6369081565b6040516001600160a01b039091168152602001610217565b6103bc602081565b60405160ff9091168152602001610217565b6103e16103dc366004612c70565b610f17565b6040516102179190612cc2565b61039c6103fc36600461281e565b611157565b61041461040f366004612d00565b61118f565b6040516102179190612d33565b61043461042f36600461281e565b611227565b6040805182516001600160a01b031681526020928301516001600160601b03169281019290925201610217565b61041461046f36600461281e565b6112a1565b61027f610482366004612d7f565b611330565b61027f610495366004612da9565b611351565b6102546104a8366004612803565b6000602081905290815260409020546001600160601b031681565b61027f6104d1366004612e75565b6113c3565b6102546104e4366004612ec2565b6113df565b6102546104f7366004612803565b61145d565b61050f61050a366004612efe565b6114b0565b60405163ffffffff9091168152602001610217565b61039c7f000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c981565b610254610559366004612f3a565b6114c5565b61041461056c366004612a7f565b61155a565b61025461057f366004612efe565b61163f565b61027f610592366004612f7c565b6116a0565b600360205281600052604060002081815481106105b357600080fd5b6000918252602090912001546001600160a01b0381169250600160a01b90046001600160601b0316905082565b6000826105ec816117cb565b60006105f88585611847565b5095945050505050565b61060a611a45565b84610614816117cb565b838061068f576040805162461bcd60e51b81526020600482015260248101919091527f5374616b6552656769737472792e6d6f6469667953747261746567795061726160448201527f6d733a206e6f20737472617465677920696e64696365732070726f766964656460648201526084015b60405180910390fd5b8281146107045760405162461bcd60e51b815260206004820152603960248201527f5374616b6552656769737472792e6d6f6469667953747261746567795061726160448201527f6d733a20696e707574206c656e677468206d69736d61746368000000000000006064820152608401610686565b60ff87166000908152600360205260408120905b828110156108555785858281811061073257610732612fd9565b90506020020160208101906107479190612fef565b8289898481811061075a5761075a612fd9565b905060200201358154811061077157610771612fd9565b9060005260206000200160000160146101000a8154816001600160601b0302191690836001600160601b031602179055508860ff167f11a5641322da1dff56a4b66eaac31ffa465295ece907cd163437793b4d009a75838a8a858181106107da576107da612fd9565b90506020020135815481106107f1576107f1612fd9565b6000918252602090912001546001600160a01b031688888581811061081857610818612fd9565b905060200201602081019061082d9190612fef565b60405161083b929190612848565b60405180910390a28061084d81613020565b915050610718565b505050505050505050565b60608061086b611b6e565b6000836001600160401b0381111561088557610885612b23565b6040519080825280602002602001820160405280156108ae578160200160208202803683370190505b5090506000846001600160401b038111156108cb576108cb612b23565b6040519080825280602002602001820160405280156108f4578160200160208202803683370190505b50905060005b85811015610a6a57600087878381811061091657610916612fd9565b919091013560f81c915061092b9050816117cb565b600080610938838d611847565b91509150806109d55760405162461bcd60e51b815260206004820152605b60248201527f5374616b6552656769737472792e72656769737465724f70657261746f723a2060448201527f4f70657261746f7220646f6573206e6f74206d656574206d696e696d756d207360648201527f74616b6520726571756972656d656e7420666f722071756f72756d0000000000608482015260a401610686565b60006109e28c8585611c21565b9050828786815181106109f7576109f7612fd9565b60200260200101906001600160601b031690816001600160601b031681525050610a218482611ea1565b868681518110610a3357610a33612fd9565b60200260200101906001600160601b031690816001600160601b031681525050505050508080610a6290613020565b9150506108fa565b509097909650945050505050565b600082815260026020908152604080832060ff851684528252808320805482518185028101850190935280835260609492939192909184015b82821015610b0a576000848152602090819020604080516060810182529185015463ffffffff8082168452600160201b82041683850152600160401b90046001600160601b031690820152825260019092019101610ab1565b5050505090505b92915050565b600080610b24848461155a565b60400151949350505050565b610b38611a45565b81610b42816117cb565b815180610bb75760405162461bcd60e51b815260206004820152603d60248201527f5374616b6552656769737472792e72656d6f7665537472617465676965733a2060448201527f6e6f20696e646963657320746f2072656d6f76652070726f76696465640000006064820152608401610686565b60ff841660009081526003602090815260408083206004909252822090915b83811015610e6f578660ff167f31fa2e2cd280c9375e13ffcf3d81e2378100186e4058f8d3ddb690b82dcd31f784888481518110610c1657610c16612fd9565b602002602001015181548110610c2e57610c2e612fd9565b600091825260209182902001546040516001600160a01b0390911681520160405180910390a28660ff167f11a5641322da1dff56a4b66eaac31ffa465295ece907cd163437793b4d009a7584888481518110610c8c57610c8c612fd9565b602002602001015181548110610ca457610ca4612fd9565b600091825260208083209190910154604080516001600160a01b039092168252918101929092520160405180910390a282548390610ce49060019061303b565b81548110610cf457610cf4612fd9565b9060005260206000200183878381518110610d1157610d11612fd9565b602002602001015181548110610d2957610d29612fd9565b600091825260209091208254910180546001600160a01b0319166001600160a01b03909216918217815591546001600160601b03600160a01b9182900416021790558254839080610d7c57610d7c613052565b60008281526020812082016000199081019190915501905581548290610da49060019061303b565b81548110610db457610db4612fd9565b9060005260206000200160009054906101000a90046001600160a01b031682878381518110610de557610de5612fd9565b602002602001015181548110610dfd57610dfd612fd9565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555081805480610e3b57610e3b613052565b600082815260209020810160001990810180546001600160a01b031916905501905580610e6781613020565b915050610bd6565b50505050505050565b6000610e82611b6e565b6000805b838110156105f8576000858583818110610ea257610ea2612fd9565b919091013560f81c9150610eb79050816117cb565b600080610ec4838b611847565b9150915080610ee65760009150600160ff84161b6001600160c01b0386161794505b6000610ef38a8585611c21565b9050610eff8482611ea1565b50505050508080610f0f90613020565b915050610e86565b60606000826001600160401b03811115610f3357610f33612b23565b604051908082528060200260200182016040528015610f5c578160200160208202803683370190505b50905060005b8381101561114c576000858583818110610f7e57610f7e612fd9565b919091013560f81c9150610f939050816117cb565b60ff81166000908152600160205260408120805463ffffffff8a169290610fbc57610fbc612fd9565b60009182526020909120015463ffffffff1611156110685760405162461bcd60e51b815260206004820152605b60248201527f5374616b6552656769737472792e676574546f74616c5374616b65496e64696360448201527f65734174426c6f636b4e756d6265723a2071756f72756d20686173206e6f207360648201527f74616b6520686973746f727920617420626c6f636b4e756d6265720000000000608482015260a401610686565b60ff8116600090815260016020526040812054905b818110156111365760ff8316600090815260016020819052604090912063ffffffff8b16916110ac848661303b565b6110b6919061303b565b815481106110c6576110c6612fd9565b60009182526020909120015463ffffffff16116111245760016110e9828461303b565b6110f3919061303b565b85858151811061110557611105612fd9565b602002602001019063ffffffff16908163ffffffff1681525050611136565b8061112e81613020565b91505061107d565b505050808061114490613020565b915050610f62565b5090505b9392505050565b6004602052816000526040600020818154811061117357600080fd5b6000918252602090912001546001600160a01b03169150829050565b60408051606081018252600080825260208083018290528284018290528582526002815283822060ff881683529052919091208054839081106111d4576111d4612fd9565b600091825260209182902060408051606081018252929091015463ffffffff8082168452600160201b82041693830193909352600160401b9092046001600160601b031691810191909152949350505050565b604080518082019091526000808252602082015260ff8316600090815260036020526040902080548390811061125f5761125f612fd9565b6000918252602091829020604080518082019091529101546001600160a01b0381168252600160a01b90046001600160601b0316918101919091529392505050565b604080516060810182526000808252602080830182905282840182905260ff8616825260019052919091208054839081106112de576112de612fd9565b600091825260209182902060408051606081018252929091015463ffffffff8082168452600160201b82041693830193909352600160401b9092046001600160601b0316918101919091529392505050565b611338611a45565b81611342816117cb565b61134c838361201b565b505050565b611359611b6e565b60005b818110156113bd57600083838381811061137857611378612fd9565b919091013560f81c915061138d9050816117cb565b600061139b86836000611c21565b90506113a78282611ea1565b50505080806113b590613020565b91505061135c565b50505050565b6113cb611a45565b816113d5816117cb565b61134c8383612084565b60ff8316600090815260016020526040812080548291908490811061140657611406612fd9565b600091825260209182902060408051606081018252919092015463ffffffff8082168352600160201b820416938201939093526001600160601b03600160401b90930492909216908201529050610b2481856124c7565b60ff8116600090815260016020819052604082208054909161147e9161303b565b8154811061148e5761148e612fd9565b600091825260209091200154600160401b90046001600160601b031692915050565b60006114bd848484612641565b949350505050565b600082815260026020908152604080832060ff8816845290915281208054829190849081106114f6576114f6612fd9565b600091825260209182902060408051606081018252919092015463ffffffff8082168352600160201b820416938201939093526001600160601b03600160401b9093049290921690820152905061154d81866124c7565b6040015195945050505050565b6040805160608082018352600080835260208084018290528385018290528682526002815284822060ff871683528152848220548551938401865282845290830182905293820152909190816115b3579150610b119050565b600085815260026020908152604080832060ff8816845290915290206115da60018461303b565b815481106115ea576115ea612fd9565b600091825260209182902060408051606081018252919092015463ffffffff8082168352600160201b820416938201939093526001600160601b03600160401b90930492909216908201529250610b11915050565b600083815260026020908152604080832060ff861684529091528120611666858585612641565b63ffffffff168154811061167c5761167c612fd9565b600091825260209091200154600160401b90046001600160601b0316949350505050565b6116a8611b6e565b60ff8316600090815260016020526040902054156117265760405162461bcd60e51b815260206004820152603560248201527f5374616b6552656769737472792e696e697469616c697a6551756f72756d3a2060448201527471756f72756d20616c72656164792065786973747360581b6064820152608401610686565b6117308382612084565b61173a838361201b565b505060ff166000908152600160208181526040808420815160608101835263ffffffff438116825281850187815293820187815283549687018455928752939095209451949093018054915193516001600160601b0316600160401b02600160401b600160a01b0319948416600160201b0267ffffffffffffffff1990931695909316949094171791909116179055565b60ff81166000908152600160205260409020546118445760405162461bcd60e51b815260206004820152603160248201527f5374616b6552656769737472792e71756f72756d4578697374733a2071756f726044820152701d5b48191bd95cc81b9bdd08195e1a5cdd607a1b6064820152608401610686565b50565b6000806000806118668660ff1660009081526003602052604090205490565b604080518082019091526000808252602082015290915060ff871660009081526004602081905260408083209051639004134760e01b81526001600160a01b037f000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c916926390041347926118db928c9201613068565b600060405180830381865afa1580156118f8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261192091908101906130c7565b905060005b83811015611a115760ff8916600090815260036020526040902080548290811061195157611951612fd9565b60009182526020808320604080518082019091529201546001600160a01b0381168352600160a01b90046001600160601b031690820152835190945083908390811061199f5761199f612fd9565b602002602001015111156119ff57670de0b6b3a764000083602001516001600160601b03168383815181106119d6576119d6612fd9565b60200260200101516119e89190613157565b6119f29190613176565b6119fc9086613198565b94505b80611a0981613020565b915050611925565b50505060ff8616600090815260208190526040902054919350506001600160601b03908116908316101590505b9250929050565b7f000000000000000000000000c3e53f4d16ae77db1c982e75a937b9f60fe636906001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611aa3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ac791906131c3565b6001600160a01b0316336001600160a01b031614611b6c5760405162461bcd60e51b815260206004820152605660248201527f5374616b6552656769737472792e6f6e6c79436f6f7264696e61746f724f776e60448201527f65723a2063616c6c6572206973206e6f7420746865206f776e6572206f6620746064820152753432903932b3b4b9ba393ca1b7b7b93234b730ba37b960511b608482015260a401610686565b565b336001600160a01b037f000000000000000000000000c3e53f4d16ae77db1c982e75a937b9f60fe636901614611b6c5760405162461bcd60e51b815260206004820152604c60248201527f5374616b6552656769737472792e6f6e6c795265676973747279436f6f72646960448201527f6e61746f723a2063616c6c6572206973206e6f7420746865205265676973747260648201526b3ca1b7b7b93234b730ba37b960a11b608482015260a401610686565b600083815260026020908152604080832060ff86168452909152812054819080611ce557600086815260026020908152604080832060ff891684528252808320815160608101835263ffffffff43811682528185018681526001600160601b03808c16958401958652845460018101865594885295909620915191909201805495519351909416600160401b02600160401b600160a01b0319938316600160201b0267ffffffffffffffff1990961691909216179390931716919091179055611e47565b600086815260026020908152604080832060ff891684529091528120611d0c60018461303b565b81548110611d1c57611d1c612fd9565b600091825260209091200180546001600160601b03600160401b909104811694509091508516831415611d555760009350505050611150565b80544363ffffffff90811691161415611d8f578054600160401b600160a01b031916600160401b6001600160601b03871602178155611e45565b805467ffffffff000000001916600160201b4363ffffffff90811682810293909317845560008a815260026020908152604080832060ff8d168452825280832081516060810183529687528683018481526001600160601b038d81169389019384528254600181018455928652939094209651960180549351915196851667ffffffffffffffff1990941693909317931690930291909117600160401b600160a01b031916600160401b93909216929092021790555b505b6040805160ff871681526001600160601b038616602082015287917f2f527d527e95d8fe40aec55377743bb779087da3f6d0d08f12e36444da62327d910160405180910390a2611e9782856127a7565b9695505050505050565b60ff821660009081526001602081905260408220805491839190611ec5908461303b565b81548110611ed557611ed5612fd9565b9060005260206000200190508360001415611f045754600160401b90046001600160601b03169150610b119050565b8054600090611f2390600160401b90046001600160601b0316866127bf565b82549091504363ffffffff90811691161415611f60578154600160401b600160a01b031916600160401b6001600160601b03831602178255612012565b815463ffffffff438116600160201b81810267ffffffff000000001990941693909317855560ff8916600090815260016020818152604080842081516060810183529586528583018581526001600160601b03808b169388019384528254958601835591865292909420945194909201805491519251909316600160401b02600160401b600160a01b031992861690960267ffffffffffffffff19909116939094169290921792909217169190911790555b95945050505050565b60ff82166000818152602081815260409182902080546bffffffffffffffffffffffff19166001600160601b03861690811790915591519182527f26eecff2b70b0a71104ff4d940ba7162d23a95c248771fc487a7be17a596b3cf910160405180910390a25050565b60008151116120e95760405162461bcd60e51b8152602060048201526038602482015260008051602061329483398151915260448201527f3a206e6f20737472617465676965732070726f766964656400000000000000006064820152608401610686565b805160ff83166000908152600360209081526040909120549061210c83836131e0565b111561217c5760405162461bcd60e51b8152602060048201526045602482015260008051602061329483398151915260448201527f3a20657863656564204d41585f5745494748494e475f46554e4354494f4e5f4c60648201526408a9c8ea8960db1b608482015260a401610686565b60005b828110156124c05760005b61219482846131e0565b811015612275578482815181106121ad576121ad612fd9565b6020026020010151600001516001600160a01b0316600360008860ff1660ff16815260200190815260200160002082815481106121ec576121ec612fd9565b6000918252602090912001546001600160a01b031614156122635760405162461bcd60e51b815260206004820152603d602482015260008051602061329483398151915260448201527f3a2063616e6e6f74206164642073616d652073747261746567792032780000006064820152608401610686565b8061226d81613020565b91505061218a565b50600084828151811061228a5761228a612fd9565b6020026020010151602001516001600160601b03161161230f5760405162461bcd60e51b8152602060048201526046602482015260008051602061329483398151915260448201527f3a2063616e6e6f74206164642073747261746567792077697468207a65726f206064820152651dd95a59da1d60d21b608482015260a401610686565b60ff85166000908152600360205260409020845185908390811061233557612335612fd9565b602090810291909101810151825460018101845560009384528284208251928401516001600160601b0316600160a01b026001600160a01b039093169290921791015560ff871682526004905260409020845185908390811061239a5761239a612fd9565b6020908102919091018101515182546001810184556000938452919092200180546001600160a01b0319166001600160a01b03909216919091179055835160ff8616907f10565e56cacbf32eca267945f054fec02e59750032d113d3302182ad967f54049086908490811061241157612411612fd9565b602090810291909101810151516040516001600160a01b0390911681520160405180910390a28460ff167f11a5641322da1dff56a4b66eaac31ffa465295ece907cd163437793b4d009a7585838151811061246e5761246e612fd9565b60200260200101516000015186848151811061248c5761248c612fd9565b6020026020010151602001516040516124a6929190612848565b60405180910390a2806124b881613020565b91505061217f565b5050505050565b816000015163ffffffff168163ffffffff16101561256c5760405162461bcd60e51b815260206004820152605660248201527f5374616b6552656769737472792e5f76616c69646174655374616b655570646160448201527f74654174426c6f636b4e756d6265723a207374616b6555706461746520697320606482015275333937b69030b33a32b910313637b1b5a73ab6b132b960511b608482015260a401610686565b602082015163ffffffff1615806125925750816020015163ffffffff168163ffffffff16105b61263d5760405162461bcd60e51b815260206004820152606a60248201527f5374616b6552656769737472792e5f76616c69646174655374616b655570646160448201527f74654174426c6f636b4e756d6265723a2074686572652069732061206e65776560648201527f72207374616b6555706461746520617661696c61626c65206265666f726520626084820152693637b1b5a73ab6b132b960b11b60a482015260c401610686565b5050565b600083815260026020908152604080832060ff86168452909152812054805b80156126e257600086815260026020908152604080832060ff89168452909152902063ffffffff85169061269560018461303b565b815481106126a5576126a5612fd9565b60009182526020909120015463ffffffff16116126d0576126c760018261303b565b92505050611150565b806126da816131f8565b915050612660565b5060405162461bcd60e51b815260206004820152608160248201527f5374616b6552656769737472792e5f6765745374616b65557064617465496e6460448201527f6578466f724f70657261746f724174426c6f636b4e756d6265723a206e6f207360648201527f74616b652075706461746520666f756e6420666f72206f70657261746f72496460848201527f20616e642071756f72756d4e756d62657220617420626c6f636b206e756d626560a4820152603960f91b60c482015260e401610686565b60006111506001600160601b0380851690841661320f565b6000808212156127e3576127d28261324e565b6127dc908461326b565b9050610b11565b6127dc8284613198565b803560ff811681146127fe57600080fd5b919050565b60006020828403121561281557600080fd5b611150826127ed565b6000806040838503121561283157600080fd5b61283a836127ed565b946020939093013593505050565b6001600160a01b039290921682526001600160601b0316602082015260400190565b6001600160a01b038116811461184457600080fd5b6000806040838503121561289257600080fd5b61289b836127ed565b915060208301356128ab8161286a565b809150509250929050565b60008083601f8401126128c857600080fd5b5081356001600160401b038111156128df57600080fd5b6020830191508360208260051b8501011115611a3e57600080fd5b60008060008060006060868803121561291257600080fd5b61291b866127ed565b945060208601356001600160401b038082111561293757600080fd5b61294389838a016128b6565b9096509450604088013591508082111561295c57600080fd5b50612969888289016128b6565b969995985093965092949392505050565b60008083601f84011261298c57600080fd5b5081356001600160401b038111156129a357600080fd5b602083019150836020828501011115611a3e57600080fd5b600080600080606085870312156129d157600080fd5b84356129dc8161286a565b93506020850135925060408501356001600160401b038111156129fe57600080fd5b612a0a8782880161297a565b95989497509550505050565b600081518084526020808501945080840160005b83811015612a4f5781516001600160601b031687529582019590820190600101612a2a565b509495945050505050565b604081526000612a6d6040830185612a16565b82810360208401526120128185612a16565b60008060408385031215612a9257600080fd5b82359150612aa2602084016127ed565b90509250929050565b6020808252825182820181905260009190848201906040850190845b81811015612b1757612b0483855163ffffffff808251168352806020830151166020840152506001600160601b0360408201511660408301525050565b9284019260609290920191600101612ac7565b50909695505050505050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715612b5b57612b5b612b23565b60405290565b604051601f8201601f191681016001600160401b0381118282101715612b8957612b89612b23565b604052919050565b60006001600160401b03821115612baa57612baa612b23565b5060051b60200190565b60008060408385031215612bc757600080fd5b612bd0836127ed565b91506020808401356001600160401b03811115612bec57600080fd5b8401601f81018613612bfd57600080fd5b8035612c10612c0b82612b91565b612b61565b81815260059190911b82018301908381019088831115612c2f57600080fd5b928401925b82841015612c4d57833582529284019290840190612c34565b80955050505050509250929050565b803563ffffffff811681146127fe57600080fd5b600080600060408486031215612c8557600080fd5b612c8e84612c5c565b925060208401356001600160401b03811115612ca957600080fd5b612cb58682870161297a565b9497909650939450505050565b6020808252825182820181905260009190848201906040850190845b81811015612b1757835163ffffffff1683529284019291840191600101612cde565b600080600060608486031215612d1557600080fd5b612d1e846127ed565b95602085013595506040909401359392505050565b815163ffffffff9081168252602080840151909116908201526040808301516001600160601b03169082015260608101610b11565b80356001600160601b03811681146127fe57600080fd5b60008060408385031215612d9257600080fd5b612d9b836127ed565b9150612aa260208401612d68565b600080600060408486031215612dbe57600080fd5b8335925060208401356001600160401b03811115612ca957600080fd5b600082601f830112612dec57600080fd5b81356020612dfc612c0b83612b91565b82815260069290921b84018101918181019086841115612e1b57600080fd5b8286015b84811015612e6a5760408189031215612e385760008081fd5b612e40612b39565b8135612e4b8161286a565b8152612e58828601612d68565b81860152835291830191604001612e1f565b509695505050505050565b60008060408385031215612e8857600080fd5b612e91836127ed565b915060208301356001600160401b03811115612eac57600080fd5b612eb885828601612ddb565b9150509250929050565b600080600060608486031215612ed757600080fd5b612ee0846127ed565b9250612eee60208501612c5c565b9150604084013590509250925092565b600080600060608486031215612f1357600080fd5b83359250612f23602085016127ed565b9150612f3160408501612c5c565b90509250925092565b60008060008060808587031215612f5057600080fd5b612f59856127ed565b9350612f6760208601612c5c565b93969395505050506040820135916060013590565b600080600060608486031215612f9157600080fd5b612f9a846127ed565b9250612fa860208501612d68565b915060408401356001600160401b03811115612fc357600080fd5b612fcf86828701612ddb565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561300157600080fd5b61115082612d68565b634e487b7160e01b600052601160045260246000fd5b60006000198214156130345761303461300a565b5060010190565b60008282101561304d5761304d61300a565b500390565b634e487b7160e01b600052603160045260246000fd5b60006040820160018060a01b03808616845260206040818601528286548085526060870191508760005282600020945060005b818110156130b957855485168352600195860195928401920161309b565b509098975050505050505050565b600060208083850312156130da57600080fd5b82516001600160401b038111156130f057600080fd5b8301601f8101851361310157600080fd5b805161310f612c0b82612b91565b81815260059190911b8201830190838101908783111561312e57600080fd5b928401925b8284101561314c57835182529284019290840190613133565b979650505050505050565b60008160001904831182151516156131715761317161300a565b500290565b60008261319357634e487b7160e01b600052601260045260246000fd5b500490565b60006001600160601b038083168185168083038211156131ba576131ba61300a565b01949350505050565b6000602082840312156131d557600080fd5b81516111508161286a565b600082198211156131f3576131f361300a565b500190565b6000816132075761320761300a565b506000190190565b60008083128015600160ff1b85018412161561322d5761322d61300a565b6001600160ff1b03840183138116156132485761324861300a565b50500390565b6000600160ff1b8214156132645761326461300a565b5060000390565b60006001600160601b038381169083168181101561328b5761328b61300a565b03939250505056fe5374616b6552656769737472792e5f6164645374726174656779506172616d73a2646970667358221220ce2a2da79be87c15711e942387be86fde0ec83dadb75f89cef24c87eb9038f3564736f6c634300080c0033", + "storage": {} + }, + "0x7969c5ed335650692bc04293b07f5bf2e7a673c0": { + "nonce": 1, + "balance": "0x0", + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106f1565b610118565b61005b61009336600461070c565b61015f565b3480156100a457600080fd5b506100ad6101d0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106f1565b61020b565b3480156100f557600080fd5b506100ad610235565b61010661029b565b61011661011161033a565b610344565b565b610120610368565b6001600160a01b0316336001600160a01b03161415610157576101548160405180602001604052806000815250600061039b565b50565b6101546100fe565b610167610368565b6001600160a01b0316336001600160a01b031614156101c8576101c38383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001925061039b915050565b505050565b6101c36100fe565b60006101da610368565b6001600160a01b0316336001600160a01b03161415610200576101fb61033a565b905090565b6102086100fe565b90565b610213610368565b6001600160a01b0316336001600160a01b0316141561015757610154816103c6565b600061023f610368565b6001600160a01b0316336001600160a01b03161415610200576101fb610368565b6060610285838360405180606001604052806027815260200161080b6027913961041a565b9392505050565b6001600160a01b03163b151590565b6102a3610368565b6001600160a01b0316336001600160a01b031614156101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101fb6104f7565b3660008037600080366000845af43d6000803e808015610363573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103a48361051f565b6000825111806103b15750805b156101c3576103c08383610260565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103ef610368565b604080516001600160a01b03928316815291841660208301520160405180910390a16101548161055f565b60606001600160a01b0384163b6104825760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610331565b600080856001600160a01b03168560405161049d91906107bb565b600060405180830381855af49150503d80600081146104d8576040519150601f19603f3d011682016040523d82523d6000602084013e6104dd565b606091505b50915091506104ed828286610608565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61038c565b61052881610641565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105c45760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610331565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60608315610617575081610285565b8251156106275782518084602001fd5b8160405162461bcd60e51b815260040161033191906107d7565b6001600160a01b0381163b6106ae5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610331565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105e7565b80356001600160a01b03811681146106ec57600080fd5b919050565b60006020828403121561070357600080fd5b610285826106d5565b60008060006040848603121561072157600080fd5b61072a846106d5565b9250602084013567ffffffffffffffff8082111561074757600080fd5b818601915086601f83011261075b57600080fd5b81358181111561076a57600080fd5b87602082850101111561077c57600080fd5b6020830194508093505050509250925092565b60005b838110156107aa578181015183820152602001610792565b838111156103c05750506000910152565b600082516107cd81846020870161078f565b9190910192915050565b60208152600082518060208401526107f681604085016020870161078f565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212201336548e393b6bf33c1e3380011fea84db160f673ebc8828297c6c2b86153c4664736f6c634300080c0033", + "storage": { + "0x0": "0x9fe46736679d2d9a65f0992f2272de9f3c7fa6e00001", + "0x1": "0x0", + "0x32": "0x82e01223d51eb87e16a03e24687edf0f294da6f1", + "0x33": "0x2aff592d03fbde5a4", + "0x64": "0x3635c9adc5dea00000", + "0x65": "0x3635c9adc5dea00000", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0xa85233c63b9ee964add6f2cffe00fd84eb32338f", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512" + } + }, + "0x82e01223d51eb87e16a03e24687edf0f294da6f1": { + "nonce": 1, + "balance": "0x0", + "code": "0x608060405234801561001057600080fd5b50600436106100b45760003560e01c806340c10f191161007157806340c10f191461014157806370a082311461015657806395d89b411461017f578063a457c2d714610187578063a9059cbb1461019a578063dd62ed3e146101ad57600080fd5b806306fdde03146100b9578063095ea7b3146100d757806318160ddd146100fa57806323b872dd1461010c578063313ce5671461011f578063395093511461012e575b600080fd5b6100c16101c0565b6040516100ce919061074c565b60405180910390f35b6100ea6100e53660046107bd565b610252565b60405190151581526020016100ce565b6002545b6040519081526020016100ce565b6100ea61011a3660046107e7565b61026a565b604051601281526020016100ce565b6100ea61013c3660046107bd565b610277565b61015461014f3660046107bd565b610299565b005b6100fe610164366004610823565b6001600160a01b031660009081526020819052604090205490565b6100c16102a7565b6100ea6101953660046107bd565b6102b6565b6100ea6101a83660046107bd565b610341565b6100fe6101bb366004610845565b61034f565b6060600380546101cf90610878565b80601f01602080910402602001604051908101604052809291908181526020018280546101fb90610878565b80156102485780601f1061021d57610100808354040283529160200191610248565b820191906000526020600020905b81548152906001019060200180831161022b57829003601f168201915b5050505050905090565b60003361026081858561037a565b5060019392505050565b600061026084848461049e565b60003361026081858561028a838361034f565b61029491906108b3565b61037a565b6102a3828261066d565b5050565b6060600480546101cf90610878565b600033816102c4828661034f565b9050838110156103295760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b610336828686840361037a565b506001949350505050565b60003361026081858561049e565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166103dc5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610320565b6001600160a01b03821661043d5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610320565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0383166105025760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610320565b6001600160a01b0382166105645760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610320565b6001600160a01b038316600090815260208190526040902054818110156105dc5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610320565b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906106139084906108b3565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161065f91815260200190565b60405180910390a350505050565b6001600160a01b0382166106c35760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610320565b80600260008282546106d591906108b3565b90915550506001600160a01b038216600090815260208190526040812080548392906107029084906108b3565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b600060208083528351808285015260005b818110156107795785810183015185820160400152820161075d565b8181111561078b576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146107b857600080fd5b919050565b600080604083850312156107d057600080fd5b6107d9836107a1565b946020939093013593505050565b6000806000606084860312156107fc57600080fd5b610805846107a1565b9250610813602085016107a1565b9150604084013590509250925092565b60006020828403121561083557600080fd5b61083e826107a1565b9392505050565b6000806040838503121561085857600080fd5b610861836107a1565b915061086f602084016107a1565b90509250929050565b600181811c9082168061088c57607f821691505b602082108114156108ad57634e487b7160e01b600052602260045260246000fd5b50919050565b600082198211156108d457634e487b7160e01b600052601160045260246000fd5b50019056fea2646970667358221220552401d00cd9de54e2b456db7512c00b5366eead89916e03c2235827f9278f5764736f6c634300080c0033", + "storage": { + "0x2": "0x10f0cf064dd59200000", + "0x3": "0x4d6f636b20546f6b656e00000000000000000000000000000000000000000014", + "0x4": "0x4d434b0000000000000000000000000000000000000000000000000000000006", + "0x14e04a66bf74771820a7400ff6cf065175b3d7eb25805a5bd1633b161af5d101": "0x5d9f943ccb6a86b8", + "0x18bbf5fcf8fe870ecff419c4677497c08b2e6a5431bb94541d06c9da3f308e55": "0x86759309fd1fd327", + "0x215be5d23550ceb1beff54fb579a765903ba2ccc85b6f79bcf9bda4e8cb86034": "0x32d96cba53cf0152", + "0x255f7b5220c638226477bd5df4d710bb8c67cc7c7eeda9567e5ef7bd98497928": "0x2aff592d03fbde5a4", + "0x2a95ee547cef07a2fff0a68144824a0d9ded35ed87da118a53e1cda4aca8b944": "0x122c6ab631ff0891", + "0x6d1035fce6503985ab075a4ff3f7ce2e57cd5a9c5e6a0589dccacfea7bcb0af4": "0x7c6d1175e13d2753", + "0x6e3431b4e42570cb9e3d926eb26f9e54de2df536ae0741ae16350d17a6c16ddc": "0x32a862794ae172cb", + "0x723077b8a1b173adc35e5f0e7e3662fd1208212cb629f9c128551ea7168da722": "0x109c6af700898375cf8", + "0x7fcecd2a720442e9bc0cf1a8a6976f9fbddf6b996dc0d78af7e94dadf360d579": "0x8042ae896b8e68bb", + "0xa1d47ef1a6916dfbe65888f77739da164feb3a9a6afc95ee57e8b3e85ea5e955": "0x216714fd5b83698d", + "0xdb302bf24b1ad5f23949da8e6b05747dc699499a995361a7bf40ec7204696d6f": "0x1c712bd73fa1ed3c" + } + }, + "0x84ea74d481ee0a5332c457a4d796187f6ba67feb": { + "nonce": 1, + "balance": "0x0", + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106f1565b610118565b61005b61009336600461070c565b61015f565b3480156100a457600080fd5b506100ad6101d0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106f1565b61020b565b3480156100f557600080fd5b506100ad610235565b61010661029b565b61011661011161033a565b610344565b565b610120610368565b6001600160a01b0316336001600160a01b03161415610157576101548160405180602001604052806000815250600061039b565b50565b6101546100fe565b610167610368565b6001600160a01b0316336001600160a01b031614156101c8576101c38383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001925061039b915050565b505050565b6101c36100fe565b60006101da610368565b6001600160a01b0316336001600160a01b03161415610200576101fb61033a565b905090565b6102086100fe565b90565b610213610368565b6001600160a01b0316336001600160a01b0316141561015757610154816103c6565b600061023f610368565b6001600160a01b0316336001600160a01b03161415610200576101fb610368565b6060610285838360405180606001604052806027815260200161080b6027913961041a565b9392505050565b6001600160a01b03163b151590565b6102a3610368565b6001600160a01b0316336001600160a01b031614156101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101fb6104f7565b3660008037600080366000845af43d6000803e808015610363573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103a48361051f565b6000825111806103b15750805b156101c3576103c08383610260565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103ef610368565b604080516001600160a01b03928316815291841660208301520160405180910390a16101548161055f565b60606001600160a01b0384163b6104825760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610331565b600080856001600160a01b03168560405161049d91906107bb565b600060405180830381855af49150503d80600081146104d8576040519150601f19603f3d011682016040523d82523d6000602084013e6104dd565b606091505b50915091506104ed828286610608565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61038c565b61052881610641565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105c45760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610331565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60608315610617575081610285565b8251156106275782518084602001fd5b8160405162461bcd60e51b815260040161033191906107d7565b6001600160a01b0381163b6106ae5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610331565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105e7565b80356001600160a01b03811681146106ec57600080fd5b919050565b60006020828403121561070357600080fd5b610285826106d5565b60008060006040848603121561072157600080fd5b61072a846106d5565b9250602084013567ffffffffffffffff8082111561074757600080fd5b818601915086601f83011261075b57600080fd5b81358181111561076a57600080fd5b87602082850101111561077c57600080fd5b6020830194508093505050509250925092565b60005b838110156107aa578181015183820152602001610792565b838111156103c05750506000910152565b600082516107cd81846020870161078f565b9190910192915050565b60208152600082518060208401526107f681604085016020870161078f565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212201336548e393b6bf33c1e3380011fea84db160f673ebc8828297c6c2b86153c4664736f6c634300080c0033", + "storage": { + "0x17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec": "0x1", + "0x295841a49a1089f4b560f91cfbb0133326654dcbb1041861fc5dde96c724a22f": "0x14000000000000000000000000000000000000000000000000", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x851356ae760d987e095750cceb3bc6014560891c", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0xc5a5c42992decbae36851359345fe25997f5c42d" + } + }, + "0x851356ae760d987e095750cceb3bc6014560891c": { + "nonce": 1, + "balance": "0x0", + "code": "0x608060405234801561001057600080fd5b50600436106101155760003560e01c80636d14a987116100a2578063bf79ce5811610071578063bf79ce58146103cc578063d5254a8c146103df578063de29fac0146103ff578063e8bb9ae61461041f578063f4e24fe51461044857600080fd5b80636d14a9871461030a5780637916cea6146103315780637ff81a8714610372578063a3db80e2146103a557600080fd5b80633fb27952116100e95780633fb27952146101df57806347b314e8146101f25780635f61a88414610233578063605747d51461028f57806368bccaac146102dd57600080fd5b8062a1f4cb1461011a57806313542a4e1461015b57806326d941f214610192578063377ed99d146101a7575b600080fd5b6101416101283660046118b7565b6003602052600090815260409020805460019091015482565b604080519283526020830191909152015b60405180910390f35b6101846101693660046118b7565b6001600160a01b031660009081526001602052604090205490565b604051908152602001610152565b6101a56101a03660046118ea565b61045b565b005b6101ca6101b53660046118ea565b60ff1660009081526004602052604090205490565b60405163ffffffff9091168152602001610152565b6101a56101ed366004611975565b610570565b61021b610200366004611a1b565b6000908152600260205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610152565b6102826102413660046118ea565b60408051808201909152600080825260208201525060ff16600090815260056020908152604091829020825180840190935280548352600101549082015290565b6040516101529190611a34565b6102a261029d366004611a4b565b6105ee565b60408051825167ffffffffffffffff1916815260208084015163ffffffff908116918301919091529282015190921690820152606001610152565b6102f06102eb366004611a75565b610681565b60405167ffffffffffffffff199091168152602001610152565b61021b7f000000000000000000000000c3e53f4d16ae77db1c982e75a937b9f60fe6369081565b61034461033f366004611a4b565b61081c565b6040805167ffffffffffffffff19909416845263ffffffff9283166020850152911690820152606001610152565b6103856103803660046118b7565b610867565b604080518351815260209384015193810193909352820152606001610152565b6101416103b33660046118ea565b6005602052600090815260409020805460019091015482565b6101846103da366004611abd565b610934565b6103f26103ed366004611b1a565b610d48565b6040516101529190611b92565b61018461040d3660046118b7565b60016020526000908152604090205481565b61021b61042d366004611a1b565b6002602052600090815260409020546001600160a01b031681565b6101a5610456366004611975565b610f62565b610463610fcb565b60ff8116600090815260046020526040902054156104e75760405162461bcd60e51b815260206004820152603660248201527f424c5341706b52656769737472792e696e697469616c697a6551756f72756d3a6044820152752071756f72756d20616c72656164792065786973747360501b60648201526084015b60405180910390fd5b60ff166000908152600460209081526040808320815160608101835284815263ffffffff4381168286019081528285018781528454600181018655948852959096209151919092018054955194518316600160e01b026001600160e01b0395909316600160c01b026001600160e01b03199096169190931c179390931791909116919091179055565b610578610fcb565b600061058383610867565b5090506105908282611082565b7f73a2b7fb844724b971802ae9b15db094d4b7192df9d7350e14eb466b9b22eb4e836105d1856001600160a01b031660009081526001602052604090205490565b846040516105e193929190611bdc565b60405180910390a1505050565b604080516060810182526000808252602080830182905282840182905260ff86168252600490529190912080548390811061062b5761062b611c48565b600091825260209182902060408051606081018252919092015467ffffffffffffffff1981841b16825263ffffffff600160c01b8204811694830194909452600160e01b90049092169082015290505b92915050565b60ff831660009081526004602052604081208054829190849081106106a8576106a8611c48565b600091825260209182902060408051606081018252919092015467ffffffffffffffff1981841b16825263ffffffff600160c01b82048116948301859052600160e01b90910481169282019290925292508516101561076f5760405162461bcd60e51b815260206004820152603e60248201527f424c5341706b52656769737472792e5f76616c696461746541706b486173684160448201527f74426c6f636b4e756d6265723a20696e64657820746f6f20726563656e74000060648201526084016104de565b604081015163ffffffff1615806107955750806040015163ffffffff168463ffffffff16105b6108135760405162461bcd60e51b815260206004820152604360248201527f424c5341706b52656769737472792e5f76616c696461746541706b486173684160448201527f74426c6f636b4e756d6265723a206e6f74206c61746573742061706b2075706460648201526261746560e81b608482015260a4016104de565b51949350505050565b6004602052816000526040600020818154811061083857600080fd5b600091825260209091200154604081901b925063ffffffff600160c01b820481169250600160e01b9091041683565b60408051808201909152600080825260208201526001600160a01b03821660008181526003602090815260408083208151808301835281548152600191820154818501529484529091528120549091908061092a5760405162461bcd60e51b815260206004820152603e60248201527f424c5341706b52656769737472792e676574526567697374657265645075626b60448201527f65793a206f70657261746f72206973206e6f742072656769737465726564000060648201526084016104de565b9094909350915050565b600061093e610fcb565b600061096c61095536869003860160408701611c5e565b805160009081526020918201519091526040902090565b90507fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb58114156109f4576040805162461bcd60e51b8152602060048201526024810191909152600080516020611e7583398151915260448201527f4b65793a2063616e6e6f74207265676973746572207a65726f207075626b657960648201526084016104de565b6001600160a01b03851660009081526001602052604090205415610a7e5760405162461bcd60e51b81526020600482015260476024820152600080516020611e7583398151915260448201527f4b65793a206f70657261746f7220616c72656164792072656769737465726564606482015266207075626b657960c81b608482015260a4016104de565b6000818152600260205260409020546001600160a01b031615610b025760405162461bcd60e51b81526020600482015260426024820152600080516020611e7583398151915260448201527f4b65793a207075626c6963206b657920616c7265616479207265676973746572606482015261195960f21b608482015260a4016104de565b604080516000917f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000191610b5b918835916020808b0135928b01359160608c01359160808d019160c08e01918d35918e8201359101611c90565b6040516020818303038152906040528051906020012060001c610b7e9190611cdb565b9050610c18610bb7610ba283610b9c368a90038a0160408b01611c5e565b906112cd565b610bb136899003890189611c5e565b90611364565b610bbf6113f8565b610c01610bf285610b9c604080518082018252600080825260209182015281518083019092526001825260029082015290565b610bb1368a90038a018a611c5e565b610c13368a90038a0160808b01611d4d565b6114b8565b610cb35760405162461bcd60e51b815260206004820152606c6024820152600080516020611e7583398151915260448201527f4b65793a2065697468657220746865204731207369676e61747572652069732060648201527f77726f6e672c206f7220473120616e642047322070726976617465206b65792060848201526b0c8de40dcdee840dac2e8c6d60a31b60a482015260c4016104de565b6001600160a01b03861660008181526003602090815260408083208982018035825560608b013560019283015590835281842087905586845260029092529182902080546001600160a01b0319168417905590517fe3fb6613af2e8930cf85d47fcf6db10192224a64c6cbe8023e0eee1ba382804191610d379160808a0190611daa565b60405180910390a250949350505050565b606060008367ffffffffffffffff811115610d6557610d65611905565b604051908082528060200260200182016040528015610d8e578160200160208202803683370190505b50905060005b84811015610f59576000868683818110610db057610db0611c48565b919091013560f81c6000818152600460205260409020549092509050801580610e13575060ff821660009081526004602052604081208054909190610df757610df7611c48565b600091825260209091200154600160c01b900463ffffffff1686105b15610ea05760405162461bcd60e51b815260206004820152605160248201527f424c5341706b52656769737472792e67657441706b496e64696365734174426c60448201527f6f636b4e756d6265723a20626c6f636b4e756d626572206973206265666f7265606482015270207468652066697273742075706461746560781b608482015260a4016104de565b805b8015610f435760ff831660009081526004602052604090208790610ec7600184611df4565b81548110610ed757610ed7611c48565b600091825260209091200154600160c01b900463ffffffff1611610f3157610f00600182611df4565b858581518110610f1257610f12611c48565b602002602001019063ffffffff16908163ffffffff1681525050610f43565b80610f3b81611e0b565b915050610ea2565b5050508080610f5190611e22565b915050610d94565b50949350505050565b610f6a610fcb565b6000610f7583610867565b509050610f8a82610f8583611725565b611082565b7ff843ecd53a563675e62107be1494fdde4a3d49aeedaf8d88c616d85346e3500e836105d1856001600160a01b031660009081526001602052604090205490565b336001600160a01b037f000000000000000000000000c3e53f4d16ae77db1c982e75a937b9f60fe6369016146110805760405162461bcd60e51b815260206004820152604e60248201527f424c5341706b52656769737472792e6f6e6c795265676973747279436f6f726460448201527f696e61746f723a2063616c6c6572206973206e6f74207468652072656769737460648201526d393c9031b7b7b93234b730ba37b960911b608482015260a4016104de565b565b604080518082019091526000808252602082015260005b83518110156112c75760008482815181106110b6576110b6611c48565b0160209081015160f81c60008181526004909252604090912054909150806111465760405162461bcd60e51b815260206004820152603d60248201527f424c5341706b52656769737472792e5f70726f6365737351756f72756d41706b60448201527f5570646174653a2071756f72756d20646f6573206e6f7420657869737400000060648201526084016104de565b60ff8216600090815260056020908152604091829020825180840190935280548352600101549082015261117a9086611364565b60ff831660008181526005602090815260408083208551808255868401805160019384015590855251835281842094845260049092528220939750919290916111c39085611df4565b815481106111d3576111d3611c48565b600091825260209091200180549091504363ffffffff908116600160c01b9092041614156112145780546001600160c01b031916604083901c1781556112b0565b805463ffffffff438116600160e01b8181026001600160e01b0394851617855560ff88166000908152600460209081526040808320815160608101835267ffffffffffffffff198b16815280840196875280830185815282546001810184559286529390942093519301805495519251871690940291909516600160c01b026001600160e01b0319949094169190941c17919091179092161790555b5050505080806112bf90611e22565b915050611099565b50505050565b60408051808201909152600080825260208201526112e96117e4565b835181526020808501519082015260408082018490526000908360608460076107d05a03fa905080801561131c5761131e565bfe5b508061135c5760405162461bcd60e51b815260206004820152600d60248201526c1958cb5b5d5b0b59985a5b1959609a1b60448201526064016104de565b505092915050565b6040805180820190915260008082526020820152611380611802565b835181526020808501518183015283516040808401919091529084015160608301526000908360808460066107d05a03fa905080801561131c57508061135c5760405162461bcd60e51b815260206004820152600d60248201526c1958cb5859190b59985a5b1959609a1b60448201526064016104de565b611400611820565b50604080516080810182527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c28183019081527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6060830152815281518083019092527f275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec82527f1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d60208381019190915281019190915290565b6040805180820182528581526020808201859052825180840190935285835282018390526000916114e7611845565b60005b60028110156116ac576000611500826006611e3d565b905084826002811061151457611514611c48565b60200201515183611526836000611e5c565b600c811061153657611536611c48565b602002015284826002811061154d5761154d611c48565b602002015160200151838260016115649190611e5c565b600c811061157457611574611c48565b602002015283826002811061158b5761158b611c48565b602002015151518361159e836002611e5c565b600c81106115ae576115ae611c48565b60200201528382600281106115c5576115c5611c48565b60200201515160016020020151836115de836003611e5c565b600c81106115ee576115ee611c48565b602002015283826002811061160557611605611c48565b60200201516020015160006002811061162057611620611c48565b602002015183611631836004611e5c565b600c811061164157611641611c48565b602002015283826002811061165857611658611c48565b60200201516020015160016002811061167357611673611c48565b602002015183611684836005611e5c565b600c811061169457611694611c48565b602002015250806116a481611e22565b9150506114ea565b506116b5611864565b60006020826101808560086107d05a03fa905080801561131c5750806117155760405162461bcd60e51b81526020600482015260156024820152741c185a5c9a5b99cb5bdc18dbd9194b59985a5b1959605a1b60448201526064016104de565b5051151598975050505050505050565b6040805180820190915260008082526020820152815115801561174a57506020820151155b15611768575050604080518082019091526000808252602082015290565b6040518060400160405280836000015181526020017f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4784602001516117ad9190611cdb565b6117d7907f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47611df4565b905292915050565b919050565b60405180606001604052806003906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b6040518060400160405280611833611882565b8152602001611840611882565b905290565b604051806101800160405280600c906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b60405180604001604052806002906020820280368337509192915050565b80356001600160a01b03811681146117df57600080fd5b6000602082840312156118c957600080fd5b6118d2826118a0565b9392505050565b803560ff811681146117df57600080fd5b6000602082840312156118fc57600080fd5b6118d2826118d9565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561193e5761193e611905565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561196d5761196d611905565b604052919050565b6000806040838503121561198857600080fd5b611991836118a0565b915060208084013567ffffffffffffffff808211156119af57600080fd5b818601915086601f8301126119c357600080fd5b8135818111156119d5576119d5611905565b6119e7601f8201601f19168501611944565b915080825287848285010111156119fd57600080fd5b80848401858401376000848284010152508093505050509250929050565b600060208284031215611a2d57600080fd5b5035919050565b81518152602080830151908201526040810161067b565b60008060408385031215611a5e57600080fd5b611a67836118d9565b946020939093013593505050565b600080600060608486031215611a8a57600080fd5b611a93846118d9565b9250602084013563ffffffff81168114611aac57600080fd5b929592945050506040919091013590565b6000806000838503610160811215611ad457600080fd5b611add856118a0565b9350610100601f1982011215611af257600080fd5b602085019250604061011f1982011215611b0b57600080fd5b50610120840190509250925092565b600080600060408486031215611b2f57600080fd5b833567ffffffffffffffff80821115611b4757600080fd5b818601915086601f830112611b5b57600080fd5b813581811115611b6a57600080fd5b876020828501011115611b7c57600080fd5b6020928301989097509590910135949350505050565b6020808252825182820181905260009190848201906040850190845b81811015611bd057835163ffffffff1683529284019291840191600101611bae565b50909695505050505050565b60018060a01b038416815260006020848184015260606040840152835180606085015260005b81811015611c1e57858101830151858201608001528201611c02565b81811115611c30576000608083870101525b50601f01601f19169290920160800195945050505050565b634e487b7160e01b600052603260045260246000fd5b600060408284031215611c7057600080fd5b611c7861191b565b82358152602083013560208201528091505092915050565b8881528760208201528660408201528560608201526040856080830137600060c082016000815260408682375050610100810192909252610120820152610140019695505050505050565b600082611cf857634e487b7160e01b600052601260045260246000fd5b500690565b600082601f830112611d0e57600080fd5b611d1661191b565b806040840185811115611d2857600080fd5b845b81811015611d42578035845260209384019301611d2a565b509095945050505050565b600060808284031215611d5f57600080fd5b6040516040810181811067ffffffffffffffff82111715611d8257611d82611905565b604052611d8f8484611cfd565b8152611d9e8460408501611cfd565b60208201529392505050565b823581526020808401359082015260c081016040838184013760808201600081526040808501823750600081529392505050565b634e487b7160e01b600052601160045260246000fd5b600082821015611e0657611e06611dde565b500390565b600081611e1a57611e1a611dde565b506000190190565b6000600019821415611e3657611e36611dde565b5060010190565b6000816000190483118215151615611e5757611e57611dde565b500290565b60008219821115611e6f57611e6f611dde565b50019056fe424c5341706b52656769737472792e7265676973746572424c535075626c6963a264697066735822122050dfc1da66444592fb84923bcfae2f8857badafecacc21f561f2badca6224c8f64736f6c634300080c0033", + "storage": { "0x0": "0xff" } + }, + "0x8a791620dd6260079bf849dc5567adc3f2fdc318": { + "nonce": 1, + "balance": "0x0", + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106f1565b610118565b61005b61009336600461070c565b61015f565b3480156100a457600080fd5b506100ad6101d0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106f1565b61020b565b3480156100f557600080fd5b506100ad610235565b61010661029b565b61011661011161033a565b610344565b565b610120610368565b6001600160a01b0316336001600160a01b03161415610157576101548160405180602001604052806000815250600061039b565b50565b6101546100fe565b610167610368565b6001600160a01b0316336001600160a01b031614156101c8576101c38383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001925061039b915050565b505050565b6101c36100fe565b60006101da610368565b6001600160a01b0316336001600160a01b03161415610200576101fb61033a565b905090565b6102086100fe565b90565b610213610368565b6001600160a01b0316336001600160a01b0316141561015757610154816103c6565b600061023f610368565b6001600160a01b0316336001600160a01b03161415610200576101fb610368565b6060610285838360405180606001604052806027815260200161080b6027913961041a565b9392505050565b6001600160a01b03163b151590565b6102a3610368565b6001600160a01b0316336001600160a01b031614156101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101fb6104f7565b3660008037600080366000845af43d6000803e808015610363573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103a48361051f565b6000825111806103b15750805b156101c3576103c08383610260565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103ef610368565b604080516001600160a01b03928316815291841660208301520160405180910390a16101548161055f565b60606001600160a01b0384163b6104825760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610331565b600080856001600160a01b03168560405161049d91906107bb565b600060405180830381855af49150503d80600081146104d8576040519150601f19603f3d011682016040523d82523d6000602084013e6104dd565b606091505b50915091506104ed828286610608565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61038c565b61052881610641565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105c45760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610331565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60608315610617575081610285565b8251156106275782518084602001fd5b8160405162461bcd60e51b815260040161033191906107d7565b6001600160a01b0381163b6106ae5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610331565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105e7565b80356001600160a01b03811681146106ec57600080fd5b919050565b60006020828403121561070357600080fd5b610285826106d5565b60008060006040848603121561072157600080fd5b61072a846106d5565b9250602084013567ffffffffffffffff8082111561074757600080fd5b818601915086601f83011261075b57600080fd5b81358181111561076a57600080fd5b87602082850101111561077c57600080fd5b6020830194508093505050509250925092565b60005b838110156107aa578181015183820152602001610792565b838111156103c05750506000910152565b600082516107cd81846020870161078f565b9190910192915050565b60208152600082518060208401526107f681604085016020870161078f565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212208c7daa35c73cc3931155de6fec176061a18c7828634d7222e2c3c877ecc7552c64736f6c634300080c0033", + "storage": { + "0x0": "0x1", + "0x33": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x97": "0x9fe46736679d2d9a65f0992f2272de9f3c7fa6e0", + "0x98": "0x0", + "0xc9": "0x1", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x9a9f2ccfde556a7e9ff0848998aa4a0cfd8863ae", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512" + } + }, + "0x8f86403a4de0bb5791fa46b8e795c547942fe4cf": { + "nonce": 1, + "balance": "0x0", + "code": "0x608060405234801561001057600080fd5b50600436106101375760003560e01c80638da5cb5b116100b8578063c4d66de81161007c578063c4d66de8146102f6578063df5cf72314610309578063e481af9d14610330578063f2fde38b14610338578063fc299dee1461034b578063fce36c7d1461035e57600080fd5b80638da5cb5b1461028f5780639926ee7d146102a0578063a364f4da146102b3578063a98fb355146102c6578063b98d0908146102d957600080fd5b806368304835116100ff57806368304835146101f25780636b3aa72e146102195780636d14a9871461023f5780636efb463614610266578063715018a61461028757600080fd5b8063171f1d5b1461013c57806333cfb7b71461016b5780633bc28c8c1461018b578063416c7e5e146101a05780635df45946146101b3575b600080fd5b61014f61014a3660046133b2565b610371565b6040805192151583529015156020830152015b60405180910390f35b61017e610179366004613418565b6104fb565b6040516101629190613435565b61019e610199366004613418565b6109ca565b005b61019e6101ae366004613490565b6109de565b6101da7f00000000000000000000000084ea74d481ee0a5332c457a4d796187f6ba67feb81565b6040516001600160a01b039091168152602001610162565b6101da7f000000000000000000000000a82ff9afd8f496c3d6ac40e2a0f282e47488cfc981565b7f0000000000000000000000000165878a594ca255338adfa4d48449f69242eb8f6101da565b6101da7f000000000000000000000000c3e53f4d16ae77db1c982e75a937b9f60fe6369081565b610279610274366004613763565b610b1a565b604051610162929190613856565b61019e611a31565b6033546001600160a01b03166101da565b61019e6102ae3660046138f6565b611a45565b61019e6102c1366004613418565b611b11565b61019e6102d43660046139a0565b611bd8565b6097546102e69060ff1681565b6040519015158152602001610162565b61019e610304366004613418565b611c2c565b6101da7f000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c981565b61017e611d40565b61019e610346366004613418565b612109565b6065546101da906001600160a01b031681565b61019e61036c3660046139f0565b61217f565b60008060007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001878760000151886020015188600001516000600281106103b9576103b9613a64565b60200201518951600160200201518a602001516000600281106103de576103de613a64565b60200201518b602001516001600281106103fa576103fa613a64565b602090810291909101518c518d8301516040516104579a99989796959401988952602089019790975260408801959095526060870193909352608086019190915260a085015260c084015260e08301526101008201526101200190565b6040516020818303038152906040528051906020012060001c61047a9190613a7a565b90506104ed61049361048c8884612537565b86906125ce565b61049b612662565b6104e36104d4856104ce604080518082018252600080825260209182015281518083019092526001825260029082015290565b90612537565b6104dd8c612722565b906125ce565b886201d4c06127b2565b909890975095505050505050565b6040516309aa152760e11b81526001600160a01b0382811660048301526060916000917f000000000000000000000000c3e53f4d16ae77db1c982e75a937b9f60fe6369016906313542a4e90602401602060405180830381865afa158015610567573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058b9190613a9c565b60405163871ef04960e01b8152600481018290529091506000906001600160a01b037f000000000000000000000000c3e53f4d16ae77db1c982e75a937b9f60fe63690169063871ef04990602401602060405180830381865afa1580156105f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061a9190613ab5565b90506001600160c01b03811615806106b457507f000000000000000000000000c3e53f4d16ae77db1c982e75a937b9f60fe636906001600160a01b0316639aa1653d6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561068b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106af9190613ade565b60ff16155b156106d057505060408051600081526020810190915292915050565b60006106e4826001600160c01b03166129d6565b90506000805b82518110156107ba577f000000000000000000000000a82ff9afd8f496c3d6ac40e2a0f282e47488cfc96001600160a01b0316633ca5a5f584838151811061073457610734613a64565b01602001516040516001600160e01b031960e084901b16815260f89190911c6004820152602401602060405180830381865afa158015610778573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079c9190613a9c565b6107a69083613b17565b9150806107b281613b2f565b9150506106ea565b506000816001600160401b038111156107d5576107d561323f565b6040519080825280602002602001820160405280156107fe578160200160208202803683370190505b5090506000805b84518110156109bd57600085828151811061082257610822613a64565b0160200151604051633ca5a5f560e01b815260f89190911c6004820181905291506000906001600160a01b037f000000000000000000000000a82ff9afd8f496c3d6ac40e2a0f282e47488cfc91690633ca5a5f590602401602060405180830381865afa158015610897573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108bb9190613a9c565b905060005b818110156109a7576040516356e4026d60e11b815260ff84166004820152602481018290527f000000000000000000000000a82ff9afd8f496c3d6ac40e2a0f282e47488cfc96001600160a01b03169063adc804da906044016040805180830381865afa158015610935573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109599190613b5f565b6000015186868151811061096f5761096f613a64565b6001600160a01b03909216602092830291909101909101528461099181613b2f565b955050808061099f90613b2f565b9150506108c0565b50505080806109b590613b2f565b915050610805565b5090979650505050505050565b6109d2612a98565b6109db81612af2565b50565b7f000000000000000000000000c3e53f4d16ae77db1c982e75a937b9f60fe636906001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a609190613ba0565b6001600160a01b0316336001600160a01b031614610b115760405162461bcd60e51b815260206004820152605c60248201527f424c535369676e6174757265436865636b65722e6f6e6c79436f6f7264696e6160448201527f746f724f776e65723a2063616c6c6572206973206e6f7420746865206f776e6560648201527f72206f6620746865207265676973747279436f6f7264696e61746f7200000000608482015260a4015b60405180910390fd5b6109db81612b5b565b6040805180820190915260608082526020820152600084610b915760405162461bcd60e51b81526020600482015260376024820152600080516020613fc883398151915260448201527f7265733a20656d7074792071756f72756d20696e7075740000000000000000006064820152608401610b08565b60408301515185148015610ba9575060a08301515185145b8015610bb9575060c08301515185145b8015610bc9575060e08301515185145b610c335760405162461bcd60e51b81526020600482015260416024820152600080516020613fc883398151915260448201527f7265733a20696e7075742071756f72756d206c656e677468206d69736d6174636064820152600d60fb1b608482015260a401610b08565b82515160208401515114610cab5760405162461bcd60e51b815260206004820152604460248201819052600080516020613fc8833981519152908201527f7265733a20696e707574206e6f6e7369676e6572206c656e677468206d69736d6064820152630c2e8c6d60e31b608482015260a401610b08565b4363ffffffff168463ffffffff1610610d1a5760405162461bcd60e51b815260206004820152603c6024820152600080516020613fc883398151915260448201527f7265733a20696e76616c6964207265666572656e636520626c6f636b000000006064820152608401610b08565b6040805180820182526000808252602080830191909152825180840190935260608084529083015290866001600160401b03811115610d5b57610d5b61323f565b604051908082528060200260200182016040528015610d84578160200160208202803683370190505b506020820152866001600160401b03811115610da257610da261323f565b604051908082528060200260200182016040528015610dcb578160200160208202803683370190505b50815260408051808201909152606080825260208201528560200151516001600160401b03811115610dff57610dff61323f565b604051908082528060200260200182016040528015610e28578160200160208202803683370190505b5081526020860151516001600160401b03811115610e4857610e4861323f565b604051908082528060200260200182016040528015610e71578160200160208202803683370190505b5081602001819052506000610f438a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051639aa1653d60e01b815290516001600160a01b037f000000000000000000000000c3e53f4d16ae77db1c982e75a937b9f60fe63690169350639aa1653d925060048083019260209291908290030181865afa158015610f1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3e9190613ade565b612ba2565b905060005b8760200151518110156111de57610f8d88602001518281518110610f6e57610f6e613a64565b6020026020010151805160009081526020918201519091526040902090565b83602001518281518110610fa357610fa3613a64565b60209081029190910101528015611063576020830151610fc4600183613bbd565b81518110610fd457610fd4613a64565b602002602001015160001c83602001518281518110610ff557610ff5613a64565b602002602001015160001c11611063576040805162461bcd60e51b8152602060048201526024810191909152600080516020613fc883398151915260448201527f7265733a206e6f6e5369676e65725075626b657973206e6f7420736f727465646064820152608401610b08565b7f000000000000000000000000c3e53f4d16ae77db1c982e75a937b9f60fe636906001600160a01b03166304ec6351846020015183815181106110a8576110a8613a64565b60200260200101518b8b6000015185815181106110c7576110c7613a64565b60200260200101516040518463ffffffff1660e01b81526004016111049392919092835263ffffffff918216602084015216604082015260600190565b602060405180830381865afa158015611121573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111459190613ab5565b6001600160c01b03168360000151828151811061116457611164613a64565b6020026020010181815250506111ca61048c61119e848660000151858151811061119057611190613a64565b602002602001015116612c35565b8a6020015184815181106111b4576111b4613a64565b6020026020010151612c6090919063ffffffff16565b9450806111d681613b2f565b915050610f48565b50506111e983612d44565b60975490935060ff16600081611200576000611282565b7f000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c96001600160a01b031663c448feb86040518163ffffffff1660e01b8152600401602060405180830381865afa15801561125e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112829190613a9c565b905060005b8a8110156119005782156113e2578963ffffffff16827f000000000000000000000000c3e53f4d16ae77db1c982e75a937b9f60fe636906001600160a01b031663249a0c428f8f868181106112de576112de613a64565b60405160e085901b6001600160e01b031916815292013560f81c600483015250602401602060405180830381865afa15801561131e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113429190613a9c565b61134c9190613b17565b116113e25760405162461bcd60e51b81526020600482015260666024820152600080516020613fc883398151915260448201527f7265733a205374616b6552656769737472792075706461746573206d7573742060648201527f62652077697468696e207769746864726177616c44656c6179426c6f636b732060848201526577696e646f7760d01b60a482015260c401610b08565b7f00000000000000000000000084ea74d481ee0a5332c457a4d796187f6ba67feb6001600160a01b03166368bccaac8d8d8481811061142357611423613a64565b9050013560f81c60f81b60f81c8c8c60a00151858151811061144757611447613a64565b60209081029190910101516040516001600160e01b031960e086901b16815260ff909316600484015263ffffffff9182166024840152166044820152606401602060405180830381865afa1580156114a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c79190613bd4565b6001600160401b0319166114ea8a604001518381518110610f6e57610f6e613a64565b67ffffffffffffffff1916146115865760405162461bcd60e51b81526020600482015260616024820152600080516020613fc883398151915260448201527f7265733a2071756f72756d41706b206861736820696e2073746f72616765206460648201527f6f6573206e6f74206d617463682070726f76696465642071756f72756d2061706084820152606b60f81b60a482015260c401610b08565b6115b68960400151828151811061159f5761159f613a64565b6020026020010151876125ce90919063ffffffff16565b95507f000000000000000000000000a82ff9afd8f496c3d6ac40e2a0f282e47488cfc96001600160a01b031663c8294c568d8d848181106115f9576115f9613a64565b9050013560f81c60f81b60f81c8c8c60c00151858151811061161d5761161d613a64565b60209081029190910101516040516001600160e01b031960e086901b16815260ff909316600484015263ffffffff9182166024840152166044820152606401602060405180830381865afa158015611679573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169d9190613bff565b856020015182815181106116b3576116b3613a64565b6001600160601b039092166020928302919091018201528501518051829081106116df576116df613a64565b6020026020010151856000015182815181106116fd576116fd613a64565b60200260200101906001600160601b031690816001600160601b0316815250506000805b8a60200151518110156118eb576117758660000151828151811061174757611747613a64565b60200260200101518f8f8681811061176157611761613a64565b600192013560f81c9290921c811614919050565b156118d9577f000000000000000000000000a82ff9afd8f496c3d6ac40e2a0f282e47488cfc96001600160a01b031663f2be94ae8f8f868181106117bb576117bb613a64565b9050013560f81c60f81b60f81c8e896020015185815181106117df576117df613a64565b60200260200101518f60e0015188815181106117fd576117fd613a64565b6020026020010151878151811061181657611816613a64565b60209081029190910101516040516001600160e01b031960e087901b16815260ff909416600485015263ffffffff92831660248501526044840191909152166064820152608401602060405180830381865afa15801561187a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061189e9190613bff565b87518051859081106118b2576118b2613a64565b602002602001018181516118c69190613c1c565b6001600160601b03169052506001909101905b806118e381613b2f565b915050611721565b505080806118f890613b2f565b915050611287565b50505060008061191a8c868a606001518b60800151610371565b915091508161198b5760405162461bcd60e51b81526020600482015260436024820152600080516020613fc883398151915260448201527f7265733a2070616972696e6720707265636f6d70696c652063616c6c206661696064820152621b195960ea1b608482015260a401610b08565b806119ec5760405162461bcd60e51b81526020600482015260396024820152600080516020613fc883398151915260448201527f7265733a207369676e617475726520697320696e76616c6964000000000000006064820152608401610b08565b50506000878260200151604051602001611a07929190613c44565b60408051808303601f190181529190528051602090910120929b929a509198505050505050505050565b611a39612a98565b611a436000612ddf565b565b336001600160a01b037f000000000000000000000000c3e53f4d16ae77db1c982e75a937b9f60fe636901614611a8d5760405162461bcd60e51b8152600401610b0890613c8c565b604051639926ee7d60e01b81526001600160a01b037f0000000000000000000000000165878a594ca255338adfa4d48449f69242eb8f1690639926ee7d90611adb9085908590600401613d51565b600060405180830381600087803b158015611af557600080fd5b505af1158015611b09573d6000803e3d6000fd5b505050505050565b336001600160a01b037f000000000000000000000000c3e53f4d16ae77db1c982e75a937b9f60fe636901614611b595760405162461bcd60e51b8152600401610b0890613c8c565b6040516351b27a6d60e11b81526001600160a01b0382811660048301527f0000000000000000000000000165878a594ca255338adfa4d48449f69242eb8f169063a364f4da906024015b600060405180830381600087803b158015611bbd57600080fd5b505af1158015611bd1573d6000803e3d6000fd5b5050505050565b611be0612a98565b60405163a98fb35560e01b81526001600160a01b037f0000000000000000000000000165878a594ca255338adfa4d48449f69242eb8f169063a98fb35590611ba3908490600401613d9c565b600054610100900460ff1615808015611c4c5750600054600160ff909116105b80611c665750303b158015611c66575060005460ff166001145b611cc95760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610b08565b6000805460ff191660011790558015611cec576000805461ff0019166101001790555b611cf68283612e31565b8015611d3c576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b606060007f000000000000000000000000c3e53f4d16ae77db1c982e75a937b9f60fe636906001600160a01b0316639aa1653d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611da2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dc69190613ade565b60ff16905080611de457505060408051600081526020810190915290565b6000805b82811015611e9957604051633ca5a5f560e01b815260ff821660048201527f000000000000000000000000a82ff9afd8f496c3d6ac40e2a0f282e47488cfc96001600160a01b031690633ca5a5f590602401602060405180830381865afa158015611e57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e7b9190613a9c565b611e859083613b17565b915080611e9181613b2f565b915050611de8565b506000816001600160401b03811115611eb457611eb461323f565b604051908082528060200260200182016040528015611edd578160200160208202803683370190505b5090506000805b7f000000000000000000000000c3e53f4d16ae77db1c982e75a937b9f60fe636906001600160a01b0316639aa1653d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f669190613ade565b60ff168110156120ff57604051633ca5a5f560e01b815260ff821660048201526000907f000000000000000000000000a82ff9afd8f496c3d6ac40e2a0f282e47488cfc96001600160a01b031690633ca5a5f590602401602060405180830381865afa158015611fda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ffe9190613a9c565b905060005b818110156120ea576040516356e4026d60e11b815260ff84166004820152602481018290527f000000000000000000000000a82ff9afd8f496c3d6ac40e2a0f282e47488cfc96001600160a01b03169063adc804da906044016040805180830381865afa158015612078573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061209c9190613b5f565b600001518585815181106120b2576120b2613a64565b6001600160a01b0390921660209283029190910190910152836120d481613b2f565b94505080806120e290613b2f565b915050612003565b505080806120f790613b2f565b915050611ee4565b5090949350505050565b612111612a98565b6001600160a01b0381166121765760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b08565b6109db81612ddf565b6065546001600160a01b031633146122145760405162461bcd60e51b815260206004820152604c60248201527f536572766963654d616e61676572426173652e6f6e6c7952657761726473496e60448201527f69746961746f723a2063616c6c6572206973206e6f742074686520726577617260648201526b32399034b734ba34b0ba37b960a11b608482015260a401610b08565b60005b818110156124e85782828281811061223157612231613a64565b90506020028101906122439190613db6565b612254906040810190602001613418565b6001600160a01b03166323b872dd333086868681811061227657612276613a64565b90506020028101906122889190613db6565b604080516001600160e01b031960e087901b1681526001600160a01b039485166004820152939092166024840152013560448201526064016020604051808303816000875af11580156122df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123039190613de1565b50600083838381811061231857612318613a64565b905060200281019061232a9190613db6565b61233b906040810190602001613418565b604051636eb1769f60e11b81523060048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152919091169063dd62ed3e90604401602060405180830381865afa1580156123a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123cd9190613a9c565b90508383838181106123e1576123e1613a64565b90506020028101906123f39190613db6565b612404906040810190602001613418565b6001600160a01b031663095ea7b37f00000000000000000000000000000000000000000000000000000000000000008387878781811061244657612446613a64565b90506020028101906124589190613db6565b604001356124669190613b17565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af11580156124b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124d59190613de1565b5050806124e190613b2f565b9050612217565b5060405163fce36c7d60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063fce36c7d90611adb9085908590600401613e59565b6040805180820190915260008082526020820152612553613165565b835181526020808501519082015260408082018490526000908360608460076107d05a03fa905080801561258657612588565bfe5b50806125c65760405162461bcd60e51b815260206004820152600d60248201526c1958cb5b5d5b0b59985a5b1959609a1b6044820152606401610b08565b505092915050565b60408051808201909152600080825260208201526125ea613183565b835181526020808501518183015283516040808401919091529084015160608301526000908360808460066107d05a03fa90508080156125865750806125c65760405162461bcd60e51b815260206004820152600d60248201526c1958cb5859190b59985a5b1959609a1b6044820152606401610b08565b61266a6131a1565b50604080516080810182527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c28183019081527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed6060830152815281518083019092527f275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec82527f1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d60208381019190915281019190915290565b604080518082019091526000808252602082015260008080612752600080516020613fa883398151915286613a7a565b90505b61275e81612eae565b9093509150600080516020613fa8833981519152828309831415612798576040805180820190915290815260208101919091529392505050565b600080516020613fa8833981519152600182089050612755565b6040805180820182528681526020808201869052825180840190935286835282018490526000918291906127e46131c6565b60005b60028110156129a95760006127fd826006613f66565b905084826002811061281157612811613a64565b60200201515183612823836000613b17565b600c811061283357612833613a64565b602002015284826002811061284a5761284a613a64565b602002015160200151838260016128619190613b17565b600c811061287157612871613a64565b602002015283826002811061288857612888613a64565b602002015151518361289b836002613b17565b600c81106128ab576128ab613a64565b60200201528382600281106128c2576128c2613a64565b60200201515160016020020151836128db836003613b17565b600c81106128eb576128eb613a64565b602002015283826002811061290257612902613a64565b60200201516020015160006002811061291d5761291d613a64565b60200201518361292e836004613b17565b600c811061293e5761293e613a64565b602002015283826002811061295557612955613a64565b60200201516020015160016002811061297057612970613a64565b602002015183612981836005613b17565b600c811061299157612991613a64565b602002015250806129a181613b2f565b9150506127e7565b506129b26131e5565b60006020826101808560088cfa9151919c9115159b50909950505050505050505050565b60606000806129e484612c35565b61ffff166001600160401b038111156129ff576129ff61323f565b6040519080825280601f01601f191660200182016040528015612a29576020820181803683370190505b5090506000805b825182108015612a41575061010081105b156120ff576001811b935085841615612a88578060f81b838381518110612a6a57612a6a613a64565b60200101906001600160f81b031916908160001a9053508160010191505b612a9181613b2f565b9050612a30565b6033546001600160a01b03163314611a435760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b08565b606554604080516001600160a01b03928316815291831660208301527fe11cddf1816a43318ca175bbc52cd0185436e9cbead7c83acc54a73e461717e3910160405180910390a1606580546001600160a01b0319166001600160a01b0392909216919091179055565b6097805460ff19168215159081179091556040519081527f40e4ed880a29e0f6ddce307457fb75cddf4feef7d3ecb0301bfdf4976a0e2dfc9060200160405180910390a150565b600080612bae84612f30565b9050808360ff166001901b11612c2c5760405162461bcd60e51b815260206004820152603f60248201527f4269746d61705574696c732e6f72646572656442797465734172726179546f4260448201527f69746d61703a206269746d61702065786365656473206d61782076616c7565006064820152608401610b08565b90505b92915050565b6000805b8215612c2f57612c4a600184613bbd565b9092169180612c5881613f85565b915050612c39565b60408051808201909152600080825260208201526102008261ffff1610612cbc5760405162461bcd60e51b815260206004820152601060248201526f7363616c61722d746f6f2d6c6172676560801b6044820152606401610b08565b8161ffff1660011415612cd0575081612c2f565b6040805180820190915260008082526020820181905284906001905b8161ffff168661ffff1610612d3957600161ffff871660ff83161c81161415612d1c57612d1984846125ce565b93505b612d2683846125ce565b92506201fffe600192831b169101612cec565b509195945050505050565b60408051808201909152600080825260208201528151158015612d6957506020820151155b15612d87575050604080518082019091526000808252602082015290565b604051806040016040528083600001518152602001600080516020613fa88339815191528460200151612dba9190613a7a565b612dd290600080516020613fa8833981519152613bbd565b905292915050565b919050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16612e9c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610b08565b612ea582612ddf565b611d3c81612af2565b60008080600080516020613fa88339815191526003600080516020613fa883398151915286600080516020613fa8833981519152888909090890506000612f24827f0c19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52600080516020613fa88339815191526130bd565b91959194509092505050565b600061010082511115612fb95760405162461bcd60e51b8152602060048201526044602482018190527f4269746d61705574696c732e6f72646572656442797465734172726179546f42908201527f69746d61703a206f7264657265644279746573417272617920697320746f6f206064820152636c6f6e6760e01b608482015260a401610b08565b8151612fc757506000919050565b60008083600081518110612fdd57612fdd613a64565b0160200151600160f89190911c81901b92505b84518110156130b45784818151811061300b5761300b613a64565b0160200151600160f89190911c1b91508282116130a05760405162461bcd60e51b815260206004820152604760248201527f4269746d61705574696c732e6f72646572656442797465734172726179546f4260448201527f69746d61703a206f72646572656442797465734172726179206973206e6f74206064820152661bdc99195c995960ca1b608482015260a401610b08565b918117916130ad81613b2f565b9050612ff0565b50909392505050565b6000806130c86131e5565b6130d0613203565b602080825281810181905260408201819052606082018890526080820187905260a082018690528260c08360056107d05a03fa925082801561258657508261315a5760405162461bcd60e51b815260206004820152601a60248201527f424e3235342e6578704d6f643a2063616c6c206661696c7572650000000000006044820152606401610b08565b505195945050505050565b60405180606001604052806003906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b60405180604001604052806131b4613221565b81526020016131c1613221565b905290565b604051806101800160405280600c906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b60405180604001604052806002906020820280368337509192915050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156132775761327761323f565b60405290565b60405161010081016001600160401b03811182821017156132775761327761323f565b604051606081016001600160401b03811182821017156132775761327761323f565b604051601f8201601f191681016001600160401b03811182821017156132ea576132ea61323f565b604052919050565b60006040828403121561330457600080fd5b61330c613255565b9050813581526020820135602082015292915050565b600082601f83011261333357600080fd5b61333b613255565b80604084018581111561334d57600080fd5b845b8181101561336757803584526020938401930161334f565b509095945050505050565b60006080828403121561338457600080fd5b61338c613255565b90506133988383613322565b81526133a78360408401613322565b602082015292915050565b60008060008061012085870312156133c957600080fd5b843593506133da86602087016132f2565b92506133e98660608701613372565b91506133f88660e087016132f2565b905092959194509250565b6001600160a01b03811681146109db57600080fd5b60006020828403121561342a57600080fd5b8135612c2c81613403565b6020808252825182820181905260009190848201906040850190845b818110156134765783516001600160a01b031683529284019291840191600101613451565b50909695505050505050565b80151581146109db57600080fd5b6000602082840312156134a257600080fd5b8135612c2c81613482565b803563ffffffff81168114612dda57600080fd5b60006001600160401b038211156134da576134da61323f565b5060051b60200190565b600082601f8301126134f557600080fd5b8135602061350a613505836134c1565b6132c2565b82815260059290921b8401810191818101908684111561352957600080fd5b8286015b8481101561354b5761353e816134ad565b835291830191830161352d565b509695505050505050565b600082601f83011261356757600080fd5b81356020613577613505836134c1565b82815260069290921b8401810191818101908684111561359657600080fd5b8286015b8481101561354b576135ac88826132f2565b83529183019160400161359a565b600082601f8301126135cb57600080fd5b813560206135db613505836134c1565b82815260059290921b840181019181810190868411156135fa57600080fd5b8286015b8481101561354b5780356001600160401b0381111561361d5760008081fd5b61362b8986838b01016134e4565b8452509183019183016135fe565b6000610180828403121561364c57600080fd5b61365461327d565b905081356001600160401b038082111561366d57600080fd5b613679858386016134e4565b8352602084013591508082111561368f57600080fd5b61369b85838601613556565b602084015260408401359150808211156136b457600080fd5b6136c085838601613556565b60408401526136d28560608601613372565b60608401526136e48560e086016132f2565b60808401526101208401359150808211156136fe57600080fd5b61370a858386016134e4565b60a084015261014084013591508082111561372457600080fd5b613730858386016134e4565b60c084015261016084013591508082111561374a57600080fd5b50613757848285016135ba565b60e08301525092915050565b60008060008060006080868803121561377b57600080fd5b8535945060208601356001600160401b038082111561379957600080fd5b818801915088601f8301126137ad57600080fd5b8135818111156137bc57600080fd5b8960208285010111156137ce57600080fd5b60208301965094506137e2604089016134ad565b935060608801359150808211156137f857600080fd5b5061380588828901613639565b9150509295509295909350565b600081518084526020808501945080840160005b8381101561384b5781516001600160601b031687529582019590820190600101613826565b509495945050505050565b60408152600083516040808401526138716080840182613812565b90506020850151603f1984830301606085015261388e8282613812565b925050508260208301529392505050565b60006001600160401b038311156138b8576138b861323f565b6138cb601f8401601f19166020016132c2565b90508281528383830111156138df57600080fd5b828260208301376000602084830101529392505050565b6000806040838503121561390957600080fd5b823561391481613403565b915060208301356001600160401b038082111561393057600080fd5b908401906060828703121561394457600080fd5b61394c6132a0565b82358281111561395b57600080fd5b83019150601f8201871361396e57600080fd5b61397d8783356020850161389f565b815260208301356020820152604083013560408201528093505050509250929050565b6000602082840312156139b257600080fd5b81356001600160401b038111156139c857600080fd5b8201601f810184136139d957600080fd5b6139e88482356020840161389f565b949350505050565b60008060208385031215613a0357600080fd5b82356001600160401b0380821115613a1a57600080fd5b818501915085601f830112613a2e57600080fd5b813581811115613a3d57600080fd5b8660208260051b8501011115613a5257600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052603260045260246000fd5b600082613a9757634e487b7160e01b600052601260045260246000fd5b500690565b600060208284031215613aae57600080fd5b5051919050565b600060208284031215613ac757600080fd5b81516001600160c01b0381168114612c2c57600080fd5b600060208284031215613af057600080fd5b815160ff81168114612c2c57600080fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115613b2a57613b2a613b01565b500190565b6000600019821415613b4357613b43613b01565b5060010190565b6001600160601b03811681146109db57600080fd5b600060408284031215613b7157600080fd5b613b79613255565b8251613b8481613403565b81526020830151613b9481613b4a565b60208201529392505050565b600060208284031215613bb257600080fd5b8151612c2c81613403565b600082821015613bcf57613bcf613b01565b500390565b600060208284031215613be657600080fd5b815167ffffffffffffffff1981168114612c2c57600080fd5b600060208284031215613c1157600080fd5b8151612c2c81613b4a565b60006001600160601b0383811690831681811015613c3c57613c3c613b01565b039392505050565b63ffffffff60e01b8360e01b1681526000600482018351602080860160005b83811015613c7f57815185529382019390820190600101613c63565b5092979650505050505050565b60208082526052908201527f536572766963654d616e61676572426173652e6f6e6c7952656769737472794360408201527f6f6f7264696e61746f723a2063616c6c6572206973206e6f742074686520726560608201527133b4b9ba393c9031b7b7b93234b730ba37b960711b608082015260a00190565b6000815180845260005b81811015613d2a57602081850181015186830182015201613d0e565b81811115613d3c576000602083870101525b50601f01601f19169290920160200192915050565b60018060a01b0383168152604060208201526000825160606040840152613d7b60a0840182613d04565b90506020840151606084015260408401516080840152809150509392505050565b602081526000613daf6020830184613d04565b9392505050565b60008235609e19833603018112613dcc57600080fd5b9190910192915050565b8035612dda81613403565b600060208284031215613df357600080fd5b8151612c2c81613482565b8183526000602080850194508260005b8581101561384b578135613e2181613403565b6001600160a01b0316875281830135613e3981613b4a565b6001600160601b0316878401526040968701969190910190600101613e0e565b60208082528181018390526000906040808401600586901b8501820187855b88811015613f5857878303603f190184528135368b9003609e19018112613e9e57600080fd5b8a0160a0813536839003601e19018112613eb757600080fd5b820180356001600160401b03811115613ecf57600080fd5b8060061b3603841315613ee157600080fd5b828752613ef3838801828c8501613dfe565b92505050613f02888301613dd6565b6001600160a01b03168886015281870135878601526060613f248184016134ad565b63ffffffff16908601526080613f3b8382016134ad565b63ffffffff16950194909452509285019290850190600101613e78565b509098975050505050505050565b6000816000190483118215151615613f8057613f80613b01565b500290565b600061ffff80831681811415613f9d57613f9d613b01565b600101939250505056fe30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47424c535369676e6174757265436865636b65722e636865636b5369676e617475a2646970667358221220b59868e680a15aa1c784bbfb5f295ed8174b98492f358f820f9596784b47890864736f6c634300080c0033", + "storage": { "0x0": "0xff" } + }, + "0x90f79bf6eb2c4f870365e785982e1f101e93b906": { + "nonce": 5, + "balance": "0x21ea4a7ec1db0e0c24a", + "code": "0x", + "storage": {} + }, + "0x95401dc811bb5740090279ba06cfa8fcf6113778": { + "nonce": 1, + "balance": "0x0", + "code": "0x608060405234801561001057600080fd5b50600436106100b35760003560e01c8063890262451161007157806389026245146101b3578063a48bb0ac146101d3578063bd29b8cd146101e6578063caa3cd76146101f9578063e2e685801461020f578063f34109221461025557600080fd5b8062bff04d146100b857806312d1d74d146100e157806326d941f2146101155780632ed583e51461012a5780636d14a9871461013d5780638121906f1461017c575b600080fd5b6100cb6100c6366004610ebd565b610268565b6040516100d89190610f39565b60405180910390f35b6100f46100ef366004610fad565b61038a565b60408051825163ffffffff16815260209283015192810192909252016100d8565b610128610123366004610fe0565b6103d0565b005b6100f4610138366004610ffb565b6104b4565b6101647f000000000000000000000000c3e53f4d16ae77db1c982e75a937b9f60fe6369081565b6040516001600160a01b0390911681526020016100d8565b61018f61018a366004610fe0565b61053a565b60408051825163ffffffff90811682526020938401511692810192909252016100d8565b6101c66101c1366004610fad565b610581565b6040516100d8919061103e565b61018f6101e1366004610fad565b6106eb565b6101286101f4366004610ebd565b610762565b610201600081565b6040519081526020016100d8565b61024061021d366004611076565b600160209081526000928352604080842090915290825290205463ffffffff1681565b60405163ffffffff90911681526020016100d8565b610240610263366004610fe0565b610830565b606061027261084f565b60008267ffffffffffffffff81111561028d5761028d6110a0565b6040519080825280602002602001820160405280156102b6578160200160208202803683370190505b50905060005b8381101561037f5760008585838181106102d8576102d86110b6565b919091013560f81c60008181526003602052604090205490925090508061031a5760405162461bcd60e51b8152600401610311906110cc565b60405180910390fd5b600061032583610905565b905061033c8984610337600185611137565b6109fe565b8085858151811061034f5761034f6110b6565b602002602001019063ffffffff16908163ffffffff168152505050505080806103779061115c565b9150506102bc565b5090505b9392505050565b60408051808201909152600080825260208201526103a88383610a88565b60408051808201909152815463ffffffff168152600190910154602082015290505b92915050565b6103d861084f565b60ff8116600090815260036020526040902054156104525760405162461bcd60e51b815260206004820152603160248201527f496e64657852656769737472792e63726561746551756f72756d3a2071756f72604482015270756d20616c72656164792065786973747360781b6064820152608401610311565b60ff166000908152600360209081526040808320815180830190925263ffffffff438116835282840185815282546001810184559286529390942091519101805492518416600160201b0267ffffffffffffffff199093169190931617179055565b604080518082019091526000808252602082015260ff8416600090815260026020908152604080832063ffffffff80881685529252909120805490918416908110610501576105016110b6565b600091825260209182902060408051808201909152600290920201805463ffffffff168252600101549181019190915290509392505050565b604080518082019091526000808252602082015261055782610ae0565b60408051808201909152905463ffffffff8082168352600160201b90910416602082015292915050565b6060600061058f8484610b22565b905060008163ffffffff1667ffffffffffffffff8111156105b2576105b26110a0565b6040519080825280602002602001820160405280156105db578160200160208202803683370190505b50905060005b8263ffffffff168110156106e2576105fa868287610c57565b82828151811061060c5761060c6110b6565b6020026020010181815250506000801b82828151811061062e5761062e6110b6565b602002602001015114156106d05760405162461bcd60e51b815260206004820152605d60248201527f496e64657852656769737472792e6765744f70657261746f724c69737441744260448201527f6c6f636b4e756d6265723a206f70657261746f7220646f6573206e6f7420657860648201527f6973742061742074686520676976656e20626c6f636b206e756d626572000000608482015260a401610311565b806106da8161115c565b9150506105e1565b50949350505050565b604080518082019091526000808252602082015260ff83166000908152600360205260409020805463ffffffff8416908110610729576107296110b6565b60009182526020918290206040805180820190915291015463ffffffff8082168352600160201b90910416918101919091529392505050565b61076a61084f565b60005b8181101561082a576000838383818110610789576107896110b6565b919091013560f81c6000818152600360205260409020549092509050806107c25760405162461bcd60e51b8152600401610311906110cc565b60ff8216600090815260016020908152604080832089845290915281205463ffffffff16906107f084610d2e565b905060006107fe8583610d68565b9050808914610812576108128186856109fe565b505050505080806108229061115c565b91505061076d565b50505050565b600061083b82610ae0565b54600160201b900463ffffffff1692915050565b336001600160a01b037f000000000000000000000000c3e53f4d16ae77db1c982e75a937b9f60fe6369016146109035760405162461bcd60e51b815260206004820152604d60248201527f496e64657852656769737472792e6f6e6c795265676973747279436f6f72646960448201527f6e61746f723a2063616c6c6572206973206e6f7420746865207265676973747260648201526c3c9031b7b7b93234b730ba37b960991b608482015260a401610311565b565b60008061091183610ae0565b805490915060009061093190600160201b900463ffffffff166001611177565b905061093e848383610d92565b60ff841660009081526002602052604081209061095c600184611137565b63ffffffff1681526020810191909152604001600020546103835760ff8416600090815260026020526040812090610995600184611137565b63ffffffff908116825260208083019390935260409182016000908120835180850190945243831684528385018281528154600180820184559284529590922093516002909502909301805463ffffffff19169490921693909317815591519101559392505050565b6000610a0a8383610a88565b9050610a1883838387610e32565b60ff83166000818152600160209081526040808320888452825291829020805463ffffffff191663ffffffff871690811790915582519384529083015285917f6ee1e4f4075f3d067176140d34e87874244dd273294c05b2218133e49a2ba6f6910160405180910390a250505050565b60ff8216600090815260026020908152604080832063ffffffff851684529091528120805490610ab960018361119f565b81548110610ac957610ac96110b6565b906000526020600020906002020191505092915050565b60ff81166000908152600360205260408120805490610b0060018361119f565b81548110610b1057610b106110b6565b90600052602060002001915050919050565b60ff8216600090815260036020526040812054805b8015610bca5760ff85166000908152600360205260408120610b5a60018461119f565b81548110610b6a57610b6a6110b6565b60009182526020918290206040805180820190915291015463ffffffff808216808452600160201b90920481169383019390935290925090861610610bb7576020015192506103ca915050565b5080610bc2816111b6565b915050610b37565b5060405162461bcd60e51b815260206004820152605560248201527f496e64657852656769737472792e5f6f70657261746f72436f756e744174426c60448201527f6f636b4e756d6265723a2071756f72756d20646964206e6f742065786973742060648201527430ba1033b4bb32b710313637b1b590373ab6b132b960591b608482015260a401610311565b60ff8316600090815260026020908152604080832063ffffffff86168452909152812054805b8015610d225760ff8616600090815260026020908152604080832063ffffffff891684529091528120610cb160018461119f565b81548110610cc157610cc16110b6565b600091825260209182902060408051808201909152600290920201805463ffffffff9081168084526001909201549383019390935290925090861610610d0f57602001519250610383915050565b5080610d1a816111b6565b915050610c7d565b50600095945050505050565b600080610d3a83610ae0565b8054909150600090610d5b90600190600160201b900463ffffffff16611137565b9050610383848383610d92565b600080610d758484610a88565b6001810154909150610d8a8585846000610e32565b949350505050565b81544363ffffffff90811691161415610dc957815463ffffffff8216600160201b0267ffffffff0000000019909116178255505050565b60ff83166000908152600360209081526040808320815180830190925263ffffffff438116835285811683850190815282546001810184559286529390942091519101805492518416600160201b0267ffffffffffffffff199093169190931617179055505050565b81544363ffffffff90811691161415610e51576001820181905561082a565b60ff93909316600090815260026020818152604080842063ffffffff968716855282528084208151808301909252438716825281830197885280546001808201835591865292909420905191909202909101805463ffffffff1916919094161783559251919092015550565b600080600060408486031215610ed257600080fd5b83359250602084013567ffffffffffffffff80821115610ef157600080fd5b818601915086601f830112610f0557600080fd5b813581811115610f1457600080fd5b876020828501011115610f2657600080fd5b6020830194508093505050509250925092565b6020808252825182820181905260009190848201906040850190845b81811015610f7757835163ffffffff1683529284019291840191600101610f55565b50909695505050505050565b803560ff81168114610f9457600080fd5b919050565b803563ffffffff81168114610f9457600080fd5b60008060408385031215610fc057600080fd5b610fc983610f83565b9150610fd760208401610f99565b90509250929050565b600060208284031215610ff257600080fd5b61038382610f83565b60008060006060848603121561101057600080fd5b61101984610f83565b925061102760208501610f99565b915061103560408501610f99565b90509250925092565b6020808252825182820181905260009190848201906040850190845b81811015610f775783518352928401929184019160010161105a565b6000806040838503121561108957600080fd5b61109283610f83565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60208082526035908201527f496e64657852656769737472792e72656769737465724f70657261746f723a206040820152741c5d5bdc9d5b48191bd95cc81b9bdd08195e1a5cdd605a1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b600063ffffffff8381169083168181101561115457611154611121565b039392505050565b600060001982141561117057611170611121565b5060010190565b600063ffffffff80831681851680830382111561119657611196611121565b01949350505050565b6000828210156111b1576111b1611121565b500390565b6000816111c5576111c5611121565b50600019019056fea2646970667358221220d9ac5617116cfbb63575c4c57546782d46bd85fd038b854bc7ca94d3631689ba64736f6c634300080c0033", + "storage": { "0x0": "0xff" } + }, + "0x959922be3caee4b8cd9a407cc3ac1c251c2007b1": { + "nonce": 1, + "balance": "0x0", + "code": "0x6080604052600436106101ee5760003560e01c80638da5cb5b1161010d578063c052bd61116100a0578063d1c64cc91161006f578063d1c64cc914610604578063ea4d3c9b14610624578063f2fde38b14610658578063f6848d2414610678578063fabc1cbc146106b357600080fd5b8063c052bd6114610584578063c1de3aef146105a4578063c2c51c40146105c4578063cf756fdf146105e457600080fd5b8063a38406a3116100dc578063a38406a3146104fa578063a6a509be1461051a578063b134427114610530578063beffbb891461056457600080fd5b80638da5cb5b1461046b5780639104c319146104895780639b4e4634146104b15780639ba06275146104c457600080fd5b8063595c6a6711610185578063715018a611610154578063715018a6146103ed57806374cdd7981461040257806384d8106214610436578063886f11951461044b57600080fd5b8063595c6a67146103565780635ac86ab71461036b5780635c975abb146103ab57806360f4062b146103c057600080fd5b8063387b1300116101c1578063387b1300146102b457806339b70e38146102d457806344e71c8014610308578063463db0381461033657600080fd5b80630e81073c146101f357806310d67a2f14610226578063136439dd14610248578063292b7b2b14610268575b600080fd5b3480156101ff57600080fd5b5061021361020e366004612406565b6106d3565b6040519081526020015b60405180910390f35b34801561023257600080fd5b50610246610241366004612432565b610911565b005b34801561025457600080fd5b5061024661026336600461244f565b6109c4565b34801561027457600080fd5b5061029c7f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e81565b6040516001600160a01b03909116815260200161021d565b3480156102c057600080fd5b506102466102cf366004612468565b610b03565b3480156102e057600080fd5b5061029c7f0000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f87570781565b34801561031457600080fd5b5061031d610ea1565b60405167ffffffffffffffff909116815260200161021d565b34801561034257600080fd5b506102466103513660046124a9565b610eca565b34801561036257600080fd5b50610246611056565b34801561037757600080fd5b5061039b6103863660046124d3565b606654600160ff9092169190911b9081161490565b604051901515815260200161021d565b3480156103b757600080fd5b50606654610213565b3480156103cc57600080fd5b506102136103db366004612432565b609b6020526000908152604090205481565b3480156103f957600080fd5b5061024661111d565b34801561040e57600080fd5b5061029c7f00000000000000000000000000000000219ab540356cbb839cbe05303d7705fa81565b34801561044257600080fd5b5061029c611131565b34801561045757600080fd5b5060655461029c906001600160a01b031681565b34801561047757600080fd5b506033546001600160a01b031661029c565b34801561049557600080fd5b5061029c73beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac081565b6102466104bf36600461253f565b61121b565b3480156104d057600080fd5b5061029c6104df366004612432565b6098602052600090815260409020546001600160a01b031681565b34801561050657600080fd5b5061029c610515366004612432565b61130a565b34801561052657600080fd5b5061021360995481565b34801561053c57600080fd5b5061029c7f000000000000000000000000a513e6e4b8f2a923d98304ec87f64353c4d5c85381565b34801561057057600080fd5b5061024661057f366004612406565b6113dc565b34801561059057600080fd5b5060975461029c906001600160a01b031681565b3480156105b057600080fd5b506102466105bf366004612432565b6115f3565b3480156105d057600080fd5b506102466105df366004612406565b611604565b3480156105f057600080fd5b506102466105ff3660046125b3565b611a07565b34801561061057600080fd5b5061021361061f3660046124a9565b611b30565b34801561063057600080fd5b5061029c7f000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c981565b34801561066457600080fd5b50610246610673366004612432565b611c3b565b34801561068457600080fd5b5061039b610693366004612432565b6001600160a01b0390811660009081526098602052604090205416151590565b3480156106bf57600080fd5b506102466106ce36600461244f565b611cb1565b6000336001600160a01b037f000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c916146107265760405162461bcd60e51b815260040161071d90612604565b60405180910390fd5b6001600160a01b0383166107a25760405162461bcd60e51b815260206004820152603a60248201527f456967656e506f644d616e616765722e6164645368617265733a20706f644f7760448201527f6e65722063616e6e6f74206265207a65726f2061646472657373000000000000606482015260840161071d565b60008212156108105760405162461bcd60e51b815260206004820152603460248201527f456967656e506f644d616e616765722e6164645368617265733a207368617265604482015273732063616e6e6f74206265206e6567617469766560601b606482015260840161071d565b61081e633b9aca0083612678565b156108915760405162461bcd60e51b815260206004820152603d60248201527f456967656e506f644d616e616765722e6164645368617265733a20736861726560448201527f73206d75737420626520612077686f6c65204777656920616d6f756e74000000606482015260840161071d565b6001600160a01b0383166000908152609b6020526040812054906108b584836126a2565b6001600160a01b0386166000818152609b6020526040908190208390555191925090600080516020613231833981519152906108f49087815260200190565b60405180910390a26109068282611e0d565b925050505b92915050565b606560009054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610964573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098891906126e3565b6001600160a01b0316336001600160a01b0316146109b85760405162461bcd60e51b815260040161071d90612700565b6109c181611e4f565b50565b60655460405163237dfb4760e11b81523360048201526001600160a01b03909116906346fbf68e90602401602060405180830381865afa158015610a0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a30919061274a565b610a4c5760405162461bcd60e51b815260040161071d9061276c565b60665481811614610ac55760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e70617573653a20696e76616c696420617474656d70742060448201527f746f20756e70617573652066756e6374696f6e616c6974790000000000000000606482015260840161071d565b606681905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d906020015b60405180910390a250565b336001600160a01b037f000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c91614610b4b5760405162461bcd60e51b815260040161071d90612604565b6001600160a01b038316610bc55760405162461bcd60e51b8152602060048201526047602482015260008051602061325183398151915260448201527f546f6b656e733a20706f644f776e65722063616e6e6f74206265207a65726f206064820152666164647265737360c81b608482015260a40161071d565b6001600160a01b038216610c425760405162461bcd60e51b815260206004820152604a602482015260008051602061325183398151915260448201527f546f6b656e733a2064657374696e6174696f6e2063616e6e6f74206265207a65606482015269726f206164647265737360b01b608482015260a40161071d565b6000811215610cb15760405162461bcd60e51b8152602060048201526041602482015260008051602061325183398151915260448201527f546f6b656e733a207368617265732063616e6e6f74206265206e6567617469766064820152606560f81b608482015260a40161071d565b610cbf633b9aca0082612678565b15610d335760405162461bcd60e51b815260206004820152604a602482015260008051602061325183398151915260448201527f546f6b656e733a20736861726573206d75737420626520612077686f6c6520476064820152691dd95a48185b5bdd5b9d60b21b608482015260a40161071d565b6001600160a01b0383166000908152609b602052604081205490811215610e26576000610d5f826127b4565b905080831115610dc4576001600160a01b0385166000908152609b6020526040812055610d8c81846127d1565b9250846001600160a01b031660008051602061323183398151915282604051610db791815260200190565b60405180910390a2610e24565b6001600160a01b0385166000908152609b602052604081208054859290610dec9084906126a2565b90915550506040518381526001600160a01b038616906000805160206132318339815191529060200160405180910390a25050505050565b505b6001600160a01b03848116600090815260986020526040908190205490516362483a2160e11b815285831660048201526024810185905291169063c490744290604401600060405180830381600087803b158015610e8357600080fd5b505af1158015610e97573d6000803e3d6000fd5b5050505050505050565b609c5460009067ffffffffffffffff1680610ec55767ffffffffffffffff91505090565b919050565b610ed2611f46565b67ffffffffffffffff8116610f645760405162461bcd60e51b815260206004820152604c60248201527f456967656e506f644d616e616765722e73657444656e6562466f726b54696d6560448201527f7374616d703a2063616e6e6f7420736574206e657744656e6562466f726b546960648201526b06d657374616d7020746f20360a41b608482015260a40161071d565b609c5467ffffffffffffffff16156110005760405162461bcd60e51b815260206004820152605360248201527f456967656e506f644d616e616765722e73657444656e6562466f726b54696d6560448201527f7374616d703a2063616e6e6f74207365742064656e6562466f726b54696d657360648201527274616d70206d6f7265207468616e206f6e636560681b608482015260a40161071d565b609c805467ffffffffffffffff191667ffffffffffffffff83169081179091556040519081527f19200b6fdad58f91b2f496b0c444fc4be3eff74a7e24b07770e04a7137bfd9db9060200160405180910390a150565b60655460405163237dfb4760e11b81523360048201526001600160a01b03909116906346fbf68e90602401602060405180830381865afa15801561109e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110c2919061274a565b6110de5760405162461bcd60e51b815260040161071d9061276c565b600019606681905560405190815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a2565b611125611f46565b61112f6000611fa0565b565b6066546000908190600190811614156111885760405162461bcd60e51b815260206004820152601960248201527814185d5cd8589b194e881a5b99195e081a5cc81c185d5cd959603a1b604482015260640161071d565b336000908152609860205260409020546001600160a01b03161561120a5760405162461bcd60e51b815260206004820152603360248201527f456967656e506f644d616e616765722e637265617465506f643a2053656e64656044820152721c88185b1c9958591e481a185cc818481c1bd9606a1b606482015260840161071d565b6000611214611ff2565b9250505090565b606654600090600190811614156112705760405162461bcd60e51b815260206004820152601960248201527814185d5cd8589b194e881a5b99195e081a5cc81c185d5cd959603a1b604482015260640161071d565b336000908152609860205260409020546001600160a01b03168061129957611296611ff2565b90505b6040516326d3918d60e21b81526001600160a01b03821690639b4e46349034906112cf908b908b908b908b908b90600401612811565b6000604051808303818588803b1580156112e857600080fd5b505af11580156112fc573d6000803e3d6000fd5b505050505050505050505050565b6001600160a01b038082166000908152609860205260408120549091168061090b576113d5836001600160a01b031660001b60405180610940016040528061090e815260200161292361090e9139604080516001600160a01b037f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e166020820152808201919091526000606082015260800160408051601f19818403018152908290526113ba9291602001612886565b60405160208183030381529060405280519060200120612157565b9392505050565b336001600160a01b037f000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c916146114245760405162461bcd60e51b815260040161071d90612604565b600081121561149b5760405162461bcd60e51b815260206004820152603760248201527f456967656e506f644d616e616765722e72656d6f76655368617265733a20736860448201527f617265732063616e6e6f74206265206e65676174697665000000000000000000606482015260840161071d565b6114a9633b9aca0082612678565b1561151e576040805162461bcd60e51b81526020600482015260248101919091527f456967656e506f644d616e616765722e72656d6f76655368617265733a20736860448201527f61726573206d75737420626520612077686f6c65204777656920616d6f756e74606482015260840161071d565b6001600160a01b0382166000908152609b602052604081205461154290839061289b565b905060008112156115d35760405162461bcd60e51b815260206004820152604f60248201527f456967656e506f644d616e616765722e72656d6f76655368617265733a20636160448201527f6e6e6f7420726573756c7420696e20706f64206f776e657220686176696e672060648201526e6e656761746976652073686172657360881b608482015260a40161071d565b6001600160a01b039092166000908152609b602052604090209190915550565b6115fb611f46565b6109c1816121b3565b6001600160a01b03808316600090815260986020526040902054839116331461167f5760405162461bcd60e51b815260206004820152602760248201527f456967656e506f644d616e616765722e6f6e6c79456967656e506f643a206e6f6044820152661d0818481c1bd960ca1b606482015260840161071d565b600260c95414156116d25760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161071d565b600260c9556001600160a01b03831661176e5760405162461bcd60e51b815260206004820152605260248201527f456967656e506f644d616e616765722e7265636f7264426561636f6e4368616960448201527f6e45544842616c616e63655570646174653a20706f644f776e65722063616e6e6064820152716f74206265207a65726f206164647265737360701b608482015260a40161071d565b61177c633b9aca00836128da565b156118155760405162461bcd60e51b815260206004820152605a60248201527f456967656e506f644d616e616765722e7265636f7264426561636f6e4368616960448201527f6e45544842616c616e63655570646174653a2073686172657344656c7461206d60648201527f75737420626520612077686f6c65204777656920616d6f756e74000000000000608482015260a40161071d565b6001600160a01b0383166000908152609b60205260408120549061183984836126a2565b6001600160a01b0386166000908152609b602052604081208290559091506118618383611e0d565b905080156119c957600081121561192c576001600160a01b037f000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c91663132d49678773beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac06118c0856127b4565b6040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401600060405180830381600087803b15801561190f57600080fd5b505af1158015611923573d6000803e3d6000fd5b505050506119c9565b604051631452b9d760e11b81526001600160a01b03878116600483015273beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac06024830152604482018390527f000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c916906328a573ae90606401600060405180830381600087803b1580156119b057600080fd5b505af11580156119c4573d6000803e3d6000fd5b505050505b856001600160a01b0316600080516020613231833981519152866040516119f291815260200190565b60405180910390a25050600160c95550505050565b600054610100900460ff1615808015611a275750600054600160ff909116105b80611a415750303b158015611a41575060005460ff166001145b611aa45760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161071d565b6000805460ff191660011790558015611ac7576000805461ff0019166101001790555b611ad0856121b3565b611ad984611fa0565b611ae383836121fd565b8015611b29576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b60975460405163321accf960e11b815267ffffffffffffffff8316600482015260009182916001600160a01b039091169063643599f290602401602060405180830381865afa158015611b87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bab91906128ee565b90508061090b5760405162461bcd60e51b815260206004820152605260248201527f456967656e506f644d616e616765722e676574426c6f636b526f6f744174546960448201527f6d657374616d703a20737461746520726f6f742061742074696d657374616d70606482015271081b9bdd081e595d08199a5b985b1a5e995960721b608482015260a40161071d565b611c43611f46565b6001600160a01b038116611ca85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161071d565b6109c181611fa0565b606560009054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d2891906126e3565b6001600160a01b0316336001600160a01b031614611d585760405162461bcd60e51b815260040161071d90612700565b606654198119606654191614611dd65760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e756e70617573653a20696e76616c696420617474656d7060448201527f7420746f2070617573652066756e6374696f6e616c6974790000000000000000606482015260840161071d565b606681905560405181815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c90602001610af8565b6000808313611e2d5760008213611e265750600061090b565b508061090b565b60008213611e4557611e3e836127b4565b905061090b565b611e3e838361289b565b6001600160a01b038116611edd5760405162461bcd60e51b815260206004820152604960248201527f5061757361626c652e5f73657450617573657252656769737472793a206e657760448201527f50617573657252656769737472792063616e6e6f7420626520746865207a65726064820152686f206164647265737360b81b608482015260a40161071d565b606554604080516001600160a01b03928316815291831660208301527f6e9fcd539896fca60e8b0f01dd580233e48a6b0f7df013b89ba7f565869acdb6910160405180910390a1606580546001600160a01b0319166001600160a01b0392909216919091179055565b6033546001600160a01b0316331461112f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161071d565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600060996000815461200390612907565b9091555060408051610940810190915261090e8082526000916120a291839133916129236020830139604080516001600160a01b037f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e166020820152808201919091526000606082015260800160408051601f198184030181529082905261208e9291602001612886565b6040516020818303038152906040526122e7565b60405163189acdbd60e31b81523360048201529091506001600160a01b0382169063c4d66de890602401600060405180830381600087803b1580156120e657600080fd5b505af11580156120fa573d6000803e3d6000fd5b50503360008181526098602052604080822080546001600160a01b0319166001600160a01b038816908117909155905192945092507f21c99d0db02213c32fff5b05cf0a718ab5f858802b91498f80d82270289d856a91a3919050565b604080516001600160f81b03196020808301919091526bffffffffffffffffffffffff193060601b16602183015260358201859052605580830185905283518084039091018152607590920190925280519101206000906113d5565b609780546001600160a01b0319166001600160a01b0383169081179091556040517f08f0470754946ccfbb446ff7fd2d6ae6af1bbdae19f85794c0cc5ed5e8ceb4f690600090a250565b6065546001600160a01b031615801561221e57506001600160a01b03821615155b6122a05760405162461bcd60e51b815260206004820152604760248201527f5061757361626c652e5f696e697469616c697a655061757365723a205f696e6960448201527f7469616c697a6550617573657228292063616e206f6e6c792062652063616c6c6064820152666564206f6e636560c81b608482015260a40161071d565b606681905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a26122e382611e4f565b5050565b6000808447101561233a5760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e6365000000604482015260640161071d565b82516123885760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f604482015260640161071d565b8383516020850187f590506001600160a01b0381166123e95760405162461bcd60e51b815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f7900000000000000604482015260640161071d565b949350505050565b6001600160a01b03811681146109c157600080fd5b6000806040838503121561241957600080fd5b8235612424816123f1565b946020939093013593505050565b60006020828403121561244457600080fd5b81356113d5816123f1565b60006020828403121561246157600080fd5b5035919050565b60008060006060848603121561247d57600080fd5b8335612488816123f1565b92506020840135612498816123f1565b929592945050506040919091013590565b6000602082840312156124bb57600080fd5b813567ffffffffffffffff811681146113d557600080fd5b6000602082840312156124e557600080fd5b813560ff811681146113d557600080fd5b60008083601f84011261250857600080fd5b50813567ffffffffffffffff81111561252057600080fd5b60208301915083602082850101111561253857600080fd5b9250929050565b60008060008060006060868803121561255757600080fd5b853567ffffffffffffffff8082111561256f57600080fd5b61257b89838a016124f6565b9097509550602088013591508082111561259457600080fd5b506125a1888289016124f6565b96999598509660400135949350505050565b600080600080608085870312156125c957600080fd5b84356125d4816123f1565b935060208501356125e4816123f1565b925060408501356125f4816123f1565b9396929550929360600135925050565b602080825260409082018190527f456967656e506f644d616e616765722e6f6e6c7944656c65676174696f6e4d61908201527f6e616765723a206e6f74207468652044656c65676174696f6e4d616e61676572606082015260800190565b634e487b7160e01b600052601260045260246000fd5b60008261268757612687612662565b500690565b634e487b7160e01b600052601160045260246000fd5b600080821280156001600160ff1b03849003851316156126c4576126c461268c565b600160ff1b83900384128116156126dd576126dd61268c565b50500190565b6000602082840312156126f557600080fd5b81516113d5816123f1565b6020808252602a908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526939903ab73830bab9b2b960b11b606082015260800190565b60006020828403121561275c57600080fd5b815180151581146113d557600080fd5b60208082526028908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526739903830bab9b2b960c11b606082015260800190565b6000600160ff1b8214156127ca576127ca61268c565b5060000390565b6000828210156127e3576127e361268c565b500390565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6060815260006128256060830187896127e8565b82810360208401526128388186886127e8565b9150508260408301529695505050505050565b6000815160005b8181101561286c5760208185018101518683015201612852565b8181111561287b576000828601525b509290920192915050565b60006123e9612895838661284b565b8461284b565b60008083128015600160ff1b8501841216156128b9576128b961268c565b6001600160ff1b03840183138116156128d4576128d461268c565b50500390565b6000826128e9576128e9612662565b500790565b60006020828403121561290057600080fd5b5051919050565b600060001982141561291b5761291b61268c565b506001019056fe608060405260405161090e38038061090e83398101604081905261002291610460565b61002e82826000610035565b505061058a565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610520565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610520565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108e7602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053b565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c65782516103bf576001600160a01b0385163b6103bf5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d0565b6103d083836103d8565b949350505050565b8151156103e85781518083602001fd5b8060405162461bcd60e51b81526004016101699190610557565b80516001600160a01b038116811461041957600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561044f578181015183820152602001610437565b838111156100f95750506000910152565b6000806040838503121561047357600080fd5b61047c83610402565b60208401519092506001600160401b038082111561049957600080fd5b818501915085601f8301126104ad57600080fd5b8151818111156104bf576104bf61041e565b604051601f8201601f19908116603f011681019083821181831017156104e7576104e761041e565b8160405282815288602084870101111561050057600080fd5b610511836020830160208801610434565b80955050505050509250929050565b60006020828403121561053257600080fd5b6102c882610402565b6000825161054d818460208701610434565b9190910192915050565b6020815260008251806020840152610576816040850160208701610434565b601f01601f19169190910160400192915050565b61034e806105996000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f260279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb9190610249565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a2565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b6060831561020d578251610206576001600160a01b0385163b6102065760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b5081610217565b610217838361021f565b949350505050565b81511561022f5781518083602001fd5b8060405162461bcd60e51b81526004016101fd91906102be565b60006020828403121561025b57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b8381101561028d578181015183820152602001610275565b8381111561029c576000848401525b50505050565b600082516102b4818460208701610272565b9190910192915050565b60208152600082518060208401526102dd816040850160208701610272565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220d51e81d3bc5ed20a26aeb05dce7e825c503b2061aa78628027300c8d65b9d89a64736f6c634300080c0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c65644e2b791dedccd9fb30141b088cabf5c14a8912b52f59375c95c010700b8c6193456967656e506f644d616e616765722e77697468647261775368617265734173a2646970667358221220c3e56c4b90c61abc2a2fe644fe1a2416e8b8ebb2c3245a3990964aab6923867664736f6c634300080c0033", + "storage": { "0x0": "0xff" } + }, + "0x976ea74026e726554db657fa54763abd0c3a0aa9": { + "nonce": 5, + "balance": "0x21ea4a7ec8e289b4553", + "code": "0x", + "storage": {} + }, + "0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc": { + "nonce": 5, + "balance": "0x21ea4a7ec763b65b4b9", + "code": "0x", + "storage": {} + }, + "0x99bba657f2bbc93c02d617f8ba121cb8fc104acf": { + "nonce": 1, + "balance": "0x0", + "code": "0x608060405234801561001057600080fd5b50600436106102d55760003560e01c80635df45946116101825780639feab859116100e9578063d72d8dd6116100a2578063e65797ad1161007c578063e65797ad14610798578063f2fde38b1461083b578063fabc1cbc1461084e578063fd39105a1461086157600080fd5b8063d72d8dd61461076a578063d75b4c8814610772578063dd8283f31461078557600080fd5b80639feab859146106cd578063a50857bf146106f4578063a96f783e14610707578063c391425e14610710578063ca0de88214610730578063ca4f2d971461075757600080fd5b8063871ef0491161013b578063871ef04914610640578063886f1195146106535780638da5cb5b1461066c5780639aa1653d146106745780639b5d177b146106935780639e9923c2146106a657600080fd5b80635df45946146105b15780636347c900146105d857806368304835146105eb5780636e3b17db14610612578063715018a61461062557806384ca52131461062d57600080fd5b8063249a0c42116102415780633c2a7f4c116101fa578063595c6a67116101d4578063595c6a671461056f5780635ac86ab7146105775780635b0b829f146105965780635c975abb146105a957600080fd5b80633c2a7f4c1461051c5780635140a5481461053c5780635865c60c1461054f57600080fd5b8063249a0c421461048957806328f61b31146104a9578063296bb064146104bc57806329d1e0c3146104cf5780632cdd1e86146104e25780633998fdd3146104f557600080fd5b806310d67a2f1161029357806310d67a2f1461039e578063125e0584146103b157806313542a4e146103d1578063136439dd146103fa5780631478851f1461040d5780631eb812da1461044057600080fd5b8062cf2ab5146102da57806303fd3492146102ef57806304ec635114610322578063054310e61461034d5780630cf4b767146103785780630d3f21341461038b575b600080fd5b6102ed6102e8366004614ac7565b61089d565b005b61030f6102fd366004614b08565b60009081526098602052604090205490565b6040519081526020015b60405180910390f35b610335610330366004614b33565b6109b3565b6040516001600160c01b039091168152602001610319565b609d54610360906001600160a01b031681565b6040516001600160a01b039091168152602001610319565b6102ed610386366004614c52565b610ba9565b6102ed610399366004614b08565b610c91565b6102ed6103ac366004614cc7565b610c9e565b61030f6103bf366004614cc7565b609f6020526000908152604090205481565b61030f6103df366004614cc7565b6001600160a01b031660009081526099602052604090205490565b6102ed610408366004614b08565b610d51565b61043061041b366004614b08565b609a6020526000908152604090205460ff1681565b6040519015158152602001610319565b61045361044e366004614ce4565b610e8e565b60408051825163ffffffff908116825260208085015190911690820152918101516001600160c01b031690820152606001610319565b61030f610497366004614d17565b609b6020526000908152604090205481565b609e54610360906001600160a01b031681565b6103606104ca366004614b08565b610f1f565b6102ed6104dd366004614cc7565b610fab565b6102ed6104f0366004614cc7565b610fbc565b6103607f00000000000000000000000067d269191c92caf3cd7723f116c85e6e9bf5593381565b61052f61052a366004614cc7565b610fcd565b6040516103199190614d32565b6102ed61054a366004614d8a565b61104c565b61056261055d366004614cc7565b61155d565b6040516103199190614e2d565b6102ed6115d1565b610430610585366004614d17565b6001805460ff9092161b9081161490565b6102ed6105a4366004614eb2565b61169d565b60015461030f565b6103607f00000000000000000000000084ea74d481ee0a5332c457a4d796187f6ba67feb81565b6103606105e6366004614b08565b6116be565b6103607f000000000000000000000000a82ff9afd8f496c3d6ac40e2a0f282e47488cfc981565b6102ed610620366004614ee6565b6116e8565b6102ed6117fe565b61030f61063b366004614f9d565b611812565b61033561064e366004614b08565b61185c565b600054610360906201000090046001600160a01b031681565b610360611867565b6096546106819060ff1681565b60405160ff9091168152602001610319565b6102ed6106a1366004615136565b611880565b6103607f0000000000000000000000009e545e3c0baab3e08cdfd552c960a1050f37304281565b61030f7f2bd82124057f0913bc3b772ce7b83e8057c1ad1f3510fc83778be20f10ec5de681565b6102ed61070236600461522f565b611bb8565b61030f60a05481565b61072361071e3660046152d7565b611d3c565b604051610319919061537c565b61030f7f4d404e3276e7ac2163d8ee476afa6a41d1f68fb71f2d8b6546b24e55ce01b72a81565b6102ed6107653660046153c6565b611df5565b609c5461030f565b6102ed6107803660046154ac565b611e5c565b6102ed61079336600461565f565b611e6f565b6108076107a6366004614d17565b60408051606080820183526000808352602080840182905292840181905260ff9490941684526097825292829020825193840183525463ffffffff8116845261ffff600160201b8204811692850192909252600160301b9004169082015290565b60408051825163ffffffff16815260208084015161ffff908116918301919091529282015190921690820152606001610319565b6102ed610849366004614cc7565b612173565b6102ed61085c366004614b08565b6121e9565b61089061086f366004614cc7565b6001600160a01b031660009081526099602052604090206001015460ff1690565b6040516103199190615733565b600154600290600490811614156108cf5760405162461bcd60e51b81526004016108c690615741565b60405180910390fd5b60005b828110156109ad5760008484838181106108ee576108ee615778565b90506020020160208101906109039190614cc7565b6001600160a01b03811660009081526099602090815260408083208151808301909252805482526001810154949550929390929183019060ff16600281111561094e5761094e614df5565b600281111561095f5761095f614df5565b9052508051909150600061097282612345565b90506000610988826001600160c01b03166123ae565b905061099585858361247a565b505050505080806109a5906157a4565b9150506108d2565b50505050565b60008381526098602052604081208054829190849081106109d6576109d6615778565b600091825260209182902060408051606081018252929091015463ffffffff808216808552600160201b8304821695850195909552600160401b9091046001600160c01b03169183019190915290925085161015610ad05760405162461bcd60e51b815260206004820152606560248201527f5265676973747279436f6f7264696e61746f722e67657451756f72756d42697460448201527f6d61704174426c6f636b4e756d6265724279496e6465783a2071756f72756d4260648201527f69746d61705570646174652069732066726f6d20616674657220626c6f636b4e6084820152643ab6b132b960d91b60a482015260c4016108c6565b602081015163ffffffff161580610af65750806020015163ffffffff168463ffffffff16105b610b9d5760405162461bcd60e51b815260206004820152606660248201527f5265676973747279436f6f7264696e61746f722e67657451756f72756d42697460448201527f6d61704174426c6f636b4e756d6265724279496e6465783a2071756f72756d4260648201527f69746d61705570646174652069732066726f6d206265666f726520626c6f636b608482015265273ab6b132b960d11b60a482015260c4016108c6565b60400151949350505050565b60013360009081526099602052604090206001015460ff166002811115610bd257610bd2614df5565b14610c455760405162461bcd60e51b815260206004820152603c60248201527f5265676973747279436f6f7264696e61746f722e757064617465536f636b657460448201527f3a206f70657261746f72206973206e6f7420726567697374657265640000000060648201526084016108c6565b33600090815260996020526040908190205490517fec2963ab21c1e50e1e582aa542af2e4bf7bf38e6e1403c27b42e1c5d6e621eaa90610c8690849061580c565b60405180910390a250565b610c99612567565b60a055565b600060029054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cf1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d15919061581f565b6001600160a01b0316336001600160a01b031614610d455760405162461bcd60e51b81526004016108c69061583c565b610d4e816125c6565b50565b60005460405163237dfb4760e11b8152336004820152620100009091046001600160a01b0316906346fbf68e90602401602060405180830381865afa158015610d9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc29190615886565b610dde5760405162461bcd60e51b81526004016108c6906158a8565b60015481811614610e575760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e70617573653a20696e76616c696420617474656d70742060448201527f746f20756e70617573652066756e6374696f6e616c697479000000000000000060648201526084016108c6565b600181905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d90602001610c86565b60408051606081018252600080825260208201819052918101919091526000838152609860205260409020805483908110610ecb57610ecb615778565b600091825260209182902060408051606081018252919092015463ffffffff8082168352600160201b820416938201939093526001600160c01b03600160401b909304929092169082015290505b92915050565b6040516308f6629d60e31b8152600481018290526000907f00000000000000000000000084ea74d481ee0a5332c457a4d796187f6ba67feb6001600160a01b0316906347b314e890602401602060405180830381865afa158015610f87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f19919061581f565b610fb3612567565b610d4e816126cb565b610fc4612567565b610d4e81612734565b6040805180820190915260008082526020820152610f196110477f2bd82124057f0913bc3b772ce7b83e8057c1ad1f3510fc83778be20f10ec5de68460405160200161102c9291909182526001600160a01b0316602082015260400190565b6040516020818303038152906040528051906020012061279d565b6127eb565b600154600290600490811614156110755760405162461bcd60e51b81526004016108c690615741565b60006110bd84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060965460ff16915061287b9050565b905084831461112e5760405162461bcd60e51b81526020600482015260436024820152600080516020615f4083398151915260448201527f6f7273466f7251756f72756d3a20696e707574206c656e677468206d69736d616064820152620e8c6d60eb1b608482015260a4016108c6565b60005b8381101561155457600085858381811061114d5761114d615778565b919091013560f81c9150369050600089898581811061116e5761116e615778565b905060200281019061118091906158f0565b6040516379a0849160e11b815260ff8616600482015291935091507f0000000000000000000000009e545e3c0baab3e08cdfd552c960a1050f3730426001600160a01b03169063f341092290602401602060405180830381865afa1580156111ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112109190615939565b63ffffffff1681146112ac5760405162461bcd60e51b81526020600482015260656024820152600080516020615f4083398151915260448201527f6f7273466f7251756f72756d3a206e756d626572206f6620757064617465642060648201527f6f70657261746f727320646f6573206e6f74206d617463682071756f72756d206084820152641d1bdd185b60da1b60a482015260c4016108c6565b6000805b828110156114f35760008484838181106112cc576112cc615778565b90506020020160208101906112e19190614cc7565b6001600160a01b03811660009081526099602090815260408083208151808301909252805482526001810154949550929390929183019060ff16600281111561132c5761132c614df5565b600281111561133d5761133d614df5565b9052508051909150600061135082612345565b905060016001600160c01b03821660ff8b161c8116146113d45760405162461bcd60e51b815260206004820152604460248201819052600080516020615f40833981519152908201527f6f7273466f7251756f72756d3a206f70657261746f72206e6f7420696e2071756064820152636f72756d60e01b608482015260a4016108c6565b856001600160a01b0316846001600160a01b03161161147f5760405162461bcd60e51b81526020600482015260676024820152600080516020615f4083398151915260448201527f6f7273466f7251756f72756d3a206f70657261746f7273206172726179206d7560648201527f737420626520736f7274656420696e20617363656e64696e6720616464726573608482015266399037b93232b960c91b60a482015260c4016108c6565b506114dd83838f8f8d908e60016114969190615956565b926114a39392919061596e565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061247a92505050565b509092506114ec9050816157a4565b90506112b0565b5060ff84166000818152609b6020908152604091829020439081905591519182527f46077d55330763f16269fd75e5761663f4192d2791747c0189b16ad31db07db4910160405180910390a2505050508061154d906157a4565b9050611131565b50505050505050565b60408051808201909152600080825260208201526001600160a01b0382166000908152609960209081526040918290208251808401909352805483526001810154909183019060ff1660028111156115b7576115b7614df5565b60028111156115c8576115c8614df5565b90525092915050565b60005460405163237dfb4760e11b8152336004820152620100009091046001600160a01b0316906346fbf68e90602401602060405180830381865afa15801561161e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116429190615886565b61165e5760405162461bcd60e51b81526004016108c6906158a8565b600019600181905560405190815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a2565b6116a5612567565b816116af8161290c565b6116b9838361298a565b505050565b609c81815481106116ce57600080fd5b6000918252602090912001546001600160a01b0316905081565b6116f0612a37565b6001600160a01b0383166000908152609f602090815260408083204290556099825280832080548251601f870185900485028101850190935285835290939092909161175d9187908790819084018382808284376000920191909152505060965460ff16915061287b9050565b9050600061176a83612345565b905060018085015460ff16600281111561178657611786614df5565b14801561179b57506001600160c01b03821615155b80156117b957506117b96001600160c01b0383811690831681161490565b15611554576115548787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612ab792505050565b611806612567565b6118106000612f29565b565b60006118527f4d404e3276e7ac2163d8ee476afa6a41d1f68fb71f2d8b6546b24e55ce01b72a878787878760405160200161102c96959493929190615998565b9695505050505050565b6000610f1982612345565b600061187b6064546001600160a01b031690565b905090565b6001805460009190811614156118a85760405162461bcd60e51b81526004016108c690615741565b83891461192b5760405162461bcd60e51b8152602060048201526044602482018190527f5265676973747279436f6f7264696e61746f722e72656769737465724f706572908201527f61746f7257697468436875726e3a20696e707574206c656e677468206d69736d6064820152630c2e8c6d60e31b608482015260a4016108c6565b60006119373388612f7b565b905061199733828888808060200260200160405190810160405280939291908181526020016000905b8282101561198c5761197d60408302860136819003810190615a1d565b81526020019060010190611960565b5050505050876130ac565b60006119de33838e8e8e8e8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c9250613239915050565b905060005b8b811015611ba9576000609760008f8f85818110611a0357611a03615778565b919091013560f81c82525060208082019290925260409081016000208151606081018352905463ffffffff811680835261ffff600160201b8304811695840195909552600160301b90910490931691810191909152845180519193509084908110611a7057611a70615778565b602002602001015163ffffffff161115611b9657611b118e8e84818110611a9957611a99615778565b9050013560f81c60f81b60f81c84604001518481518110611abc57611abc615778565b60200260200101513386602001518681518110611adb57611adb615778565b60200260200101518d8d88818110611af557611af5615778565b905060400201803603810190611b0b9190615a1d565b866137fa565b611b96898984818110611b2657611b26615778565b9050604002016020016020810190611b3e9190614cc7565b8f8f8590866001611b4f9190615956565b92611b5c9392919061596e565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612ab792505050565b5080611ba1816157a4565b9150506119e3565b50505050505050505050505050565b600180546000919081161415611be05760405162461bcd60e51b81526004016108c690615741565b6000611bec3385612f7b565b90506000611c3533838b8b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c9250613239915050565b51905060005b88811015611d305760008a8a83818110611c5757611c57615778565b919091013560f81c600081815260976020526040902054855191935063ffffffff169150849084908110611c8d57611c8d615778565b602002602001015163ffffffff161115611d1d5760405162461bcd60e51b8152602060048201526044602482018190527f5265676973747279436f6f7264696e61746f722e72656769737465724f706572908201527f61746f723a206f70657261746f7220636f756e742065786365656473206d6178606482015263696d756d60e01b608482015260a4016108c6565b5080611d28816157a4565b915050611c3b565b50505050505050505050565b6060600082516001600160401b03811115611d5957611d59614b6b565b604051908082528060200260200182016040528015611d82578160200160208202803683370190505b50905060005b8351811015611ded57611db485858381518110611da757611da7615778565b6020026020010151613acf565b828281518110611dc657611dc6615778565b63ffffffff9092166020928302919091019091015280611de5816157a4565b915050611d88565b509392505050565b6001805460029081161415611e1c5760405162461bcd60e51b81526004016108c690615741565b6116b93384848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612ab792505050565b611e64612567565b6116b9838383613c0b565b600054610100900460ff1615808015611e8f5750600054600160ff909116105b80611ea95750303b158015611ea9575060005460ff166001145b611f0c5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016108c6565b6000805460ff191660011790558015611f2f576000805461ff0019166101001790555b82518451148015611f41575081518351145b611fab5760405162461bcd60e51b815260206004820152603560248201527f5265676973747279436f6f7264696e61746f722e696e697469616c697a653a206044820152740d2dce0eae840d8cadccee8d040dad2e6dac2e8c6d605b1b60648201526084016108c6565b611fb489612f29565b611fbe8686613e22565b611fc7886126cb565b611fd087612734565b609c80546001818101835560008381527faf85b9071dfafeac1409d3f1d19bafc9bc7c37974cde8df0ee6168f0086e539c92830180546001600160a01b037f000000000000000000000000a82ff9afd8f496c3d6ac40e2a0f282e47488cfc981166001600160a01b03199283161790925585548085018755850180547f00000000000000000000000084ea74d481ee0a5332c457a4d796187f6ba67feb841690831617905585549384019095559190920180547f0000000000000000000000009e545e3c0baab3e08cdfd552c960a1050f37304290921691909316179091555b84518110156121215761210f8582815181106120ce576120ce615778565b60200260200101518583815181106120e8576120e8615778565b602002602001015185848151811061210257612102615778565b6020026020010151613c0b565b80612119816157a4565b9150506120b0565b508015612168576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050565b61217b612567565b6001600160a01b0381166121e05760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016108c6565b610d4e81612f29565b600060029054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561223c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612260919061581f565b6001600160a01b0316336001600160a01b0316146122905760405162461bcd60e51b81526004016108c69061583c565b60015419811960015419161461230e5760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e756e70617573653a20696e76616c696420617474656d7060448201527f7420746f2070617573652066756e6374696f6e616c697479000000000000000060648201526084016108c6565b600181905560405181815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c90602001610c86565b600081815260986020526040812054806123625750600092915050565b600083815260986020526040902061237b600183615a39565b8154811061238b5761238b615778565b600091825260209091200154600160401b90046001600160c01b03169392505050565b60606000806123bc84613f12565b61ffff166001600160401b038111156123d7576123d7614b6b565b6040519080825280601f01601f191660200182016040528015612401576020820181803683370190505b5090506000805b825182108015612419575061010081105b15612470576001811b935085841615612460578060f81b83838151811061244257612442615778565b60200101906001600160f81b031916908160001a9053508160010191505b612469816157a4565b9050612408565b5090949350505050565b60018260200151600281111561249257612492614df5565b1461249c57505050565b81516040516333567f7f60e11b81526000906001600160a01b037f000000000000000000000000a82ff9afd8f496c3d6ac40e2a0f282e47488cfc916906366acfefe906124f190889086908890600401615a50565b6020604051808303816000875af1158015612510573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125349190615a80565b90506001600160c01b03811615612560576125608561255b836001600160c01b03166123ae565b612ab7565b5050505050565b33612570611867565b6001600160a01b0316146118105760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108c6565b6001600160a01b0381166126545760405162461bcd60e51b815260206004820152604960248201527f5061757361626c652e5f73657450617573657252656769737472793a206e657760448201527f50617573657252656769737472792063616e6e6f7420626520746865207a65726064820152686f206164647265737360b81b608482015260a4016108c6565b600054604080516001600160a01b03620100009093048316815291831660208301527f6e9fcd539896fca60e8b0f01dd580233e48a6b0f7df013b89ba7f565869acdb6910160405180910390a1600080546001600160a01b03909216620100000262010000600160b01b0319909216919091179055565b609d54604080516001600160a01b03928316815291831660208301527f315457d8a8fe60f04af17c16e2f5a5e1db612b31648e58030360759ef8f3528c910160405180910390a1609d80546001600160a01b0319166001600160a01b0392909216919091179055565b609e54604080516001600160a01b03928316815291831660208301527f8f30ab09f43a6c157d7fce7e0a13c003042c1c95e8a72e7a146a21c0caa24dc9910160405180910390a1609e80546001600160a01b0319166001600160a01b0392909216919091179055565b6000610f196127aa613f3d565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60408051808201909152600080825260208201526000808061281b600080516020615f8083398151915286615abf565b90505b61282781614064565b9093509150600080516020615f80833981519152828309831415612861576040805180820190915290815260208101919091529392505050565b600080516020615f8083398151915260018208905061281e565b600080612887846140e6565b9050808360ff166001901b116129055760405162461bcd60e51b815260206004820152603f60248201527f4269746d61705574696c732e6f72646572656442797465734172726179546f4260448201527f69746d61703a206269746d61702065786365656473206d61782076616c75650060648201526084016108c6565b9392505050565b60965460ff90811690821610610d4e5760405162461bcd60e51b815260206004820152603760248201527f5265676973747279436f6f7264696e61746f722e71756f72756d45786973747360448201527f3a2071756f72756d20646f6573206e6f7420657869737400000000000000000060648201526084016108c6565b60ff8216600081815260976020908152604091829020845181548684018051888701805163ffffffff90951665ffffffffffff199094168417600160201b61ffff938416021767ffff0000000000001916600160301b95831695909502949094179094558551918252518316938101939093525116918101919091527f3ee6fe8d54610244c3e9d3c066ae4aee997884aa28f10616ae821925401318ac9060600160405180910390a25050565b609e546001600160a01b031633146118105760405162461bcd60e51b815260206004820152603a60248201527f5265676973747279436f6f7264696e61746f722e6f6e6c79456a6563746f723a60448201527f2063616c6c6572206973206e6f742074686520656a6563746f7200000000000060648201526084016108c6565b6001600160a01b0382166000908152609960205260409020805460018083015460ff166002811115612aeb57612aeb614df5565b14612b6a5760405162461bcd60e51b815260206004820152604360248201527f5265676973747279436f6f7264696e61746f722e5f646572656769737465724f60448201527f70657261746f723a206f70657261746f72206973206e6f7420726567697374656064820152621c995960ea1b608482015260a4016108c6565b609654600090612b7e90859060ff1661287b565b90506000612b8b83612345565b90506001600160c01b038216612c095760405162461bcd60e51b815260206004820152603b60248201527f5265676973747279436f6f7264696e61746f722e5f646572656769737465724f60448201527f70657261746f723a206269746d61702063616e6e6f742062652030000000000060648201526084016108c6565b612c206001600160c01b0383811690831681161490565b612cb85760405162461bcd60e51b815260206004820152605960248201527f5265676973747279436f6f7264696e61746f722e5f646572656769737465724f60448201527f70657261746f723a206f70657261746f72206973206e6f74207265676973746560648201527f72656420666f72207370656369666965642071756f72756d7300000000000000608482015260a4016108c6565b6001600160c01b0382811619821616612cd18482614273565b6001600160c01b038116612da05760018501805460ff191660021790556040516351b27a6d60e11b81526001600160a01b0388811660048301527f00000000000000000000000067d269191c92caf3cd7723f116c85e6e9bf55933169063a364f4da90602401600060405180830381600087803b158015612d5157600080fd5b505af1158015612d65573d6000803e3d6000fd5b50506040518692506001600160a01b038a1691507f396fdcb180cb0fea26928113fb0fd1c3549863f9cd563e6a184f1d578116c8e490600090a35b60405163f4e24fe560e01b81526001600160a01b037f00000000000000000000000084ea74d481ee0a5332c457a4d796187f6ba67feb169063f4e24fe590612dee908a908a90600401615ad3565b600060405180830381600087803b158015612e0857600080fd5b505af1158015612e1c573d6000803e3d6000fd5b505060405163bd29b8cd60e01b81526001600160a01b037f000000000000000000000000a82ff9afd8f496c3d6ac40e2a0f282e47488cfc916925063bd29b8cd9150612e6e9087908a90600401615af7565b600060405180830381600087803b158015612e8857600080fd5b505af1158015612e9c573d6000803e3d6000fd5b505060405163bd29b8cd60e01b81526001600160a01b037f0000000000000000000000009e545e3c0baab3e08cdfd552c960a1050f37304216925063bd29b8cd9150612eee9087908a90600401615af7565b600060405180830381600087803b158015612f0857600080fd5b505af1158015612f1c573d6000803e3d6000fd5b5050505050505050505050565b606480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6040516309aa152760e11b81526001600160a01b0383811660048301526000917f00000000000000000000000084ea74d481ee0a5332c457a4d796187f6ba67feb909116906313542a4e90602401602060405180830381865afa158015612fe6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061300a9190615b10565b905080610f19577f00000000000000000000000084ea74d481ee0a5332c457a4d796187f6ba67feb6001600160a01b031663bf79ce58848461304b87610fcd565b6040518463ffffffff1660e01b815260040161306993929190615b29565b6020604051808303816000875af1158015613088573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129059190615b10565b6020808201516000908152609a909152604090205460ff16156131525760405162461bcd60e51b815260206004820152605260248201527f5265676973747279436f6f7264696e61746f722e5f766572696679436875726e60448201527f417070726f7665725369676e61747572653a20636875726e417070726f766572606482015271081cd85b1d08185b1c9958591e481d5cd95960721b608482015260a4016108c6565b42816040015110156131e75760405162461bcd60e51b815260206004820152605260248201527f5265676973747279436f6f7264696e61746f722e5f766572696679436875726e60448201527f417070726f7665725369676e61747572653a20636875726e417070726f766572606482015271081cda59db985d1d5c9948195e1c1a5c995960721b608482015260a4016108c6565b602080820180516000908152609a909252604091829020805460ff19166001179055609d549051918301516109ad926001600160a01b03909216916132329188918891889190611812565b8351614433565b61325d60405180606001604052806060815260200160608152602001606081525090565b60006132a586868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060965460ff16915061287b9050565b905060006132b288612345565b90506001600160c01b0382166133305760405162461bcd60e51b815260206004820152603960248201527f5265676973747279436f6f7264696e61746f722e5f72656769737465724f706560448201527f7261746f723a206269746d61702063616e6e6f7420626520300000000000000060648201526084016108c6565b8082166001600160c01b0316156133e65760405162461bcd60e51b815260206004820152606860248201527f5265676973747279436f6f7264696e61746f722e5f72656769737465724f706560448201527f7261746f723a206f70657261746f7220616c726561647920726567697374657260648201527f656420666f7220736f6d652071756f72756d73206265696e672072656769737460848201526732b932b2103337b960c11b60a482015260c4016108c6565b60a0546001600160a01b038a166000908152609f60205260409020546001600160c01b038381169085161791429161341e9190615956565b1061349f5760405162461bcd60e51b815260206004820152604560248201527f5265676973747279436f6f7264696e61746f722e5f72656769737465724f706560448201527f7261746f723a206f70657261746f722063616e6e6f74207265726567697374656064820152641c881e595d60da1b608482015260a4016108c6565b6134a98982614273565b887fec2963ab21c1e50e1e582aa542af2e4bf7bf38e6e1403c27b42e1c5d6e621eaa876040516134d9919061580c565b60405180910390a260016001600160a01b038b1660009081526099602052604090206001015460ff16600281111561351357613513614df5565b1461362c576040805180820182528a8152600160208083018281526001600160a01b038f166000908152609990925293902082518155925183820180549394939192909160ff19169083600281111561356e5761356e614df5565b021790555050604051639926ee7d60e01b81526001600160a01b037f00000000000000000000000067d269191c92caf3cd7723f116c85e6e9bf55933169150639926ee7d906135c3908d908990600401615ba8565b600060405180830381600087803b1580156135dd57600080fd5b505af11580156135f1573d6000803e3d6000fd5b50506040518b92506001600160a01b038d1691507fe8e68cef1c3a761ed7be7e8463a375f27f7bc335e51824223cacce636ec5c3fe90600090a35b604051631fd93ca960e11b81526001600160a01b037f00000000000000000000000084ea74d481ee0a5332c457a4d796187f6ba67feb1690633fb279529061367c908d908c908c90600401615c1c565b600060405180830381600087803b15801561369657600080fd5b505af11580156136aa573d6000803e3d6000fd5b5050604051632550477760e01b81526001600160a01b037f000000000000000000000000a82ff9afd8f496c3d6ac40e2a0f282e47488cfc916925063255047779150613700908d908d908d908d90600401615c41565b6000604051808303816000875af115801561371f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526137479190810190615ccd565b60408087019190915260208601919091525162bff04d60e01b81526001600160a01b037f0000000000000000000000009e545e3c0baab3e08cdfd552c960a1050f373042169062bff04d906137a4908c908c908c90600401615d30565b6000604051808303816000875af11580156137c3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526137eb9190810190615d4a565b84525050509695505050505050565b6020808301516001600160a01b03808216600081815260999094526040909320549192908716141561387a5760405162461bcd60e51b81526020600482015260356024820152600080516020615f6083398151915260448201527439371d1031b0b73737ba1031b43ab9371039b2b63360591b60648201526084016108c6565b8760ff16846000015160ff16146138f75760405162461bcd60e51b81526020600482015260476024820152600080516020615f6083398151915260448201527f726e3a2071756f72756d4e756d626572206e6f74207468652073616d65206173606482015266081cda59db995960ca1b608482015260a4016108c6565b604051635401ed2760e01b81526004810182905260ff891660248201526000907f000000000000000000000000a82ff9afd8f496c3d6ac40e2a0f282e47488cfc96001600160a01b031690635401ed2790604401602060405180830381865afa158015613968573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061398c9190615de3565b905061399881856145ed565b6001600160601b0316866001600160601b031611613a2b5760405162461bcd60e51b81526020600482015260566024820152600080516020615f6083398151915260448201527f726e3a20696e636f6d696e67206f70657261746f722068617320696e7375666660648201527534b1b4b2b73a1039ba30b5b2903337b91031b43ab93760511b608482015260a4016108c6565b613a358885614611565b6001600160601b0316816001600160601b0316106121685760405162461bcd60e51b815260206004820152605c6024820152600080516020615f6083398151915260448201527f726e3a2063616e6e6f74206b69636b206f70657261746f722077697468206d6f60648201527f7265207468616e206b69636b424950734f66546f74616c5374616b6500000000608482015260a4016108c6565b600081815260986020526040812054815b81811015613b61576001613af48284615a39565b613afe9190615a39565b92508463ffffffff16609860008681526020019081526020016000208463ffffffff1681548110613b3157613b31615778565b60009182526020909120015463ffffffff1611613b4f575050610f19565b80613b59816157a4565b915050613ae0565b5060405162461bcd60e51b815260206004820152606c60248201527f5265676973747279436f6f7264696e61746f722e67657451756f72756d42697460448201527f6d6170496e6465784174426c6f636b4e756d6265723a206e6f206269746d617060648201527f2075706461746520666f756e6420666f72206f70657261746f7249642061742060848201526b313637b1b590373ab6b132b960a11b60a482015260c4016108c6565b60965460ff1660c08110613c7f5760405162461bcd60e51b815260206004820152603560248201527f5265676973747279436f6f7264696e61746f722e63726561746551756f72756d6044820152740e881b585e081c5d5bdc9d5b5cc81c995858da1959605a1b60648201526084016108c6565b613c8a816001615e00565b6096805460ff191660ff9290921691909117905580613ca9818661298a565b60405160016296b58960e01b031981526001600160a01b037f000000000000000000000000a82ff9afd8f496c3d6ac40e2a0f282e47488cfc9169063ff694a7790613cfc90849088908890600401615e25565b600060405180830381600087803b158015613d1657600080fd5b505af1158015613d2a573d6000803e3d6000fd5b505060405163136ca0f960e11b815260ff841660048201527f0000000000000000000000009e545e3c0baab3e08cdfd552c960a1050f3730426001600160a01b031692506326d941f29150602401600060405180830381600087803b158015613d9257600080fd5b505af1158015613da6573d6000803e3d6000fd5b505060405163136ca0f960e11b815260ff841660048201527f00000000000000000000000084ea74d481ee0a5332c457a4d796187f6ba67feb6001600160a01b031692506326d941f29150602401600060405180830381600087803b158015613e0e57600080fd5b505af1158015612168573d6000803e3d6000fd5b6000546201000090046001600160a01b0316158015613e4957506001600160a01b03821615155b613ecb5760405162461bcd60e51b815260206004820152604760248201527f5061757361626c652e5f696e697469616c697a655061757365723a205f696e6960448201527f7469616c697a6550617573657228292063616e206f6e6c792062652063616c6c6064820152666564206f6e636560c81b608482015260a4016108c6565b600181905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a2613f0e826125c6565b5050565b6000805b8215610f1957613f27600184615a39565b9092169180613f3581615e9e565b915050613f16565b6000306001600160a01b037f00000000000000000000000099bba657f2bbc93c02d617f8ba121cb8fc104acf16148015613f9657507f0000000000000000000000000000000000000000000000000000000000007a6946145b15613fc057507f406317ba320aa1ce27f534da819f43f06d3f4ae2bb66e781d9097ad693209a7090565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f6ec8a99f0e7f9ebde7354a446dcb9423f3af9c58f386a53c59c5b384f9e82d11828401527f6bda7e3f385e48841048390444cced5cc795af87758af67622e5f4f0882c4a9960608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b60008080600080516020615f808339815191526003600080516020615f8083398151915286600080516020615f808339815191528889090908905060006140da827f0c19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52600080516020615f8083398151915261462b565b91959194509092505050565b60006101008251111561416f5760405162461bcd60e51b8152602060048201526044602482018190527f4269746d61705574696c732e6f72646572656442797465734172726179546f42908201527f69746d61703a206f7264657265644279746573417272617920697320746f6f206064820152636c6f6e6760e01b608482015260a4016108c6565b815161417d57506000919050565b6000808360008151811061419357614193615778565b0160200151600160f89190911c81901b92505b845181101561426a578481815181106141c1576141c1615778565b0160200151600160f89190911c1b91508282116142565760405162461bcd60e51b815260206004820152604760248201527f4269746d61705574696c732e6f72646572656442797465734172726179546f4260448201527f69746d61703a206f72646572656442797465734172726179206973206e6f74206064820152661bdc99195c995960ca1b608482015260a4016108c6565b91811791614263816157a4565b90506141a6565b50909392505050565b60008281526098602052604090205480614318576000838152609860209081526040808320815160608101835263ffffffff43811682528185018681526001600160c01b03808a16958401958652845460018101865594885295909620915191909201805495519351909416600160401b026001600160401b03938316600160201b0267ffffffffffffffff1990961691909216179390931716919091179055505050565b6000838152609860205260408120614331600184615a39565b8154811061434157614341615778565b600091825260209091200180549091504363ffffffff908116911614156143855780546001600160401b0316600160401b6001600160c01b038516021781556109ad565b805463ffffffff438116600160201b81810267ffffffff0000000019909416939093178455600087815260986020908152604080832081516060810183529485528483018481526001600160c01b03808c1693870193845282546001810184559286529390942094519401805493519151909216600160401b026001600160401b0391861690960267ffffffffffffffff199093169390941692909217179190911691909117905550505050565b6001600160a01b0383163b1561454d57604051630b135d3f60e11b808252906001600160a01b03851690631626ba7e906144739086908690600401615af7565b602060405180830381865afa158015614490573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144b49190615ec0565b6001600160e01b031916146116b95760405162461bcd60e51b815260206004820152605360248201527f454950313237315369676e61747572655574696c732e636865636b5369676e6160448201527f747572655f454950313237313a2045524331323731207369676e6174757265206064820152721d995c9a599a58d85d1a5bdb8819985a5b1959606a1b608482015260a4016108c6565b826001600160a01b031661456183836146da565b6001600160a01b0316146116b95760405162461bcd60e51b815260206004820152604760248201527f454950313237315369676e61747572655574696c732e636865636b5369676e6160448201527f747572655f454950313237313a207369676e6174757265206e6f742066726f6d6064820152661039b4b3b732b960c91b608482015260a4016108c6565b6020810151600090612710906146079061ffff1685615eea565b6129059190615f19565b6040810151600090612710906146079061ffff1685615eea565b600080614636614a47565b61463e614a65565b602080825281810181905260408201819052606082018890526080820187905260a082018690528260c08360056107d05a03fa925082801561467f57614681565bfe5b50826146cf5760405162461bcd60e51b815260206004820152601a60248201527f424e3235342e6578704d6f643a2063616c6c206661696c75726500000000000060448201526064016108c6565b505195945050505050565b60008060006146e985856146f6565b91509150611ded81614766565b60008082516041141561472d5760208301516040840151606085015160001a61472187828585614921565b9450945050505061475f565b825160401415614757576020830151604084015161474c868383614a0e565b93509350505061475f565b506000905060025b9250929050565b600081600481111561477a5761477a614df5565b14156147835750565b600181600481111561479757614797614df5565b14156147e55760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016108c6565b60028160048111156147f9576147f9614df5565b14156148475760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016108c6565b600381600481111561485b5761485b614df5565b14156148b45760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016108c6565b60048160048111156148c8576148c8614df5565b1415610d4e5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b60648201526084016108c6565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156149585750600090506003614a05565b8460ff16601b1415801561497057508460ff16601c14155b156149815750600090506004614a05565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156149d5573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166149fe57600060019250925050614a05565b9150600090505b94509492505050565b6000806001600160ff1b03831681614a2b60ff86901c601b615956565b9050614a3987828885614921565b935093505050935093915050565b60405180602001604052806001906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b60008083601f840112614a9557600080fd5b5081356001600160401b03811115614aac57600080fd5b6020830191508360208260051b850101111561475f57600080fd5b60008060208385031215614ada57600080fd5b82356001600160401b03811115614af057600080fd5b614afc85828601614a83565b90969095509350505050565b600060208284031215614b1a57600080fd5b5035919050565b63ffffffff81168114610d4e57600080fd5b600080600060608486031215614b4857600080fd5b833592506020840135614b5a81614b21565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b0381118282101715614ba357614ba3614b6b565b60405290565b604080519081016001600160401b0381118282101715614ba357614ba3614b6b565b604051601f8201601f191681016001600160401b0381118282101715614bf357614bf3614b6b565b604052919050565b60006001600160401b03831115614c1457614c14614b6b565b614c27601f8401601f1916602001614bcb565b9050828152838383011115614c3b57600080fd5b828260208301376000602084830101529392505050565b600060208284031215614c6457600080fd5b81356001600160401b03811115614c7a57600080fd5b8201601f81018413614c8b57600080fd5b614c9a84823560208401614bfb565b949350505050565b6001600160a01b0381168114610d4e57600080fd5b8035614cc281614ca2565b919050565b600060208284031215614cd957600080fd5b813561290581614ca2565b60008060408385031215614cf757600080fd5b50508035926020909101359150565b803560ff81168114614cc257600080fd5b600060208284031215614d2957600080fd5b61290582614d06565b815181526020808301519082015260408101610f19565b60008083601f840112614d5b57600080fd5b5081356001600160401b03811115614d7257600080fd5b60208301915083602082850101111561475f57600080fd5b60008060008060408587031215614da057600080fd5b84356001600160401b0380821115614db757600080fd5b614dc388838901614a83565b90965094506020870135915080821115614ddc57600080fd5b50614de987828801614d49565b95989497509550505050565b634e487b7160e01b600052602160045260246000fd5b60038110614e2957634e487b7160e01b600052602160045260246000fd5b9052565b815181526020808301516040830191614e4890840182614e0b565b5092915050565b803561ffff81168114614cc257600080fd5b600060608284031215614e7357600080fd5b614e7b614b81565b90508135614e8881614b21565b8152614e9660208301614e4f565b6020820152614ea760408301614e4f565b604082015292915050565b60008060808385031215614ec557600080fd5b614ece83614d06565b9150614edd8460208501614e61565b90509250929050565b600080600060408486031215614efb57600080fd5b8335614f0681614ca2565b925060208401356001600160401b03811115614f2157600080fd5b614f2d86828701614d49565b9497909650939450505050565b60006001600160401b03821115614f5357614f53614b6b565b5060051b60200190565b600060408284031215614f6f57600080fd5b614f77614ba9565b9050614f8282614d06565b81526020820135614f9281614ca2565b602082015292915050565b600080600080600060a08688031215614fb557600080fd5b8535614fc081614ca2565b945060208681013594506040808801356001600160401b03811115614fe457600080fd5b8801601f81018a13614ff557600080fd5b803561500861500382614f3a565b614bcb565b81815260069190911b8201840190848101908c83111561502757600080fd5b928501925b8284101561504d5761503e8d85614f5d565b8252928401929085019061502c565b999c989b5098996060810135995060800135979650505050505050565b6000610100828403121561507d57600080fd5b50919050565b60008083601f84011261509557600080fd5b5081356001600160401b038111156150ac57600080fd5b6020830191508360208260061b850101111561475f57600080fd5b6000606082840312156150d957600080fd5b6150e1614b81565b905081356001600160401b038111156150f957600080fd5b8201601f8101841361510a57600080fd5b61511984823560208401614bfb565b825250602082013560208201526040820135604082015292915050565b60008060008060008060008060006101a08a8c03121561515557600080fd5b89356001600160401b038082111561516c57600080fd5b6151788d838e01614d49565b909b50995060208c013591508082111561519157600080fd5b61519d8d838e01614d49565b90995097508791506151b28d60408e0161506a565b96506101408c01359150808211156151c957600080fd5b6151d58d838e01615083565b90965094506101608c01359150808211156151ef57600080fd5b6151fb8d838e016150c7565b93506101808c013591508082111561521257600080fd5b5061521f8c828d016150c7565b9150509295985092959850929598565b600080600080600080610160878903121561524957600080fd5b86356001600160401b038082111561526057600080fd5b61526c8a838b01614d49565b9098509650602089013591508082111561528557600080fd5b6152918a838b01614d49565b90965094508491506152a68a60408b0161506a565b93506101408901359150808211156152bd57600080fd5b506152ca89828a016150c7565b9150509295509295509295565b600080604083850312156152ea57600080fd5b82356152f581614b21565b91506020838101356001600160401b0381111561531157600080fd5b8401601f8101861361532257600080fd5b803561533061500382614f3a565b81815260059190911b8201830190838101908883111561534f57600080fd5b928401925b8284101561536d57833582529284019290840190615354565b80955050505050509250929050565b6020808252825182820181905260009190848201906040850190845b818110156153ba57835163ffffffff1683529284019291840191600101615398565b50909695505050505050565b600080602083850312156153d957600080fd5b82356001600160401b038111156153ef57600080fd5b614afc85828601614d49565b6001600160601b0381168114610d4e57600080fd5b600082601f83011261542157600080fd5b8135602061543161500383614f3a565b82815260069290921b8401810191818101908684111561545057600080fd5b8286015b848110156154a1576040818903121561546d5760008081fd5b615475614ba9565b813561548081614ca2565b81528185013561548f816153fb565b81860152835291830191604001615454565b509695505050505050565b600080600060a084860312156154c157600080fd5b6154cb8585614e61565b925060608401356154db816153fb565b915060808401356001600160401b038111156154f657600080fd5b61550286828701615410565b9150509250925092565b600082601f83011261551d57600080fd5b8135602061552d61500383614f3a565b8281526060928302850182019282820191908785111561554c57600080fd5b8387015b8581101561556f576155628982614e61565b8452928401928101615550565b5090979650505050505050565b600082601f83011261558d57600080fd5b8135602061559d61500383614f3a565b82815260059290921b840181019181810190868411156155bc57600080fd5b8286015b848110156154a15780356155d3816153fb565b83529183019183016155c0565b600082601f8301126155f157600080fd5b8135602061560161500383614f3a565b82815260059290921b8401810191818101908684111561562057600080fd5b8286015b848110156154a15780356001600160401b038111156156435760008081fd5b6156518986838b0101615410565b845250918301918301615624565b600080600080600080600080610100898b03121561567c57600080fd5b61568589614cb7565b975061569360208a01614cb7565b96506156a160408a01614cb7565b95506156af60608a01614cb7565b94506080890135935060a08901356001600160401b03808211156156d257600080fd5b6156de8c838d0161550c565b945060c08b01359150808211156156f457600080fd5b6157008c838d0161557c565b935060e08b013591508082111561571657600080fd5b506157238b828c016155e0565b9150509295985092959890939650565b60208101610f198284614e0b565b60208082526019908201527f5061757361626c653a20696e6465782069732070617573656400000000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006000198214156157b8576157b861578e565b5060010190565b6000815180845260005b818110156157e5576020818501810151868301820152016157c9565b818111156157f7576000602083870101525b50601f01601f19169290920160200192915050565b60208152600061290560208301846157bf565b60006020828403121561583157600080fd5b815161290581614ca2565b6020808252602a908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526939903ab73830bab9b2b960b11b606082015260800190565b60006020828403121561589857600080fd5b8151801515811461290557600080fd5b60208082526028908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526739903830bab9b2b960c11b606082015260800190565b6000808335601e1984360301811261590757600080fd5b8301803591506001600160401b0382111561592157600080fd5b6020019150600581901b360382131561475f57600080fd5b60006020828403121561594b57600080fd5b815161290581614b21565b600082198211156159695761596961578e565b500190565b6000808585111561597e57600080fd5b8386111561598b57600080fd5b5050820193919092039150565b600060c08201888352602060018060a01b03808a16828601526040898187015260c0606087015283895180865260e088019150848b01955060005b818110156159fd578651805160ff16845286015185168684015295850195918301916001016159d3565b505060808701989098525050505060a09091019190915250949350505050565b600060408284031215615a2f57600080fd5b6129058383614f5d565b600082821015615a4b57615a4b61578e565b500390565b60018060a01b0384168152826020820152606060408201526000615a7760608301846157bf565b95945050505050565b600060208284031215615a9257600080fd5b81516001600160c01b038116811461290557600080fd5b634e487b7160e01b600052601260045260246000fd5b600082615ace57615ace615aa9565b500690565b6001600160a01b0383168152604060208201819052600090614c9a908301846157bf565b828152604060208201526000614c9a60408301846157bf565b600060208284031215615b2257600080fd5b5051919050565b6001600160a01b03841681526101608101615b51602083018580358252602090810135910152565b615b6b606083016040860180358252602090810135910152565b60406080850160a084013760e0820160008152604060c0860182375060006101208301908152835190526020909201516101409091015292915050565b60018060a01b0383168152604060208201526000825160606040840152615bd260a08401826157bf565b90506020840151606084015260408401516080840152809150509392505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b0384168152604060208201819052600090615a779083018486615bf3565b60018060a01b0385168152836020820152606060408201526000611852606083018486615bf3565b600082601f830112615c7a57600080fd5b81516020615c8a61500383614f3a565b82815260059290921b84018101918181019086841115615ca957600080fd5b8286015b848110156154a1578051615cc0816153fb565b8352918301918301615cad565b60008060408385031215615ce057600080fd5b82516001600160401b0380821115615cf757600080fd5b615d0386838701615c69565b93506020850151915080821115615d1957600080fd5b50615d2685828601615c69565b9150509250929050565b838152604060208201526000615a77604083018486615bf3565b60006020808385031215615d5d57600080fd5b82516001600160401b03811115615d7357600080fd5b8301601f81018513615d8457600080fd5b8051615d9261500382614f3a565b81815260059190911b82018301908381019087831115615db157600080fd5b928401925b82841015615dd8578351615dc981614b21565b82529284019290840190615db6565b979650505050505050565b600060208284031215615df557600080fd5b8151612905816153fb565b600060ff821660ff84168060ff03821115615e1d57615e1d61578e565b019392505050565b60006060820160ff8616835260206001600160601b03808716828601526040606081870152838751808652608088019150848901955060005b81811015615e8e57865180516001600160a01b031684528601518516868401529585019591830191600101615e5e565b50909a9950505050505050505050565b600061ffff80831681811415615eb657615eb661578e565b6001019392505050565b600060208284031215615ed257600080fd5b81516001600160e01b03198116811461290557600080fd5b60006001600160601b0380831681851681830481118215151615615f1057615f1061578e565b02949350505050565b60006001600160601b0380841680615f3357615f33615aa9565b9216919091049291505056fe5265676973747279436f6f7264696e61746f722e7570646174654f70657261745265676973747279436f6f7264696e61746f722e5f76616c696461746543687530644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47a264697066735822122068fdae2edb27a825c00ed8e9cca7bd8f78770e62fe1a36efacc218ef7525479e64736f6c634300080c0033", + "storage": { "0x0": "0xff" } + }, + "0x9a676e781a523b5d0c0e43731313a708cb607508": { + "nonce": 1, + "balance": "0x0", + "code": "0x608060405234801561001057600080fd5b50600436106101425760003560e01c80638da5cb5b116100b8578063d79aceab1161007c578063d79aceab146102f8578063df5cf7231461031f578063ec76f44214610346578063f2fde38b14610359578063f698da251461036c578063fabc1cbc1461037457600080fd5b80638da5cb5b1461029b5780639926ee7d146102ac578063a1060c88146102bf578063a364f4da146102d2578063a98fb355146102e557600080fd5b806349075da31161010a57806349075da3146101fa578063595c6a67146102355780635ac86ab71461023d5780635c975abb14610260578063715018a614610268578063886f11951461027057600080fd5b806310d67a2f14610147578063136439dd1461015c5780631794bb3c1461016f57806320606b7014610182578063374823b5146101bc575b600080fd5b61015a6101553660046118ab565b610387565b005b61015a61016a3660046118cf565b610443565b61015a61017d3660046118e8565b610582565b6101a97f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6040519081526020015b60405180910390f35b6101ea6101ca366004611929565b609960209081526000928352604080842090915290825290205460ff1681565b60405190151581526020016101b3565b610228610208366004611955565b609860209081526000928352604080842090915290825290205460ff1681565b6040516101b391906119a4565b61015a6106ac565b6101ea61024b3660046119cc565b606654600160ff9092169190911b9081161490565b6066546101a9565b61015a610773565b606554610283906001600160a01b031681565b6040516001600160a01b0390911681526020016101b3565b6033546001600160a01b0316610283565b61015a6102ba366004611a5f565b610787565b6101a96102cd366004611b46565b610b1a565b61015a6102e03660046118ab565b610bd3565b61015a6102f3366004611b8c565b610d3c565b6101a97fda2c89bafdd34776a2b8bb9c83c82f419e20cc8c67207f70edd58249b92661bd81565b6102837f000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c981565b61015a6103543660046118cf565b610d83565b61015a6103673660046118ab565b610e2e565b6101a9610ea4565b61015a6103823660046118cf565b610ee2565b606560009054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103fe9190611bfe565b6001600160a01b0316336001600160a01b0316146104375760405162461bcd60e51b815260040161042e90611c1b565b60405180910390fd5b6104408161103e565b50565b60655460405163237dfb4760e11b81523360048201526001600160a01b03909116906346fbf68e90602401602060405180830381865afa15801561048b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104af9190611c65565b6104cb5760405162461bcd60e51b815260040161042e90611c87565b606654818116146105445760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e70617573653a20696e76616c696420617474656d70742060448201527f746f20756e70617573652066756e6374696f6e616c6974790000000000000000606482015260840161042e565b606681905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d906020015b60405180910390a250565b600054610100900460ff16158080156105a25750600054600160ff909116105b806105bc5750303b1580156105bc575060005460ff166001145b61061f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161042e565b6000805460ff191660011790558015610642576000805461ff0019166101001790555b61064c8383611135565b61065461121f565b609755610660846112b6565b80156106a6576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b60655460405163237dfb4760e11b81523360048201526001600160a01b03909116906346fbf68e90602401602060405180830381865afa1580156106f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107189190611c65565b6107345760405162461bcd60e51b815260040161042e90611c87565b600019606681905560405190815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a2565b61077b611308565b61078560006112b6565b565b606654600090600190811614156107dc5760405162461bcd60e51b815260206004820152601960248201527814185d5cd8589b194e881a5b99195e081a5cc81c185d5cd959603a1b604482015260640161042e565b42826040015110156108445760405162461bcd60e51b815260206004820152603e6024820152600080516020611dac83398151915260448201527f56533a206f70657261746f72207369676e617475726520657870697265640000606482015260840161042e565b60013360009081526098602090815260408083206001600160a01b038816845290915290205460ff16600181111561087e5761087e61198e565b14156108e05760405162461bcd60e51b815260206004820152603f6024820152600080516020611dac83398151915260448201527f56533a206f70657261746f7220616c7265616479207265676973746572656400606482015260840161042e565b6001600160a01b038316600090815260996020908152604080832085830151845290915290205460ff16156109645760405162461bcd60e51b81526020600482015260366024820152600080516020611dac8339815191526044820152751594ce881cd85b1d08185b1c9958591e481cdc195b9d60521b606482015260840161042e565b6040516336b87bd760e11b81526001600160a01b0384811660048301527f000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c91690636d70f7ae90602401602060405180830381865afa1580156109ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ee9190611c65565b610a645760405162461bcd60e51b815260206004820152604d6024820152600080516020611dac83398151915260448201527f56533a206f70657261746f72206e6f74207265676973746572656420746f204560648201526c1a59d95b93185e595c881e595d609a1b608482015260a40161042e565b6000610a7a843385602001518660400151610b1a565b9050610a8b84828560000151611362565b3360008181526098602090815260408083206001600160a01b0389168085529083528184208054600160ff199182168117909255609985528386208a860151875290945293829020805490931684179092555190917ff0952b1c65271d819d39983d2abb044b9cace59bcc4d4dd389f586ebdcb15b4191610b0c91906119a4565b60405180910390a350505050565b604080517fda2c89bafdd34776a2b8bb9c83c82f419e20cc8c67207f70edd58249b92661bd6020808301919091526001600160a01b0387811683850152861660608301526080820185905260a08083018590528351808403909101815260c0909201909252805191012060009081610b90610ea4565b60405161190160f01b602082015260228101919091526042810183905260620160408051808303601f190181529190528051602090910120979650505050505050565b60665460009060019081161415610c285760405162461bcd60e51b815260206004820152601960248201527814185d5cd8589b194e881a5b99195e081a5cc81c185d5cd959603a1b604482015260640161042e565b60013360009081526098602090815260408083206001600160a01b038716845290915290205460ff166001811115610c6257610c6261198e565b14610cd55760405162461bcd60e51b815260206004820152603f60248201527f4156534469726563746f72792e646572656769737465724f70657261746f724660448201527f726f6d4156533a206f70657261746f72206e6f74207265676973746572656400606482015260840161042e565b3360008181526098602090815260408083206001600160a01b0387168085529252808320805460ff191690555190917ff0952b1c65271d819d39983d2abb044b9cace59bcc4d4dd389f586ebdcb15b4191610d3091906119a4565b60405180910390a35050565b336001600160a01b03167fa89c1dc243d8908a96dd84944bcc97d6bc6ac00dd78e20621576be6a3c9437138383604051610d77929190611ccf565b60405180910390a25050565b33600090815260996020908152604080832084845290915290205460ff1615610e085760405162461bcd60e51b815260206004820152603160248201527f4156534469726563746f72792e63616e63656c53616c743a2063616e6e6f742060448201527018d85b98d95b081cdc195b9d081cd85b1d607a1b606482015260840161042e565b33600090815260996020908152604080832093835292905220805460ff19166001179055565b610e36611308565b6001600160a01b038116610e9b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161042e565b610440816112b6565b60007f0000000000000000000000000000000000000000000000000000000000007a69461415610ed5575060975490565b610edd61121f565b905090565b606560009054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f599190611bfe565b6001600160a01b0316336001600160a01b031614610f895760405162461bcd60e51b815260040161042e90611c1b565b6066541981196066541916146110075760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e756e70617573653a20696e76616c696420617474656d7060448201527f7420746f2070617573652066756e6374696f6e616c6974790000000000000000606482015260840161042e565b606681905560405181815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c90602001610577565b6001600160a01b0381166110cc5760405162461bcd60e51b815260206004820152604960248201527f5061757361626c652e5f73657450617573657252656769737472793a206e657760448201527f50617573657252656769737472792063616e6e6f7420626520746865207a65726064820152686f206164647265737360b81b608482015260a40161042e565b606554604080516001600160a01b03928316815291831660208301527f6e9fcd539896fca60e8b0f01dd580233e48a6b0f7df013b89ba7f565869acdb6910160405180910390a1606580546001600160a01b0319166001600160a01b0392909216919091179055565b6065546001600160a01b031615801561115657506001600160a01b03821615155b6111d85760405162461bcd60e51b815260206004820152604760248201527f5061757361626c652e5f696e697469616c697a655061757365723a205f696e6960448201527f7469616c697a6550617573657228292063616e206f6e6c792062652063616c6c6064820152666564206f6e636560c81b608482015260a40161042e565b606681905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a261121b8261103e565b5050565b604080518082018252600a81526922b4b3b2b72630bcb2b960b11b60209182015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527f71b625cfad44bac63b13dba07f2e1d6084ee04b6f8752101ece6126d584ee6ea81840152466060820152306080808301919091528351808303909101815260a0909101909252815191012090565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6033546001600160a01b031633146107855760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161042e565b6001600160a01b0383163b1561148157604051630b135d3f60e11b808252906001600160a01b03851690631626ba7e906113a29086908690600401611cfe565b602060405180830381865afa1580156113bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113e39190611d5b565b6001600160e01b0319161461147c5760405162461bcd60e51b815260206004820152605360248201527f454950313237315369676e61747572655574696c732e636865636b5369676e6160448201527f747572655f454950313237313a2045524331323731207369676e6174757265206064820152721d995c9a599a58d85d1a5bdb8819985a5b1959606a1b608482015260a40161042e565b505050565b826001600160a01b03166114958383611521565b6001600160a01b03161461147c5760405162461bcd60e51b815260206004820152604760248201527f454950313237315369676e61747572655574696c732e636865636b5369676e6160448201527f747572655f454950313237313a207369676e6174757265206e6f742066726f6d6064820152661039b4b3b732b960c91b608482015260a40161042e565b60008060006115308585611545565b9150915061153d816115b5565b509392505050565b60008082516041141561157c5760208301516040840151606085015160001a61157087828585611770565b945094505050506115ae565b8251604014156115a6576020830151604084015161159b86838361185d565b9350935050506115ae565b506000905060025b9250929050565b60008160048111156115c9576115c961198e565b14156115d25750565b60018160048111156115e6576115e661198e565b14156116345760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161042e565b60028160048111156116485761164861198e565b14156116965760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161042e565b60038160048111156116aa576116aa61198e565b14156117035760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161042e565b60048160048111156117175761171761198e565b14156104405760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b606482015260840161042e565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156117a75750600090506003611854565b8460ff16601b141580156117bf57508460ff16601c14155b156117d05750600090506004611854565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611824573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661184d57600060019250925050611854565b9150600090505b94509492505050565b6000806001600160ff1b0383168161187a60ff86901c601b611d85565b905061188887828885611770565b935093505050935093915050565b6001600160a01b038116811461044057600080fd5b6000602082840312156118bd57600080fd5b81356118c881611896565b9392505050565b6000602082840312156118e157600080fd5b5035919050565b6000806000606084860312156118fd57600080fd5b833561190881611896565b9250602084013561191881611896565b929592945050506040919091013590565b6000806040838503121561193c57600080fd5b823561194781611896565b946020939093013593505050565b6000806040838503121561196857600080fd5b823561197381611896565b9150602083013561198381611896565b809150509250929050565b634e487b7160e01b600052602160045260246000fd5b60208101600283106119c657634e487b7160e01b600052602160045260246000fd5b91905290565b6000602082840312156119de57600080fd5b813560ff811681146118c857600080fd5b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715611a2857611a286119ef565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611a5757611a576119ef565b604052919050565b60008060408385031215611a7257600080fd5b8235611a7d81611896565b915060208381013567ffffffffffffffff80821115611a9b57600080fd5b9085019060608288031215611aaf57600080fd5b611ab7611a05565b823582811115611ac657600080fd5b8301601f81018913611ad757600080fd5b803583811115611ae957611ae96119ef565b611afb601f8201601f19168701611a2e565b93508084528986828401011115611b1157600080fd5b808683018786013760008682860101525050818152838301358482015260408301356040820152809450505050509250929050565b60008060008060808587031215611b5c57600080fd5b8435611b6781611896565b93506020850135611b7781611896565b93969395505050506040820135916060013590565b60008060208385031215611b9f57600080fd5b823567ffffffffffffffff80821115611bb757600080fd5b818501915085601f830112611bcb57600080fd5b813581811115611bda57600080fd5b866020828501011115611bec57600080fd5b60209290920196919550909350505050565b600060208284031215611c1057600080fd5b81516118c881611896565b6020808252602a908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526939903ab73830bab9b2b960b11b606082015260800190565b600060208284031215611c7757600080fd5b815180151581146118c857600080fd5b60208082526028908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526739903830bab9b2b960c11b606082015260800190565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b82815260006020604081840152835180604085015260005b81811015611d3257858101830151858201606001528201611d16565b81811115611d44576000606083870101525b50601f01601f191692909201606001949350505050565b600060208284031215611d6d57600080fd5b81516001600160e01b0319811681146118c857600080fd5b60008219821115611da657634e487b7160e01b600052601160045260246000fd5b50019056fe4156534469726563746f72792e72656769737465724f70657261746f72546f41a264697066735822122035e4c3eaa31b1c91dc8871d6557e0f59b044c1022304a54b456956202097c72f64736f6c634300080c0033", + "storage": { "0x0": "0xff" } + }, + "0x9a9f2ccfde556a7e9ff0848998aa4a0cfd8863ae": { + "nonce": 1, + "balance": "0x0", + "code": "0x60806040526004361061014b5760003560e01c806385594e58116100b6578063e4f4f8871161006f578063e4f4f887146103cc578063e5db06c014610405578063eb990c5914610425578063ecb7cb1b14610445578063f2fde38b14610472578063fabc1cbc1461049257600080fd5b806385594e5814610317578063886f1195146103445780638da5cb5b14610364578063c0db354c14610382578063ca661c0414610395578063d44e1b76146103ac57600080fd5b806350f73e7c1161010857806350f73e7c14610254578063595c6a67146102785780635ac86ab71461028d5780635c975abb146102cd578063715018a6146102e257806375608896146102f757600080fd5b806310d67a2f14610150578063136439dd146101725780631f39d87f146101925780633e1de008146101c85780634665bcda146101e85780634d50f9a414610234575b600080fd5b34801561015c57600080fd5b5061017061016b36600461196d565b6104b2565b005b34801561017e57600080fd5b5061017061018d366004611991565b61056e565b34801561019e57600080fd5b506101b26101ad36600461196d565b6106ad565b6040516101bf91906119c8565b60405180910390f35b3480156101d457600080fd5b506101b26101e336600461196d565b6108a8565b3480156101f457600080fd5b5061021c7f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe681565b6040516001600160a01b0390911681526020016101bf565b34801561024057600080fd5b5061017061024f366004611991565b6109ee565b34801561026057600080fd5b5061026a60c95481565b6040519081526020016101bf565b34801561028457600080fd5b506101706109ff565b34801561029957600080fd5b506102bd6102a8366004611a15565b609854600160ff9092169190911b9081161490565b60405190151581526020016101bf565b3480156102d957600080fd5b5060985461026a565b3480156102ee57600080fd5b50610170610ac6565b34801561030357600080fd5b506102bd610312366004611a38565b610ada565b34801561032357600080fd5b50610337610332366004611a38565b610b5d565b6040516101bf9190611a64565b34801561035057600080fd5b5060975461021c906001600160a01b031681565b34801561037057600080fd5b506033546001600160a01b031661021c565b610170610390366004611a72565b610bdd565b3480156103a157600080fd5b5061026a62034bc081565b3480156103b857600080fd5b506101706103c7366004611991565b610e9d565b3480156103d857600080fd5b5061026a6103e736600461196d565b6001600160a01b0316600090815260ca602052604090206001015490565b34801561041157600080fd5b50610170610420366004611a38565b610f31565b34801561043157600080fd5b50610170610440366004611aab565b610fc6565b34801561045157600080fd5b5061046561046036600461196d565b6110ee565b6040516101bf9190611af1565b34801561047e57600080fd5b5061017061048d36600461196d565b6111a8565b34801561049e57600080fd5b506101706104ad366004611991565b61121e565b609760009054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610505573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105299190611b47565b6001600160a01b0316336001600160a01b0316146105625760405162461bcd60e51b815260040161055990611b64565b60405180910390fd5b61056b8161137a565b50565b60975460405163237dfb4760e11b81523360048201526001600160a01b03909116906346fbf68e90602401602060405180830381865afa1580156105b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105da9190611bae565b6105f65760405162461bcd60e51b815260040161055990611bd0565b6098548181161461066f5760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e70617573653a20696e76616c696420617474656d70742060448201527f746f20756e70617573652066756e6374696f6e616c69747900000000000000006064820152608401610559565b609881905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d906020015b60405180910390a250565b6001600160a01b038116600090815260ca6020526040812080546001909101546060926106da8383611c2e565b90508060005b82811015610786576001600160a01b038716600090815260ca6020526040812060010161070d8388611c45565b8154811061071d5761071d611c5d565b6000918252602091829020604080518082019091529101546001600160e01b0381168252600160e01b900463ffffffff1691810182905260c95490925061076391611c45565b4310156107735781925050610786565b508061077e81611c73565b9150506106e0565b508060008167ffffffffffffffff8111156107a3576107a3611c8e565b6040519080825280602002602001820160405280156107e857816020015b60408051808201909152600080825260208201528152602001906001900390816107c15790505b509050811561089d5760005b8281101561089b576001600160a01b038916600090815260ca602052604090206001016108218289611c45565b8154811061083157610831611c5d565b6000918252602091829020604080518082019091529101546001600160e01b0381168252600160e01b900463ffffffff1691810191909152825183908390811061087d5761087d611c5d565b6020026020010181905250808061089390611c73565b9150506107f4565b505b979650505050505050565b6001600160a01b038116600090815260ca6020526040812080546001909101546060926108d58383611c2e565b905060008167ffffffffffffffff8111156108f2576108f2611c8e565b60405190808252806020026020018201604052801561093757816020015b60408051808201909152600080825260208201528152602001906001900390816109105790505b50905060005b828110156109e4576001600160a01b038716600090815260ca6020526040902060010161096a8287611c45565b8154811061097a5761097a611c5d565b6000918252602091829020604080518082019091529101546001600160e01b0381168252600160e01b900463ffffffff169181019190915282518390839081106109c6576109c6611c5d565b602002602001018190525080806109dc90611c73565b91505061093d565b5095945050505050565b6109f6611471565b61056b816114cb565b60975460405163237dfb4760e11b81523360048201526001600160a01b03909116906346fbf68e90602401602060405180830381865afa158015610a47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a6b9190611bae565b610a875760405162461bcd60e51b815260040161055990611bd0565b600019609881905560405190815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a2565b610ace611471565b610ad86000611593565b565b6001600160a01b038216600090815260ca60205260408120548210801590610b54575060c9546001600160a01b038416600090815260ca60205260409020600101805484908110610b2d57610b2d611c5d565b600091825260209091200154610b509190600160e01b900463ffffffff16611c45565b4310155b90505b92915050565b60408051808201909152600080825260208201526001600160a01b038316600090815260ca60205260409020600101805483908110610b9e57610b9e611c5d565b6000918252602091829020604080518082019091529101546001600160e01b0381168252600160e01b900463ffffffff16918101919091529392505050565b60405163a38406a360e01b81526001600160a01b038084166004830152839133917f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe6169063a38406a390602401602060405180830381865afa158015610c47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6b9190611b47565b6001600160a01b031614610ce75760405162461bcd60e51b815260206004820152603d60248201527f44656c617965645769746864726177616c526f757465722e6f6e6c794569676560448201527f6e506f643a206e6f7420706f644f776e6572277320456967656e506f640000006064820152608401610559565b60985460009060019081161415610d105760405162461bcd60e51b815260040161055990611ca4565b6001600160a01b038316610da65760405162461bcd60e51b815260206004820152605160248201527f44656c617965645769746864726177616c526f757465722e637265617465446560448201527f6c617965645769746864726177616c3a20726563697069656e742063616e6e6f60648201527074206265207a65726f206164647265737360781b608482015260a401610559565b346001600160e01b03811615610e96576040805180820182526001600160e01b03808416825263ffffffff43811660208085019182526001600160a01b038a16600081815260ca8352968720600190810180548083018255818a5293892088519551909616600160e01b029490961693909317939091019290925593525490917fb8f1b14c7caf74150801dcc9bc18d575cbeaf5b421943497e409df92c92e0f5991889188918691610e5791611c2e565b604080516001600160a01b0395861681529490931660208501526001600160e01b039091169183019190915260608201526080015b60405180910390a1505b5050505050565b60026065541415610ef05760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610559565b600260655560985460009060019081161415610f1e5760405162461bcd60e51b815260040161055990611ca4565b610f2833836115e5565b50506001606555565b60026065541415610f845760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610559565b600260655560985460009060019081161415610fb25760405162461bcd60e51b815260040161055990611ca4565b610fbc83836115e5565b5050600160655550565b600054610100900460ff1615808015610fe65750600054600160ff909116105b806110005750303b158015611000575060005460ff166001145b6110635760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610559565b6000805460ff191660011790558015611086576000805461ff0019166101001790555b61108f85611593565b6110998484611750565b6110a2826114cb565b8015610e96576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b6040805180820190915260008152606060208201526001600160a01b038216600090815260ca6020908152604080832081518083018352815481526001820180548451818702810187019095528085529195929486810194939192919084015b8282101561119a57600084815260209081902060408051808201909152908401546001600160e01b0381168252600160e01b900463ffffffff168183015282526001909201910161114e565b505050915250909392505050565b6111b0611471565b6001600160a01b0381166112155760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610559565b61056b81611593565b609760009054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611271573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112959190611b47565b6001600160a01b0316336001600160a01b0316146112c55760405162461bcd60e51b815260040161055990611b64565b6098541981196098541916146113435760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e756e70617573653a20696e76616c696420617474656d7060448201527f7420746f2070617573652066756e6374696f6e616c69747900000000000000006064820152608401610559565b609881905560405181815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c906020016106a2565b6001600160a01b0381166114085760405162461bcd60e51b815260206004820152604960248201527f5061757361626c652e5f73657450617573657252656769737472793a206e657760448201527f50617573657252656769737472792063616e6e6f7420626520746865207a65726064820152686f206164647265737360b81b608482015260a401610559565b609754604080516001600160a01b03928316815291831660208301527f6e9fcd539896fca60e8b0f01dd580233e48a6b0f7df013b89ba7f565869acdb6910160405180910390a1609780546001600160a01b0319166001600160a01b0392909216919091179055565b6033546001600160a01b03163314610ad85760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610559565b62034bc08111156115525760405162461bcd60e51b815260206004820152604560248201527f44656c617965645769746864726177616c526f757465722e5f7365745769746860448201527f64726177616c44656c6179426c6f636b733a206e657756616c756520746f6f206064820152646c6172676560d81b608482015260a401610559565b60c95460408051918252602082018390527f4ffb00400574147429ee377a5633386321e66d45d8b14676014b5fa393e61e9e910160405180910390a160c955565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b038216600090815260ca602052604081208054600190910154825b848110801561161e57508161161c8285611c45565b105b156116cb576001600160a01b038616600090815260ca602052604081206001016116488386611c45565b8154811061165857611658611c5d565b6000918252602091829020604080518082019091529101546001600160e01b0381168252600160e01b900463ffffffff1691810182905260c95490925061169e91611c45565b4310156116ab57506116cb565b80516116c0906001600160e01b031686611c45565b945050600101611607565b6116d58184611c45565b6001600160a01b038716600090815260ca602052604090205583156116fe576116fe868561183a565b7f6b7151500bd0b5cc211bcc47b3029831b769004df4549e8e1c9a69da05bb0943868561172b8487611c45565b604080516001600160a01b039094168452602084019290925290820152606001610e8c565b6097546001600160a01b031615801561177157506001600160a01b03821615155b6117f35760405162461bcd60e51b815260206004820152604760248201527f5061757361626c652e5f696e697469616c697a655061757365723a205f696e6960448201527f7469616c697a6550617573657228292063616e206f6e6c792062652063616c6c6064820152666564206f6e636560c81b608482015260a401610559565b609881905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a26118368261137a565b5050565b8047101561188a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610559565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146118d7576040519150601f19603f3d011682016040523d82523d6000602084013e6118dc565b606091505b50509050806119535760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610559565b505050565b6001600160a01b038116811461056b57600080fd5b60006020828403121561197f57600080fd5b813561198a81611958565b9392505050565b6000602082840312156119a357600080fd5b5035919050565b80516001600160e01b0316825260209081015163ffffffff16910152565b602080825282518282018190526000919060409081850190868401855b82811015611a08576119f88483516119aa565b92840192908501906001016119e5565b5091979650505050505050565b600060208284031215611a2757600080fd5b813560ff8116811461198a57600080fd5b60008060408385031215611a4b57600080fd5b8235611a5681611958565b946020939093013593505050565b60408101610b5782846119aa565b60008060408385031215611a8557600080fd5b8235611a9081611958565b91506020830135611aa081611958565b809150509250929050565b60008060008060808587031215611ac157600080fd5b8435611acc81611958565b93506020850135611adc81611958565b93969395505050506040820135916060013590565b602080825282518282015282810151604080840181905281516060850181905260009392830191849160808701905b8084101561089b57611b338286516119aa565b938501936001939093019290820190611b20565b600060208284031215611b5957600080fd5b815161198a81611958565b6020808252602a908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526939903ab73830bab9b2b960b11b606082015260800190565b600060208284031215611bc057600080fd5b8151801515811461198a57600080fd5b60208082526028908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526739903830bab9b2b960c11b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b600082821015611c4057611c40611c18565b500390565b60008219821115611c5857611c58611c18565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600019821415611c8757611c87611c18565b5060010190565b634e487b7160e01b600052604160045260246000fd5b60208082526019908201527f5061757361626c653a20696e646578206973207061757365640000000000000060408201526060019056fea26469706673582212209d542c62da84e9e3c0daf5d0574b8f3f6680f8ecf8ac38362e643b9e21612c1064736f6c634300080c0033", + "storage": { "0x0": "0xff" } + }, + "0x9e545e3c0baab3e08cdfd552c960a1050f373042": { + "nonce": 1, + "balance": "0x0", + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106f1565b610118565b61005b61009336600461070c565b61015f565b3480156100a457600080fd5b506100ad6101d0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106f1565b61020b565b3480156100f557600080fd5b506100ad610235565b61010661029b565b61011661011161033a565b610344565b565b610120610368565b6001600160a01b0316336001600160a01b03161415610157576101548160405180602001604052806000815250600061039b565b50565b6101546100fe565b610167610368565b6001600160a01b0316336001600160a01b031614156101c8576101c38383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001925061039b915050565b505050565b6101c36100fe565b60006101da610368565b6001600160a01b0316336001600160a01b03161415610200576101fb61033a565b905090565b6102086100fe565b90565b610213610368565b6001600160a01b0316336001600160a01b0316141561015757610154816103c6565b600061023f610368565b6001600160a01b0316336001600160a01b03161415610200576101fb610368565b6060610285838360405180606001604052806027815260200161080b6027913961041a565b9392505050565b6001600160a01b03163b151590565b6102a3610368565b6001600160a01b0316336001600160a01b031614156101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101fb6104f7565b3660008037600080366000845af43d6000803e808015610363573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103a48361051f565b6000825111806103b15750805b156101c3576103c08383610260565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103ef610368565b604080516001600160a01b03928316815291841660208301520160405180910390a16101548161055f565b60606001600160a01b0384163b6104825760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610331565b600080856001600160a01b03168560405161049d91906107bb565b600060405180830381855af49150503d80600081146104d8576040519150601f19603f3d011682016040523d82523d6000602084013e6104dd565b606091505b50915091506104ed828286610608565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61038c565b61052881610641565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105c45760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610331565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60608315610617575081610285565b8251156106275782518084602001fd5b8160405162461bcd60e51b815260040161033191906107d7565b6001600160a01b0381163b6106ae5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610331565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105e7565b80356001600160a01b03811681146106ec57600080fd5b919050565b60006020828403121561070357600080fd5b610285826106d5565b60008060006040848603121561072157600080fd5b61072a846106d5565b9250602084013567ffffffffffffffff8082111561074757600080fd5b818601915086601f83011261075b57600080fd5b81358181111561076a57600080fd5b87602082850101111561077c57600080fd5b6020830194508093505050509250925092565b60005b838110156107aa578181015183820152602001610792565b838111156103c05750506000910152565b600082516107cd81846020870161078f565b9190910192915050565b60208152600082518060208401526107f681604085016020870161078f565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212201336548e393b6bf33c1e3380011fea84db160f673ebc8828297c6c2b86153c4664736f6c634300080c0033", + "storage": { + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x95401dc811bb5740090279ba06cfa8fcf6113778", + "0x3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92eff": "0x1", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0xc5a5c42992decbae36851359345fe25997f5c42d", + "0xcfb339bd1c51c488f6134f4ac63d1594afad827b3401c3fc51ed1da74a8ca14e": "0x14" + } + }, + "0x9fe46736679d2d9a65f0992f2272de9f3c7fa6e0": { + "nonce": 1, + "balance": "0x0", + "code": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c806346fbf68e146100515780638568520614610089578063ce5484281461009e578063eab66d7a146100b1575b600080fd5b61007461005f366004610313565b60006020819052908152604090205460ff1681565b60405190151581526020015b60405180910390f35b61009c610097366004610335565b6100dc565b005b61009c6100ac366004610313565b61011d565b6001546100c4906001600160a01b031681565b6040516001600160a01b039091168152602001610080565b6001546001600160a01b0316331461010f5760405162461bcd60e51b815260040161010690610371565b60405180910390fd5b6101198282610153565b5050565b6001546001600160a01b031633146101475760405162461bcd60e51b815260040161010690610371565b61015081610220565b50565b6001600160a01b0382166101bf5760405162461bcd60e51b815260206004820152602d60248201527f50617573657252656769737472792e5f7365745061757365723a207a65726f2060448201526c1859191c995cdcc81a5b9c1d5d609a1b6064820152608401610106565b6001600160a01b03821660008181526020818152604091829020805460ff19168515159081179091558251938452908301527f65d3a1fd4c13f05cba164f80d03ce90fb4b5e21946bfc3ab7dbd434c2d0b9152910160405180910390a15050565b6001600160a01b03811661028e5760405162461bcd60e51b815260206004820152602f60248201527f50617573657252656769737472792e5f736574556e7061757365723a207a657260448201526e1bc81859191c995cdcc81a5b9c1d5d608a1b6064820152608401610106565b600154604080516001600160a01b03928316815291831660208301527f06b4167a2528887a1e97a366eefe8549bfbf1ea3e6ac81cb2564a934d20e8892910160405180910390a1600180546001600160a01b0319166001600160a01b0392909216919091179055565b80356001600160a01b038116811461030e57600080fd5b919050565b60006020828403121561032557600080fd5b61032e826102f7565b9392505050565b6000806040838503121561034857600080fd5b610351836102f7565b91506020830135801515811461036657600080fd5b809150509250929050565b6020808252602a908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526939903ab73830bab9b2b960b11b60608201526080019056fea26469706673582212203b45f7c66225e5887e8907d44b53ad76d03563101c6febf801e78006f96642e664736f6c634300080c0033", + "storage": { + "0x1": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x723077b8a1b173adc35e5f0e7e3662fd1208212cb629f9c128551ea7168da722": "0x1" + } + }, + "0xa0ee7a142d267c1f36714e4a8f75612f20a79720": { + "nonce": 5, + "balance": "0x21ea4a7ecb052eeae48", + "code": "0x", + "storage": {} + }, + "0xa513e6e4b8f2a923d98304ec87f64353c4d5c853": { + "nonce": 1, + "balance": "0x0", + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106f1565b610118565b61005b61009336600461070c565b61015f565b3480156100a457600080fd5b506100ad6101d0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106f1565b61020b565b3480156100f557600080fd5b506100ad610235565b61010661029b565b61011661011161033a565b610344565b565b610120610368565b6001600160a01b0316336001600160a01b03161415610157576101548160405180602001604052806000815250600061039b565b50565b6101546100fe565b610167610368565b6001600160a01b0316336001600160a01b031614156101c8576101c38383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001925061039b915050565b505050565b6101c36100fe565b60006101da610368565b6001600160a01b0316336001600160a01b03161415610200576101fb61033a565b905090565b6102086100fe565b90565b610213610368565b6001600160a01b0316336001600160a01b0316141561015757610154816103c6565b600061023f610368565b6001600160a01b0316336001600160a01b03161415610200576101fb610368565b6060610285838360405180606001604052806027815260200161080b6027913961041a565b9392505050565b6001600160a01b03163b151590565b6102a3610368565b6001600160a01b0316336001600160a01b031614156101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101fb6104f7565b3660008037600080366000845af43d6000803e808015610363573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103a48361051f565b6000825111806103b15750805b156101c3576103c08383610260565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103ef610368565b604080516001600160a01b03928316815291841660208301520160405180910390a16101548161055f565b60606001600160a01b0384163b6104825760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610331565b600080856001600160a01b03168560405161049d91906107bb565b600060405180830381855af49150503d80600081146104d8576040519150601f19603f3d011682016040523d82523d6000602084013e6104dd565b606091505b50915091506104ed828286610608565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61038c565b61052881610641565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105c45760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610331565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60608315610617575081610285565b8251156106275782518084602001fd5b8160405162461bcd60e51b815260040161033191906107d7565b6001600160a01b0381163b6106ae5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610331565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105e7565b80356001600160a01b03811681146106ec57600080fd5b919050565b60006020828403121561070357600080fd5b610285826106d5565b60008060006040848603121561072157600080fd5b61072a846106d5565b9250602084013567ffffffffffffffff8082111561074757600080fd5b818601915086601f83011261075b57600080fd5b81358181111561076a57600080fd5b87602082850101111561077c57600080fd5b6020830194508093505050509250925092565b60005b838110156107aa578181015183820152602001610792565b838111156103c05750506000910152565b600082516107cd81846020870161078f565b9190910192915050565b60208152600082518060208401526107f681604085016020870161078f565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212208c7daa35c73cc3931155de6fec176061a18c7828634d7222e2c3c877ecc7552c64736f6c634300080c0033", + "storage": { + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0xb306bf915c4d645ff596e518faf3f9669b97016", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512" + } + }, + "0xa51c1fc2f0d1a1b8494ed1fe312d7c3a78ed91c0": { + "nonce": 1, + "balance": "0x0", + "code": "0x608060405234801561001057600080fd5b50600436106103425760003560e01c8063635bbd10116101b8578063b7f06ebe11610104578063cf80873e116100a2578063f16172b01161007c578063f16172b014610908578063f2fde38b1461091b578063f698da251461092e578063fabc1cbc1461093657600080fd5b8063cf80873e146108c1578063da8be864146108e2578063eea9064b146108f557600080fd5b8063c488375a116100de578063c488375a146107de578063c5e480db146107fe578063c94b5111146108a4578063ca661c04146108b757600080fd5b8063b7f06ebe14610784578063bb45fef2146107a7578063c448feb8146107d557600080fd5b8063886f1195116101715780639104c3191161014b5780639104c3191461070f57806399be81c81461072a578063a17884841461073d578063b13442711461075d57600080fd5b8063886f1195146106cb5780638da5cb5b146106de57806390041347146106ef57600080fd5b8063635bbd101461063657806365da1264146106495780636d70f7ae14610672578063715018a614610685578063778e55f31461068d5780637f548071146106b857600080fd5b806328a573ae116102925780634665bcda11610230578063597b36da1161020a578063597b36da146105e55780635ac86ab7146105f85780635c975abb1461061b57806360d7faed1461062357600080fd5b80634665bcda146105ac5780634fc40b61146105d3578063595c6a67146105dd57600080fd5b806339b70e381161026c57806339b70e38146104f45780633cdeb5e0146105335780633e28391d14610562578063433773821461058557600080fd5b806328a573ae146104ae57806329c77d4f146104c157806333404396146104e157600080fd5b8063132d4967116102ff57806316928365116102d957806316928365146104285780631bbce0911461046157806320606b701461047457806322bf40e41461049b57600080fd5b8063132d4967146103ef578063136439dd146104025780631522bf021461041557600080fd5b80630449ca391461034757806304a4f9791461036d5780630b9f487a146103945780630dd8dd02146103a75780630f589e59146103c757806310d67a2f146103dc575b600080fd5b61035a610355366004614835565b610949565b6040519081526020015b60405180910390f35b61035a7f14bde674c9f64b2ad00eaaee4a8bed1fabef35c7507e3c5b9cfc9436909a2dad81565b61035a6103a236600461489b565b6109ce565b6103ba6103b5366004614835565b610a90565b60405161036491906148f6565b6103da6103d5366004614993565b610df9565b005b6103da6103ea3660046149e6565b610f3e565b6103da6103fd366004614a0a565b610ff1565b6103da610410366004614a4b565b6110a8565b6103da610423366004614a64565b6111e7565b61035a6104363660046149e6565b6001600160a01b0316600090815260996020526040902060010154600160a01b900463ffffffff1690565b61035a61046f366004614a0a565b6111fb565b61035a7f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6103da6104a9366004614acf565b611229565b6103da6104bc366004614a0a565b61136d565b61035a6104cf3660046149e6565b609b6020526000908152604090205481565b6103da6104ef366004614b76565b61141d565b61051b7f0000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f87570781565b6040516001600160a01b039091168152602001610364565b61051b6105413660046149e6565b6001600160a01b039081166000908152609960205260409020600101541690565b6105756105703660046149e6565b61155a565b6040519015158152602001610364565b61035a7f39111bc4a4d688e1f685123d7497d4615370152a8ee4a0593e647bd06ad8bb0b81565b61051b7f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe681565b61035a6213c68081565b6103da61157a565b61035a6105f3366004614e73565b611641565b610575610606366004614eaf565b606654600160ff9092169190911b9081161490565b60665461035a565b6103da610631366004614ee0565b611671565b6103da610644366004614a4b565b61170c565b61051b6106573660046149e6565b609a602052600090815260409020546001600160a01b031681565b6105756106803660046149e6565b61171d565b6103da61173e565b61035a61069b366004614f6f565b609860209081526000928352604080842090915290825290205481565b6103da6106c6366004615050565b611752565b60655461051b906001600160a01b031681565b6033546001600160a01b031661051b565b6107026106fd3660046150e0565b61197e565b604051610364919061516a565b61051b73beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac081565b6103da61073836600461517d565b611a58565b61035a61074b3660046149e6565b609f6020526000908152604090205481565b61051b7f000000000000000000000000a513e6e4b8f2a923d98304ec87f64353c4d5c85381565b610575610792366004614a4b565b609e6020526000908152604090205460ff1681565b6105756107b53660046151b2565b609c60209081526000928352604080842090915290825290205460ff1681565b61035a609d5481565b61035a6107ec3660046149e6565b60a16020526000908152604090205481565b61086e61080c3660046149e6565b6040805160608082018352600080835260208084018290529284018190526001600160a01b03948516815260998352839020835191820184528054851682526001015493841691810191909152600160a01b90920463ffffffff169082015290565b6040805182516001600160a01b039081168252602080850151909116908201529181015163ffffffff1690820152606001610364565b61035a6108b23660046151de565b611b2a565b61035a62034bc081565b6108d46108cf3660046149e6565b611be3565b60405161036492919061525f565b6103ba6108f03660046149e6565b611f9b565b6103da610903366004615284565b61245f565b6103da6109163660046152dc565b61257c565b6103da6109293660046149e6565b61260d565b61035a612683565b6103da610944366004614a4b565b6126c1565b609d54600090815b838110156109c657600060a16000878785818110610971576109716152f8565b905060200201602081019061098691906149e6565b6001600160a01b03166001600160a01b03168152602001908152602001600020549050828111156109b5578092505b506109bf81615324565b9050610951565b509392505050565b604080517f14bde674c9f64b2ad00eaaee4a8bed1fabef35c7507e3c5b9cfc9436909a2dad6020808301919091526001600160a01b038681168385015288811660608401528716608083015260a0820185905260c08083018590528351808403909101815260e0909201909252805191012060009081610a4c612683565b60405161190160f01b602082015260228101919091526042810183905260620160408051808303601f19018152919052805160209091012098975050505050505050565b60665460609060019060029081161415610ac55760405162461bcd60e51b8152600401610abc9061533f565b60405180910390fd5b6000836001600160401b03811115610adf57610adf614c18565b604051908082528060200260200182016040528015610b08578160200160208202803683370190505b50336000908152609a60205260408120549192506001600160a01b03909116905b85811015610dee57868682818110610b4357610b436152f8565b9050602002810190610b559190615376565b610b63906020810190615396565b9050878783818110610b7757610b776152f8565b9050602002810190610b899190615376565b610b939080615396565b905014610c085760405162461bcd60e51b815260206004820152603860248201527f44656c65676174696f6e4d616e616765722e717565756557697468647261776160448201527f6c3a20696e707574206c656e677468206d69736d6174636800000000000000006064820152608401610abc565b33878783818110610c1b57610c1b6152f8565b9050602002810190610c2d9190615376565b610c3e9060608101906040016149e6565b6001600160a01b031614610cba5760405162461bcd60e51b815260206004820152603c60248201527f44656c65676174696f6e4d616e616765722e717565756557697468647261776160448201527f6c3a2077697468647261776572206d757374206265207374616b6572000000006064820152608401610abc565b610dbf3383898985818110610cd157610cd16152f8565b9050602002810190610ce39190615376565b610cf49060608101906040016149e6565b8a8a86818110610d0657610d066152f8565b9050602002810190610d189190615376565b610d229080615396565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508e92508d9150889050818110610d6857610d686152f8565b9050602002810190610d7a9190615376565b610d88906020810190615396565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061281d92505050565b838281518110610dd157610dd16152f8565b602090810291909101015280610de681615324565b915050610b29565b509095945050505050565b610e023361155a565b15610e885760405162461bcd60e51b815260206004820152604a60248201527f44656c65676174696f6e4d616e616765722e726567697374657241734f70657260448201527f61746f723a2063616c6c657220697320616c7265616479206163746976656c796064820152690819195b1959d85d195960b21b608482015260a401610abc565b610e923384612ddd565b604080518082019091526060815260006020820152610eb43380836000612fd0565b336001600160a01b03167f8e8485583a2310d41f7c82b9427d0bd49bad74bb9cff9d3402a29d8f9b28a0e285604051610eed91906153df565b60405180910390a2336001600160a01b03167f02a919ed0e2acad1dd90f17ef2fa4ae5462ee1339170034a8531cca4b67080908484604051610f30929190615431565b60405180910390a250505050565b606560009054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fb59190615460565b6001600160a01b0316336001600160a01b031614610fe55760405162461bcd60e51b8152600401610abc9061547d565b610fee81613266565b50565b336001600160a01b037f0000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f8757071614806110505750336001600160a01b037f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe616145b61106c5760405162461bcd60e51b8152600401610abc906154c7565b6110758361155a565b156110a3576001600160a01b038084166000908152609a6020526040902054166110a18185858561335d565b505b505050565b60655460405163237dfb4760e11b81523360048201526001600160a01b03909116906346fbf68e90602401602060405180830381865afa1580156110f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111149190615524565b6111305760405162461bcd60e51b8152600401610abc90615541565b606654818116146111a95760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e70617573653a20696e76616c696420617474656d70742060448201527f746f20756e70617573652066756e6374696f6e616c69747900000000000000006064820152608401610abc565b606681905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d906020015b60405180910390a250565b6111ef6133d8565b6110a184848484613432565b6001600160a01b0383166000908152609b602052604081205461122085828686611b2a565b95945050505050565b600054610100900460ff16158080156112495750600054600160ff909116105b806112635750303b158015611263575060005460ff166001145b6112c65760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610abc565b6000805460ff1916600117905580156112e9576000805461ff0019166101001790555b6112f38888613658565b6112fb613742565b609755611307896137d9565b6113108661382b565b61131c85858585613432565b8015611362576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050565b336001600160a01b037f0000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f8757071614806113cc5750336001600160a01b037f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe616145b6113e85760405162461bcd60e51b8152600401610abc906154c7565b6113f18361155a565b156110a3576001600160a01b038084166000908152609a6020526040902054166110a181858585613925565b606654600290600490811614156114465760405162461bcd60e51b8152600401610abc9061533f565b600260c95414156114995760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610abc565b600260c95560005b88811015611549576115398a8a838181106114be576114be6152f8565b90506020028101906114d09190615589565b8989848181106114e2576114e26152f8565b90506020028101906114f49190615396565b898986818110611506576115066152f8565b9050602002013588888781811061151f5761151f6152f8565b9050602002016020810190611534919061559f565b6139a0565b61154281615324565b90506114a1565b5050600160c9555050505050505050565b6001600160a01b039081166000908152609a602052604090205416151590565b60655460405163237dfb4760e11b81523360048201526001600160a01b03909116906346fbf68e90602401602060405180830381865afa1580156115c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115e69190615524565b6116025760405162461bcd60e51b8152600401610abc90615541565b600019606681905560405190815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a2565b6000816040516020016116549190615630565b604051602081830303815290604052805190602001209050919050565b6066546002906004908116141561169a5760405162461bcd60e51b8152600401610abc9061533f565b600260c95414156116ed5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610abc565b600260c9556116ff86868686866139a0565b5050600160c95550505050565b6117146133d8565b610fee8161382b565b6001600160a01b039081166000818152609a60205260409020549091161490565b6117466133d8565b61175060006137d9565b565b42836020015110156117d65760405162461bcd60e51b815260206004820152604160248201527f44656c65676174696f6e4d616e616765722e64656c6567617465546f4279536960448201527f676e61747572653a207374616b6572207369676e6174757265206578706972656064820152601960fa1b608482015260a401610abc565b6117df8561155a565b156118685760405162461bcd60e51b815260206004820152604d60248201527f44656c65676174696f6e4d616e616765722e64656c6567617465546f4279536960448201527f676e61747572653a207374616b657220697320616c726561647920616374697660648201526c195b1e4819195b1959d85d1959609a1b608482015260a401610abc565b6118718461171d565b6118fd5760405162461bcd60e51b815260206004820152605160248201527f44656c65676174696f6e4d616e616765722e64656c6567617465546f4279536960448201527f676e61747572653a206f70657261746f72206973206e6f7420726567697374656064820152703932b21034b71022b4b3b2b72630bcb2b960791b608482015260a401610abc565b6000609b6000876001600160a01b03166001600160a01b0316815260200190815260200160002054905060006119398783888860200151611b2a565b6001600160a01b0388166000908152609b602052604090206001840190558551909150611969908890839061418a565b61197587878686612fd0565b50505050505050565b6060600082516001600160401b0381111561199b5761199b614c18565b6040519080825280602002602001820160405280156119c4578160200160208202803683370190505b50905060005b83518110156109c6576001600160a01b03851660009081526098602052604081208551909190869084908110611a0257611a026152f8565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110611a3d57611a3d6152f8565b6020908102919091010152611a5181615324565b90506119ca565b611a613361171d565b611ae35760405162461bcd60e51b815260206004820152604760248201527f44656c65676174696f6e4d616e616765722e7570646174654f70657261746f7260448201527f4d657461646174615552493a2063616c6c6572206d75737420626520616e206f6064820152663832b930ba37b960c91b608482015260a401610abc565b336001600160a01b03167f02a919ed0e2acad1dd90f17ef2fa4ae5462ee1339170034a8531cca4b67080908383604051611b1e929190615431565b60405180910390a25050565b604080517f39111bc4a4d688e1f685123d7497d4615370152a8ee4a0593e647bd06ad8bb0b6020808301919091526001600160a01b0387811683850152851660608301526080820186905260a08083018590528351808403909101815260c0909201909252805191012060009081611ba0612683565b60405161190160f01b602082015260228101919091526042810183905260620160408051808303601f190181529190528051602090910120979650505050505050565b6040516360f4062b60e01b81526001600160a01b03828116600483015260609182916000917f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe6909116906360f4062b90602401602060405180830381865afa158015611c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c779190615643565b6040516394f649dd60e01b81526001600160a01b03868116600483015291925060009182917f0000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f875707909116906394f649dd90602401600060405180830381865afa158015611ce7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d0f91908101906156b7565b9150915060008313611d2657909590945092505050565b606080835160001415611de0576040805160018082528183019092529060208083019080368337505060408051600180825281830190925292945090506020808301908036833701905050905073beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac082600081518110611d9b57611d9b6152f8565b60200260200101906001600160a01b031690816001600160a01b0316815250508481600081518110611dcf57611dcf6152f8565b602002602001018181525050611f8e565b8351611ded906001615771565b6001600160401b03811115611e0457611e04614c18565b604051908082528060200260200182016040528015611e2d578160200160208202803683370190505b50915081516001600160401b03811115611e4957611e49614c18565b604051908082528060200260200182016040528015611e72578160200160208202803683370190505b50905060005b8451811015611f0c57848181518110611e9357611e936152f8565b6020026020010151838281518110611ead57611ead6152f8565b60200260200101906001600160a01b031690816001600160a01b031681525050838181518110611edf57611edf6152f8565b6020026020010151828281518110611ef957611ef96152f8565b6020908102919091010152600101611e78565b5073beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac08260018451611f319190615789565b81518110611f4157611f416152f8565b60200260200101906001600160a01b031690816001600160a01b031681525050848160018451611f719190615789565b81518110611f8157611f816152f8565b6020026020010181815250505b9097909650945050505050565b60665460609060019060029081161415611fc75760405162461bcd60e51b8152600401610abc9061533f565b611fd08361155a565b6120505760405162461bcd60e51b8152602060048201526044602482018190527f44656c65676174696f6e4d616e616765722e756e64656c65676174653a207374908201527f616b6572206d7573742062652064656c65676174656420746f20756e64656c656064820152636761746560e01b608482015260a401610abc565b6120598361171d565b156120cc5760405162461bcd60e51b815260206004820152603d60248201527f44656c65676174696f6e4d616e616765722e756e64656c65676174653a206f7060448201527f657261746f72732063616e6e6f7420626520756e64656c6567617465640000006064820152608401610abc565b6001600160a01b0383166121485760405162461bcd60e51b815260206004820152603c60248201527f44656c65676174696f6e4d616e616765722e756e64656c65676174653a20636160448201527f6e6e6f7420756e64656c6567617465207a65726f2061646472657373000000006064820152608401610abc565b6001600160a01b038084166000818152609a60205260409020549091169033148061217b5750336001600160a01b038216145b806121a257506001600160a01b038181166000908152609960205260409020600101541633145b6122145760405162461bcd60e51b815260206004820152603d60248201527f44656c65676174696f6e4d616e616765722e756e64656c65676174653a20636160448201527f6c6c65722063616e6e6f7420756e64656c6567617465207374616b65720000006064820152608401610abc565b60008061222086611be3565b9092509050336001600160a01b0387161461227657826001600160a01b0316866001600160a01b03167ff0eddf07e6ea14f388b47e1e94a0f464ecbd9eed4171130e0fc0e99fb4030a8a60405160405180910390a35b826001600160a01b0316866001600160a01b03167ffee30966a256b71e14bc0ebfc94315e28ef4a97a7131a9e2b7a310a73af4467660405160405180910390a36001600160a01b0386166000908152609a6020526040902080546001600160a01b031916905581516122f8576040805160008152602081019091529450612456565b81516001600160401b0381111561231157612311614c18565b60405190808252806020026020018201604052801561233a578160200160208202803683370190505b50945060005b8251811015612454576040805160018082528183019092526000916020808301908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090508483815181106123a0576123a06152f8565b6020026020010151826000815181106123bb576123bb6152f8565b60200260200101906001600160a01b031690816001600160a01b0316815250508383815181106123ed576123ed6152f8565b602002602001015181600081518110612408576124086152f8565b60200260200101818152505061242189878b858561281d565b888481518110612433576124336152f8565b6020026020010181815250505050808061244c90615324565b915050612340565b505b50505050919050565b6124683361155a565b156124e65760405162461bcd60e51b815260206004820152604260248201527f44656c65676174696f6e4d616e616765722e64656c6567617465546f3a20737460448201527f616b657220697320616c7265616479206163746976656c792064656c65676174606482015261195960f21b608482015260a401610abc565b6124ef8361171d565b6125705760405162461bcd60e51b815260206004820152604660248201527f44656c65676174696f6e4d616e616765722e64656c6567617465546f3a206f7060448201527f657261746f72206973206e6f74207265676973746572656420696e2045696765606482015265372630bcb2b960d11b608482015260a401610abc565b6110a333848484612fd0565b6125853361171d565b6126035760405162461bcd60e51b815260206004820152604360248201527f44656c65676174696f6e4d616e616765722e6d6f646966794f70657261746f7260448201527f44657461696c733a2063616c6c6572206d75737420626520616e206f706572616064820152623a37b960e91b608482015260a401610abc565b610fee3382612ddd565b6126156133d8565b6001600160a01b03811661267a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610abc565b610fee816137d9565b60007f0000000000000000000000000000000000000000000000000000000000007a694614156126b4575060975490565b6126bc613742565b905090565b606560009054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612714573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127389190615460565b6001600160a01b0316336001600160a01b0316146127685760405162461bcd60e51b8152600401610abc9061547d565b6066541981196066541916146127e65760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e756e70617573653a20696e76616c696420617474656d7060448201527f7420746f2070617573652066756e6374696f6e616c69747900000000000000006064820152608401610abc565b606681905560405181815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c906020016111dc565b60006001600160a01b0386166128b45760405162461bcd60e51b815260206004820152605060248201527f44656c65676174696f6e4d616e616765722e5f72656d6f76655368617265734160448201527f6e6451756575655769746864726177616c3a207374616b65722063616e6e6f7460648201526f206265207a65726f206164647265737360801b608482015260a401610abc565b825161293e5760405162461bcd60e51b815260206004820152604d60248201527f44656c65676174696f6e4d616e616765722e5f72656d6f76655368617265734160448201527f6e6451756575655769746864726177616c3a207374726174656769657320636160648201526c6e6e6f7420626520656d70747960981b608482015260a401610abc565b60005b8351811015612ceb576001600160a01b03861615612997576129978688868481518110612970576129706152f8565b602002602001015186858151811061298a5761298a6152f8565b602002602001015161335d565b73beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac06001600160a01b03168482815181106129c7576129c76152f8565b60200260200101516001600160a01b03161415612a90577f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe66001600160a01b031663beffbb8988858481518110612a2057612a206152f8565b60200260200101516040518363ffffffff1660e01b8152600401612a599291906001600160a01b03929092168252602082015260400190565b600060405180830381600087803b158015612a7357600080fd5b505af1158015612a87573d6000803e3d6000fd5b50505050612ce3565b846001600160a01b0316876001600160a01b03161480612b6257507f0000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f8757076001600160a01b0316639b4da03d858381518110612aec57612aec6152f8565b60200260200101516040518263ffffffff1660e01b8152600401612b1f91906001600160a01b0391909116815260200190565b602060405180830381865afa158015612b3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b609190615524565b155b612c2e5760405162461bcd60e51b8152602060048201526084602482018190527f44656c65676174696f6e4d616e616765722e5f72656d6f76655368617265734160448301527f6e6451756575655769746864726177616c3a2077697468647261776572206d7560648301527f73742062652073616d652061646472657373206173207374616b657220696620908201527f746869726450617274795472616e7366657273466f7262696464656e2061726560a482015263081cd95d60e21b60c482015260e401610abc565b7f0000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f8757076001600160a01b0316638c80d4e588868481518110612c7057612c706152f8565b6020026020010151868581518110612c8a57612c8a6152f8565b60200260200101516040518463ffffffff1660e01b8152600401612cb0939291906157a0565b600060405180830381600087803b158015612cca57600080fd5b505af1158015612cde573d6000803e3d6000fd5b505050505b600101612941565b506001600160a01b0386166000908152609f60205260408120805491829190612d1383615324565b919050555060006040518060e00160405280896001600160a01b03168152602001886001600160a01b03168152602001876001600160a01b031681526020018381526020014363ffffffff1681526020018681526020018581525090506000612d7b82611641565b6000818152609e602052604090819020805460ff19166001179055519091507f9009ab153e8014fbfb02f2217f5cde7aa7f9ad734ae85ca3ee3f4ca2fdd499f990612dc990839085906157c4565b60405180910390a198975050505050505050565b6213c680612df160608301604084016157dd565b63ffffffff161115612ea65760405162461bcd60e51b815260206004820152606c60248201527f44656c65676174696f6e4d616e616765722e5f7365744f70657261746f72446560448201527f7461696c733a207374616b65724f70744f757457696e646f77426c6f636b732060648201527f63616e6e6f74206265203e204d41585f5354414b45525f4f50545f4f55545f5760848201526b494e444f575f424c4f434b5360a01b60a482015260c401610abc565b6001600160a01b0382166000908152609960205260409081902060010154600160a01b900463ffffffff1690612ee290606084019084016157dd565b63ffffffff161015612f785760405162461bcd60e51b815260206004820152605360248201527f44656c65676174696f6e4d616e616765722e5f7365744f70657261746f72446560448201527f7461696c733a207374616b65724f70744f757457696e646f77426c6f636b732060648201527218d85b9b9bdd08189948191958dc99585cd959606a1b608482015260a401610abc565b6001600160a01b03821660009081526099602052604090208190612f9c828261581a565b505060405133907ffebe5cd24b2cbc7b065b9d0fdeb904461e4afcff57dd57acda1e7832031ba7ac90611b1e9084906153df565b60665460009060019081161415612ff95760405162461bcd60e51b8152600401610abc9061533f565b6001600160a01b0380851660009081526099602052604090206001015416801580159061302f5750336001600160a01b03821614155b80156130445750336001600160a01b03861614155b156131b15742846020015110156130c35760405162461bcd60e51b815260206004820152603760248201527f44656c65676174696f6e4d616e616765722e5f64656c65676174653a2061707060448201527f726f766572207369676e617475726520657870697265640000000000000000006064820152608401610abc565b6001600160a01b0381166000908152609c6020908152604080832086845290915290205460ff161561315d5760405162461bcd60e51b815260206004820152603760248201527f44656c65676174696f6e4d616e616765722e5f64656c65676174653a2061707060448201527f726f76657253616c7420616c7265616479207370656e740000000000000000006064820152608401610abc565b6001600160a01b0381166000908152609c6020908152604080832086845282528220805460ff1916600117905585015161319e9088908890859088906109ce565b90506131af8282876000015161418a565b505b6001600160a01b038681166000818152609a602052604080822080546001600160a01b031916948a169485179055517fc3ee9f2e5fda98e8066a1f745b2df9285f416fe98cf2559cd21484b3d87433049190a360008061321088611be3565b9150915060005b82518110156113625761325e888a858481518110613237576132376152f8565b6020026020010151858581518110613251576132516152f8565b6020026020010151613925565b600101613217565b6001600160a01b0381166132f45760405162461bcd60e51b815260206004820152604960248201527f5061757361626c652e5f73657450617573657252656769737472793a206e657760448201527f50617573657252656769737472792063616e6e6f7420626520746865207a65726064820152686f206164647265737360b81b608482015260a401610abc565b606554604080516001600160a01b03928316815291831660208301527f6e9fcd539896fca60e8b0f01dd580233e48a6b0f7df013b89ba7f565869acdb6910160405180910390a1606580546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03808516600090815260986020908152604080832093861683529290529081208054839290613394908490615789565b92505081905550836001600160a01b03167f6909600037b75d7b4733aedd815442b5ec018a827751c832aaff64eba5d6d2dd848484604051610f30939291906157a0565b6033546001600160a01b031633146117505760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610abc565b8281146134ba5760405162461bcd60e51b815260206004820152604a60248201527f44656c65676174696f6e4d616e616765722e5f7365745374726174656779576960448201527f746864726177616c44656c6179426c6f636b733a20696e707574206c656e67746064820152690d040dad2e6dac2e8c6d60b31b608482015260a401610abc565b8260005b818110156136505760008686838181106134da576134da6152f8565b90506020020160208101906134ef91906149e6565b6001600160a01b038116600090815260a1602052604081205491925086868581811061351d5761351d6152f8565b90506020020135905062034bc08111156135e15760405162461bcd60e51b815260206004820152607360248201527f44656c65676174696f6e4d616e616765722e5f7365745374726174656779576960448201527f746864726177616c44656c6179426c6f636b733a205f7769746864726177616c60648201527f44656c6179426c6f636b732063616e6e6f74206265203e204d41585f5749544860848201527244524157414c5f44454c41595f424c4f434b5360681b60a482015260c401610abc565b6001600160a01b038316600081815260a160209081526040918290208490558151928352820184905281018290527f0e7efa738e8b0ce6376a0c1af471655540d2e9a81647d7b09ed823018426576d9060600160405180910390a15050508061364990615324565b90506134be565b505050505050565b6065546001600160a01b031615801561367957506001600160a01b03821615155b6136fb5760405162461bcd60e51b815260206004820152604760248201527f5061757361626c652e5f696e697469616c697a655061757365723a205f696e6960448201527f7469616c697a6550617573657228292063616e206f6e6c792062652063616c6c6064820152666564206f6e636560c81b608482015260a401610abc565b606681905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a261373e82613266565b5050565b604080518082018252600a81526922b4b3b2b72630bcb2b960b11b60209182015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527f71b625cfad44bac63b13dba07f2e1d6084ee04b6f8752101ece6126d584ee6ea81840152466060820152306080808301919091528351808303909101815260a0909101909252815191012090565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b62034bc08111156138e45760405162461bcd60e51b815260206004820152607160248201527f44656c65676174696f6e4d616e616765722e5f7365744d696e5769746864726160448201527f77616c44656c6179426c6f636b733a205f6d696e5769746864726177616c446560648201527f6c6179426c6f636b732063616e6e6f74206265203e204d41585f5749544844526084820152704157414c5f44454c41595f424c4f434b5360781b60a482015260c401610abc565b609d5460408051918252602082018390527fafa003cd76f87ff9d62b35beea889920f33c0c42b8d45b74954d61d50f4b6b69910160405180910390a1609d55565b6001600160a01b0380851660009081526098602090815260408083209386168352929052908120805483929061395c908490615771565b92505081905550836001600160a01b03167f1ec042c965e2edd7107b51188ee0f383e22e76179041ab3a9d18ff151405166c848484604051610f30939291906157a0565b60006139ae6105f38761587d565b6000818152609e602052604090205490915060ff16613a2f5760405162461bcd60e51b815260206004820152604360248201526000805160206159b583398151915260448201527f645769746864726177616c3a20616374696f6e206973206e6f7420696e20717560648201526265756560e81b608482015260a401610abc565b609d544390613a4460a0890160808a016157dd565b63ffffffff16613a549190615771565b1115613adc5760405162461bcd60e51b815260206004820152605f60248201526000805160206159b583398151915260448201527f645769746864726177616c3a206d696e5769746864726177616c44656c61794260648201527f6c6f636b7320706572696f6420686173206e6f74207965742070617373656400608482015260a401610abc565b613aec60608701604088016149e6565b6001600160a01b0316336001600160a01b031614613b795760405162461bcd60e51b815260206004820152605060248201526000805160206159b583398151915260448201527f645769746864726177616c3a206f6e6c7920776974686472617765722063616e60648201526f1031b7b6b83632ba329030b1ba34b7b760811b608482015260a401610abc565b8115613bfb57613b8c60a0870187615396565b85149050613bfb5760405162461bcd60e51b815260206004820152604260248201526000805160206159b583398151915260448201527f645769746864726177616c3a20696e707574206c656e677468206d69736d61746064820152610c6d60f31b608482015260a401610abc565b6000818152609e60205260409020805460ff191690558115613d605760005b613c2760a0880188615396565b9050811015613d5a574360a16000613c4260a08b018b615396565b85818110613c5257613c526152f8565b9050602002016020810190613c6791906149e6565b6001600160a01b03168152602081019190915260400160002054613c9160a08a0160808b016157dd565b63ffffffff16613ca19190615771565b1115613cbf5760405162461bcd60e51b8152600401610abc9061588f565b613d52613ccf60208901896149e6565b33613cdd60a08b018b615396565b85818110613ced57613ced6152f8565b9050602002016020810190613d0291906149e6565b613d0f60c08c018c615396565b86818110613d1f57613d1f6152f8565b905060200201358a8a87818110613d3857613d386152f8565b9050602002016020810190613d4d91906149e6565b614344565b600101613c1a565b5061414f565b336000908152609a60205260408120546001600160a01b0316905b613d8860a0890189615396565b905081101561414c574360a16000613da360a08c018c615396565b85818110613db357613db36152f8565b9050602002016020810190613dc891906149e6565b6001600160a01b03168152602081019190915260400160002054613df260a08b0160808c016157dd565b63ffffffff16613e029190615771565b1115613e205760405162461bcd60e51b8152600401610abc9061588f565b73beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac0613e4260a08a018a615396565b83818110613e5257613e526152f8565b9050602002016020810190613e6791906149e6565b6001600160a01b03161415613fb7576000613e8560208a018a6149e6565b905060006001600160a01b037f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe616630e81073c83613ec660c08e018e615396565b87818110613ed657613ed66152f8565b6040516001600160e01b031960e087901b1681526001600160a01b03909416600485015260200291909101356024830152506044016020604051808303816000875af1158015613f2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f4e9190615643565b6001600160a01b038084166000908152609a6020526040902054919250168015613faf57613faf8184613f8460a08f018f615396565b88818110613f9457613f946152f8565b9050602002016020810190613fa991906149e6565b85613925565b505050614144565b7f0000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f8757076001600160a01b031663c4623ea133898985818110613ff957613ff96152f8565b905060200201602081019061400e91906149e6565b61401b60a08d018d615396565b8681811061402b5761402b6152f8565b905060200201602081019061404091906149e6565b61404d60c08e018e615396565b8781811061405d5761405d6152f8565b60405160e088901b6001600160e01b03191681526001600160a01b03968716600482015294861660248601529290941660448401526020909102013560648201526084019050600060405180830381600087803b1580156140bd57600080fd5b505af11580156140d1573d6000803e3d6000fd5b505050506001600160a01b038216156141445761414482336140f660a08c018c615396565b85818110614106576141066152f8565b905060200201602081019061411b91906149e6565b61412860c08d018d615396565b86818110614138576141386152f8565b90506020020135613925565b600101613d7b565b50505b6040518181527fc97098c2f658800b4df29001527f7324bcdffcf6e8751a699ab920a1eced5b1d9060200160405180910390a1505050505050565b6001600160a01b0383163b156142a457604051630b135d3f60e11b808252906001600160a01b03851690631626ba7e906141ca9086908690600401615917565b602060405180830381865afa1580156141e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061420b9190615974565b6001600160e01b031916146110a35760405162461bcd60e51b815260206004820152605360248201527f454950313237315369676e61747572655574696c732e636865636b5369676e6160448201527f747572655f454950313237313a2045524331323731207369676e6174757265206064820152721d995c9a599a58d85d1a5bdb8819985a5b1959606a1b608482015260a401610abc565b826001600160a01b03166142b88383614484565b6001600160a01b0316146110a35760405162461bcd60e51b815260206004820152604760248201527f454950313237315369676e61747572655574696c732e636865636b5369676e6160448201527f747572655f454950313237313a207369676e6174757265206e6f742066726f6d6064820152661039b4b3b732b960c91b608482015260a401610abc565b6001600160a01b03831673beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac014156143ef5760405162387b1360e81b81526001600160a01b037f0000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe6169063387b1300906143b8908890889087906004016157a0565b600060405180830381600087803b1580156143d257600080fd5b505af11580156143e6573d6000803e3d6000fd5b5050505061447d565b60405163c608c7f360e01b81526001600160a01b03858116600483015284811660248301526044820184905282811660648301527f0000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f875707169063c608c7f390608401600060405180830381600087803b15801561446957600080fd5b505af1158015611362573d6000803e3d6000fd5b5050505050565b600080600061449385856144a0565b915091506109c681614510565b6000808251604114156144d75760208301516040840151606085015160001a6144cb878285856146cb565b94509450505050614509565b82516040141561450157602083015160408401516144f68683836147b8565b935093505050614509565b506000905060025b9250929050565b60008160048111156145245761452461599e565b141561452d5750565b60018160048111156145415761454161599e565b141561458f5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610abc565b60028160048111156145a3576145a361599e565b14156145f15760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610abc565b60038160048111156146055761460561599e565b141561465e5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610abc565b60048160048111156146725761467261599e565b1415610fee5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610abc565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561470257506000905060036147af565b8460ff16601b1415801561471a57508460ff16601c14155b1561472b57506000905060046147af565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561477f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166147a8576000600192509250506147af565b9150600090505b94509492505050565b6000806001600160ff1b038316816147d560ff86901c601b615771565b90506147e3878288856146cb565b935093505050935093915050565b60008083601f84011261480357600080fd5b5081356001600160401b0381111561481a57600080fd5b6020830191508360208260051b850101111561450957600080fd5b6000806020838503121561484857600080fd5b82356001600160401b0381111561485e57600080fd5b61486a858286016147f1565b90969095509350505050565b6001600160a01b0381168114610fee57600080fd5b803561489681614876565b919050565b600080600080600060a086880312156148b357600080fd5b85356148be81614876565b945060208601356148ce81614876565b935060408601356148de81614876565b94979396509394606081013594506080013592915050565b6020808252825182820181905260009190848201906040850190845b8181101561492e57835183529284019291840191600101614912565b50909695505050505050565b60006060828403121561494c57600080fd5b50919050565b60008083601f84011261496457600080fd5b5081356001600160401b0381111561497b57600080fd5b60208301915083602082850101111561450957600080fd5b6000806000608084860312156149a857600080fd5b6149b2858561493a565b925060608401356001600160401b038111156149cd57600080fd5b6149d986828701614952565b9497909650939450505050565b6000602082840312156149f857600080fd5b8135614a0381614876565b9392505050565b600080600060608486031215614a1f57600080fd5b8335614a2a81614876565b92506020840135614a3a81614876565b929592945050506040919091013590565b600060208284031215614a5d57600080fd5b5035919050565b60008060008060408587031215614a7a57600080fd5b84356001600160401b0380821115614a9157600080fd5b614a9d888389016147f1565b90965094506020870135915080821115614ab657600080fd5b50614ac3878288016147f1565b95989497509550505050565b60008060008060008060008060c0898b031215614aeb57600080fd5b8835614af681614876565b97506020890135614b0681614876565b9650604089013595506060890135945060808901356001600160401b0380821115614b3057600080fd5b614b3c8c838d016147f1565b909650945060a08b0135915080821115614b5557600080fd5b50614b628b828c016147f1565b999c989b5096995094979396929594505050565b6000806000806000806000806080898b031215614b9257600080fd5b88356001600160401b0380821115614ba957600080fd5b614bb58c838d016147f1565b909a50985060208b0135915080821115614bce57600080fd5b614bda8c838d016147f1565b909850965060408b0135915080821115614bf357600080fd5b614bff8c838d016147f1565b909650945060608b0135915080821115614b5557600080fd5b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b0381118282101715614c5057614c50614c18565b60405290565b604080519081016001600160401b0381118282101715614c5057614c50614c18565b604051601f8201601f191681016001600160401b0381118282101715614ca057614ca0614c18565b604052919050565b63ffffffff81168114610fee57600080fd5b803561489681614ca8565b60006001600160401b03821115614cde57614cde614c18565b5060051b60200190565b600082601f830112614cf957600080fd5b81356020614d0e614d0983614cc5565b614c78565b82815260059290921b84018101918181019086841115614d2d57600080fd5b8286015b84811015614d51578035614d4481614876565b8352918301918301614d31565b509695505050505050565b600082601f830112614d6d57600080fd5b81356020614d7d614d0983614cc5565b82815260059290921b84018101918181019086841115614d9c57600080fd5b8286015b84811015614d515780358352918301918301614da0565b600060e08284031215614dc957600080fd5b614dd1614c2e565b9050614ddc8261488b565b8152614dea6020830161488b565b6020820152614dfb6040830161488b565b604082015260608201356060820152614e1660808301614cba565b608082015260a08201356001600160401b0380821115614e3557600080fd5b614e4185838601614ce8565b60a084015260c0840135915080821115614e5a57600080fd5b50614e6784828501614d5c565b60c08301525092915050565b600060208284031215614e8557600080fd5b81356001600160401b03811115614e9b57600080fd5b614ea784828501614db7565b949350505050565b600060208284031215614ec157600080fd5b813560ff81168114614a0357600080fd5b8015158114610fee57600080fd5b600080600080600060808688031215614ef857600080fd5b85356001600160401b0380821115614f0f57600080fd5b9087019060e0828a031215614f2357600080fd5b90955060208701359080821115614f3957600080fd5b50614f46888289016147f1565b909550935050604086013591506060860135614f6181614ed2565b809150509295509295909350565b60008060408385031215614f8257600080fd5b8235614f8d81614876565b91506020830135614f9d81614876565b809150509250929050565b600060408284031215614fba57600080fd5b614fc2614c56565b905081356001600160401b0380821115614fdb57600080fd5b818401915084601f830112614fef57600080fd5b813560208282111561500357615003614c18565b615015601f8301601f19168201614c78565b9250818352868183860101111561502b57600080fd5b8181850182850137600081838501015282855280860135818601525050505092915050565b600080600080600060a0868803121561506857600080fd5b853561507381614876565b9450602086013561508381614876565b935060408601356001600160401b038082111561509f57600080fd5b6150ab89838a01614fa8565b945060608801359150808211156150c157600080fd5b506150ce88828901614fa8565b95989497509295608001359392505050565b600080604083850312156150f357600080fd5b82356150fe81614876565b915060208301356001600160401b0381111561511957600080fd5b61512585828601614ce8565b9150509250929050565b600081518084526020808501945080840160005b8381101561515f57815187529582019590820190600101615143565b509495945050505050565b602081526000614a03602083018461512f565b6000806020838503121561519057600080fd5b82356001600160401b038111156151a657600080fd5b61486a85828601614952565b600080604083850312156151c557600080fd5b82356151d081614876565b946020939093013593505050565b600080600080608085870312156151f457600080fd5b84356151ff81614876565b935060208501359250604085013561521681614876565b9396929550929360600135925050565b600081518084526020808501945080840160005b8381101561515f5781516001600160a01b03168752958201959082019060010161523a565b6040815260006152726040830185615226565b8281036020840152611220818561512f565b60008060006060848603121561529957600080fd5b83356152a481614876565b925060208401356001600160401b038111156152bf57600080fd5b6152cb86828701614fa8565b925050604084013590509250925092565b6000606082840312156152ee57600080fd5b614a03838361493a565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006000198214156153385761533861530e565b5060010190565b60208082526019908201527f5061757361626c653a20696e6465782069732070617573656400000000000000604082015260600190565b60008235605e1983360301811261538c57600080fd5b9190910192915050565b6000808335601e198436030181126153ad57600080fd5b8301803591506001600160401b038211156153c757600080fd5b6020019150600581901b360382131561450957600080fd5b6060810182356153ee81614876565b6001600160a01b03908116835260208401359061540a82614876565b166020830152604083013561541e81614ca8565b63ffffffff811660408401525092915050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60006020828403121561547257600080fd5b8151614a0381614876565b6020808252602a908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526939903ab73830bab9b2b960b11b606082015260800190565b60208082526037908201527f44656c65676174696f6e4d616e616765723a206f6e6c7953747261746567794d60408201527f616e616765724f72456967656e506f644d616e61676572000000000000000000606082015260800190565b60006020828403121561553657600080fd5b8151614a0381614ed2565b60208082526028908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526739903830bab9b2b960c11b606082015260800190565b6000823560de1983360301811261538c57600080fd5b6000602082840312156155b157600080fd5b8135614a0381614ed2565b600060018060a01b03808351168452806020840151166020850152806040840151166040850152506060820151606084015263ffffffff608083015116608084015260a082015160e060a085015261561760e0850182615226565b905060c083015184820360c0860152611220828261512f565b602081526000614a0360208301846155bc565b60006020828403121561565557600080fd5b5051919050565b600082601f83011261566d57600080fd5b8151602061567d614d0983614cc5565b82815260059290921b8401810191818101908684111561569c57600080fd5b8286015b84811015614d5157805183529183019183016156a0565b600080604083850312156156ca57600080fd5b82516001600160401b03808211156156e157600080fd5b818501915085601f8301126156f557600080fd5b81516020615705614d0983614cc5565b82815260059290921b8401810191818101908984111561572457600080fd5b948201945b8386101561574b57855161573c81614876565b82529482019490820190615729565b9188015191965090935050508082111561576457600080fd5b506151258582860161565c565b600082198211156157845761578461530e565b500190565b60008282101561579b5761579b61530e565b500390565b6001600160a01b039384168152919092166020820152604081019190915260600190565b828152604060208201526000614ea760408301846155bc565b6000602082840312156157ef57600080fd5b8135614a0381614ca8565b80546001600160a01b0319166001600160a01b0392909216919091179055565b813561582581614876565b61582f81836157fa565b5060018101602083013561584281614876565b61584c81836157fa565b50604083013561585b81614ca8565b815463ffffffff60a01b191660a09190911b63ffffffff60a01b161790555050565b60006158893683614db7565b92915050565b6020808252606e908201526000805160206159b583398151915260408201527f645769746864726177616c3a207769746864726177616c44656c6179426c6f6360608201527f6b7320706572696f6420686173206e6f74207965742070617373656420666f7260808201526d207468697320737472617465677960901b60a082015260c00190565b82815260006020604081840152835180604085015260005b8181101561594b5785810183015185820160600152820161592f565b8181111561595d576000606083870101525b50601f01601f191692909201606001949350505050565b60006020828403121561598657600080fd5b81516001600160e01b031981168114614a0357600080fd5b634e487b7160e01b600052602160045260246000fdfe44656c65676174696f6e4d616e616765722e5f636f6d706c6574655175657565a2646970667358221220ec834024adf0a9419f052ddc442578f901c15c4578ea4aab2a9105542cbc9c9964736f6c634300080c0033", + "storage": { "0x0": "0xff" } + }, + "0xa82ff9afd8f496c3d6ac40e2a0f282e47488cfc9": { + "nonce": 1, + "balance": "0x0", + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106f1565b610118565b61005b61009336600461070c565b61015f565b3480156100a457600080fd5b506100ad6101d0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106f1565b61020b565b3480156100f557600080fd5b506100ad610235565b61010661029b565b61011661011161033a565b610344565b565b610120610368565b6001600160a01b0316336001600160a01b03161415610157576101548160405180602001604052806000815250600061039b565b50565b6101546100fe565b610167610368565b6001600160a01b0316336001600160a01b031614156101c8576101c38383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001925061039b915050565b505050565b6101c36100fe565b60006101da610368565b6001600160a01b0316336001600160a01b03161415610200576101fb61033a565b905090565b6102086100fe565b90565b610213610368565b6001600160a01b0316336001600160a01b0316141561015757610154816103c6565b600061023f610368565b6001600160a01b0316336001600160a01b03161415610200576101fb610368565b6060610285838360405180606001604052806027815260200161080b6027913961041a565b9392505050565b6001600160a01b03163b151590565b6102a3610368565b6001600160a01b0316336001600160a01b031614156101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101fb6104f7565b3660008037600080366000845af43d6000803e808015610363573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103a48361051f565b6000825111806103b15750805b156101c3576103c08383610260565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103ef610368565b604080516001600160a01b03928316815291841660208301520160405180910390a16101548161055f565b60606001600160a01b0384163b6104825760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610331565b600080856001600160a01b03168560405161049d91906107bb565b600060405180830381855af49150503d80600081146104d8576040519150601f19603f3d011682016040523d82523d6000602084013e6104dd565b606091505b50915091506104ed828286610608565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61038c565b61052881610641565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105c45760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610331565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60608315610617575081610285565b8251156106275782518084602001fd5b8160405162461bcd60e51b815260040161033191906107d7565b6001600160a01b0381163b6106ae5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610331565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105e7565b80356001600160a01b03811681146106ec57600080fd5b919050565b60006020828403121561070357600080fd5b610285826106d5565b60008060006040848603121561072157600080fd5b61072a846106d5565b9250602084013567ffffffffffffffff8082111561074757600080fd5b818601915086601f83011261075b57600080fd5b81358181111561076a57600080fd5b87602082850101111561077c57600080fd5b6020830194508093505050509250925092565b60005b838110156107aa578181015183820152602001610792565b838111156103c05750506000910152565b600082516107cd81846020870161078f565b9190910192915050565b60208152600082518060208401526107f681604085016020870161078f565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212201336548e393b6bf33c1e3380011fea84db160f673ebc8828297c6c2b86153c4664736f6c634300080c0033", + "storage": { + "0xeb5be412f275a18f6e4d622aee4ff40b21467c926224771b782d4c095d1444b": "0x14", + "0x17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec": "0x1", + "0x295841a49a1089f4b560f91cfbb0133326654dcbb1041861fc5dde96c724a22f": "0x7969c5ed335650692bc04293b07f5bf2e7a673c0", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x70e0ba845a1a0f2da3359c97e0285013525ffc49", + "0x3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92eff": "0x1", + "0xa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49": "0x1", + "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5": "0x0", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0xc5a5c42992decbae36851359345fe25997f5c42d", + "0xcfb339bd1c51c488f6134f4ac63d1594afad827b3401c3fc51ed1da74a8ca14e": "0xde0b6b3a76400007969c5ed335650692bc04293b07f5bf2e7a673c0" + } + }, + "0xa85233c63b9ee964add6f2cffe00fd84eb32338f": { + "nonce": 1, + "balance": "0x0", + "code": "0x608060405234801561001057600080fd5b506004361061018e5760003560e01c80635c975abb116100de578063ab5921e111610097578063df6fadc111610071578063df6fadc114610366578063e3dae51c14610381578063f3e7387514610394578063fabc1cbc146103a757600080fd5b8063ab5921e11461032b578063ce7c2ac214610340578063d9caed121461035357600080fd5b80635c975abb146102c857806361b01b5d146102d05780637a8b2637146102d9578063886f1195146102ec5780638c871019146103055780638f6a62401461031857600080fd5b80633a98ef391161014b578063485cc95511610125578063485cc9551461026b578063553ca5f81461027e578063595c6a67146102915780635ac86ab71461029957600080fd5b80633a98ef391461023857806343fe08b01461024f57806347e7ef241461025857600080fd5b8063019e27291461019357806310d67a2f146101a857806311c70c9d146101bb578063136439dd146101ce5780632495a599146101e157806339b70e3814610211575b600080fd5b6101a66101a13660046117b8565b6103ba565b005b6101a66101b6366004611802565b61049d565b6101a66101c936600461181f565b610550565b6101a66101dc366004611841565b610605565b6032546101f4906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101f47f0000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f87570781565b61024160335481565b604051908152602001610208565b61024160645481565b61024161026636600461185a565b610749565b6101a6610279366004611886565b6108ed565b61024161028c366004611802565b6109bb565b6101a66109cf565b6102b86102a73660046118bf565b6001805460ff9092161b9081161490565b6040519015158152602001610208565b600154610241565b61024160655481565b6102416102e7366004611841565b610a9b565b6000546101f4906201000090046001600160a01b031681565b610241610313366004611841565b610ae6565b610241610326366004611802565b610af1565b610333610aff565b6040516102089190611912565b61024161034e366004611802565b610b1f565b6101a6610361366004611945565b610bb4565b60645460655460408051928352602083019190915201610208565b61024161038f366004611841565b610d7d565b6102416103a2366004611841565b610db6565b6101a66103b5366004611841565b610dc1565b600054610100900460ff16158080156103da5750600054600160ff909116105b806103f45750303b1580156103f4575060005460ff166001145b6104195760405162461bcd60e51b815260040161041090611986565b60405180910390fd5b6000805460ff19166001179055801561043c576000805461ff0019166101001790555b6104468585610f1d565b610450838361102a565b8015610496576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b600060029054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104f0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051491906119d4565b6001600160a01b0316336001600160a01b0316146105445760405162461bcd60e51b8152600401610410906119f1565b61054d816110bb565b50565b600060029054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c791906119d4565b6001600160a01b0316336001600160a01b0316146105f75760405162461bcd60e51b8152600401610410906119f1565b6106018282610f1d565b5050565b60005460405163237dfb4760e11b8152336004820152620100009091046001600160a01b0316906346fbf68e90602401602060405180830381865afa158015610652573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106769190611a3b565b6106925760405162461bcd60e51b815260040161041090611a5d565b6001548181161461070b5760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e70617573653a20696e76616c696420617474656d70742060448201527f746f20756e70617573652066756e6374696f6e616c69747900000000000000006064820152608401610410565b600181905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d906020015b60405180910390a250565b6001805460009182918116141561079e5760405162461bcd60e51b815260206004820152601960248201527814185d5cd8589b194e881a5b99195e081a5cc81c185d5cd959603a1b6044820152606401610410565b336001600160a01b037f0000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f87570716146108165760405162461bcd60e51b815260206004820181905260248201527f5374726174656779426173652e6f6e6c7953747261746567794d616e616765726044820152606401610410565b61082084846111c0565b60335460006108316103e883611abb565b905060006103e86108406112a2565b61084a9190611abb565b905060006108588783611ad3565b9050806108658489611aea565b61086f9190611b09565b9550856108d55760405162461bcd60e51b815260206004820152602e60248201527f5374726174656779426173652e6465706f7369743a206e65775368617265732060448201526d63616e6e6f74206265207a65726f60901b6064820152608401610410565b6108df8685611abb565b603355505050505092915050565b600054610100900460ff161580801561090d5750600054600160ff909116105b806109275750303b158015610927575060005460ff166001145b6109435760405162461bcd60e51b815260040161041090611986565b6000805460ff191660011790558015610966576000805461ff0019166101001790555b610970838361102a565b80156109b6576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006109c96102e783610b1f565b92915050565b60005460405163237dfb4760e11b8152336004820152620100009091046001600160a01b0316906346fbf68e90602401602060405180830381865afa158015610a1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a409190611a3b565b610a5c5760405162461bcd60e51b815260040161041090611a5d565b600019600181905560405190815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a2565b6000806103e8603354610aae9190611abb565b905060006103e8610abd6112a2565b610ac79190611abb565b905081610ad48583611aea565b610ade9190611b09565b949350505050565b60006109c982610d7d565b60006109c96103a283610b1f565b60606040518060800160405280604d8152602001611b61604d9139905090565b604051633d3f06c960e11b81526001600160a01b0382811660048301523060248301526000917f0000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f87570790911690637a7e0d9290604401602060405180830381865afa158015610b90573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c99190611b2b565b6001805460029081161415610c075760405162461bcd60e51b815260206004820152601960248201527814185d5cd8589b194e881a5b99195e081a5cc81c185d5cd959603a1b6044820152606401610410565b336001600160a01b037f0000000000000000000000005fc8d32690cc91d4c39d9d3abcbd16989f8757071614610c7f5760405162461bcd60e51b815260206004820181905260248201527f5374726174656779426173652e6f6e6c7953747261746567794d616e616765726044820152606401610410565b610c8a848484611314565b60335480831115610d195760405162461bcd60e51b815260206004820152604d60248201527f5374726174656779426173652e77697468647261773a20616d6f756e7453686160448201527f726573206d757374206265206c657373207468616e206f7220657175616c207460648201526c6f20746f74616c53686172657360981b608482015260a401610410565b6000610d276103e883611abb565b905060006103e8610d366112a2565b610d409190611abb565b9050600082610d4f8784611aea565b610d599190611b09565b9050610d658685611ad3565b603355610d73888883611397565b5050505050505050565b6000806103e8603354610d909190611abb565b905060006103e8610d9f6112a2565b610da99190611abb565b905080610ad48386611aea565b60006109c982610a9b565b600060029054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e3891906119d4565b6001600160a01b0316336001600160a01b031614610e685760405162461bcd60e51b8152600401610410906119f1565b600154198119600154191614610ee65760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e756e70617573653a20696e76616c696420617474656d7060448201527f7420746f2070617573652066756e6374696f6e616c69747900000000000000006064820152608401610410565b600181905560405181815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c9060200161073e565b60645460408051918252602082018490527ff97ed4e083acac67830025ecbc756d8fe847cdbdca4cee3fe1e128e98b54ecb5910160405180910390a160655460408051918252602082018390527f6ab181e0440bfbf4bacdf2e99674735ce6638005490688c5f994f5399353e452910160405180910390a18082111561101f5760405162461bcd60e51b815260206004820152604b60248201527f53747261746567794261736554564c4c696d6974732e5f73657454564c4c696d60448201527f6974733a206d61785065724465706f7369742065786365656473206d6178546f60648201526a74616c4465706f7369747360a81b608482015260a401610410565b606491909155606555565b600054610100900460ff166110955760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610410565b603280546001600160a01b0319166001600160a01b0384161790556106018160006113ab565b6001600160a01b0381166111495760405162461bcd60e51b815260206004820152604960248201527f5061757361626c652e5f73657450617573657252656769737472793a206e657760448201527f50617573657252656769737472792063616e6e6f7420626520746865207a65726064820152686f206164647265737360b81b608482015260a401610410565b600054604080516001600160a01b03620100009093048316815291831660208301527f6e9fcd539896fca60e8b0f01dd580233e48a6b0f7df013b89ba7f565869acdb6910160405180910390a1600080546001600160a01b03909216620100000262010000600160b01b0319909216919091179055565b60645481111561122a5760405162461bcd60e51b815260206004820152602f60248201527f53747261746567794261736554564c4c696d6974733a206d617820706572206460448201526e195c1bdcda5d08195e18d959591959608a1b6064820152608401610410565b6065546112356112a2565b11156112985760405162461bcd60e51b815260206004820152602c60248201527f53747261746567794261736554564c4c696d6974733a206d6178206465706f7360448201526b1a5d1cc8195e18d95959195960a21b6064820152608401610410565b6106018282611497565b6032546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156112eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130f9190611b2b565b905090565b6032546001600160a01b038381169116146109b65760405162461bcd60e51b815260206004820152603b60248201527f5374726174656779426173652e77697468647261773a2043616e206f6e6c792060448201527f77697468647261772074686520737472617465677920746f6b656e00000000006064820152608401610410565b6109b66001600160a01b0383168483611513565b6000546201000090046001600160a01b03161580156113d257506001600160a01b03821615155b6114545760405162461bcd60e51b815260206004820152604760248201527f5061757361626c652e5f696e697469616c697a655061757365723a205f696e6960448201527f7469616c697a6550617573657228292063616e206f6e6c792062652063616c6c6064820152666564206f6e636560c81b608482015260a401610410565b600181905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a2610601826110bb565b6032546001600160a01b038381169116146106015760405162461bcd60e51b815260206004820152603660248201527f5374726174656779426173652e6465706f7369743a2043616e206f6e6c79206460448201527532b837b9b4ba103ab73232b9363cb4b733aa37b5b2b760511b6064820152608401610410565b604080516001600160a01b03848116602483015260448083018590528351808403909101815260649092018352602080830180516001600160e01b031663a9059cbb60e01b17905283518085019094528084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564908401526109b6928692916000916115a3918516908490611620565b8051909150156109b657808060200190518101906115c19190611a3b565b6109b65760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610410565b606061162f8484600085611639565b90505b9392505050565b60608247101561169a5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610410565b6001600160a01b0385163b6116f15760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610410565b600080866001600160a01b0316858760405161170d9190611b44565b60006040518083038185875af1925050503d806000811461174a576040519150601f19603f3d011682016040523d82523d6000602084013e61174f565b606091505b509150915061175f82828661176a565b979650505050505050565b60608315611779575081611632565b8251156117895782518084602001fd5b8160405162461bcd60e51b81526004016104109190611912565b6001600160a01b038116811461054d57600080fd5b600080600080608085870312156117ce57600080fd5b843593506020850135925060408501356117e7816117a3565b915060608501356117f7816117a3565b939692955090935050565b60006020828403121561181457600080fd5b8135611632816117a3565b6000806040838503121561183257600080fd5b50508035926020909101359150565b60006020828403121561185357600080fd5b5035919050565b6000806040838503121561186d57600080fd5b8235611878816117a3565b946020939093013593505050565b6000806040838503121561189957600080fd5b82356118a4816117a3565b915060208301356118b4816117a3565b809150509250929050565b6000602082840312156118d157600080fd5b813560ff8116811461163257600080fd5b60005b838110156118fd5781810151838201526020016118e5565b8381111561190c576000848401525b50505050565b60208152600082518060208401526119318160408501602087016118e2565b601f01601f19169190910160400192915050565b60008060006060848603121561195a57600080fd5b8335611965816117a3565b92506020840135611975816117a3565b929592945050506040919091013590565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6000602082840312156119e657600080fd5b8151611632816117a3565b6020808252602a908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526939903ab73830bab9b2b960b11b606082015260800190565b600060208284031215611a4d57600080fd5b8151801515811461163257600080fd5b60208082526028908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526739903830bab9b2b960c11b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b60008219821115611ace57611ace611aa5565b500190565b600082821015611ae557611ae5611aa5565b500390565b6000816000190483118215151615611b0457611b04611aa5565b500290565b600082611b2657634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215611b3d57600080fd5b5051919050565b60008251611b568184602087016118e2565b919091019291505056fe4261736520537472617465677920696d706c656d656e746174696f6e20746f20696e68657269742066726f6d20666f72206d6f726520636f6d706c657820696d706c656d656e746174696f6e73a2646970667358221220bf3cc5a9074b03779f5525e7ba18cf89a122b3987055f3aad740baa37788b0fc64736f6c634300080c0033", + "storage": { "0x0": "0xff" } + }, + "0xb7f8bc63bbcad18155201308c8f3540b07f84f5e": { + "nonce": 1, + "balance": "0x0", + "code": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c80633659cfe61461005c5780635c60da1b14610071578063715018a61461009a5780638da5cb5b146100a2578063f2fde38b146100b3575b600080fd5b61006f61006a3660046102ee565b6100c6565b005b6001546001600160a01b03165b6040516001600160a01b03909116815260200160405180910390f35b61006f61010e565b6000546001600160a01b031661007e565b61006f6100c13660046102ee565b610122565b6100ce6101af565b6100d781610209565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6101166101af565b610120600061029e565b565b61012a6101af565b6001600160a01b0381166101945760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61019d8161029e565b50565b6001600160a01b03163b151590565b6000546001600160a01b031633146101205760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161018b565b6001600160a01b0381163b61027c5760405162461bcd60e51b815260206004820152603360248201527f5570677261646561626c65426561636f6e3a20696d706c656d656e746174696f6044820152721b881a5cc81b9bdd08184818dbdb9d1c9858dd606a1b606482015260840161018b565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006020828403121561030057600080fd5b81356001600160a01b038116811461031757600080fd5b939250505056fea26469706673582212200e8818173dd5805031e87ecf233aa41e6cdab273b0e161d25e10f5ff49cb023464736f6c634300080c0033", + "storage": { + "0x0": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x1": "0x610178da211fef7d417bc0e6fed39f05609ad788" + } + }, + "0xc3e53f4d16ae77db1c982e75a937b9f60fe63690": { + "nonce": 1, + "balance": "0x0", + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106f1565b610118565b61005b61009336600461070c565b61015f565b3480156100a457600080fd5b506100ad6101d0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106f1565b61020b565b3480156100f557600080fd5b506100ad610235565b61010661029b565b61011661011161033a565b610344565b565b610120610368565b6001600160a01b0316336001600160a01b03161415610157576101548160405180602001604052806000815250600061039b565b50565b6101546100fe565b610167610368565b6001600160a01b0316336001600160a01b031614156101c8576101c38383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001925061039b915050565b505050565b6101c36100fe565b60006101da610368565b6001600160a01b0316336001600160a01b03161415610200576101fb61033a565b905090565b6102086100fe565b90565b610213610368565b6001600160a01b0316336001600160a01b0316141561015757610154816103c6565b600061023f610368565b6001600160a01b0316336001600160a01b03161415610200576101fb610368565b6060610285838360405180606001604052806027815260200161080b6027913961041a565b9392505050565b6001600160a01b03163b151590565b6102a3610368565b6001600160a01b0316336001600160a01b031614156101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101fb6104f7565b3660008037600080366000845af43d6000803e808015610363573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103a48361051f565b6000825111806103b15750805b156101c3576103c08383610260565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103ef610368565b604080516001600160a01b03928316815291841660208301520160405180910390a16101548161055f565b60606001600160a01b0384163b6104825760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610331565b600080856001600160a01b03168560405161049d91906107bb565b600060405180830381855af49150503d80600081146104d8576040519150601f19603f3d011682016040523d82523d6000602084013e6104dd565b606091505b50915091506104ed828286610608565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61038c565b61052881610641565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105c45760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610331565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60608315610617575081610285565b8251156106275782518084602001fd5b8160405162461bcd60e51b815260040161033191906107d7565b6001600160a01b0381163b6106ae5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610331565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105e7565b80356001600160a01b03811681146106ec57600080fd5b919050565b60006020828403121561070357600080fd5b610285826106d5565b60008060006040848603121561072157600080fd5b61072a846106d5565b9250602084013567ffffffffffffffff8082111561074757600080fd5b818601915086601f83011261075b57600080fd5b81358181111561076a57600080fd5b87602082850101111561077c57600080fd5b6020830194508093505050509250925092565b60005b838110156107aa578181015183820152602001610792565b838111156103c05750506000910152565b600082516107cd81846020870161078f565b9190910192915050565b60208152600082518060208401526107f681604085016020870161078f565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212201336548e393b6bf33c1e3380011fea84db160f673ebc8828297c6c2b86153c4664736f6c634300080c0033", + "storage": { + "0x0": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb922660001", + "0x1": "0x0", + "0x64": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x96": "0x1", + "0x9c": "0x3", + "0x9d": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x9e": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x99bba657f2bbc93c02d617f8ba121cb8fc104acf", + "0x683723e34a772b6e4f2c919bba7fa32ed8ea11a8325f54da7db716e9d9dd98c7": "0x643a9800002710", + "0xaf85b9071dfafeac1409d3f1d19bafc9bc7c37974cde8df0ee6168f0086e539c": "0xa82ff9afd8f496c3d6ac40e2a0f282e47488cfc9", + "0xaf85b9071dfafeac1409d3f1d19bafc9bc7c37974cde8df0ee6168f0086e539d": "0x84ea74d481ee0a5332c457a4d796187f6ba67feb", + "0xaf85b9071dfafeac1409d3f1d19bafc9bc7c37974cde8df0ee6168f0086e539e": "0x9e545e3c0baab3e08cdfd552c960a1050f373042", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0xc5a5c42992decbae36851359345fe25997f5c42d" + } + }, + "0xc5a5c42992decbae36851359345fe25997f5c42d": { + "nonce": 1, + "balance": "0x0", + "code": "0x60806040526004361061007b5760003560e01c80639623609d1161004e5780639623609d1461011157806399a88ec414610124578063f2fde38b14610144578063f3b7dead1461016457600080fd5b8063204e1c7a14610080578063715018a6146100bc5780637eff275e146100d35780638da5cb5b146100f3575b600080fd5b34801561008c57600080fd5b506100a061009b366004610499565b610184565b6040516001600160a01b03909116815260200160405180910390f35b3480156100c857600080fd5b506100d1610215565b005b3480156100df57600080fd5b506100d16100ee3660046104bd565b610229565b3480156100ff57600080fd5b506000546001600160a01b03166100a0565b6100d161011f36600461050c565b610291565b34801561013057600080fd5b506100d161013f3660046104bd565b610300565b34801561015057600080fd5b506100d161015f366004610499565b610336565b34801561017057600080fd5b506100a061017f366004610499565b6103b4565b6000806000836001600160a01b03166040516101aa90635c60da1b60e01b815260040190565b600060405180830381855afa9150503d80600081146101e5576040519150601f19603f3d011682016040523d82523d6000602084013e6101ea565b606091505b5091509150816101f957600080fd5b8080602001905181019061020d91906105e2565b949350505050565b61021d6103da565b6102276000610434565b565b6102316103da565b6040516308f2839760e41b81526001600160a01b038281166004830152831690638f283970906024015b600060405180830381600087803b15801561027557600080fd5b505af1158015610289573d6000803e3d6000fd5b505050505050565b6102996103da565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906102c990869086906004016105ff565b6000604051808303818588803b1580156102e257600080fd5b505af11580156102f6573d6000803e3d6000fd5b5050505050505050565b6103086103da565b604051631b2ce7f360e11b81526001600160a01b038281166004830152831690633659cfe69060240161025b565b61033e6103da565b6001600160a01b0381166103a85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6103b181610434565b50565b6000806000836001600160a01b03166040516101aa906303e1469160e61b815260040190565b6000546001600160a01b031633146102275760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161039f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146103b157600080fd5b6000602082840312156104ab57600080fd5b81356104b681610484565b9392505050565b600080604083850312156104d057600080fd5b82356104db81610484565b915060208301356104eb81610484565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561052157600080fd5b833561052c81610484565b9250602084013561053c81610484565b9150604084013567ffffffffffffffff8082111561055957600080fd5b818601915086601f83011261056d57600080fd5b81358181111561057f5761057f6104f6565b604051601f8201601f19908116603f011681019083821181831017156105a7576105a76104f6565b816040528281528960208487010111156105c057600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000602082840312156105f457600080fd5b81516104b681610484565b60018060a01b038316815260006020604081840152835180604085015260005b8181101561063b5785810183015185820160600152820161061f565b8181111561064d576000606083870101525b50601f01601f19169290920160600194935050505056fea2646970667358221220ae83da88aa745645e0903b6f358ca5e804fa34d55129288512b1d1135213cfa264736f6c634300080c0033", + "storage": { "0x0": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" } + }, + "0xcf7ed3acca5a467e9e704c703e8d87f634fb0fc9": { + "nonce": 1, + "balance": "0x0", + "code": "0x6080604052348015600f57600080fd5b506004361060285760003560e01c8063c298557814602d575b600080fd5b600060405190815260200160405180910390f3fea2646970667358221220911e890115ba4d90995b51eca07ab7d0f34b9d8c6d41bd770b671745d3c513e764736f6c634300080c0033", + "storage": {} + }, + "0xdc64a140aa3e981100a9beca4e685f962f0cf6c9": { + "nonce": 1, + "balance": "0x0", + "code": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106f1565b610118565b61005b61009336600461070c565b61015f565b3480156100a457600080fd5b506100ad6101d0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106f1565b61020b565b3480156100f557600080fd5b506100ad610235565b61010661029b565b61011661011161033a565b610344565b565b610120610368565b6001600160a01b0316336001600160a01b03161415610157576101548160405180602001604052806000815250600061039b565b50565b6101546100fe565b610167610368565b6001600160a01b0316336001600160a01b031614156101c8576101c38383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506001925061039b915050565b505050565b6101c36100fe565b60006101da610368565b6001600160a01b0316336001600160a01b03161415610200576101fb61033a565b905090565b6102086100fe565b90565b610213610368565b6001600160a01b0316336001600160a01b0316141561015757610154816103c6565b600061023f610368565b6001600160a01b0316336001600160a01b03161415610200576101fb610368565b6060610285838360405180606001604052806027815260200161080b6027913961041a565b9392505050565b6001600160a01b03163b151590565b6102a3610368565b6001600160a01b0316336001600160a01b031614156101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101fb6104f7565b3660008037600080366000845af43d6000803e808015610363573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b6103a48361051f565b6000825111806103b15750805b156101c3576103c08383610260565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103ef610368565b604080516001600160a01b03928316815291841660208301520160405180910390a16101548161055f565b60606001600160a01b0384163b6104825760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610331565b600080856001600160a01b03168560405161049d91906107bb565b600060405180830381855af49150503d80600081146104d8576040519150601f19603f3d011682016040523d82523d6000602084013e6104dd565b606091505b50915091506104ed828286610608565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61038c565b61052881610641565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105c45760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610331565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60608315610617575081610285565b8251156106275782518084602001fd5b8160405162461bcd60e51b815260040161033191906107d7565b6001600160a01b0381163b6106ae5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610331565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105e7565b80356001600160a01b03811681146106ec57600080fd5b919050565b60006020828403121561070357600080fd5b610285826106d5565b60008060006040848603121561072157600080fd5b61072a846106d5565b9250602084013567ffffffffffffffff8082111561074757600080fd5b818601915086601f83011261075b57600080fd5b81358181111561076a57600080fd5b87602082850101111561077c57600080fd5b6020830194508093505050509250925092565b60005b838110156107aa578181015183820152602001610792565b838111156103c05750506000910152565b600082516107cd81846020870161078f565b9190910192915050565b60208152600082518060208401526107f681604085016020870161078f565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212208c7daa35c73cc3931155de6fec176061a18c7828634d7222e2c3c877ecc7552c64736f6c634300080c0033", + "storage": { + "0x0": "0x1", + "0x33": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x65": "0x9fe46736679d2d9a65f0992f2272de9f3c7fa6e0", + "0x66": "0x0", + "0x97": "0xd65ac9700cec4e530497617d02afdf0d5de3ed18466aca1578edcbce0d40ee16", + "0x9d": "0x1", + "0xb1cdf5a4280cdcae6d2af15c18d251ea85a80430b891fe5bfffbb270660cc3c": "0x14dc79964da2c08b23698b3d3cc7ca32193d9955", + "0xb1cdf5a4280cdcae6d2af15c18d251ea85a80430b891fe5bfffbb270660cc3d": "0x780000000000000000000000000000000000000000", + "0x1063b73b8687bec89da8fd85d38f55297da48db3eb5a5635177460bfbd54d2f7": "0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc", + "0x116efb584c245ab1e259fd48652f9fa06b040e13b0e1edee2d5b6ccf7340ab8e": "0x122c6ab631ff0891", + "0x20eba981400e854213ca904052ef13bb3e67bd8837bce1f4d5b572b3c25d30db": "0x976ea74026e726554db657fa54763abd0c3a0aa9", + "0x2229733d36372df8e0b3f818b24f5a978a09155179d6eeea21a1577e0dc01761": "0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f", + "0x272ae914a21a3d080d09966954c43b6914ed6465c160d5e0b30dcf50a1fe65e6": "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", + "0x2a87202aac51ae870d8a982d6008c3a8491bbd6ab1b932dff95c7607e91790e5": "0xa0ee7a142d267c1f36714e4a8f75612f20a79720", + "0x2a87202aac51ae870d8a982d6008c3a8491bbd6ab1b932dff95c7607e91790e6": "0x780000000000000000000000000000000000000000", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0xa51c1fc2f0d1a1b8494ed1fe312d7c3a78ed91c0", + "0x49a70597ef29004851896244499a40a21cc9ea6e729c9f2fd16705389f497869": "0x32d96cba53cf0152", + "0x519b983e2ba668682b54fa96c5e2c1964c3c7d3fcee5983542094edbf173fb79": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x53c21a771edff16642f32399d0d956b30040b7f23e2c5814dc643f3cc02a4193": "0x15d34aaf54267db7d7c367839aaf71a00a2c6a65", + "0x53c21a771edff16642f32399d0d956b30040b7f23e2c5814dc643f3cc02a4194": "0x780000000000000000000000000000000000000000", + "0x5537953c5931bb3324635b8a62fcd48ed85f69d971c1b52be74be44052edfaaa": "0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f", + "0x5537953c5931bb3324635b8a62fcd48ed85f69d971c1b52be74be44052edfaab": "0x780000000000000000000000000000000000000000", + "0x59f5a4240bf30ca996de5adb8dea8d506a07c8f240d09839f94262ae5684c424": "0x1c712bd73fa1ed3c", + "0x66c3328bfc9a1b3b24f8aa1a973bffe77deefb8db183659a188ca883b6cf47df": "0x32a862794ae172cb", + "0x7d39d721001b6c8eea82a01e62bb4f199c3c6abe21b76c93d3524ca8e9838e7a": "0x19aa30cbbe932840", + "0x7ee06c8cc51564bcc85135e6862eb14f38e4d886aecad027fb823ccf88fb6930": "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", + "0x7ee06c8cc51564bcc85135e6862eb14f38e4d886aecad027fb823ccf88fb6931": "0x780000000000000000000000000000000000000000", + "0x8d3b610f76751fc6eada1faa0ed094b37dfbc805b6397c880f8b5e357a26578c": "0xa0ee7a142d267c1f36714e4a8f75612f20a79720", + "0x8e6548dfdd4829df65d500d43f44375544d20cf5ae5e5837827032d18fcabd92": "0x5d9f943ccb6a86b8", + "0x8f860cbeb62c731e655387fff25d44bacdc8842fd619b450ee8efa3b786cab3c": "0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "0x950a635156201645af68a77e0374d6040d13a14b4038433d79e059400a0319fd": "0x7c6d1175e13d2753", + "0xa171cf075962c193ded1068e75c6f7c61df473071063755035c02cc67e6e6f4b": "0x86759309fd1fd327", + "0xa35929ce48fc2bc04f780eaa67083da5dbbcdf7a8139cda43bfe5da8b9f5aa94": "0x90f79bf6eb2c4f870365e785982e1f101e93b906", + "0xa392ff54d1ec60421c7704d63601362bebccab548773174860adf512e09ea622": "0x8042ae896b8e68bb", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512", + "0xb7604da75fbe3efd6ed69f0f84dfc6815b462c54f7544931958dd4a4906f9633": "0x976ea74026e726554db657fa54763abd0c3a0aa9", + "0xb7604da75fbe3efd6ed69f0f84dfc6815b462c54f7544931958dd4a4906f9634": "0x780000000000000000000000000000000000000000", + "0xb8a51e34643c50a4eeb6190188b9c391956ec3efa7c93a5de935000dbfb02d01": "0x14dc79964da2c08b23698b3d3cc7ca32193d9955", + "0xbccdbbaa08c67ed3c9f8cc0718284231db38856ff2018db58a0a6a32d108e7da": "0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "0xbccdbbaa08c67ed3c9f8cc0718284231db38856ff2018db58a0a6a32d108e7db": "0x780000000000000000000000000000000000000000", + "0xc53fea0dc16735322f7cda6e551ad512582820d9d61bb81d8a88f376d949d3ec": "0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc", + "0xc53fea0dc16735322f7cda6e551ad512582820d9d61bb81d8a88f376d949d3ed": "0x780000000000000000000000000000000000000000", + "0xc93f834da62e9a0171acb61e59b29b53e9d7427af093624011cf5d487571c929": "0x216714fd5b83698d", + "0xd345862d33f44988e30d7b974712ef161e0fdc4d2730008791f6bea4909ac059": "0x90f79bf6eb2c4f870365e785982e1f101e93b906", + "0xd345862d33f44988e30d7b974712ef161e0fdc4d2730008791f6bea4909ac05a": "0x780000000000000000000000000000000000000000", + "0xef22f60a4f33c96c194cd2c5d9995a32089ced0ed28fd56c8350ae2abc81884b": "0x15d34aaf54267db7d7c367839aaf71a00a2c6a65", + "0xf65abb752b68aade6528b7544cdd4ccde4bafa7f342f11137100423e6209ffd5": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0xf65abb752b68aade6528b7544cdd4ccde4bafa7f342f11137100423e6209ffd6": "0x780000000000000000000000000000000000000000" + } + }, + "0xe6e340d132b5f46d1e472debcd681b2abc16e57e": { + "nonce": 1, + "balance": "0x0", + "code": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c806346fbf68e146100515780638568520614610089578063ce5484281461009e578063eab66d7a146100b1575b600080fd5b61007461005f366004610313565b60006020819052908152604090205460ff1681565b60405190151581526020015b60405180910390f35b61009c610097366004610335565b6100dc565b005b61009c6100ac366004610313565b61011d565b6001546100c4906001600160a01b031681565b6040516001600160a01b039091168152602001610080565b6001546001600160a01b0316331461010f5760405162461bcd60e51b815260040161010690610371565b60405180910390fd5b6101198282610153565b5050565b6001546001600160a01b031633146101475760405162461bcd60e51b815260040161010690610371565b61015081610220565b50565b6001600160a01b0382166101bf5760405162461bcd60e51b815260206004820152602d60248201527f50617573657252656769737472792e5f7365745061757365723a207a65726f2060448201526c1859191c995cdcc81a5b9c1d5d609a1b6064820152608401610106565b6001600160a01b03821660008181526020818152604091829020805460ff19168515159081179091558251938452908301527f65d3a1fd4c13f05cba164f80d03ce90fb4b5e21946bfc3ab7dbd434c2d0b9152910160405180910390a15050565b6001600160a01b03811661028e5760405162461bcd60e51b815260206004820152602f60248201527f50617573657252656769737472792e5f736574556e7061757365723a207a657260448201526e1bc81859191c995cdcc81a5b9c1d5d608a1b6064820152608401610106565b600154604080516001600160a01b03928316815291831660208301527f06b4167a2528887a1e97a366eefe8549bfbf1ea3e6ac81cb2564a934d20e8892910160405180910390a1600180546001600160a01b0319166001600160a01b0392909216919091179055565b80356001600160a01b038116811461030e57600080fd5b919050565b60006020828403121561032557600080fd5b61032e826102f7565b9392505050565b6000806040838503121561034857600080fd5b610351836102f7565b91506020830135801515811461036657600080fd5b809150509250929050565b6020808252602a908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526939903ab73830bab9b2b960b11b60608201526080019056fea264697066735822122027e896eed5afe944d6cc172aef72e26108db4cb82871c29ee297686046c2ee4d64736f6c634300080c0033", + "storage": { + "0x1": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "0x723077b8a1b173adc35e5f0e7e3662fd1208212cb629f9c128551ea7168da722": "0x1" + } + }, + "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512": { + "nonce": 1, + "balance": "0x0", + "code": "0x60806040526004361061007b5760003560e01c80639623609d1161004e5780639623609d1461011157806399a88ec414610124578063f2fde38b14610144578063f3b7dead1461016457600080fd5b8063204e1c7a14610080578063715018a6146100bc5780637eff275e146100d35780638da5cb5b146100f3575b600080fd5b34801561008c57600080fd5b506100a061009b366004610499565b610184565b6040516001600160a01b03909116815260200160405180910390f35b3480156100c857600080fd5b506100d1610215565b005b3480156100df57600080fd5b506100d16100ee3660046104bd565b610229565b3480156100ff57600080fd5b506000546001600160a01b03166100a0565b6100d161011f36600461050c565b610291565b34801561013057600080fd5b506100d161013f3660046104bd565b610300565b34801561015057600080fd5b506100d161015f366004610499565b610336565b34801561017057600080fd5b506100a061017f366004610499565b6103b4565b6000806000836001600160a01b03166040516101aa90635c60da1b60e01b815260040190565b600060405180830381855afa9150503d80600081146101e5576040519150601f19603f3d011682016040523d82523d6000602084013e6101ea565b606091505b5091509150816101f957600080fd5b8080602001905181019061020d91906105e2565b949350505050565b61021d6103da565b6102276000610434565b565b6102316103da565b6040516308f2839760e41b81526001600160a01b038281166004830152831690638f283970906024015b600060405180830381600087803b15801561027557600080fd5b505af1158015610289573d6000803e3d6000fd5b505050505050565b6102996103da565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906102c990869086906004016105ff565b6000604051808303818588803b1580156102e257600080fd5b505af11580156102f6573d6000803e3d6000fd5b5050505050505050565b6103086103da565b604051631b2ce7f360e11b81526001600160a01b038281166004830152831690633659cfe69060240161025b565b61033e6103da565b6001600160a01b0381166103a85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6103b181610434565b50565b6000806000836001600160a01b03166040516101aa906303e1469160e61b815260040190565b6000546001600160a01b031633146102275760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161039f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146103b157600080fd5b6000602082840312156104ab57600080fd5b81356104b681610484565b9392505050565b600080604083850312156104d057600080fd5b82356104db81610484565b915060208301356104eb81610484565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561052157600080fd5b833561052c81610484565b9250602084013561053c81610484565b9150604084013567ffffffffffffffff8082111561055957600080fd5b818601915086601f83011261056d57600080fd5b81358181111561057f5761057f6104f6565b604051601f8201601f19908116603f011681019083821181831017156105a7576105a76104f6565b816040528281528960208487010111156105c057600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000602082840312156105f457600080fd5b81516104b681610484565b60018060a01b038316815260006020604081840152835180604085015260005b8181101561063b5785810183015185820160600152820161061f565b8181111561064d576000606083870101525b50601f01601f19169290920160600194935050505056fea26469706673582212205d703140b3d7633f5056bca74c52cf5e96f5aa70a84f9ec827f11ff16c3ae59e64736f6c634300080c0033", + "storage": { "0x0": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" } + }, + "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266": { + "nonce": 105, + "balance": "0x219387eb3cc861484a1", + "code": "0x", + "storage": {} + } + } +} diff --git a/crates/testing-utils/anvil/src/anvil.rs b/crates/testing-utils/anvil/src/anvil.rs index 29278f7..b6f059b 100644 --- a/crates/testing-utils/anvil/src/anvil.rs +++ b/crates/testing-utils/anvil/src/anvil.rs @@ -6,8 +6,9 @@ use testcontainers::{ }; use tokio::io::AsyncBufReadExt; -const ANVIL_IMAGE: &str = "ghcr.io/foundry-rs/foundry"; -const ANVIL_TAG: &str = "nightly-5b7e4cb3c882b28f3c32ba580de27ce7381f415a"; +pub const ANVIL_IMAGE: &str = "ghcr.io/foundry-rs/foundry"; +pub const ANVIL_TAG: &str = "nightly-5b7e4cb3c882b28f3c32ba580de27ce7381f415a"; +pub const ANVIL_STATE_PATH: &str = "./crates/testing-utils/anvil/data"; // relative path from the project root fn workspace_dir() -> PathBuf { let output = gadget_std::process::Command::new(env!("CARGO")) diff --git a/crates/testing-utils/anvil/src/lib.rs b/crates/testing-utils/anvil/src/lib.rs index 0eb39b5..aebcacc 100644 --- a/crates/testing-utils/anvil/src/lib.rs +++ b/crates/testing-utils/anvil/src/lib.rs @@ -1,2 +1,5 @@ pub mod anvil; pub mod wait_transaction; + +pub use anvil::*; +pub use wait_transaction::*;