diff --git a/circuits/lib/src/configs/default/mod.nr b/circuits/lib/src/configs/default/mod.nr index f2b4b39294..70e6219e5c 100644 --- a/circuits/lib/src/configs/default/mod.nr +++ b/circuits/lib/src/configs/default/mod.nr @@ -4,8 +4,8 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. // -// Unico punto in cui si cambia il param-set: re-esporta insecure o production -// (in futuro altri param-set). I circuiti usano tutti lib::configs::default::*. +// Only place where we change param-set: re-export insecure or production. +// (in future any other param-set). All circuits use lib::configs::default::*. pub use super::committee::micro::{H, N_PARTIES, T}; pub use super::insecure::dkg; diff --git a/crates/aggregator/src/proof_fold.rs b/crates/aggregator/src/proof_fold.rs index 34c6095a25..00614f9f68 100644 --- a/crates/aggregator/src/proof_fold.rs +++ b/crates/aggregator/src/proof_fold.rs @@ -9,6 +9,7 @@ use e3_events::{ prelude::*, BusHandle, ComputeRequest, CorrelationId, E3id, EventContext, Proof, Sequenced, ZkRequest, }; +use e3_fhe_params::BfvPreset; use tracing::{error, info}; /// Manages the state of a sequential `FoldProofs` operation. @@ -29,10 +30,12 @@ pub struct ProofFoldState { pub result: Option, /// `start` was called with zero proofs — folding is complete with no aggregate. pub fold_input_was_empty: bool, + /// BFV preset for circuit artifact resolution. + params_preset: BfvPreset, } impl ProofFoldState { - pub fn new() -> Self { + pub fn new(params_preset: BfvPreset) -> Self { ProofFoldState { correlation: None, accumulated: None, @@ -40,6 +43,7 @@ impl ProofFoldState { total_steps: None, result: None, fold_input_was_empty: false, + params_preset, } } @@ -196,6 +200,7 @@ impl ProofFoldState { proof1: acc, proof2: next, target_evm, + params_preset: self.params_preset, }, corr, e3_id.clone(), diff --git a/crates/aggregator/src/publickey_aggregator.rs b/crates/aggregator/src/publickey_aggregator.rs index 09791cb83a..371670b69d 100644 --- a/crates/aggregator/src/publickey_aggregator.rs +++ b/crates/aggregator/src/publickey_aggregator.rs @@ -223,6 +223,7 @@ impl PublicKeyAggregator { share_proofs: party_proofs, decryption_proofs: vec![], pre_dishonest: no_proof_parties.into_iter().collect(), + params_preset: self.params_preset, }, ec, )?; @@ -416,7 +417,7 @@ impl PublicKeyAggregator { dkg_node_proofs: HashMap::new(), honest_party_ids: honest_party_ids.clone(), dishonest_parties: dishonest_parties.clone(), - cross_node_fold: ProofFoldState::new(), + cross_node_fold: ProofFoldState::new(self.params_preset), c5_proof_pending: None, last_ec: Some(ec.clone()), }) @@ -611,7 +612,7 @@ impl PublicKeyAggregator { }; if cross_node_fold.needs_restart() { warn!("cross-node fold stuck mid-step on restart — resetting and re-folding from persisted proofs"); - cross_node_fold = ProofFoldState::new(); + cross_node_fold = ProofFoldState::new(self.params_preset); } cross_node_fold.start( proofs, diff --git a/crates/aggregator/src/threshold_plaintext_aggregator.rs b/crates/aggregator/src/threshold_plaintext_aggregator.rs index 955ce108f6..52495d8fcc 100644 --- a/crates/aggregator/src/threshold_plaintext_aggregator.rs +++ b/crates/aggregator/src/threshold_plaintext_aggregator.rs @@ -204,7 +204,7 @@ impl ThresholdPlaintextAggregator { e3_id: params.e3_id, params_preset: params.params_preset, state, - c6_fold: ProofFoldState::new(), + c6_fold: ProofFoldState::new(params.params_preset), c7_proofs_pending: None, last_ec: None, } @@ -352,6 +352,7 @@ impl ThresholdPlaintextAggregator { share_proofs: party_proofs, decryption_proofs: vec![], pre_dishonest: BTreeSet::new(), + params_preset: self.params_preset, }, ec, )?; diff --git a/crates/events/src/enclave_event/compute_request/zk.rs b/crates/events/src/enclave_event/compute_request/zk.rs index d20e70923f..7f92598053 100644 --- a/crates/events/src/enclave_event/compute_request/zk.rs +++ b/crates/events/src/enclave_event/compute_request/zk.rs @@ -42,6 +42,7 @@ pub enum ZkRequest { proof1: Proof, proof2: Proof, target_evm: bool, + params_preset: BfvPreset, }, } @@ -346,6 +347,8 @@ impl PkGenerationProofResponse { pub struct VerifyShareProofsRequest { /// Proofs grouped by sender party_id. pub party_proofs: Vec, + /// BFV preset for parameter resolution (determines circuit artifact directory). + pub params_preset: BfvPreset, } /// All signed proofs from a single sender to verify. @@ -386,6 +389,8 @@ pub struct PartyVerificationResult { pub struct VerifyShareDecryptionProofsRequest { /// C4 proofs grouped by sender party_id. pub party_proofs: Vec, + /// BFV preset for parameter resolution (determines circuit artifact directory). + pub params_preset: BfvPreset, } /// C4 proofs from a single sender to verify. diff --git a/crates/events/src/enclave_event/share_verification.rs b/crates/events/src/enclave_event/share_verification.rs index b529c4257e..f67f5a210c 100644 --- a/crates/events/src/enclave_event/share_verification.rs +++ b/crates/events/src/enclave_event/share_verification.rs @@ -42,6 +42,8 @@ pub struct ShareVerificationDispatched { /// Parties already identified as dishonest before verification /// (e.g., missing/incomplete proofs). Merged into the final result. pub pre_dishonest: BTreeSet, + /// BFV preset for circuit artifact resolution. + pub params_preset: e3_fhe_params::BfvPreset, } /// ShareVerificationActor → ThresholdKeyshare: verification results. diff --git a/crates/fhe-params/src/presets.rs b/crates/fhe-params/src/presets.rs index 6bc3ec1ed4..4c3ec32c17 100644 --- a/crates/fhe-params/src/presets.rs +++ b/crates/fhe-params/src/presets.rs @@ -377,6 +377,18 @@ impl BfvPreset { } } + /// Returns the security tier for this preset. + pub fn security_tier(&self) -> SecurityTier { + self.metadata().security + } + + /// Returns the directory name for circuit artifacts (e.g. `"insecure-512"`, `"secure-8192"`). + /// Threshold and DKG presets at the same degree share the same compiled circuits. + pub fn artifacts_dir(&self) -> String { + let meta = self.metadata(); + format!("{}-{}", meta.security.as_config_str(), meta.degree) + } + pub fn search_defaults(&self) -> Option { match self { BfvPreset::InsecureThreshold512 => Some(PresetSearchDefaults { @@ -537,4 +549,18 @@ mod tests { assert!(BfvPreset::InsecureDkg512.search_defaults().is_none()); assert!(BfvPreset::SecureDkg8192.search_defaults().is_none()); } + + #[test] + fn test_artifacts_dir() { + assert_eq!( + BfvPreset::InsecureThreshold512.artifacts_dir(), + "insecure-512" + ); + assert_eq!(BfvPreset::InsecureDkg512.artifacts_dir(), "insecure-512"); + assert_eq!( + BfvPreset::SecureThreshold8192.artifacts_dir(), + "secure-8192" + ); + assert_eq!(BfvPreset::SecureDkg8192.artifacts_dir(), "secure-8192"); + } } diff --git a/crates/keyshare/src/threshold_keyshare.rs b/crates/keyshare/src/threshold_keyshare.rs index 9b1bb54457..cf8dc401de 100644 --- a/crates/keyshare/src/threshold_keyshare.rs +++ b/crates/keyshare/src/threshold_keyshare.rs @@ -1421,6 +1421,7 @@ impl ThresholdKeyshare { share_proofs: party_proofs_to_verify, decryption_proofs: Vec::new(), pre_dishonest, + params_preset: self.share_enc_preset, }, ec, )?; @@ -2048,6 +2049,7 @@ impl ThresholdKeyshare { share_proofs: Vec::new(), decryption_proofs: party_proofs, pre_dishonest, + params_preset: self.share_enc_preset, }, ec, )?; diff --git a/crates/multithread/src/multithread.rs b/crates/multithread/src/multithread.rs index 3c1a0e267c..823ea86ca0 100644 --- a/crates/multithread/src/multithread.rs +++ b/crates/multithread/src/multithread.rs @@ -360,6 +360,7 @@ fn handle_pk_aggregation_proof( // 7. Generate proof via Provable trait (C5 is always EVM-targeted for on-chain verification) let circuit = PkAggregationCircuit; let bb_work_id = zk_bb_work_id(&request); + let artifacts_dir = req.params_preset.artifacts_dir(); let proof = circuit .prove_with_variant( prover, @@ -367,6 +368,7 @@ fn handle_pk_aggregation_proof( &circuit_data, &bb_work_id, CircuitVariant::Evm, + &artifacts_dir, ) .map_err(|e| { ComputeRequestError::new( @@ -420,6 +422,7 @@ fn handle_threshold_share_decryption_proof( let mut proofs = Vec::with_capacity(num_indices); let mut wrapped_proofs = Vec::with_capacity(num_indices); let bb_work_base = zk_bb_work_id(&request); + let artifacts_dir = req.params_preset.artifacts_dir(); for i in 0..num_indices { // Deserialize ciphertext @@ -458,7 +461,13 @@ fn handle_threshold_share_decryption_proof( let circuit = e3_zk_helpers::threshold::share_decryption::ShareDecryptionCircuit; let idx_work_id = format!("{bb_work_base}_c6_{i}"); let proof = circuit - .prove(prover, &req.params_preset, &circuit_data, &idx_work_id) + .prove( + prover, + &req.params_preset, + &circuit_data, + &idx_work_id, + &artifacts_dir, + ) .map_err(|e| { ComputeRequestError::new( ComputeRequestErrorKind::Zk(ZkEventError::ProofGenerationFailed(format!( @@ -471,15 +480,16 @@ fn handle_threshold_share_decryption_proof( if req.proof_aggregation_enabled { let wrap_id = format!("{bb_work_base}_c6_{i}_w"); - let wrapped = generate_wrapper_proof(prover, &proof, &wrap_id).map_err(|e| { - ComputeRequestError::new( - ComputeRequestErrorKind::Zk(ZkEventError::ProofGenerationFailed(format!( - "C6 wrapper proof[{}]: {}", - i, e - ))), - request.clone(), - ) - })?; + let wrapped = generate_wrapper_proof(prover, &proof, &wrap_id, &artifacts_dir) + .map_err(|e| { + ComputeRequestError::new( + ComputeRequestErrorKind::Zk(ZkEventError::ProofGenerationFailed(format!( + "C6 wrapper proof[{}]: {}", + i, e + ))), + request.clone(), + ) + })?; wrapped_proofs.push(wrapped); } proofs.push(proof); @@ -685,9 +695,18 @@ fn handle_zk_request( proof1, proof2, target_evm, + params_preset, } => timefunc("zk_fold_proofs", id, || { let bb_work_id = zk_bb_work_id(&request); - match generate_fold_proof(&prover, &proof1, &proof2, &bb_work_id, target_evm) { + let artifacts_dir = params_preset.artifacts_dir(); + match generate_fold_proof( + &prover, + &proof1, + &proof2, + &bb_work_id, + target_evm, + &artifacts_dir, + ) { Ok(proof) => Ok(ComputeResponse::zk( ZkResponse::FoldProofs(FoldProofsResponse { proof }), request.correlation_id, @@ -785,11 +804,18 @@ fn handle_share_computation_proof( let bb_work = zk_bb_work_id(&request); let inner_job_id = format!("{bb_work}_c2_inner"); let wrap_job_id = format!("{bb_work}_c2_wrap"); + let artifacts_dir = req.params_preset.artifacts_dir(); // 7. Inner C2 proof (sk_share_computation or e_sm_share_computation) let circuit = ShareComputationCircuit; let proof = circuit - .prove(prover, &req.params_preset, &circuit_data, &inner_job_id) + .prove( + prover, + &req.params_preset, + &circuit_data, + &inner_job_id, + &artifacts_dir, + ) .map_err(|e| { ComputeRequestError::new( ComputeRequestErrorKind::Zk(ZkEventError::ProofGenerationFailed(e.to_string())), @@ -798,12 +824,13 @@ fn handle_share_computation_proof( })?; // 8. Wrap inner proof for fold aggregation (`share_computation` wrapper) - let wrapped_proof = generate_wrapper_proof(prover, &proof, &wrap_job_id).map_err(|e| { - ComputeRequestError::new( - ComputeRequestErrorKind::Zk(ZkEventError::ProofGenerationFailed(e.to_string())), - request.clone(), - ) - })?; + let wrapped_proof = generate_wrapper_proof(prover, &proof, &wrap_job_id, &artifacts_dir) + .map_err(|e| { + ComputeRequestError::new( + ComputeRequestErrorKind::Zk(ZkEventError::ProofGenerationFailed(e.to_string())), + request.clone(), + ) + })?; // 9. Return inner + wrapped C2 proofs Ok(ComputeResponse::zk( @@ -873,9 +900,16 @@ fn handle_pk_generation_proof( let circuit = PkGenerationCircuit; let bb_work = zk_bb_work_id(&request); let wrap_job_id = format!("{bb_work}_c1_wrap"); + let artifacts_dir = req.params_preset.artifacts_dir(); let proof = circuit - .prove(prover, &req.params_preset, &circuit_data, &bb_work) + .prove( + prover, + &req.params_preset, + &circuit_data, + &bb_work, + &artifacts_dir, + ) .map_err(|e| { ComputeRequestError::new( ComputeRequestErrorKind::Zk(ZkEventError::ProofGenerationFailed(e.to_string())), @@ -883,12 +917,13 @@ fn handle_pk_generation_proof( ) })?; - let wrapped_proof = generate_wrapper_proof(prover, &proof, &wrap_job_id).map_err(|e| { - ComputeRequestError::new( - ComputeRequestErrorKind::Zk(ZkEventError::ProofGenerationFailed(e.to_string())), - request.clone(), - ) - })?; + let wrapped_proof = generate_wrapper_proof(prover, &proof, &wrap_job_id, &artifacts_dir) + .map_err(|e| { + ComputeRequestError::new( + ComputeRequestErrorKind::Zk(ZkEventError::ProofGenerationFailed(e.to_string())), + request.clone(), + ) + })?; // 6. Return response Ok(ComputeResponse::zk( @@ -924,10 +959,17 @@ fn handle_pk_bfv_proof( .params_preset .threshold_counterpart() .unwrap_or_else(|| BfvPreset::InsecureThreshold512); + let artifacts_dir = req.params_preset.artifacts_dir(); // But here we have to pass the InsecureThreshold512 preset because the underlaying witness generator // builds both params, but will only use the DKG one let proof = circuit - .prove(prover, &preset_counterpart, &circuit_data, &bb_work) + .prove( + prover, + &preset_counterpart, + &circuit_data, + &bb_work, + &artifacts_dir, + ) .map_err(|e| { ComputeRequestError::new( ComputeRequestErrorKind::Zk(ZkEventError::ProofGenerationFailed(e.to_string())), @@ -935,12 +977,13 @@ fn handle_pk_bfv_proof( ) })?; - let wrapped_proof = generate_wrapper_proof(prover, &proof, &wrap_job_id).map_err(|e| { - ComputeRequestError::new( - ComputeRequestErrorKind::Zk(ZkEventError::ProofGenerationFailed(e.to_string())), - request.clone(), - ) - })?; + let wrapped_proof = generate_wrapper_proof(prover, &proof, &wrap_job_id, &artifacts_dir) + .map_err(|e| { + ComputeRequestError::new( + ComputeRequestErrorKind::Zk(ZkEventError::ProofGenerationFailed(e.to_string())), + request.clone(), + ) + })?; Ok(ComputeResponse::zk( ZkResponse::PkBfv(PkBfvProofResponse::new(proof, wrapped_proof)), @@ -1014,8 +1057,15 @@ fn handle_share_encryption_proof( let circuit = ShareEncryptionCircuit; let bb_work = zk_bb_work_id(&request); let wrap_job_id = format!("{bb_work}_c3_wrap"); + let artifacts_dir = req.params_preset.artifacts_dir(); let proof = circuit - .prove(prover, &req.params_preset, &circuit_data, &bb_work) + .prove( + prover, + &req.params_preset, + &circuit_data, + &bb_work, + &artifacts_dir, + ) .map_err(|e| { ComputeRequestError::new( ComputeRequestErrorKind::Zk(ZkEventError::ProofGenerationFailed(e.to_string())), @@ -1023,12 +1073,13 @@ fn handle_share_encryption_proof( ) })?; - let wrapped_proof = generate_wrapper_proof(prover, &proof, &wrap_job_id).map_err(|e| { - ComputeRequestError::new( - ComputeRequestErrorKind::Zk(ZkEventError::ProofGenerationFailed(e.to_string())), - request.clone(), - ) - })?; + let wrapped_proof = generate_wrapper_proof(prover, &proof, &wrap_job_id, &artifacts_dir) + .map_err(|e| { + ComputeRequestError::new( + ComputeRequestErrorKind::Zk(ZkEventError::ProofGenerationFailed(e.to_string())), + request.clone(), + ) + })?; Ok(ComputeResponse::zk( ZkResponse::ShareEncryption(ShareEncryptionProofResponse { @@ -1108,8 +1159,15 @@ fn handle_dkg_share_decryption_proof( let circuit = ShareDecryptionCircuit; let bb_work = zk_bb_work_id(&request); let wrap_job_id = format!("{bb_work}_c4_wrap"); + let artifacts_dir = req.params_preset.artifacts_dir(); let proof = circuit - .prove(prover, &req.params_preset, &circuit_data, &bb_work) + .prove( + prover, + &req.params_preset, + &circuit_data, + &bb_work, + &artifacts_dir, + ) .map_err(|e| { ComputeRequestError::new( ComputeRequestErrorKind::Zk(ZkEventError::ProofGenerationFailed(e.to_string())), @@ -1117,12 +1175,13 @@ fn handle_dkg_share_decryption_proof( ) })?; - let wrapped_proof = generate_wrapper_proof(prover, &proof, &wrap_job_id).map_err(|e| { - ComputeRequestError::new( - ComputeRequestErrorKind::Zk(ZkEventError::ProofGenerationFailed(e.to_string())), - request.clone(), - ) - })?; + let wrapped_proof = generate_wrapper_proof(prover, &proof, &wrap_job_id, &artifacts_dir) + .map_err(|e| { + ComputeRequestError::new( + ComputeRequestErrorKind::Zk(ZkEventError::ProofGenerationFailed(e.to_string())), + request.clone(), + ) + })?; // 6. Return response Ok(ComputeResponse::zk( @@ -1143,11 +1202,12 @@ fn zk_verify_share_proof_bundle( proof: &Proof, e3_id_str: &str, party_id: u64, + artifacts_dir: &str, ) -> Result { if proof.circuit == CircuitName::ShareComputation { - prover.verify_wrapper_proof(proof, e3_id_str, party_id) + prover.verify_wrapper_proof(proof, e3_id_str, party_id, artifacts_dir) } else { - prover.verify_proof(proof, e3_id_str, party_id) + prover.verify_proof(proof, e3_id_str, party_id, artifacts_dir) } } @@ -1157,6 +1217,7 @@ fn handle_verify_share_proofs( request: ComputeRequest, ) -> Result { let e3_id_str = request.e3_id.to_string(); + let artifacts_dir = req.params_preset.artifacts_dir(); // ECDSA validation (signature recovery, signer consistency, e3_id match) // is handled by ShareVerificationActor before dispatching to multithread. @@ -1188,7 +1249,8 @@ fn handle_verify_share_proofs( // 2. ZK proof verification let proof = &signed_proof.payload.proof; - let result = zk_verify_share_proof_bundle(prover, proof, &e3_id_str, sender); + let result = + zk_verify_share_proof_bundle(prover, proof, &e3_id_str, sender, &artifacts_dir); match result { Ok(true) => continue, Ok(false) | Err(_) => { @@ -1227,6 +1289,7 @@ fn handle_verify_share_decryption_proofs( request: ComputeRequest, ) -> Result { let e3_id_str = request.e3_id.to_string(); + let artifacts_dir = req.params_preset.artifacts_dir(); // ECDSA validation (signature recovery, signer consistency, e3_id match) // is handled by ShareVerificationActor before dispatching to multithread. @@ -1272,7 +1335,7 @@ fn handle_verify_share_decryption_proofs( // 2. ZK proof verification let proof = &signed_proof.payload.proof; - let result = prover.verify_proof(proof, &e3_id_str, sender); + let result = prover.verify_proof(proof, &e3_id_str, sender, &artifacts_dir); match result { Ok(true) => continue, Ok(false) | Err(_) => { @@ -1388,6 +1451,7 @@ fn handle_decrypted_shares_aggregation_proof( let circuit = DecryptedSharesAggregationCircuit; let idx_work_id = format!("{}_c7_{}", zk_bb_work_id(&request), i); + let artifacts_dir = req.params_preset.artifacts_dir(); let proof = circuit .prove_with_variant( prover, @@ -1395,6 +1459,7 @@ fn handle_decrypted_shares_aggregation_proof( &circuit_data, &idx_work_id, CircuitVariant::Evm, + &artifacts_dir, ) .map_err(|e| { ComputeRequestError::new( diff --git a/crates/tests/tests/integration.rs b/crates/tests/tests/integration.rs index 8cdfd6c383..0bb5fd5c78 100644 --- a/crates/tests/tests/integration.rs +++ b/crates/tests/tests/integration.rs @@ -134,8 +134,10 @@ async fn setup_test_zk_backend() -> (ZkBackend, tempfile::TempDir) { } // ── recursive/ variant (inner/base proofs, uses .vk_noir) ────────── + // Tests use insecure params, so fixtures go under insecure-512/ + let preset_dir = circuits_dir.join("insecure-512"); - let rv = circuits_dir.join("recursive"); + let rv = preset_dir.join("recursive"); // T0 (pk) copy_circuit( @@ -221,7 +223,7 @@ async fn setup_test_zk_backend() -> (ZkBackend, tempfile::TempDir) { // ── default/ variant (wrapper & fold proofs, uses .vk_recursive) ─── - let dv = circuits_dir.join("default"); + let dv = preset_dir.join("default"); // DKG wrapper circuits let dkg_wrapper_base = dv.join("recursive_aggregation/wrapper/dkg"); @@ -305,7 +307,7 @@ async fn setup_test_zk_backend() -> (ZkBackend, tempfile::TempDir) { // ── evm/ variant (on-chain verification: C5, C7, fold) ─────────── - let ev = circuits_dir.join("evm"); + let ev = preset_dir.join("evm"); // C5 (pk_aggregation) — EVM-targeted copy_circuit( @@ -878,7 +880,7 @@ async fn test_trbfv_actor() -> Result<()> { // Trigger actor DKG let e3_id = E3id::new("0", 1); - let proof_aggregation_enabled = true; + let proof_aggregation_enabled = false; let e3_requested = E3Requested { e3_id: e3_id.clone(), diff --git a/crates/zk-prover/src/actors/accusation_manager.rs b/crates/zk-prover/src/actors/accusation_manager.rs index 428dd7b28a..cb20b9abfd 100644 --- a/crates/zk-prover/src/actors/accusation_manager.rs +++ b/crates/zk-prover/src/actors/accusation_manager.rs @@ -132,6 +132,9 @@ pub struct AccusationManager { /// Vote timeout duration. vote_timeout: Duration, + + /// BFV preset for circuit artifact resolution. + params_preset: e3_fhe_params::BfvPreset, } impl AccusationManager { @@ -141,6 +144,7 @@ impl AccusationManager { signer: PrivateKeySigner, committee: Vec
, threshold_m: usize, + params_preset: e3_fhe_params::BfvPreset, ) -> Self { let my_address = signer.address(); Self { @@ -156,6 +160,7 @@ impl AccusationManager { buffered_votes: HashMap::new(), pending_reverifications: HashMap::new(), vote_timeout: DEFAULT_VOTE_TIMEOUT, + params_preset, } } @@ -165,8 +170,9 @@ impl AccusationManager { signer: PrivateKeySigner, committee: Vec
, threshold_m: usize, + params_preset: e3_fhe_params::BfvPreset, ) -> Addr { - let addr = Self::new(bus, e3_id, signer, committee, threshold_m).start(); + let addr = Self::new(bus, e3_id, signer, committee, threshold_m, params_preset).start(); bus.subscribe(EventType::ProofVerificationFailed, addr.clone().into()); bus.subscribe(EventType::ProofVerificationPassed, addr.clone().into()); bus.subscribe(EventType::ProofFailureAccusation, addr.clone().into()); @@ -635,6 +641,7 @@ impl AccusationManager { let request = ComputeRequest::zk( ZkRequest::VerifyShareProofs(VerifyShareProofsRequest { party_proofs: vec![party_proof], + params_preset: self.params_preset, }), correlation_id, self.e3_id.clone(), diff --git a/crates/zk-prover/src/actors/accusation_manager_ext.rs b/crates/zk-prover/src/actors/accusation_manager_ext.rs index b7fdc7f97e..9fce515c85 100644 --- a/crates/zk-prover/src/actors/accusation_manager_ext.rs +++ b/crates/zk-prover/src/actors/accusation_manager_ext.rs @@ -89,6 +89,7 @@ impl E3Extension for AccusationManagerExtension { self.signer.clone(), committee_addresses, threshold_m, + meta.params_preset, ); ctx.set_event_recipient("accusation_manager", Some(addr.into())); diff --git a/crates/zk-prover/src/actors/node_proof_aggregator.rs b/crates/zk-prover/src/actors/node_proof_aggregator.rs index dd0ca42287..abfa05167f 100644 --- a/crates/zk-prover/src/actors/node_proof_aggregator.rs +++ b/crates/zk-prover/src/actors/node_proof_aggregator.rs @@ -47,6 +47,8 @@ struct RollingAggregationState { fold_correlation: Option, /// EventContext for publishing. last_ec: EventContext, + /// BFV preset for circuit artifact resolution. + params_preset: e3_fhe_params::BfvPreset, } /// Actor that incrementally folds DKG inner proofs into a single node-level proof. @@ -108,6 +110,7 @@ impl NodeProofAggregator { // C0 + C1 + C2a + C2b + C3a×sk_enc + C3b×e_sm_enc + C4a + C4b let total_expected = 4 + sk_enc_count + e_sm_enc_count + 2; + let params_preset = msg.proof_request.params_preset; self.states.entry(e3_id.clone()).or_insert_with(|| { info!( "NodeProofAggregator: initializing state for E3 {} party {} (total_expected={}, ~{} fold steps)", @@ -123,6 +126,7 @@ impl NodeProofAggregator { remaining: total_expected, fold_correlation: None, last_ec: ec, + params_preset, } }); } @@ -211,6 +215,7 @@ impl NodeProofAggregator { proof1: acc, proof2: next_proof, target_evm: false, + params_preset: state.params_preset, }, corr, e3_id_clone, diff --git a/crates/zk-prover/src/actors/proof_request.rs b/crates/zk-prover/src/actors/proof_request.rs index 75bcd71fb4..638126bdc1 100644 --- a/crates/zk-prover/src/actors/proof_request.rs +++ b/crates/zk-prover/src/actors/proof_request.rs @@ -265,10 +265,12 @@ impl ProofRequestActor { } /// Returns true if proof aggregation (wrapping/folding) is enabled for this E3. + /// Defaults to `false` when metadata is missing (e.g. after restart) to avoid + /// requiring wrapped proofs that were never generated. fn is_proof_aggregation_enabled(&self, e3_id: &E3id) -> bool { self.node_agg_meta .get(e3_id) - .map_or(true, |m| m.proof_aggregation_enabled) + .map_or(false, |m| m.proof_aggregation_enabled) } fn handle_encryption_key_pending(&mut self, msg: TypedEvent) { diff --git a/crates/zk-prover/src/actors/proof_verification.rs b/crates/zk-prover/src/actors/proof_verification.rs index d9d1371509..b93481af20 100644 --- a/crates/zk-prover/src/actors/proof_verification.rs +++ b/crates/zk-prover/src/actors/proof_verification.rs @@ -15,11 +15,12 @@ use actix::{Actor, Addr, AsyncContext, Context, Handler, Message, Recipient}; use alloy::primitives::{keccak256, Address, Bytes}; use alloy::sol_types::SolValue; use e3_events::{ - BusHandle, E3id, EnclaveEvent, EnclaveEventData, EncryptionKey, EncryptionKeyCreated, - EncryptionKeyReceived, EventContext, EventPublisher, EventSubscriber, EventType, Proof, - ProofType, ProofVerificationFailed, ProofVerificationPassed, Sequenced, SignedProofFailed, - SignedProofPayload, TypedEvent, + BusHandle, CiphernodeSelected, E3id, EnclaveEvent, EnclaveEventData, EncryptionKey, + EncryptionKeyCreated, EncryptionKeyReceived, EventContext, EventPublisher, EventSubscriber, + EventType, Proof, ProofType, ProofVerificationFailed, ProofVerificationPassed, Sequenced, + SignedProofFailed, SignedProofPayload, TypedEvent, }; +use e3_fhe_params::BfvPreset; use e3_utils::NotifySync; use tracing::{error, info, warn}; @@ -30,6 +31,7 @@ pub struct ZkVerificationRequest { pub e3_id: E3id, pub key: Arc, pub sender: Recipient>, + pub artifacts_dir: String, } #[derive(Debug, Clone, Message)] @@ -51,6 +53,8 @@ pub struct ProofVerificationActor { bus: BusHandle, verifier: Recipient>, pending: HashMap<(E3id, u64), PendingVerification>, + /// Tracks `BfvPreset` per E3 so we can derive `artifacts_dir` for proof verification. + presets: HashMap, } impl ProofVerificationActor { @@ -59,6 +63,7 @@ impl ProofVerificationActor { bus: bus.clone(), verifier, pending: HashMap::new(), + presets: HashMap::new(), } } @@ -67,6 +72,7 @@ impl ProofVerificationActor { verifier: Recipient>, ) -> Addr { let addr = Self::new(bus, verifier).start(); + bus.subscribe(EventType::CiphernodeSelected, addr.clone().into()); bus.subscribe(EventType::EncryptionKeyReceived, addr.clone().into()); addr } @@ -139,12 +145,23 @@ impl ProofVerificationActor { }, ); + let Some(preset) = self.presets.get(&msg.e3_id).copied() else { + error!( + "No BfvPreset known for e3_id={} — cannot determine circuit artifacts directory. \ + This can happen if CiphernodeSelected was missed (e.g. after restart). Rejecting key from party {}.", + msg.e3_id, msg.key.party_id + ); + return; + }; + let artifacts_dir = preset.artifacts_dir(); + let request = TypedEvent::new( ZkVerificationRequest { proof: proof.clone(), e3_id: msg.e3_id, key: msg.key, sender: ctx.address().recipient(), + artifacts_dir, }, ec, ); @@ -181,6 +198,9 @@ impl Handler for ProofVerificationActor { fn handle(&mut self, msg: EnclaveEvent, ctx: &mut Self::Context) -> Self::Result { let (msg, ec) = msg.into_components(); match msg { + EnclaveEventData::CiphernodeSelected(data) => { + self.presets.insert(data.e3_id.clone(), data.params_preset); + } EnclaveEventData::EncryptionKeyReceived(data) => { self.notify_sync(ctx, TypedEvent::new(data, ec)) } diff --git a/crates/zk-prover/src/actors/share_verification.rs b/crates/zk-prover/src/actors/share_verification.rs index f8f73e9b64..584582dd1e 100644 --- a/crates/zk-prover/src/actors/share_verification.rs +++ b/crates/zk-prover/src/actors/share_verification.rs @@ -90,6 +90,8 @@ struct PendingVerification { party_proof_hashes: HashMap>, /// Cached (proof_type, public_signals) per party — for commitment consistency checking. party_public_signals: HashMap>, + /// BFV preset for circuit artifact resolution. + params_preset: e3_fhe_params::BfvPreset, } /// Pending consistency check — stored between ECDSA pass and ZK dispatch. @@ -124,6 +126,8 @@ struct PendingConsistencyCheck { /// Original ECDSA-passed decryption proofs for ZK dispatch. /// Populated for DecryptionProofs. ecdsa_passed_decryption_proofs: Vec, + /// BFV preset for circuit artifact resolution. + params_preset: e3_fhe_params::BfvPreset, } /// Filter out inconsistent parties and collect dispatched party IDs. @@ -194,6 +198,7 @@ impl ShareVerificationActor { e3_id, msg.kind ); + let params_preset = msg.params_preset; match msg.kind { VerificationKind::ShareProofs | VerificationKind::ThresholdDecryptionProofs @@ -205,6 +210,7 @@ impl ShareVerificationActor { msg.share_proofs, msg.pre_dishonest, ec, + params_preset, |pending, passed| { pending.ecdsa_passed_share_proofs = passed; }, @@ -217,6 +223,7 @@ impl ShareVerificationActor { msg.decryption_proofs, msg.pre_dishonest, ec, + params_preset, |pending, passed| { pending.ecdsa_passed_decryption_proofs = passed; }, @@ -237,6 +244,7 @@ impl ShareVerificationActor { party_proofs: Vec

, pre_dishonest: BTreeSet, ec: EventContext, + params_preset: e3_fhe_params::BfvPreset, store_passed_proofs: impl FnOnce(&mut PendingConsistencyCheck, Vec

), ) { let e3_id_str = e3_id.to_string(); @@ -355,6 +363,7 @@ impl ShareVerificationActor { party_public_signals, ecdsa_passed_share_proofs: Vec::new(), ecdsa_passed_decryption_proofs: Vec::new(), + params_preset, }; store_passed_proofs(&mut pending, ecdsa_passed_parties); self.pending_consistency.insert(correlation_id, pending); @@ -446,6 +455,7 @@ impl ShareVerificationActor { let req = ComputeRequest::zk( ZkRequest::VerifyShareProofs(VerifyShareProofsRequest { party_proofs: passed, + params_preset: pending.params_preset, }), zk_correlation_id, pending.e3_id.clone(), @@ -469,6 +479,7 @@ impl ShareVerificationActor { let req = ComputeRequest::zk( ZkRequest::VerifyShareDecryptionProofs(VerifyShareDecryptionProofsRequest { party_proofs: passed, + params_preset: pending.params_preset, }), zk_correlation_id, pending.e3_id.clone(), @@ -510,6 +521,7 @@ impl ShareVerificationActor { party_addresses, party_proof_hashes, party_public_signals, + params_preset: pending.params_preset, }, ); diff --git a/crates/zk-prover/src/actors/zk_actor.rs b/crates/zk-prover/src/actors/zk_actor.rs index 8f1abe3f54..51d3a483e3 100644 --- a/crates/zk-prover/src/actors/zk_actor.rs +++ b/crates/zk-prover/src/actors/zk_actor.rs @@ -49,9 +49,9 @@ impl Handler> for ZkActor { ); let e3_id_str = msg.e3_id.to_string(); - let result = self - .prover - .verify_proof(&msg.proof, &e3_id_str, msg.key.party_id); + let result = + self.prover + .verify_proof(&msg.proof, &e3_id_str, msg.key.party_id, &msg.artifacts_dir); let response = TypedEvent::new( match result { diff --git a/crates/zk-prover/src/circuits/recursive_aggregation/mod.rs b/crates/zk-prover/src/circuits/recursive_aggregation/mod.rs index fb98e4e0d9..3843a48a02 100644 --- a/crates/zk-prover/src/circuits/recursive_aggregation/mod.rs +++ b/crates/zk-prover/src/circuits/recursive_aggregation/mod.rs @@ -61,6 +61,7 @@ pub fn generate_wrapper_proof( prover: &ZkProver, proof: &Proof, e3_id: &str, + artifacts_dir: &str, ) -> Result { let inner_circuit = proof.circuit; let wrapper_circuit = inner_circuit.wrapper_artifact_circuit(); @@ -69,7 +70,7 @@ pub fn generate_wrapper_proof( let public_inputs = vec![bytes_to_field_strings(&proof.public_signals)?]; let vk_artifacts = vk::load_vk_artifacts( - &prover.circuits_dir(CircuitVariant::Recursive), + &prover.circuits_dir(CircuitVariant::Recursive, artifacts_dir), inner_circuit, )?; @@ -82,7 +83,7 @@ pub fn generate_wrapper_proof( let dir_path = wrapper_circuit.wrapper_dir_path(); let circuit_path = prover - .circuits_dir(CircuitVariant::Default) + .circuits_dir(CircuitVariant::Default, artifacts_dir) .join(&dir_path) .join(format!("{}.json", wrapper_circuit.as_str())); let compiled = CompiledCircuit::from_file(&circuit_path)?; @@ -93,7 +94,7 @@ pub fn generate_wrapper_proof( let witness_gen = WitnessGenerator::new(); let witness = witness_gen.generate_witness(&compiled, input_map)?; - prover.generate_wrapper_proof(wrapper_circuit, &witness, e3_id) + prover.generate_wrapper_proof(wrapper_circuit, &witness, e3_id, artifacts_dir) } /// Full input for the fold circuit (recursive_aggregation/fold). @@ -143,13 +144,14 @@ pub fn generate_fold_proof( proof2: &Proof, e3_id: &str, target_evm: bool, + artifacts_dir: &str, ) -> Result { let vk1 = vk::load_vk_for_fold_input( - &prover.circuits_dir(CircuitVariant::Default), + &prover.circuits_dir(CircuitVariant::Default, artifacts_dir), proof1.circuit, )?; let vk2 = vk::load_vk_for_fold_input( - &prover.circuits_dir(CircuitVariant::Default), + &prover.circuits_dir(CircuitVariant::Default, artifacts_dir), proof2.circuit, )?; @@ -188,7 +190,7 @@ pub fn generate_fold_proof( }; let dir_path = CircuitName::Fold.dir_path(); let circuit_path = prover - .circuits_dir(variant) + .circuits_dir(variant, artifacts_dir) .join(&dir_path) .join(format!("{}.json", CircuitName::Fold.as_str())); let compiled = CompiledCircuit::from_file(&circuit_path)?; @@ -200,9 +202,9 @@ pub fn generate_fold_proof( let witness = witness_gen.generate_witness(&compiled, input_map)?; if target_evm { - prover.generate_final_fold_proof(&witness, e3_id) + prover.generate_final_fold_proof(&witness, e3_id, artifacts_dir) } else { - prover.generate_fold_proof(&witness, e3_id) + prover.generate_fold_proof(&witness, e3_id, artifacts_dir) } } @@ -294,6 +296,7 @@ mod tests { } let preset = BfvPreset::InsecureThreshold512; + let artifacts_dir = preset.artifacts_dir(); let sample = PkCircuitData::generate_sample(preset).expect("sample data generation should succeed"); @@ -301,12 +304,18 @@ mod tests { // First generate the inner proof with prove() (Recursive Variant) let inner_proof = PkCircuit - .prove(&prover, &preset, &sample, &format!("{e3_id}_inner_0")) + .prove( + &prover, + &preset, + &sample, + &format!("{e3_id}_inner_0"), + &artifacts_dir, + ) .expect("inner prove() should succeed"); let start = std::time::Instant::now(); - let wrapper_proof = - generate_wrapper_proof(&prover, &inner_proof, e3_id).expect("wrapper (1 proof)"); + let wrapper_proof = generate_wrapper_proof(&prover, &inner_proof, e3_id, &artifacts_dir) + .expect("wrapper (1 proof)"); let elapsed = start.elapsed(); eprintln!("1-proof wrapper generation: {:?}", elapsed); @@ -314,7 +323,7 @@ mod tests { assert!(!wrapper_proof.public_signals.is_empty()); let verified = prover - .verify_wrapper_proof(&wrapper_proof, e3_id, 0) + .verify_wrapper_proof(&wrapper_proof, e3_id, 0, &artifacts_dir) .expect("verification should not error"); assert!(verified, "wrapper proof should verify successfully"); @@ -361,6 +370,7 @@ mod tests { } let preset = BfvPreset::InsecureThreshold512; + let artifacts_dir = preset.artifacts_dir(); let committee = CiphernodesCommitteeSize::Micro.values(); let sample_a = ShareDecryptionCircuitData::generate_sample( preset, @@ -376,19 +386,38 @@ mod tests { // First generate the inner proofs with prove() (Recursive Variant) let inner_proof_a = ShareDecryptionCircuit - .prove(&prover, &preset, &sample_a, &format!("{e3_id}_inner_0")) + .prove( + &prover, + &preset, + &sample_a, + &format!("{e3_id}_inner_0"), + &artifacts_dir, + ) .expect("inner prove() A should succeed"); let inner_proof_b = ShareDecryptionCircuit - .prove(&prover, &preset, &sample_b, &format!("{e3_id}_inner_1")) + .prove( + &prover, + &preset, + &sample_b, + &format!("{e3_id}_inner_1"), + &artifacts_dir, + ) .expect("inner prove() B should succeed"); let start = std::time::Instant::now(); - let wrapper_a = - generate_wrapper_proof(&prover, &inner_proof_a, e3_id).expect("wrapper (proof A)"); - let wrapper_b = - generate_wrapper_proof(&prover, &inner_proof_b, e3_id).expect("wrapper (proof B)"); - let fold_proof = generate_fold_proof(&prover, &wrapper_a, &wrapper_b, e3_id, false) - .expect("fold 2 wrappers"); + let wrapper_a = generate_wrapper_proof(&prover, &inner_proof_a, e3_id, &artifacts_dir) + .expect("wrapper (proof A)"); + let wrapper_b = generate_wrapper_proof(&prover, &inner_proof_b, e3_id, &artifacts_dir) + .expect("wrapper (proof B)"); + let fold_proof = generate_fold_proof( + &prover, + &wrapper_a, + &wrapper_b, + e3_id, + false, + &artifacts_dir, + ) + .expect("fold 2 wrappers"); let elapsed = start.elapsed(); eprintln!("2-proof (wrapper each + fold) generation: {:?}", elapsed); @@ -396,7 +425,7 @@ mod tests { assert!(!fold_proof.public_signals.is_empty()); let verified = prover - .verify_fold_proof(&fold_proof, e3_id, 0) + .verify_fold_proof(&fold_proof, e3_id, 0, &artifacts_dir) .expect("verification should not error"); assert!(verified, "fold of 2 wrappers should verify successfully"); @@ -463,6 +492,7 @@ mod tests { } let preset = BfvPreset::InsecureThreshold512; + let artifacts_dir = preset.artifacts_dir(); let committee = CiphernodesCommitteeSize::Micro.values(); let sd = preset.search_defaults().expect("search_defaults"); @@ -490,11 +520,18 @@ mod tests { // Generate inner proofs first with prove() (Recursive Variant) let pk_inner_proof = PkCircuit - .prove(&prover, &preset, &pk_sample, &format!("{e3_id}_pk_inner_0")) + .prove( + &prover, + &preset, + &pk_sample, + &format!("{e3_id}_pk_inner_0"), + &artifacts_dir, + ) .expect("pk inner prove() should succeed"); let pk_wrapper_proof = - generate_wrapper_proof(&prover, &pk_inner_proof, e3_id).expect("pk wrapper"); + generate_wrapper_proof(&prover, &pk_inner_proof, e3_id, &artifacts_dir) + .expect("pk wrapper"); let enc_inner_secret = ShareEncryptionCircuit .prove( @@ -502,6 +539,7 @@ mod tests { &preset, &share_enc_sample_secret, &format!("{e3_id}_enc_inner_0"), + &artifacts_dir, ) .expect("share_encryption inner prove() (secret) should succeed"); let enc_inner_noise = ShareEncryptionCircuit @@ -510,19 +548,23 @@ mod tests { &preset, &share_enc_sample_noise, &format!("{e3_id}_enc_inner_1"), + &artifacts_dir, ) .expect("share_encryption inner prove() (noise) should succeed"); - let share_enc_wrapper_1 = generate_wrapper_proof(&prover, &enc_inner_secret, e3_id) - .expect("share_encryption wrapper (secret)"); - let share_enc_wrapper_2 = generate_wrapper_proof(&prover, &enc_inner_noise, e3_id) - .expect("share_encryption wrapper (noise)"); + let share_enc_wrapper_1 = + generate_wrapper_proof(&prover, &enc_inner_secret, e3_id, &artifacts_dir) + .expect("share_encryption wrapper (secret)"); + let share_enc_wrapper_2 = + generate_wrapper_proof(&prover, &enc_inner_noise, e3_id, &artifacts_dir) + .expect("share_encryption wrapper (noise)"); let share_enc_fold_proof = generate_fold_proof( &prover, &share_enc_wrapper_1, &share_enc_wrapper_2, e3_id, false, + &artifacts_dir, ) .expect("fold share_enc wrappers"); let fold_proof = generate_fold_proof( @@ -531,6 +573,7 @@ mod tests { &pk_wrapper_proof, e3_id, false, + &artifacts_dir, ) .expect("fold"); @@ -539,7 +582,7 @@ mod tests { assert_eq!(fold_proof.circuit, e3_events::CircuitName::Fold); let verified = prover - .verify_fold_proof(&fold_proof, e3_id, 0) + .verify_fold_proof(&fold_proof, e3_id, 0, &artifacts_dir) .expect("verification should not error"); assert!(verified, "fold proof should verify successfully"); diff --git a/crates/zk-prover/src/circuits/utils.rs b/crates/zk-prover/src/circuits/utils.rs index b69aed71e0..8c24180621 100644 --- a/crates/zk-prover/src/circuits/utils.rs +++ b/crates/zk-prover/src/circuits/utils.rs @@ -37,9 +37,16 @@ pub fn prove_recursive_circuit( circuit_name: CircuitName, input: &impl serde::Serialize, e3_id: &str, + artifacts_dir: &str, ) -> Result { - let witness = generate_recursive_witness(prover, circuit_name, input)?; - prover.generate_proof_with_variant(circuit_name, &witness, e3_id, CircuitVariant::Recursive) + let witness = generate_recursive_witness(prover, circuit_name, input, artifacts_dir)?; + prover.generate_proof_with_variant( + circuit_name, + &witness, + e3_id, + CircuitVariant::Recursive, + artifacts_dir, + ) } /// Shared helper: load compiled circuit from Recursive dir, serialize input, generate witness. @@ -47,8 +54,9 @@ fn generate_recursive_witness( prover: &ZkProver, circuit_name: CircuitName, input: &impl serde::Serialize, + artifacts_dir: &str, ) -> Result, ZkError> { - let recursive_dir = prover.circuits_dir(CircuitVariant::Recursive); + let recursive_dir = prover.circuits_dir(CircuitVariant::Recursive, artifacts_dir); let circuit_path = recursive_dir .join(circuit_name.dir_path()) .join(format!("{}.json", circuit_name.as_str())); diff --git a/crates/zk-prover/src/prover.rs b/crates/zk-prover/src/prover.rs index 13957bcc11..98f1ecb5db 100644 --- a/crates/zk-prover/src/prover.rs +++ b/crates/zk-prover/src/prover.rs @@ -28,8 +28,8 @@ impl ZkProver { } } - pub fn circuits_dir(&self, variant: CircuitVariant) -> PathBuf { - self.circuits_dir.join(variant.as_str()) + pub fn circuits_dir(&self, variant: CircuitVariant, artifacts_dir: &str) -> PathBuf { + self.circuits_dir.join(artifacts_dir).join(variant.as_str()) } pub fn work_dir(&self) -> &PathBuf { @@ -45,8 +45,15 @@ impl ZkProver { circuit: CircuitName, witness_data: &[u8], e3_id: &str, + artifacts_dir: &str, ) -> Result { - self.generate_proof_with_variant(circuit, witness_data, e3_id, CircuitVariant::Recursive) + self.generate_proof_with_variant( + circuit, + witness_data, + e3_id, + CircuitVariant::Recursive, + artifacts_dir, + ) } pub fn generate_evm_proof( @@ -54,8 +61,15 @@ impl ZkProver { circuit: CircuitName, witness_data: &[u8], e3_id: &str, + artifacts_dir: &str, ) -> Result { - self.generate_proof_with_variant(circuit, witness_data, e3_id, CircuitVariant::Evm) + self.generate_proof_with_variant( + circuit, + witness_data, + e3_id, + CircuitVariant::Evm, + artifacts_dir, + ) } pub fn generate_proof_with_variant( @@ -64,8 +78,16 @@ impl ZkProver { witness_data: &[u8], e3_id: &str, variant: CircuitVariant, + artifacts_dir: &str, ) -> Result { - self.generate_proof_impl(circuit, witness_data, e3_id, &circuit.dir_path(), variant) + self.generate_proof_impl( + circuit, + witness_data, + e3_id, + &circuit.dir_path(), + variant, + artifacts_dir, + ) } /// Wrapper proof (Default variant, wrapper dir). @@ -74,6 +96,7 @@ impl ZkProver { circuit: CircuitName, witness_data: &[u8], e3_id: &str, + artifacts_dir: &str, ) -> Result { self.generate_proof_impl( circuit, @@ -81,11 +104,17 @@ impl ZkProver { e3_id, &circuit.wrapper_dir_path(), CircuitVariant::Default, + artifacts_dir, ) } /// Fold proof (Default variant). - pub fn generate_fold_proof(&self, witness_data: &[u8], e3_id: &str) -> Result { + pub fn generate_fold_proof( + &self, + witness_data: &[u8], + e3_id: &str, + artifacts_dir: &str, + ) -> Result { let dir = CircuitName::Fold.dir_path(); self.generate_proof_impl( CircuitName::Fold, @@ -93,6 +122,7 @@ impl ZkProver { e3_id, &dir, CircuitVariant::Default, + artifacts_dir, ) } @@ -101,6 +131,7 @@ impl ZkProver { &self, witness_data: &[u8], e3_id: &str, + artifacts_dir: &str, ) -> Result { let dir = CircuitName::Fold.dir_path(); self.generate_proof_impl( @@ -109,6 +140,7 @@ impl ZkProver { e3_id, &dir, CircuitVariant::Evm, + artifacts_dir, ) } @@ -119,6 +151,7 @@ impl ZkProver { e3_id: &str, dir_path: &str, variant: CircuitVariant, + artifacts_dir: &str, ) -> Result { self.generate_proof_impl_with_dir( circuit, @@ -126,7 +159,7 @@ impl ZkProver { e3_id, dir_path, variant, - self.circuits_dir(variant), + self.circuits_dir(variant, artifacts_dir), ) } @@ -236,8 +269,20 @@ impl ZkProver { } /// Verifies a proof (Recursive variant, matching `prove()`). - pub fn verify_proof(&self, proof: &Proof, e3_id: &str, party_id: u64) -> Result { - self.verify_proof_with_variant(proof, e3_id, party_id, CircuitVariant::Recursive) + pub fn verify_proof( + &self, + proof: &Proof, + e3_id: &str, + party_id: u64, + artifacts_dir: &str, + ) -> Result { + self.verify_proof_with_variant( + proof, + e3_id, + party_id, + CircuitVariant::Recursive, + artifacts_dir, + ) } pub fn verify_proof_with_variant( @@ -246,6 +291,7 @@ impl ZkProver { e3_id: &str, party_id: u64, variant: CircuitVariant, + artifacts_dir: &str, ) -> Result { self.verify_proof_impl( proof.circuit, @@ -255,6 +301,7 @@ impl ZkProver { e3_id, party_id, variant, + artifacts_dir, ) } @@ -263,8 +310,9 @@ impl ZkProver { proof: &Proof, e3_id: &str, party_id: u64, + artifacts_dir: &str, ) -> Result { - self.verify_proof_with_variant(proof, e3_id, party_id, CircuitVariant::Evm) + self.verify_proof_with_variant(proof, e3_id, party_id, CircuitVariant::Evm, artifacts_dir) } /// Verifies a wrapper proof (Default Variant, wrapper dir). @@ -273,6 +321,7 @@ impl ZkProver { proof: &Proof, e3_id: &str, party_id: u64, + artifacts_dir: &str, ) -> Result { self.verify_proof_impl( proof.circuit, @@ -282,6 +331,7 @@ impl ZkProver { e3_id, party_id, CircuitVariant::Default, + artifacts_dir, ) } @@ -291,6 +341,7 @@ impl ZkProver { proof: &Proof, e3_id: &str, party_id: u64, + artifacts_dir: &str, ) -> Result { use e3_events::CircuitName; if proof.circuit != CircuitName::Fold { @@ -307,6 +358,7 @@ impl ZkProver { e3_id, party_id, CircuitVariant::Default, + artifacts_dir, ) } @@ -319,6 +371,7 @@ impl ZkProver { e3_id: &str, party_id: u64, variant: CircuitVariant, + artifacts_dir: &str, ) -> Result { if !self.bb_binary.exists() { return Err(ZkError::BbNotInstalled); @@ -326,7 +379,7 @@ impl ZkProver { let verifier_target = variant.verifier_target(); let vk_path = self - .circuits_dir(variant) + .circuits_dir(variant, artifacts_dir) .join(&dir_path) .join(format!("{}.vk", circuit.as_str())); if !vk_path.exists() { @@ -416,7 +469,7 @@ mod tests { let backend = ZkBackend::new(BBPath::Default(bb_binary), circuits_dir, work_dir); let prover = ZkProver::new(&backend); - let result = prover.generate_proof(CircuitName::PkBfv, b"witness", "e3-1"); + let result = prover.generate_proof(CircuitName::PkBfv, b"witness", "e3-1", "insecure-512"); assert!(matches!(result, Err(ZkError::BbNotInstalled))); } } diff --git a/crates/zk-prover/src/traits.rs b/crates/zk-prover/src/traits.rs index fbf7fcd8a2..7b99d4cbcb 100644 --- a/crates/zk-prover/src/traits.rs +++ b/crates/zk-prover/src/traits.rs @@ -58,12 +58,20 @@ pub trait Provable: Send + Sync { params: &Self::Params, input: &Self::Input, e3_id: &str, + artifacts_dir: &str, ) -> Result where Self::Inputs: Computation + serde::Serialize, ::Error: Display, { - self.prove_with_variant(prover, params, input, e3_id, CircuitVariant::Recursive) + self.prove_with_variant( + prover, + params, + input, + e3_id, + CircuitVariant::Recursive, + artifacts_dir, + ) } fn prove_with_variant( @@ -73,6 +81,7 @@ pub trait Provable: Send + Sync { input: &Self::Input, e3_id: &str, variant: CircuitVariant, + artifacts_dir: &str, ) -> Result where Self::Inputs: Computation + serde::Serialize, @@ -82,7 +91,7 @@ pub trait Provable: Send + Sync { let resolved_name = self.resolve_circuit_name(params, input); let circuit_path = prover - .circuits_dir(variant) + .circuits_dir(variant, artifacts_dir) .join(resolved_name.dir_path()) .join(format!("{}.json", resolved_name.as_str())); @@ -91,7 +100,7 @@ pub trait Provable: Send + Sync { let witness_gen = WitnessGenerator::new(); let witness = witness_gen.generate_witness(&circuit, inputs)?; - prover.generate_proof_with_variant(resolved_name, &witness, e3_id, variant) + prover.generate_proof_with_variant(resolved_name, &witness, e3_id, variant, artifacts_dir) } fn verify( @@ -100,8 +109,16 @@ pub trait Provable: Send + Sync { proof: &Proof, e3_id: &str, party_id: u64, + artifacts_dir: &str, ) -> Result { - self.verify_with_variant(prover, proof, e3_id, party_id, CircuitVariant::Recursive) + self.verify_with_variant( + prover, + proof, + e3_id, + party_id, + CircuitVariant::Recursive, + artifacts_dir, + ) } fn verify_with_variant( @@ -111,6 +128,7 @@ pub trait Provable: Send + Sync { e3_id: &str, party_id: u64, variant: CircuitVariant, + artifacts_dir: &str, ) -> Result { if !self.valid_circuits().contains(&proof.circuit) { return Err(ZkError::VerifyFailed(format!( @@ -124,6 +142,6 @@ pub trait Provable: Send + Sync { "Verifying proof for circuit {} with e3_id {} and party_id {}", proof.circuit, e3_id, party_id ); - prover.verify_proof_with_variant(proof, e3_id, party_id, variant) + prover.verify_proof_with_variant(proof, e3_id, party_id, variant, artifacts_dir) } } diff --git a/crates/zk-prover/tests/backend_tests.rs b/crates/zk-prover/tests/backend_tests.rs index e0f7dea600..ccfadd9800 100644 --- a/crates/zk-prover/tests/backend_tests.rs +++ b/crates/zk-prover/tests/backend_tests.rs @@ -95,6 +95,11 @@ fn test_prover_requires_bb() { let backend = test_backend(temp.path(), ZkConfig::default()); let prover = ZkProver::new(&backend); - let result = prover.generate_proof(e3_events::CircuitName::PkBfv, b"witness", "e3-1"); + let result = prover.generate_proof( + e3_events::CircuitName::PkBfv, + b"witness", + "e3-1", + "insecure-512", + ); assert!(matches!(result, Err(e3_zk_prover::ZkError::BbNotInstalled))); } diff --git a/crates/zk-prover/tests/common/helpers.rs b/crates/zk-prover/tests/common/helpers.rs index 867b122380..dbe24c178f 100644 --- a/crates/zk-prover/tests/common/helpers.rs +++ b/crates/zk-prover/tests/common/helpers.rs @@ -41,12 +41,11 @@ pub async fn setup_compiled_circuit(backend: &ZkBackend, group: &str, circuit_na vk_evm_path.display() ); + // Tests use insecure params — fixtures go under insecure-512/ + let preset_dir = backend.circuits_dir.join("insecure-512"); + // Set up the evm variant directory (keccak VK + hash) - let evm_dir = backend - .circuits_dir - .join("evm") - .join(group) - .join(circuit_name); + let evm_dir = preset_dir.join("evm").join(group).join(circuit_name); fs::create_dir_all(&evm_dir).await.unwrap(); fs::copy(&json_path, evm_dir.join(format!("{circuit_name}.json"))) .await @@ -64,11 +63,7 @@ pub async fn setup_compiled_circuit(backend: &ZkBackend, group: &str, circuit_na } // Set up the default variant directory (noir-recursive-no-zk VK for wrapper/fold proofs) - let default_dir = backend - .circuits_dir - .join("default") - .join(group) - .join(circuit_name); + let default_dir = preset_dir.join("default").join(group).join(circuit_name); fs::create_dir_all(&default_dir).await.unwrap(); fs::copy(&json_path, default_dir.join(format!("{circuit_name}.json"))) .await @@ -95,11 +90,7 @@ pub async fn setup_compiled_circuit(backend: &ZkBackend, group: &str, circuit_na } // Set up the recursive variant directory (noir-recursive VK for inner/base proofs) - let recursive_dir = backend - .circuits_dir - .join("recursive") - .join(group) - .join(circuit_name); + let recursive_dir = preset_dir.join("recursive").join(group).join(circuit_name); fs::create_dir_all(&recursive_dir).await.unwrap(); fs::copy( &json_path, diff --git a/crates/zk-prover/tests/integration_tests.rs b/crates/zk-prover/tests/integration_tests.rs index 38b3ec49c5..2286473a30 100644 --- a/crates/zk-prover/tests/integration_tests.rs +++ b/crates/zk-prover/tests/integration_tests.rs @@ -79,27 +79,38 @@ async fn test_full_flow_download_circuits_prove_and_verify() { let result = backend.download_circuits().await; assert!(result.is_ok(), "download_circuits failed: {:?}", result); - assert!(backend - .circuits_dir - .join("default") - .join("dkg") - .join("pk") - .join("pk.json") - .exists()); - assert!(backend - .circuits_dir - .join("default") - .join("dkg") - .join("pk") - .join("pk.vk") - .exists()); - assert!(backend - .circuits_dir - .join("evm") - .join("dkg") - .join("pk") - .join("pk.vk") - .exists()); + // Circuit artifacts are nested under the preset directory (e.g. insecure-512/) + let preset_dir = backend.circuits_dir.join("insecure-512"); + assert!( + preset_dir + .join("default") + .join("dkg") + .join("pk") + .join("pk.json") + .exists(), + "expected circuit at {}/default/dkg/pk/pk.json", + preset_dir.display() + ); + assert!( + preset_dir + .join("default") + .join("dkg") + .join("pk") + .join("pk.vk") + .exists(), + "expected VK at {}/default/dkg/pk/pk.vk", + preset_dir.display() + ); + assert!( + preset_dir + .join("evm") + .join("dkg") + .join("pk") + .join("pk.vk") + .exists(), + "expected evm VK at {}/evm/dkg/pk/pk.vk", + preset_dir.display() + ); let result = backend.ensure_installed().await; assert!(result.is_ok(), "ensure_installed failed: {:?}", result); @@ -118,7 +129,7 @@ async fn test_full_flow_download_circuits_prove_and_verify() { let e3_id = "integration-test-full-flow"; let proof = PkCircuit - .prove(&prover, &preset, &sample, e3_id) + .prove(&prover, &preset, &sample, e3_id, &preset.artifacts_dir()) .expect("proof generation should succeed"); assert!(!proof.data.is_empty(), "proof data should not be empty"); @@ -129,7 +140,7 @@ async fn test_full_flow_download_circuits_prove_and_verify() { let party_id = 0; let verified = PkCircuit - .verify(&prover, &proof, e3_id, party_id) + .verify(&prover, &proof, e3_id, party_id, &preset.artifacts_dir()) .expect("verification call should not error"); assert!(verified, "proof should verify successfully"); diff --git a/crates/zk-prover/tests/local_e2e_tests.rs b/crates/zk-prover/tests/local_e2e_tests.rs index 14dc28e8bc..a593e6d239 100644 --- a/crates/zk-prover/tests/local_e2e_tests.rs +++ b/crates/zk-prover/tests/local_e2e_tests.rs @@ -468,8 +468,9 @@ macro_rules! e2e_proof_tests { return; }; + let artifacts_dir = preset.artifacts_dir(); let proof = circuit - .prove_with_variant(&prover, &preset, &sample, e3_id, $variant) + .prove_with_variant(&prover, &preset, &sample, e3_id, $variant, &artifacts_dir) .expect("proof generation should succeed"); assert!(!proof.data.is_empty(), "proof data should not be empty"); @@ -477,7 +478,7 @@ macro_rules! e2e_proof_tests { let party_id = 1; let verification_result = - circuit.verify_with_variant(&prover, &proof, e3_id, party_id, $variant); + circuit.verify_with_variant(&prover, &proof, e3_id, party_id, $variant, &artifacts_dir); assert!( verification_result.as_ref().is_ok_and(|&v| v), "Proof verification failed: {:?}", @@ -512,8 +513,9 @@ async fn test_pk_generation_commitment_consistency() { return; }; + let artifacts_dir = preset.artifacts_dir(); let proof = circuit - .prove(&prover, &preset, &sample, e3_id) + .prove(&prover, &preset, &sample, e3_id, &artifacts_dir) .expect("proof generation should succeed"); let computation_output = PkGenerationCircuit::compute(preset, &sample).unwrap(); @@ -559,8 +561,9 @@ async fn test_pk_bfv_commitment_consistency() { return; }; + let artifacts_dir = preset.artifacts_dir(); let proof = circuit - .prove(&prover, &preset, &sample, e3_id) + .prove(&prover, &preset, &sample, e3_id, &artifacts_dir) .expect("proof generation should succeed"); // Verify the commitment from the proof is a valid field element @@ -597,8 +600,9 @@ async fn test_share_computation_sk_commitment_consistency() { return; }; + let artifacts_dir = preset.artifacts_dir(); let proof = circuit - .prove(&prover, &preset, &sample, e3_id) + .prove(&prover, &preset, &sample, e3_id, &artifacts_dir) .expect("inner sk_share_computation proof should succeed"); assert_eq!( @@ -629,8 +633,9 @@ async fn test_share_computation_e_sm_commitment_consistency() { return; }; + let artifacts_dir = preset.artifacts_dir(); let proof = circuit - .prove(&prover, &preset, &sample, e3_id) + .prove(&prover, &preset, &sample, e3_id, &artifacts_dir) .expect("inner e_sm_share_computation proof should succeed"); assert_eq!( @@ -663,8 +668,16 @@ async fn test_pk_aggregation_commitment_consistency() { // C5 uses Evm variant in production; Recursive fails because commitment hashes (256-bit) // exceed the noir-recursive verifier's limb bound. + let artifacts_dir = preset.artifacts_dir(); let proof = circuit - .prove_with_variant(&prover, &preset, &sample, e3_id, CircuitVariant::Evm) + .prove_with_variant( + &prover, + &preset, + &sample, + e3_id, + CircuitVariant::Evm, + &artifacts_dir, + ) .expect("proof generation should succeed"); let computation_output = PkAggregationCircuit::compute(preset, &sample).unwrap(); @@ -706,8 +719,16 @@ async fn test_threshold_share_decryption_commitment_consistency() { return; }; + let artifacts_dir = preset.artifacts_dir(); let proof = circuit - .prove_with_variant(&prover, &preset, &sample, e3_id, CircuitVariant::Recursive) + .prove_with_variant( + &prover, + &preset, + &sample, + e3_id, + CircuitVariant::Recursive, + &artifacts_dir, + ) .expect("proof generation should succeed"); let computation_output = ThresholdShareDecryptionCircuit::compute(preset, &sample).unwrap(); @@ -741,6 +762,7 @@ async fn test_c4_sk_commitment_is_c6_expected_sk_input_e2e() { let e3_id_c4 = "c4-e2e"; let e3_id_c6 = "c6-e2e"; + let artifacts_dir = preset.artifacts_dir(); let c4_proof = DkgShareDecryptionCircuit .prove_with_variant( @@ -749,6 +771,7 @@ async fn test_c4_sk_commitment_is_c6_expected_sk_input_e2e() { &dkg_sample, e3_id_c4, CircuitVariant::Recursive, + &artifacts_dir, ) .expect("C4 proof generation should succeed"); @@ -759,6 +782,7 @@ async fn test_c4_sk_commitment_is_c6_expected_sk_input_e2e() { &c6_sample, e3_id_c6, CircuitVariant::Recursive, + &artifacts_dir, ) .expect("C6 proof generation should succeed"); @@ -841,6 +865,7 @@ async fn test_c4_c6_sk_commitment_aligned_transcript_e2e() { let e3_id_c4 = "c4-align"; let e3_id_c6 = "c6-align"; + let artifacts_dir = preset.artifacts_dir(); let c4_proof = DkgShareDecryptionCircuit .prove_with_variant( @@ -849,6 +874,7 @@ async fn test_c4_c6_sk_commitment_aligned_transcript_e2e() { &dkg_sample, e3_id_c4, CircuitVariant::Recursive, + &artifacts_dir, ) .expect("C4 proof generation should succeed"); @@ -859,6 +885,7 @@ async fn test_c4_c6_sk_commitment_aligned_transcript_e2e() { &c6_sample, e3_id_c6, CircuitVariant::Recursive, + &artifacts_dir, ) .expect("C6 proof generation should succeed"); @@ -909,8 +936,16 @@ async fn test_decrypted_shares_aggregation_commitment_consistency() { return; }; + let artifacts_dir = preset.artifacts_dir(); let proof = circuit - .prove_with_variant(&prover, &preset, &sample, e3_id, CircuitVariant::Recursive) + .prove_with_variant( + &prover, + &preset, + &sample, + e3_id, + CircuitVariant::Recursive, + &artifacts_dir, + ) .expect("proof generation should succeed"); let computation_output = DecryptedSharesAggregationCircuit::compute(preset, &sample).unwrap(); diff --git a/packages/enclave-contracts/artifacts/contracts/Enclave.sol/Enclave.json b/packages/enclave-contracts/artifacts/contracts/Enclave.sol/Enclave.json index 2a34d6c780..da5ef9efa5 100644 --- a/packages/enclave-contracts/artifacts/contracts/Enclave.sol/Enclave.json +++ b/packages/enclave-contracts/artifacts/contracts/Enclave.sol/Enclave.json @@ -2539,11 +2539,11 @@ "type": "function" } ], - "bytecode": "0x6080604052348015600e575f5ffd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b615a05806100d65f395ff3fe608060405234801561000f575f5ffd5b50600436106102ce575f3560e01c80639117173c11610182578063cb649617116100e0578063f0691cba1161008f578063f0691cba14610886578063f2fde38b14610899578063f3ceba3a146108ac578063f81b8ef6146108cd578063fad8e111146108e0578063fbdb3237146108f3578063fd2f3d011461091b575f5ffd5b8063cb649617146107ef578063cbd16872146107f8578063cf0f34c41461080b578063cfbdc98d1461081e578063d8afed3e1461084d578063e59e469514610860578063ea71aa5714610873575f5ffd5b8063a87f4ab91161013c578063a87f4ab914610607578063ac3d2f4214610759578063b27392d514610781578063bb2d1b8214610794578063bff232c1146107a7578063c1ab0f1f146107ba578063c4ccafa2146107cd575f5ffd5b80639117173c146105625780639231238614610575578063929a8faf1461058857806399c6679d146105a95780639c8570c8146105d15780639e57b934146105f4575f5ffd5b80635d1684181161022f57806381476ec2116101e957806381476ec2146104e7578063830d7181146104fa578063858142431461050d5780638da5cb5b146105205780638dcdd86b146105285780638e5ce3ad1461053a57806390173a411461054d575f5ffd5b80635d1684181461047d578063647846a51461049d5780636db5c8fd146104b0578063715018a6146104b95780637c8c3b4d146104c15780637cfa9d74146104d4575f5ffd5b806336c5d38a1161028b57806336c5d38a1461039b5780634017daf0146103ca578063406ed35c146103f75780634147a360146104175780634d600e5d146104445780634e92ec63146104575780634fc772641461046a575f5ffd5b806302a3a9c9146102d25780630ef81b2f146102e757806310bc62811461032557806311bd61d91461034d57806315cce224146103755780631ba7294514610388575b5f5ffd5b6102e56102e03660046145d4565b61092e565b005b61030f6102f53660046145f6565b5f908152600960205260409020546001600160a01b031690565b60405161031c919061461a565b60405180910390f35b61030f6103333660046145f6565b60096020525f90815260409020546001600160a01b031681565b61036061035b366004614641565b6109da565b60405163ffffffff909116815260200161031c565b6102e56103833660046145d4565b610a16565b6102e5610396366004614679565b610abb565b6103bd6103a93660046145f6565b5f908152600f602052604090205460ff1690565b60405161031c91906146bb565b6103dd6103d83660046145f6565b610acf565b60405161031c9e9d9c9b9a99989796959493929190614707565b61040a6104053660046145f6565b610c7a565b60405161031c91906148e1565b6104366104253660046145f6565b600c6020525f908152604090205481565b60405190815260200161031c565b6102e56104523660046148fe565b610ef7565b6102e56104653660046145f6565b611134565b6102e56104783660046145d4565b6111c3565b61049061048b366004614994565b611256565b60405161031c91906149ad565b60045461030f906001600160a01b031681565b61043660055481565b6102e56112ed565b6102e56104cf3660046149bf565b611300565b6102e56104e23660046145f6565b611389565b6102e56104f53660046149ed565b611488565b6102e5610508366004614a4a565b61157c565b60015461030f906001600160a01b031681565b61030f611688565b5f5461030f906001600160a01b031681565b60035461030f906001600160a01b031681565b6105556116b6565b60405161031c9190614a98565b6102e56105703660046145f6565b6116fc565b6105556105833660046145f6565b61186a565b61059b6105963660046145f6565b6118c3565b60405161031c929190614ab9565b61030f6105b73660046145f6565b5f908152601060205260409020546001600160a01b031690565b6105e46105df366004614acf565b6118ea565b604051901515815260200161031c565b610436610602366004614b46565b611b82565b61074c604080516101e0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081019190915250604080516101e0810182526018548152601954602080830191909152601a5492820192909252601b546060820152601c546080820152601d5460a0820152601e5460c0820152601f546001600160a01b03811660e083015261ffff600160a01b82048116610100840152600160b01b82048116610120840152600160c01b82048116610140840152600160d01b82048116610160840152600160e01b90910416610180820152905463ffffffff8082166101a0840152640100000000909104166101c082015290565b60405161031c9190614b7d565b61030f6107673660046145f6565b5f908152600a60205260409020546001600160a01b031690565b6105e461078f366004614c8a565b612157565b6102e56107a2366004614d2f565b612387565b6102e56107b53660046145d4565b612443565b6102e56107c83660046149ed565b6124ea565b6105e46107db3660046145d4565b60076020525f908152604090205460ff1681565b61043660065481565b6102e56108063660046149bf565b6125a7565b6102e56108193660046145f6565b612661565b61084061082c3660046145f6565b5f908152600d602052604090205460ff1690565b60405161031c9190614d69565b6102e561085b366004614d77565b61269e565b6102e561086e3660046145d4565b61292b565b6102e5610881366004614d91565b6129c5565b60025461030f906001600160a01b031681565b6102e56108a73660046145d4565b612c72565b6108bf6108ba366004614b46565b612cac565b60405161031c929190614dc8565b6103bd6108db3660046145f6565b61358d565b6102e56108ee3660046145d4565b613727565b61030f6109013660046145f6565b600a6020525f90815260409020546001600160a01b031681565b6102e56109293660046145d4565b6137bf565b61093661384e565b6001600160a01b0381166109915760405162461bcd60e51b815260206004820152601f60248201527f496e76616c6964204533526566756e644d616e6167657220616464726573730060448201526064015b60405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040517f9557d04c1c0b16f93f13b69aed23b3b6ab935bff3c53ac81d17896d3583542ed905f90a250565b6012602052815f5260405f2081600281106109f3575f80fd5b60089182820401919006600402915091509054906101000a900463ffffffff1681565b610a1e61384e565b6001600160a01b03811615801590610a4457506004546001600160a01b03828116911614155b8190610a645760405163eddf07f560e01b8152600401610988919061461a565b50600480546001600160a01b0319166001600160a01b0383161790556040517f722ff84c1234b2482061def5c82c6b5080c117b3cbb69d686844a051e4b8e7f390610ab090839061461a565b60405180910390a150565b610ac361384e565b610acc81613880565b50565b60086020525f9081526040902080546001820154600283015460058401546006850154600786018054959660ff95861696949593946001600160a01b03841694600160a01b90940490931692909190610b2790614de8565b80601f0160208091040260200160405190810160405280929190818152602001828054610b5390614de8565b8015610b9e5780601f10610b7557610100808354040283529160200191610b9e565b820191905f5260205f20905b815481529060010190602001808311610b8157829003601f168201915b50505060088401546009850154600a860154600b870154600c8801805497986001600160a01b03958616989490951696509194509291610bdd90614de8565b80601f0160208091040260200160405190810160405280929190818152602001828054610c0990614de8565b8015610c545780601f10610c2b57610100808354040283529160200191610c54565b820191905f5260205f20905b815481529060010190602001808311610c3757829003601f168201915b505050600d90930154919250506001600160a01b0381169060ff600160a01b909104168e565b610c82614442565b5f8281526008602090815260409182902082516101e08101909352805483526001810154909183019060ff166003811115610cbf57610cbf614693565b6003811115610cd057610cd0614693565b8152600282810154602083015260408051808201808352919093019291600385019182845b815481526020019060010190808311610cf55750505091835250506005820154602082015260068201546001600160a01b0381166040830152600160a01b900460ff166060820152600782018054608090920191610d5290614de8565b80601f0160208091040260200160405190810160405280929190818152602001828054610d7e90614de8565b8015610dc95780601f10610da057610100808354040283529160200191610dc9565b820191905f5260205f20905b815481529060010190602001808311610dac57829003601f168201915b505050918352505060088201546001600160a01b0390811660208301526009830154166040820152600a8201546060820152600b8201546080820152600c8201805460a090920191610e1a90614de8565b80601f0160208091040260200160405190810160405280929190818152602001828054610e4690614de8565b8015610e915780601f10610e6857610100808354040283529160200191610e91565b820191905f5260205f20905b815481529060010190602001808311610e7457829003601f168201915b5050509183525050600d91909101546001600160a01b038082166020840152600160a01b90910460ff16151560409092019190915260a0820151919250839116610ef15760405163cd6f4a4f60e01b815260040161098891815260200190565b50919050565b5f610f0061393d565b805490915060ff600160401b82041615906001600160401b03165f81158015610f265750825b90505f826001600160401b03166001148015610f415750303b155b905081158015610f4f575080155b15610f6d5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610f9757845460ff60401b1916600160401b1785555b610fa033613967565b610fa987612661565b610fb28b613727565b610fbb8a61292b565b610fc48961092e565b610fcd88610a16565b610fd686613880565b604080516101e08101825261c3508082526161a86020808401829052611388948401859052601460608501819052620249f0608086018190526207a12060a087018190526107d060c088018190525f60e089018190526103e86101008a015261012089018190526109c46101408a018190526101608a018b90526101808a01526101a089018190526101c090980197909752601895909555601993909355601a95909555601b94909455601c55601d55601e55601f80546001600160f01b031916690138827101388000007d60a31b179055805467ffffffffffffffff191690556110bf611688565b6001600160a01b03168c6001600160a01b0316146110e0576110e08c612c72565b831561112657845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050505050565b61113c61384e565b5f8181526009602052604090205481906001600160a01b0316611175576040516381c4951960e01b815260040161098891815260200190565b505f818152600960205260409081902080546001600160a01b0319169055517f104eb329a192aef26eddea07c2af5ad2587792e62b37ed4045b6ba59bc5540fc90610ab09083815260200190565b6111cb61384e565b6001600160a01b0381165f90815260076020526040902054819060ff16611206576040516321ac7c5f60e01b8152600401610988919061461a565b506001600160a01b0381165f9081526007602052604090819020805460ff19169055517f56070b80bd617fcd2f7a284861edb488830a38f9dedcd77b2cb2f4eac17743e790610ab090839061461a565b600b6020525f90815260409020805461126e90614de8565b80601f016020809104026020016040519081016040528092919081815260200182805461129a90614de8565b80156112e55780601f106112bc576101008083540402835291602001916112e5565b820191905f5260205f20905b8154815290600101906020018083116112c857829003601f168201915b505050505081565b6112f561384e565b6112fe5f613978565b565b61130861384e565b6001600160a01b0381161580159061133957505f828152600a60205260409020546001600160a01b03828116911614155b829061135b576040516381c4951960e01b815260040161098891815260200190565b505f918252600a602052604090912080546001600160a01b0319166001600160a01b03909216919091179055565b5f546001600160a01b031633146113b35760405163b56831db60e01b815260040160405180910390fd5b5f818152600d602052604090205460ff1660018160068111156113d8576113d8614693565b146113fd57816001826040516337e1404160e01b815260040161098893929190614e1a565b5f828152600d60205260409020805460ff191660021790556015546114229042614e4f565b5f838152600e602052604080822092909255905183917fc44405af9078047712501f519e1fb900c2896c62b488336f84529c72ae16e6f191a2815f5160206159d95f395f51905f526001600260405161147c929190614e62565b60405180910390a25050565b5f546001600160a01b031633146114b25760405163b56831db60e01b815260040160405180910390fd5b5f828152600860209081526040808320600d9092529091205460ff1660028160068111156114e2576114e2614693565b1461150757836002826040516337e1404160e01b815260040161098893929190614e1a565b5f848152600d6020526040808220805460ff19166003179055600a84018590555185917f11df18edb9bc9cd90a79068e0e208b630202148643d797d6150e7bacb733e63c91a2835f5160206159d95f395f51905f526002600360405161156e929190614e62565b60405180910390a250505050565b61158461384e565b806115c05760405162461bcd60e51b815260206004820152600c60248201526b456d70747920706172616d7360a01b6044820152606401610988565b60ff83165f908152600b6020526040902080546115dc90614de8565b15905061162b5760405162461bcd60e51b815260206004820152601b60248201527f506172616d53657420616c7265616479207265676973746572656400000000006044820152606401610988565b60ff83165f908152600b60205260409020611647828483614ef0565b507f6e4a4ea7f38fc775e616080b155744337e6216848e886a69c918b4ab84da219583838360405161167b93929190614fcc565b60405180910390a1505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6116d760405180606001604052805f81526020015f81526020015f81525090565b5060408051606081018252601554815260165460208201526017549181019190915290565b5f818152600d602052604090205460ff16600681600681111561172157611721614693565b14829061174457604051637cb2d48360e11b815260040161098891815260200190565b505f828152600c60205260409020548281611775576040516345ba89d560e11b815260040161098891815260200190565b505f838152600c6020526040812081905561178f846139e8565b5f858152601160205260409020546002549192506001600160a01b03908116916117bc9183911685613ad5565b60025460405163da19b69760e01b81526001600160a01b039091169063da19b697906117f2908890879087908790600401615034565b5f604051808303815f87803b158015611809575f5ffd5b505af115801561181b573d5f5f3e3d5ffd5b50505050847f5297818f48a66292b8b3e2caab83eec531b669bb20807fd38cf006adb2a0731784845160405161185b929190918252602082015260400190565b60405180910390a25050505050565b61188b60405180606001604052805f81526020015f81526020015f81525090565b505f908152600e6020908152604091829020825160608101845281548152600182015492810192909252600201549181019190915290565b5f818152600d6020526040812054819060ff166118e08482613b32565b9250925050915091565b5f5f6118f587610c7a565b5f888152600d602052604090205490915060ff16600381600681111561191d5761191d614693565b1488600383909192611945576040516337e1404160e01b815260040161098893929190614e1a565b5050505f888152600e60209081526040918290208251606081018452815481526001820154928101839052600290910154928101929092528990428110156119a9576040516308f3034360e31b815260048101929092526024820152604401610988565b50506060830151602001518990428111156119e05760405163017e35e560e71b815260048101929092526024820152604401610988565b5050610160830151899015611a0b57604051637eb9cea960e11b815260040161098891815260200190565b505f8888604051611a1d92919061507f565b60408051918290039091205f8c815260086020908152838220600b01839055600d905291909120805460ff19166004179055601754909150611a5f9042614e4f565b5f8b8152600e6020526040908190206002019190915560a08501519051632f0e1bbf60e01b81526001600160a01b0390911690632f0e1bbf90611aac908d9085908c908c9060040161508e565b6020604051808303815f875af1158015611ac8573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611aec91906150ba565b9450888886611b1057604051632f9f8ab960e01b81526004016109889291906150d5565b5050897f7cc27e4a5626cbc4f8ba1a927b0448de55e6a114bc87660331270c5109ade0718a8a604051611b449291906150d5565b60405180910390a2895f5160206159d95f395f51905f5260036004604051611b6d929190614e62565b60405180910390a25050505095945050505050565b5f80600b81611b9760a0860160808701614994565b60ff1660ff1681526020019081526020015f208054611bb590614de8565b905011611bd45760405162461bcd60e51b8152600401610988906150e8565b5f601281611be5602086018661511f565b6003811115611bf657611bf6614693565b6003811115611c0757611c07614693565b8152602081019190915260409081015f20815180830190925260028282826020028201915f905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411611c2e579050505050505090505f81600160028110611c8557611c8561506b565b602002015163ffffffff1611835f016020810190611ca3919061511f565b90611cc25760405163286c068d60e11b81526004016109889190615138565b506020808201518251604080516101e081018252601854815260195481860152601a5491810191909152601b546060820152601c546080820152601d5460a0820152601e5460c0820152601f546001600160a01b03811660e0830152600160a01b810461ffff908116610100840152600160b01b82048116610120840152600160c01b82048116610140840152600160d01b82048116610160840152600160e01b90910416610180820152925463ffffffff8181166101a0860181905264010000000090920481166101c086015292831693919092169115611ded576101a081015163ffffffff16846001602002015163ffffffff161015865f016020810190611dcc919061511f565b90611deb5760405163010b971d60e31b81526004016109889190615138565b505b6101c081015163ffffffff1615611e3c576101c081015184519063ffffffff9081169082161015611e3a57604051630a4b6b6360e11b815263ffffffff9091166004820152602401610988565b505b60408601356020870135811015611e695760405163174b5a0760e21b815260040161098891815260200190565b506101808101516017545f9161271091611e879161ffff1690615146565b611e91919061515d565b61271061ffff1683610160015161ffff16601560010154611eb29190615146565b611ebc919061515d565b61271061ffff1684610140015161ffff1660155f0154611edc9190615146565b611ee6919061515d565b5f5460408051634f87c3a560e11b8152815160208e81013594938f0135936001600160a01b031692639f0f874a92600480830193928290030181865afa158015611f32573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f56919061517c565b611f609190614e4f565b611f6a9190615193565b611f749190614e4f565b611f7e9190614e4f565b611f889190614e4f565b90505f611f96600186615193565b611fa1906002615146565b611fac906002615146565b611fb7906006614e4f565b90505f85845f0151611fc99190615146565b905081868560200151611fdc9190615146565b611fe69190615146565b611ff09082614e4f565b90506001861115612038576002612008600188615193565b6120129088615146565b85604001516120219190615146565b61202b919061515d565b6120359082614e4f565b90505b81868560c001516120499190615146565b6120539190615146565b61205d9082614e4f565b9050828685606001516120709190615146565b61207a9190615146565b6120849082614e4f565b90508484608001516120969190615146565b6120a09082614e4f565b905060018511156120e85760026120b8600187615193565b6120c29087615146565b85604001516120d19190615146565b6120db919061515d565b6120e59082614e4f565b90505b60a08401516120f79082614e4f565b610100850151909150612710906121129061ffff1682614e4f565b61211c9083615146565b612126919061515d565b9750878061214a57604051638c4fcd9360e01b815260040161098891815260200190565b5050505050505050919050565b5f5f61216289610c7a565b5f8a8152600d602052604090205490915060ff16600481600681111561218a5761218a614693565b148a6004839091926121b2576040516337e1404160e01b815260040161098893929190614e1a565b5050505f8a8152600e602090815260409182902082516060810184528154815260018201549281019290925260020154918101829052908b9042811015612215576040516308f3034360e31b815260048101929092526024820152604401610988565b50505f8b8152600860205260409020600c016122328a8c83614ef0565b505f8b8152600d6020526040902080546005919060ff191660018302179055508261010001516001600160a01b0316635bf48e3a8b8b60405161227692919061507f565b6040519081900381206001600160e01b031960e084901b1682526122a4918c908c908c908c906004016151a6565b602060405180830381865afa1580156122bf573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122e391906150ba565b935089898561230757604051632f9f8ab960e01b81526004016109889291906150d5565b50506123128b613cba565b8a7f3a140076c461ebc41d74833ae0ee8bbc8079a135a63392098cd381e84350b69b8b8b8b8b60405161234894939291906151de565b60405180910390a28a5f5160206159d95f395f51905f5260046005604051612371929190614e62565b60405180910390a2505050979650505050505050565b5f546001600160a01b03163314806123a957506003546001600160a01b031633145b6123c657604051639e75a8b560e01b815260040160405180910390fd5b5f8160ff161180156123dc5750600d60ff821611155b6124215760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b2103330b4b63ab932903932b0b9b7b760511b6044820152606401610988565b61243f828260ff16600d81111561243a5761243a614693565b614126565b5050565b61244b61384e565b6001600160a01b0381166124a15760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420536c617368696e674d616e616765722061646472657373006044820152606401610988565b600380546001600160a01b0319166001600160a01b0383169081179091556040517f4ccc8ed483c7c44c3602c3c38afc2c014a8f1d2dc210dfe58ebeeeead230f8e0905f90a250565b6003546001600160a01b03163314612515576040516357d6948d60e11b815260040160405180910390fd5b60025460405163c1ab0f1f60e01b815260048101849052602481018390526001600160a01b039091169063c1ab0f1f906044015f604051808303815f87803b15801561255f575f5ffd5b505af1158015612571573d5f5f3e3d5ffd5b50505050817f4f41a3b0a032ebcae925f2ace77d507435840ca4b2dbaffdd7723fa8d72ee5428260405161147c91815260200190565b6125af61384e565b6001600160a01b038116158015906125e057505f828152600960205260409020546001600160a01b03828116911614155b8290612602576040516381c4951960e01b815260040161098891815260200190565b505f8281526009602090815260409182902080546001600160a01b0319166001600160a01b03851617905590518381527ff4041a3f914dac3bc9bf5f003ba41f28dbb84abe42f4e07c76266f5c8ceecb69910160405180910390a15050565b61266961384e565b60058190556040518181527fba0716ba1ee2ea8ecc4c64119b4537cdb42a99d82acf92af5b87607b8b52355290602001610ab0565b6126a661384e565b6127106126bb61012083016101008401615229565b61ffff1611156126d361012083016101008401615229565b906126f8576040516301027fc160e21b815261ffff9091166004820152602401610988565b5061271061270e61014083016101208401615229565b61ffff16111561272661014083016101208401615229565b9061274b576040516301027fc160e21b815261ffff9091166004820152602401610988565b5061271061276161016083016101408401615229565b61ffff16111561277961016083016101408401615229565b9061279e57604051633239953960e01b815261ffff9091166004820152602401610988565b506127106127b461018083016101608401615229565b61ffff1611156127cc61018083016101608401615229565b906127f157604051633239953960e01b815261ffff9091166004820152602401610988565b506127106128076101a083016101808401615229565b61ffff16111561281f6101a083016101808401615229565b9061284457604051633239953960e01b815261ffff9091166004820152602401610988565b5061285761014082016101208301615229565b61ffff16158061288057505f612874610100830160e084016145d4565b6001600160a01b031614155b61289d5760405163015f92ff60e51b815260040160405180910390fd5b6128af6101e082016101c08301615260565b63ffffffff166128c76101c083016101a08401615260565b63ffffffff1610156128ec576040516392f55c6560e01b815260040160405180910390fd5b8060186128f9828261529f565b9050507fbf3951313e980027eb48ce363fdb707286195ec6a0f802ac153927cf929c3fc681604051610ab0919061545d565b61293361384e565b6001600160a01b0381161580159061295957506001546001600160a01b03828116911614155b8190612979576040516320252f0b60e01b8152600401610988919061461a565b50600180546001600160a01b0319166001600160a01b0383161790556040517fad4055f18cdad6f4bdd71afe3a72cbeee964217943e1bde38f138289e981a9a790610ab090839061461a565b6129cd61384e565b6129da6020820182615260565b63ffffffff166129f06040830160208401615260565b63ffffffff1610158015612a1557505f612a0d6020830183615260565b63ffffffff16115b612a3257604051634564ab9b60e01b815260040160405180910390fd5b604080516101e0810182526018548152601954602080830191909152601a5492820192909252601b546060820152601c546080820152601d5460a0820152601e5460c0820152601f546001600160a01b03811660e083015261ffff600160a01b82048116610100840152600160b01b82048116610120840152600160c01b82048116610140840152600160d01b82048116610160840152600160e01b90910416610180820152905463ffffffff8082166101a08401819052640100000000909204166101c083015215612b6b576101a081015163ffffffff16612b1b6040840160208501615260565b63ffffffff161015612b336040840160208501615260565b826101a001519091612b6857604051633ccc4c2160e21b815263ffffffff928316600482015291166024820152604401610988565b50505b6101c081015163ffffffff1615612be2576101c081015163ffffffff16612b956020840184615260565b63ffffffff161015612baa6020840184615260565b826101c001519091612bdf5760405163156c4e5b60e11b815263ffffffff928316600482015291166024820152604401610988565b50505b8160125f856003811115612bf857612bf8614693565b6003811115612c0957612c09614693565b815260208101919091526040015f20612c239160026144bf565b50826003811115612c3657612c36614693565b7f8b56fae526eee054f0849759a99fc7d4ff3823824ebf097a56f7d78adb6b34fa83604051612c659190615567565b60405180910390a2505050565b612c7a61384e565b6001600160a01b038116612ca3575f604051631e4fbdf760e01b8152600401610988919061461a565b610acc81613978565b5f612cb5614442565b5f601281612cc6602087018761511f565b6003811115612cd757612cd7614693565b6003811115612ce857612ce8614693565b8152602081019190915260409081015f20815180830190925260028282826020028201915f905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411612d0f579050505050505090505f81600160028110612d6657612d6661506b565b602002015163ffffffff1611845f016020810190612d84919061511f565b90612da35760405163286c068d60e11b81526004016109889190615138565b50602084013542811015612dcd57604051630b99e87960e01b815260040161098891815260200190565b5060408401356020850135811015612dfb5760405163174b5a0760e21b815260040161098891815260200190565b506017546016545f9190612e13426040890135615193565b612e1d9190614e4f565b612e279190614e4f565b905060055481108190612e50576040516313b783af60e21b815260040161098891815260200190565b5060075f612e6460808801606089016145d4565b6001600160a01b0316815260208101919091526040015f205460ff16612e9060808701606088016145d4565b90612eaf5760405163295a6a6f60e11b8152600401610988919061461a565b505f612eba86611b82565b60068054965090915085905f612ecf836155a7565b9091555050604080514460208201529081018690525f9060600160408051601f1981840301815291815281516020928301205f898152600c84528281208690556004546011855283822080546001600160a01b03199081166001600160a01b0393841617909155601f805460138852868520805461ffff191661ffff600160b01b909304929092169190911790555460148752858420805483169190931617909155600d8552838220805460ff191660011790556010909452829020805433941693909317909255601654919250612faa9190890135614e4f565b5f878152600e6020908152604090912060010191909155818652612fd09088018861511f565b85602001906003811115612fe657612fe6614693565b90816003811115612ff957612ff9614693565b905250436040808701919091528051808201825290602089019060029083908390808284375f92019190915250505060608087019190915261304190608089019089016145d4565b6001600160a01b031660a08087019190915261306290880160808901614994565b60ff1660c08087019190915261307a908801886155bf565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050505060e0808701919091526130c7906101008901908901615601565b15156101c08601525f610140860181905261016086018190526040805160208101909152908152610180860152336101a08601819052600454613117916001600160a01b03909116903085614281565b5f600b8161312b60a08b0160808c01614994565b60ff1660ff1681526020019081526020015f20805461314990614de8565b80601f016020809104026020016040519081016040528092919081815260200182805461317590614de8565b80156131c05780601f10613197576101008083540402835291602001916131c0565b820191905f5260205f20905b8154815290600101906020018083116131a357829003601f168201915b505050505090505f8151116131e75760405162461bcd60e51b8152600401610988906150e8565b5f6131f860808a0160608b016145d4565b6001600160a01b031663fefd9a8b89858561321660a08f018f6155bf565b8f8060c0019061322691906155bf565b6040518863ffffffff1660e01b8152600401613248979695949392919061561c565b6020604051808303815f875af1158015613264573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613288919061517c565b5f818152600960205260409020549091506001600160a01b031681816132c4576040516381c4951960e01b815260040161098891815260200190565b505f828152600a60205260409020546001600160a01b031682816132fe576040516381c4951960e01b815260040161098891815260200190565b50608089018390526001600160a01b038083166101008b015281166101208a01525f8a81526008602090815260409091208a518155908a0151600180830180548d94939260ff19919091169083600381111561335c5761335c614693565b021790555060408201518160020155606082015181600301906002613382929190614560565b506080820151600582015560a082015160068201805460c085015160ff16600160a01b026001600160a81b03199091166001600160a01b039093169290921791909117905560e082015160078201906133db9082615670565b506101008201516008820180546001600160a01b039283166001600160a01b031991821617909155610120840151600984018054919093169116179055610140820151600a820155610160820151600b820155610180820151600c8201906134439082615670565b506101a0820151600d90910180546101c0909301511515600160a01b026001600160a81b03199093166001600160a01b0392831617929092179091555f5460405163291a691b60e01b815291169063291a691b906134a9908d9089908d90600401615725565b6020604051808303815f875af11580156134c5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906134e991906150ba565b61350657604051630d8dbe2560e01b815260040160405180910390fd5b61351660808c0160608d016145d4565b6001600160a01b03167f5090c9764b5cd13df7afc0013f733dfbe6eaf1b6ddc22a5e291fa387efd4c15e8b8b604051613550929190614dc8565b60405180910390a2895f5160206159d95f395f51905f525f6001604051613578929190614e62565b60405180910390a25050505050505050915091565b5f818152600d602052604081205460ff16818160068111156135b1576135b1614693565b036135d657826001826040516337e1404160e01b815260040161098893929190614e1a565b60058160068111156135ea576135ea614693565b0361360b5760405163462c7bed60e01b815260048101849052602401610988565b600681600681111561361f5761361f614693565b0361364057604051633de16e3560e11b815260048101849052602401610988565b5f61364b8483613b32565b935090508061367057604051639f65d93560e01b815260048101859052602401610988565b5f848152600d6020526040902080546006919060ff191660018302179055505f848152600f60205260409020805484919060ff1916600183600d8111156136b9576136b9614693565b0217905550835f5160206159d95f395f51905f528360066040516136de929190614e62565b60405180910390a2837fe20209be7caae6e76291267cfa711353981274bf127e94f16eb9ec44b68582bb838560405161371892919061576a565b60405180910390a25050919050565b61372f61384e565b6001600160a01b0381161580159061375457505f546001600160a01b03828116911614155b8190613774576040516375ac4eb760e11b8152600401610988919061461a565b505f80546001600160a01b0319166001600160a01b0383161790556040517f80052b810d39120cf6c976cca504a21703f585521dc7a41c6d241090e6c579b690610ab090839061461a565b6001600160a01b0381165f90815260076020526040902054819060ff16156137fb5760405163b29d459560e01b8152600401610988919061461a565b506001600160a01b0381165f9081526007602052604090819020805460ff19166001179055517fb8d368517268f297fff00825d67d098763117d061360d31027be5b2e1a59d46790610ab090839061461a565b33613857611688565b6001600160a01b0316146112fe573360405163118cdaa760e01b8152600401610988919061461a565b803561389f5760405163055f269d60e01b815260040160405180910390fd5b5f8160200135116138c35760405163055f269d60e01b815260040160405180910390fd5b5f8160400135116138e75760405163055f269d60e01b815260040160405180910390fd5b80356015819055602080830135601681905560408085013560178190558151948552928401919091528201527f7e86ba16b805e2835af5c5b7aa5a942ced8bcc1fb95a05fbe42dae3862350a1690606001610ab0565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005b92915050565b61396f6142c0565b610acc816142e5565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f818152600f602052604090205460609060ff16600181600d811115613a1057613a10614693565b1480613a2d5750600281600d811115613a2b57613a2b614693565b145b15613a65575f5b604051908082528060200260200182016040528015613a5d578160200160208202803683370190505b509392505050565b5f5460405162beb08960e51b8152600481018590526001600160a01b03909116906317d61120906024015f60405180830381865afa925050508015613acb57506040513d5f823e601f3d908101601f19168201604052613ac89190810190615841565b60015b613a5d575f613a34565b613b2d83846001600160a01b031663a9059cbb8585604051602401613afb929190615906565b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506142ed565b505050565b5f828152600e60209081526040808320815160608101835281548152600182015493810193909352600201548282015282549051632800d82960e01b81526004810186905283929183916001600160a01b0390911690632800d82990602401602060405180830381865afa158015613bac573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613bd0919061517c565b90506001856006811115613be657613be6614693565b148015613bf257508042115b15613c0557600180935093505050613cb3565b6002856006811115613c1957613c19614693565b148015613c265750815142115b15613c3a5760016003935093505050613cb3565b6003856006811115613c4e57613c4e614693565b148015613c5e5750816020015142115b15613c725760016006935093505050613cb3565b6004856006811115613c8657613c86614693565b148015613c965750816040015142115b15613caa576001600a935093505050613cb3565b5f5f9350935050505b9250929050565b5f805460405162beb08960e51b8152600481018490526001600160a01b03909116906317d61120906024015f60405180830381865afa158015613cff573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052613d269190810190615841565b5080515f848152600c60209081526040808320805490849055601190925282205493945091926001600160a01b031690829003613dc5576002546040516341489f1560e01b81526001600160a01b03909116906341489f1590613d919088908890869060040161591f565b5f604051808303815f87803b158015613da8575f5ffd5b505af1158015613dba573d5f5f3e3d5ffd5b505050505050505050565b825f03613e66575f858152601060205260409020546001600160a01b03168015613dfd57613dfd6001600160a01b0383168285613ad5565b6002546040516341489f1560e01b81526001600160a01b03909116906341489f1590613e319089908990879060040161591f565b5f604051808303815f87803b158015613e48575f5ffd5b505af1158015613e5a573d5f5f3e3d5ffd5b50505050505050505050565b5f85815260136020908152604080832054601490925282205461ffff909116906001600160a01b03168115801590613ea657506001600160a01b03811615155b15613ee257612710613ebc61ffff841687615146565b613ec6919061515d565b92508215613ee257613ee26001600160a01b0385168285613ad5565b5f613eed8487615193565b90505f876001600160401b03811115613f0857613f08614e7d565b604051908082528060200260200182016040528015613f31578160200160208202803683370190505b5090505f613f3f898461515d565b90505f805b8a811015613f7e5782848281518110613f5f57613f5f61506b565b6020908102919091010152613f748383614e4f565b9150600101613f44565b505f613f8a8286615193565b90508015613fc7578084613f9f60018e615193565b81518110613faf57613faf61506b565b60200260200101818151613fc39190614e4f565b9052505b600154613fe1906001600160a01b038b8116911687614350565b60015f9054906101000a90046001600160a01b03166001600160a01b031663dd8c818e8a8e876040518463ffffffff1660e01b81526004016140259392919061597f565b5f604051808303815f87803b15801561403c575f5ffd5b505af115801561404e573d5f5f3e3d5ffd5b505060015461406c92506001600160a01b038c81169250165f614350565b8c7fac9fe8ad7f55eac03284399116ecafc104f10459773f4cdf47063c46e5be335a8d8660405161409e9291906159b4565b60405180910390a260025f9054906101000a90046001600160a01b03166001600160a01b03166341489f158e8e8c6040518463ffffffff1660e01b81526004016140ea9392919061591f565b5f604051808303815f87803b158015614101575f5ffd5b505af1158015614113573d5f5f3e3d5ffd5b5050505050505050505050505050505050565b5f828152600d602052604081205460ff169081600681111561414a5761414a614693565b0361416f57826001826040516337e1404160e01b815260040161098893929190614e1a565b600581600681111561418357614183614693565b036141a45760405163462c7bed60e01b815260048101849052602401610988565b60068160068111156141b8576141b8614693565b036141d957604051633de16e3560e11b815260048101849052602401610988565b5f838152600d6020526040902080546006919060ff191660018302179055505f838152600f60205260409020805483919060ff1916600183600d81111561422257614222614693565b0217905550825f5160206159d95f395f51905f52826006604051614247929190614e62565b60405180910390a2827fe20209be7caae6e76291267cfa711353981274bf127e94f16eb9ec44b68582bb8284604051612c6592919061576a565b6040516001600160a01b0384811660248301528381166044830152606482018390526142ba9186918216906323b872dd90608401613afb565b50505050565b6142c86143e0565b6112fe57604051631afcd79f60e31b815260040160405180910390fd5b612c7a6142c0565b5f5f60205f8451602086015f885af18061430c576040513d5f823e3d81fd5b50505f513d91508115614323578060011415614330565b6001600160a01b0384163b155b156142ba5783604051635274afe760e01b8152600401610988919061461a565b5f836001600160a01b031663095ea7b38484604051602401614373929190615906565b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505090506143ac84826143f9565b6142ba576143d684856001600160a01b031663095ea7b3865f604051602401613afb929190615906565b6142ba84826142ed565b5f6143e961393d565b54600160401b900460ff16919050565b5f5f5f5f60205f8651602088015f8a5af192503d91505f5190508280156144385750811561442a5780600114614438565b5f866001600160a01b03163b115b9695505050505050565b604080516101e081019091525f808252602082019081526020015f815260200161446a61458e565b81525f602082018190526040820181905260608083018290526080830181905260a0830182905260c0830182905260e08301829052610100830182905261012083015261014082018190526101609091015290565b600183019183908215614550579160200282015f5b8382111561451e57833563ffffffff1683826101000a81548163ffffffff021916908363ffffffff16021790555092602001926004016020816003010492830192600103026144d4565b801561454e5782816101000a81549063ffffffff021916905560040160208160030104928301926001030261451e565b505b5061455c9291506145ac565b5090565b8260028101928215614550579160200282015b82811115614550578251825591602001919060010190614573565b60405180604001604052806002906020820280368337509192915050565b5b8082111561455c575f81556001016145ad565b6001600160a01b0381168114610acc575f5ffd5b5f602082840312156145e4575f5ffd5b81356145ef816145c0565b9392505050565b5f60208284031215614606575f5ffd5b5035919050565b6001600160a01b03169052565b6001600160a01b0391909116815260200190565b80356004811061463c575f5ffd5b919050565b5f5f60408385031215614652575f5ffd5b61465b8361462e565b946020939093013593505050565b5f60608284031215610ef1575f5ffd5b5f60608284031215614689575f5ffd5b6145ef8383614669565b634e487b7160e01b5f52602160045260245ffd5b600e81106146b7576146b7614693565b9052565b6020810161396182846146a7565b600481106146b7576146b7614693565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b8e8152614717602082018f6146c9565b8c60408201528b6060820152614730608082018c61460d565b60ff8a1660a08201526101c060c08201525f6147506101c083018b6146d9565b61475d60e084018b61460d565b61476b61010084018a61460d565b876101208401528661014084015282810361016084015261478c81876146d9565b91505061479d61018083018561460d565b8215156101a08301529f9e505050505050505050505050505050565b805f5b60028110156142ba5781518452602093840193909101906001016147bc565b805182525f60208201516147f260208501826146c9565b5060408201516040840152606082015161480f60608501826147b9565b50608082015160a084015260a082015161482c60c085018261460d565b5060c082015160ff811660e08501525060e08201516102006101008501526148586102008501826146d9565b905061010083015161486e61012086018261460d565b5061012083015161488361014086018261460d565b506101408301516101608501526101608301516101808501526101808301518482036101a08601526148b582826146d9565b9150506101a08301516148cc6101c086018261460d565b506101c08301518015156101e0860152613a5d565b602081525f6145ef60208301846147db565b803561463c816145c0565b5f5f5f5f5f5f5f610120888a031215614915575f5ffd5b8735614920816145c0565b96506020880135614930816145c0565b95506040880135614940816145c0565b94506060880135614950816145c0565b93506080880135614960816145c0565b925060a088013591506149768960c08a01614669565b905092959891949750929550565b803560ff8116811461463c575f5ffd5b5f602082840312156149a4575f5ffd5b6145ef82614984565b602081525f6145ef60208301846146d9565b5f5f604083850312156149d0575f5ffd5b8235915060208301356149e2816145c0565b809150509250929050565b5f5f604083850312156149fe575f5ffd5b50508035926020909101359150565b5f5f83601f840112614a1d575f5ffd5b5081356001600160401b03811115614a33575f5ffd5b602083019150836020828501011115613cb3575f5ffd5b5f5f5f60408486031215614a5c575f5ffd5b614a6584614984565b925060208401356001600160401b03811115614a7f575f5ffd5b614a8b86828701614a0d565b9497909650939450505050565b81518152602080830151908201526040808301519082015260608101613961565b8215158152604081016145ef60208301846146a7565b5f5f5f5f5f60608688031215614ae3575f5ffd5b8535945060208601356001600160401b03811115614aff575f5ffd5b614b0b88828901614a0d565b90955093505060408601356001600160401b03811115614b29575f5ffd5b614b3588828901614a0d565b969995985093965092949392505050565b5f60208284031215614b56575f5ffd5b81356001600160401b03811115614b6b575f5ffd5b820161010081850312156145ef575f5ffd5b5f6101e082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e0830151614bd760e084018261460d565b50610100830151614bef61010084018261ffff169052565b50610120830151614c0761012084018261ffff169052565b50610140830151614c1f61014084018261ffff169052565b50610160830151614c3761016084018261ffff169052565b50610180830151614c4f61018084018261ffff169052565b506101a0830151614c696101a084018263ffffffff169052565b506101c0830151614c836101c084018263ffffffff169052565b5092915050565b5f5f5f5f5f5f5f6080888a031215614ca0575f5ffd5b8735965060208801356001600160401b03811115614cbc575f5ffd5b614cc88a828b01614a0d565b90975095505060408801356001600160401b03811115614ce6575f5ffd5b614cf28a828b01614a0d565b90955093505060608801356001600160401b03811115614d10575f5ffd5b614d1c8a828b01614a0d565b989b979a50959850939692959293505050565b5f5f60408385031215614d40575f5ffd5b82359150614d5060208401614984565b90509250929050565b600781106146b7576146b7614693565b602081016139618284614d59565b5f6101e0828403128015614d89575f5ffd5b509092915050565b5f5f60608385031215614da2575f5ffd5b614dab8361462e565b915083606084011115614dbc575f5ffd5b50926020919091019150565b828152604060208201525f614de060408301846147db565b949350505050565b600181811c90821680614dfc57607f821691505b602082108103610ef157634e487b7160e01b5f52602260045260245ffd5b83815260608101614e2e6020830185614d59565b614de06040830184614d59565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561396157613961614e3b565b60408101614e708285614d59565b6145ef6020830184614d59565b634e487b7160e01b5f52604160045260245ffd5b601f821115613b2d57805f5260205f20601f840160051c81016020851015614eb65750805b601f840160051c820191505b81811015614ed5575f8155600101614ec2565b5050505050565b5f19600383901b1c191660019190911b1790565b6001600160401b03831115614f0757614f07614e7d565b614f1b83614f158354614de8565b83614e91565b5f601f841160018114614f47575f8515614f355750838201355b614f3f8682614edc565b845550614ed5565b5f83815260208120601f198716915b82811015614f765786850135825560209485019460019092019101614f56565b5086821015614f92575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60ff84168152604060208201525f614fe8604083018486614fa4565b95945050505050565b5f8151808452602084019350602083015f5b8281101561502a5781516001600160a01b0316865260209586019590910190600101615003565b5093949350505050565b848152836020820152608060408201525f6150526080830185614ff1565b905060018060a01b038316606083015295945050505050565b634e487b7160e01b5f52603260045260245ffd5b818382375f9101908152919050565b848152836020820152606060408201525f614438606083018486614fa4565b8015158114610acc575f5ffd5b5f602082840312156150ca575f5ffd5b81516145ef816150ad565b602081525f614de0602083018486614fa4565b6020808252601c908201527f42465620706172616d20736574206e6f74207265676973746572656400000000604082015260600190565b5f6020828403121561512f575f5ffd5b6145ef8261462e565b6020810161396182846146c9565b808202811582820484141761396157613961614e3b565b5f8261517757634e487b7160e01b5f52601260045260245ffd5b500490565b5f6020828403121561518c575f5ffd5b5051919050565b8181038181111561396157613961614e3b565b858152606060208201525f6151bf606083018688614fa4565b82810360408401526151d2818587614fa4565b98975050505050505050565b604081525f6151f1604083018688614fa4565b8281036020840152615204818587614fa4565b979650505050505050565b61ffff81168114610acc575f5ffd5b803561463c8161520f565b5f60208284031215615239575f5ffd5b81356145ef8161520f565b63ffffffff81168114610acc575f5ffd5b803561463c81615244565b5f60208284031215615270575f5ffd5b81356145ef81615244565b5f8135613961816145c0565b5f81356139618161520f565b5f813561396181615244565b813581556020820135600182015560408201356002820155606082013560038201556080820135600482015560a0820135600582015560c082013560068201556007810161530f6152f260e0850161527b565b82546001600160a01b0319166001600160a01b0391909116178255565b61533f61531f6101008501615287565b82805461ffff60a01b191660a09290921b61ffff60a01b16919091179055565b61536f61534f6101208501615287565b82805461ffff60b01b191660b09290921b61ffff60b01b16919091179055565b61539f61537f6101408501615287565b82805461ffff60c01b191660c09290921b61ffff60c01b16919091179055565b6153cf6153af6101608501615287565b82805461ffff60d01b191660d09290921b61ffff60d01b16919091179055565b6153ff6153df6101808501615287565b82805461ffff60e01b191660e09290921b61ffff60e01b16919091179055565b506008810161542b6154146101a08501615293565b825463ffffffff191663ffffffff91909116178255565b613b2d61543b6101c08501615293565b825467ffffffff00000000191660209190911b67ffffffff0000000016178255565b813581526020808301359082015260408083013590820152606080830135908201526080808301359082015260a0808301359082015260c080830135908201526101e081016154ae60e084016148f3565b6154bb60e084018261460d565b506154c9610100840161521e565b61ffff166101008301526154e0610120840161521e565b61ffff166101208301526154f7610140840161521e565b61ffff1661014083015261550e610160840161521e565b61ffff16610160830152615525610180840161521e565b61ffff1661018083015261553c6101a08401615255565b63ffffffff166101a08301526155556101c08401615255565b63ffffffff81166101c0840152614c83565b6040810181835f5b600281101561559e57813561558381615244565b63ffffffff168352602092830192919091019060010161556f565b50505092915050565b5f600182016155b8576155b8614e3b565b5060010190565b5f5f8335601e198436030181126155d4575f5ffd5b8301803591506001600160401b038211156155ed575f5ffd5b602001915036819003821315613cb3575f5ffd5b5f60208284031215615611575f5ffd5b81356145ef816150ad565b87815286602082015260a060408201525f61563a60a08301886146d9565b828103606084015261564d818789614fa4565b90508281036080840152615662818587614fa4565b9a9950505050505050505050565b81516001600160401b0381111561568957615689614e7d565b61569d816156978454614de8565b84614e91565b6020601f8211600181146156ca575f83156156b85750848201515b6156c28482614edc565b855550614ed5565b5f84815260208120601f198516915b828110156156f957878501518255602094850194600190920191016156d9565b508482101561571657868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b838152602081018390526080810160408201835f5b600281101561575f57815163ffffffff1683526020928301929091019060010161573a565b505050949350505050565b604081016157788285614d59565b6145ef60208301846146a7565b604051601f8201601f191681016001600160401b03811182821017156157ad576157ad614e7d565b604052919050565b5f6001600160401b038211156157cd576157cd614e7d565b5060051b60200190565b5f82601f8301126157e6575f5ffd5b81516157f96157f4826157b5565b615785565b8082825260208201915060208360051b86010192508583111561581a575f5ffd5b602085015b8381101561583757805183526020928301920161581f565b5095945050505050565b5f5f60408385031215615852575f5ffd5b82516001600160401b03811115615867575f5ffd5b8301601f81018513615877575f5ffd5b80516158856157f4826157b5565b8082825260208201915060208360051b8501019250878311156158a6575f5ffd5b6020840193505b828410156158d15783516158c0816145c0565b8252602093840193909101906158ad565b8095505050505060208301516001600160401b038111156158f0575f5ffd5b6158fc858286016157d7565b9150509250929050565b6001600160a01b03929092168252602082015260400190565b838152606060208201525f6159376060830185614ff1565b905060018060a01b0383166040830152949350505050565b5f8151808452602084019350602083015f5b8281101561502a578151865260209586019590910190600101615961565b6001600160a01b03841681526060602082018190525f906159a290830185614ff1565b8281036040840152614438818561594f565b604081525f6159c66040830185614ff1565b8281036020840152614fe8818561594f56fe1b418a230a21d37a078bf8f16decbde8ccceacd77159371f62f0d4ea00d19967a164736f6c634300081c000a", - "deployedBytecode": "0x608060405234801561000f575f5ffd5b50600436106102ce575f3560e01c80639117173c11610182578063cb649617116100e0578063f0691cba1161008f578063f0691cba14610886578063f2fde38b14610899578063f3ceba3a146108ac578063f81b8ef6146108cd578063fad8e111146108e0578063fbdb3237146108f3578063fd2f3d011461091b575f5ffd5b8063cb649617146107ef578063cbd16872146107f8578063cf0f34c41461080b578063cfbdc98d1461081e578063d8afed3e1461084d578063e59e469514610860578063ea71aa5714610873575f5ffd5b8063a87f4ab91161013c578063a87f4ab914610607578063ac3d2f4214610759578063b27392d514610781578063bb2d1b8214610794578063bff232c1146107a7578063c1ab0f1f146107ba578063c4ccafa2146107cd575f5ffd5b80639117173c146105625780639231238614610575578063929a8faf1461058857806399c6679d146105a95780639c8570c8146105d15780639e57b934146105f4575f5ffd5b80635d1684181161022f57806381476ec2116101e957806381476ec2146104e7578063830d7181146104fa578063858142431461050d5780638da5cb5b146105205780638dcdd86b146105285780638e5ce3ad1461053a57806390173a411461054d575f5ffd5b80635d1684181461047d578063647846a51461049d5780636db5c8fd146104b0578063715018a6146104b95780637c8c3b4d146104c15780637cfa9d74146104d4575f5ffd5b806336c5d38a1161028b57806336c5d38a1461039b5780634017daf0146103ca578063406ed35c146103f75780634147a360146104175780634d600e5d146104445780634e92ec63146104575780634fc772641461046a575f5ffd5b806302a3a9c9146102d25780630ef81b2f146102e757806310bc62811461032557806311bd61d91461034d57806315cce224146103755780631ba7294514610388575b5f5ffd5b6102e56102e03660046145d4565b61092e565b005b61030f6102f53660046145f6565b5f908152600960205260409020546001600160a01b031690565b60405161031c919061461a565b60405180910390f35b61030f6103333660046145f6565b60096020525f90815260409020546001600160a01b031681565b61036061035b366004614641565b6109da565b60405163ffffffff909116815260200161031c565b6102e56103833660046145d4565b610a16565b6102e5610396366004614679565b610abb565b6103bd6103a93660046145f6565b5f908152600f602052604090205460ff1690565b60405161031c91906146bb565b6103dd6103d83660046145f6565b610acf565b60405161031c9e9d9c9b9a99989796959493929190614707565b61040a6104053660046145f6565b610c7a565b60405161031c91906148e1565b6104366104253660046145f6565b600c6020525f908152604090205481565b60405190815260200161031c565b6102e56104523660046148fe565b610ef7565b6102e56104653660046145f6565b611134565b6102e56104783660046145d4565b6111c3565b61049061048b366004614994565b611256565b60405161031c91906149ad565b60045461030f906001600160a01b031681565b61043660055481565b6102e56112ed565b6102e56104cf3660046149bf565b611300565b6102e56104e23660046145f6565b611389565b6102e56104f53660046149ed565b611488565b6102e5610508366004614a4a565b61157c565b60015461030f906001600160a01b031681565b61030f611688565b5f5461030f906001600160a01b031681565b60035461030f906001600160a01b031681565b6105556116b6565b60405161031c9190614a98565b6102e56105703660046145f6565b6116fc565b6105556105833660046145f6565b61186a565b61059b6105963660046145f6565b6118c3565b60405161031c929190614ab9565b61030f6105b73660046145f6565b5f908152601060205260409020546001600160a01b031690565b6105e46105df366004614acf565b6118ea565b604051901515815260200161031c565b610436610602366004614b46565b611b82565b61074c604080516101e0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081019190915250604080516101e0810182526018548152601954602080830191909152601a5492820192909252601b546060820152601c546080820152601d5460a0820152601e5460c0820152601f546001600160a01b03811660e083015261ffff600160a01b82048116610100840152600160b01b82048116610120840152600160c01b82048116610140840152600160d01b82048116610160840152600160e01b90910416610180820152905463ffffffff8082166101a0840152640100000000909104166101c082015290565b60405161031c9190614b7d565b61030f6107673660046145f6565b5f908152600a60205260409020546001600160a01b031690565b6105e461078f366004614c8a565b612157565b6102e56107a2366004614d2f565b612387565b6102e56107b53660046145d4565b612443565b6102e56107c83660046149ed565b6124ea565b6105e46107db3660046145d4565b60076020525f908152604090205460ff1681565b61043660065481565b6102e56108063660046149bf565b6125a7565b6102e56108193660046145f6565b612661565b61084061082c3660046145f6565b5f908152600d602052604090205460ff1690565b60405161031c9190614d69565b6102e561085b366004614d77565b61269e565b6102e561086e3660046145d4565b61292b565b6102e5610881366004614d91565b6129c5565b60025461030f906001600160a01b031681565b6102e56108a73660046145d4565b612c72565b6108bf6108ba366004614b46565b612cac565b60405161031c929190614dc8565b6103bd6108db3660046145f6565b61358d565b6102e56108ee3660046145d4565b613727565b61030f6109013660046145f6565b600a6020525f90815260409020546001600160a01b031681565b6102e56109293660046145d4565b6137bf565b61093661384e565b6001600160a01b0381166109915760405162461bcd60e51b815260206004820152601f60248201527f496e76616c6964204533526566756e644d616e6167657220616464726573730060448201526064015b60405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040517f9557d04c1c0b16f93f13b69aed23b3b6ab935bff3c53ac81d17896d3583542ed905f90a250565b6012602052815f5260405f2081600281106109f3575f80fd5b60089182820401919006600402915091509054906101000a900463ffffffff1681565b610a1e61384e565b6001600160a01b03811615801590610a4457506004546001600160a01b03828116911614155b8190610a645760405163eddf07f560e01b8152600401610988919061461a565b50600480546001600160a01b0319166001600160a01b0383161790556040517f722ff84c1234b2482061def5c82c6b5080c117b3cbb69d686844a051e4b8e7f390610ab090839061461a565b60405180910390a150565b610ac361384e565b610acc81613880565b50565b60086020525f9081526040902080546001820154600283015460058401546006850154600786018054959660ff95861696949593946001600160a01b03841694600160a01b90940490931692909190610b2790614de8565b80601f0160208091040260200160405190810160405280929190818152602001828054610b5390614de8565b8015610b9e5780601f10610b7557610100808354040283529160200191610b9e565b820191905f5260205f20905b815481529060010190602001808311610b8157829003601f168201915b50505060088401546009850154600a860154600b870154600c8801805497986001600160a01b03958616989490951696509194509291610bdd90614de8565b80601f0160208091040260200160405190810160405280929190818152602001828054610c0990614de8565b8015610c545780601f10610c2b57610100808354040283529160200191610c54565b820191905f5260205f20905b815481529060010190602001808311610c3757829003601f168201915b505050600d90930154919250506001600160a01b0381169060ff600160a01b909104168e565b610c82614442565b5f8281526008602090815260409182902082516101e08101909352805483526001810154909183019060ff166003811115610cbf57610cbf614693565b6003811115610cd057610cd0614693565b8152600282810154602083015260408051808201808352919093019291600385019182845b815481526020019060010190808311610cf55750505091835250506005820154602082015260068201546001600160a01b0381166040830152600160a01b900460ff166060820152600782018054608090920191610d5290614de8565b80601f0160208091040260200160405190810160405280929190818152602001828054610d7e90614de8565b8015610dc95780601f10610da057610100808354040283529160200191610dc9565b820191905f5260205f20905b815481529060010190602001808311610dac57829003601f168201915b505050918352505060088201546001600160a01b0390811660208301526009830154166040820152600a8201546060820152600b8201546080820152600c8201805460a090920191610e1a90614de8565b80601f0160208091040260200160405190810160405280929190818152602001828054610e4690614de8565b8015610e915780601f10610e6857610100808354040283529160200191610e91565b820191905f5260205f20905b815481529060010190602001808311610e7457829003601f168201915b5050509183525050600d91909101546001600160a01b038082166020840152600160a01b90910460ff16151560409092019190915260a0820151919250839116610ef15760405163cd6f4a4f60e01b815260040161098891815260200190565b50919050565b5f610f0061393d565b805490915060ff600160401b82041615906001600160401b03165f81158015610f265750825b90505f826001600160401b03166001148015610f415750303b155b905081158015610f4f575080155b15610f6d5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610f9757845460ff60401b1916600160401b1785555b610fa033613967565b610fa987612661565b610fb28b613727565b610fbb8a61292b565b610fc48961092e565b610fcd88610a16565b610fd686613880565b604080516101e08101825261c3508082526161a86020808401829052611388948401859052601460608501819052620249f0608086018190526207a12060a087018190526107d060c088018190525f60e089018190526103e86101008a015261012089018190526109c46101408a018190526101608a018b90526101808a01526101a089018190526101c090980197909752601895909555601993909355601a95909555601b94909455601c55601d55601e55601f80546001600160f01b031916690138827101388000007d60a31b179055805467ffffffffffffffff191690556110bf611688565b6001600160a01b03168c6001600160a01b0316146110e0576110e08c612c72565b831561112657845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050505050565b61113c61384e565b5f8181526009602052604090205481906001600160a01b0316611175576040516381c4951960e01b815260040161098891815260200190565b505f818152600960205260409081902080546001600160a01b0319169055517f104eb329a192aef26eddea07c2af5ad2587792e62b37ed4045b6ba59bc5540fc90610ab09083815260200190565b6111cb61384e565b6001600160a01b0381165f90815260076020526040902054819060ff16611206576040516321ac7c5f60e01b8152600401610988919061461a565b506001600160a01b0381165f9081526007602052604090819020805460ff19169055517f56070b80bd617fcd2f7a284861edb488830a38f9dedcd77b2cb2f4eac17743e790610ab090839061461a565b600b6020525f90815260409020805461126e90614de8565b80601f016020809104026020016040519081016040528092919081815260200182805461129a90614de8565b80156112e55780601f106112bc576101008083540402835291602001916112e5565b820191905f5260205f20905b8154815290600101906020018083116112c857829003601f168201915b505050505081565b6112f561384e565b6112fe5f613978565b565b61130861384e565b6001600160a01b0381161580159061133957505f828152600a60205260409020546001600160a01b03828116911614155b829061135b576040516381c4951960e01b815260040161098891815260200190565b505f918252600a602052604090912080546001600160a01b0319166001600160a01b03909216919091179055565b5f546001600160a01b031633146113b35760405163b56831db60e01b815260040160405180910390fd5b5f818152600d602052604090205460ff1660018160068111156113d8576113d8614693565b146113fd57816001826040516337e1404160e01b815260040161098893929190614e1a565b5f828152600d60205260409020805460ff191660021790556015546114229042614e4f565b5f838152600e602052604080822092909255905183917fc44405af9078047712501f519e1fb900c2896c62b488336f84529c72ae16e6f191a2815f5160206159d95f395f51905f526001600260405161147c929190614e62565b60405180910390a25050565b5f546001600160a01b031633146114b25760405163b56831db60e01b815260040160405180910390fd5b5f828152600860209081526040808320600d9092529091205460ff1660028160068111156114e2576114e2614693565b1461150757836002826040516337e1404160e01b815260040161098893929190614e1a565b5f848152600d6020526040808220805460ff19166003179055600a84018590555185917f11df18edb9bc9cd90a79068e0e208b630202148643d797d6150e7bacb733e63c91a2835f5160206159d95f395f51905f526002600360405161156e929190614e62565b60405180910390a250505050565b61158461384e565b806115c05760405162461bcd60e51b815260206004820152600c60248201526b456d70747920706172616d7360a01b6044820152606401610988565b60ff83165f908152600b6020526040902080546115dc90614de8565b15905061162b5760405162461bcd60e51b815260206004820152601b60248201527f506172616d53657420616c7265616479207265676973746572656400000000006044820152606401610988565b60ff83165f908152600b60205260409020611647828483614ef0565b507f6e4a4ea7f38fc775e616080b155744337e6216848e886a69c918b4ab84da219583838360405161167b93929190614fcc565b60405180910390a1505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6116d760405180606001604052805f81526020015f81526020015f81525090565b5060408051606081018252601554815260165460208201526017549181019190915290565b5f818152600d602052604090205460ff16600681600681111561172157611721614693565b14829061174457604051637cb2d48360e11b815260040161098891815260200190565b505f828152600c60205260409020548281611775576040516345ba89d560e11b815260040161098891815260200190565b505f838152600c6020526040812081905561178f846139e8565b5f858152601160205260409020546002549192506001600160a01b03908116916117bc9183911685613ad5565b60025460405163da19b69760e01b81526001600160a01b039091169063da19b697906117f2908890879087908790600401615034565b5f604051808303815f87803b158015611809575f5ffd5b505af115801561181b573d5f5f3e3d5ffd5b50505050847f5297818f48a66292b8b3e2caab83eec531b669bb20807fd38cf006adb2a0731784845160405161185b929190918252602082015260400190565b60405180910390a25050505050565b61188b60405180606001604052805f81526020015f81526020015f81525090565b505f908152600e6020908152604091829020825160608101845281548152600182015492810192909252600201549181019190915290565b5f818152600d6020526040812054819060ff166118e08482613b32565b9250925050915091565b5f5f6118f587610c7a565b5f888152600d602052604090205490915060ff16600381600681111561191d5761191d614693565b1488600383909192611945576040516337e1404160e01b815260040161098893929190614e1a565b5050505f888152600e60209081526040918290208251606081018452815481526001820154928101839052600290910154928101929092528990428110156119a9576040516308f3034360e31b815260048101929092526024820152604401610988565b50506060830151602001518990428111156119e05760405163017e35e560e71b815260048101929092526024820152604401610988565b5050610160830151899015611a0b57604051637eb9cea960e11b815260040161098891815260200190565b505f8888604051611a1d92919061507f565b60408051918290039091205f8c815260086020908152838220600b01839055600d905291909120805460ff19166004179055601754909150611a5f9042614e4f565b5f8b8152600e6020526040908190206002019190915560a08501519051632f0e1bbf60e01b81526001600160a01b0390911690632f0e1bbf90611aac908d9085908c908c9060040161508e565b6020604051808303815f875af1158015611ac8573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611aec91906150ba565b9450888886611b1057604051632f9f8ab960e01b81526004016109889291906150d5565b5050897f7cc27e4a5626cbc4f8ba1a927b0448de55e6a114bc87660331270c5109ade0718a8a604051611b449291906150d5565b60405180910390a2895f5160206159d95f395f51905f5260036004604051611b6d929190614e62565b60405180910390a25050505095945050505050565b5f80600b81611b9760a0860160808701614994565b60ff1660ff1681526020019081526020015f208054611bb590614de8565b905011611bd45760405162461bcd60e51b8152600401610988906150e8565b5f601281611be5602086018661511f565b6003811115611bf657611bf6614693565b6003811115611c0757611c07614693565b8152602081019190915260409081015f20815180830190925260028282826020028201915f905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411611c2e579050505050505090505f81600160028110611c8557611c8561506b565b602002015163ffffffff1611835f016020810190611ca3919061511f565b90611cc25760405163286c068d60e11b81526004016109889190615138565b506020808201518251604080516101e081018252601854815260195481860152601a5491810191909152601b546060820152601c546080820152601d5460a0820152601e5460c0820152601f546001600160a01b03811660e0830152600160a01b810461ffff908116610100840152600160b01b82048116610120840152600160c01b82048116610140840152600160d01b82048116610160840152600160e01b90910416610180820152925463ffffffff8181166101a0860181905264010000000090920481166101c086015292831693919092169115611ded576101a081015163ffffffff16846001602002015163ffffffff161015865f016020810190611dcc919061511f565b90611deb5760405163010b971d60e31b81526004016109889190615138565b505b6101c081015163ffffffff1615611e3c576101c081015184519063ffffffff9081169082161015611e3a57604051630a4b6b6360e11b815263ffffffff9091166004820152602401610988565b505b60408601356020870135811015611e695760405163174b5a0760e21b815260040161098891815260200190565b506101808101516017545f9161271091611e879161ffff1690615146565b611e91919061515d565b61271061ffff1683610160015161ffff16601560010154611eb29190615146565b611ebc919061515d565b61271061ffff1684610140015161ffff1660155f0154611edc9190615146565b611ee6919061515d565b5f5460408051634f87c3a560e11b8152815160208e81013594938f0135936001600160a01b031692639f0f874a92600480830193928290030181865afa158015611f32573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f56919061517c565b611f609190614e4f565b611f6a9190615193565b611f749190614e4f565b611f7e9190614e4f565b611f889190614e4f565b90505f611f96600186615193565b611fa1906002615146565b611fac906002615146565b611fb7906006614e4f565b90505f85845f0151611fc99190615146565b905081868560200151611fdc9190615146565b611fe69190615146565b611ff09082614e4f565b90506001861115612038576002612008600188615193565b6120129088615146565b85604001516120219190615146565b61202b919061515d565b6120359082614e4f565b90505b81868560c001516120499190615146565b6120539190615146565b61205d9082614e4f565b9050828685606001516120709190615146565b61207a9190615146565b6120849082614e4f565b90508484608001516120969190615146565b6120a09082614e4f565b905060018511156120e85760026120b8600187615193565b6120c29087615146565b85604001516120d19190615146565b6120db919061515d565b6120e59082614e4f565b90505b60a08401516120f79082614e4f565b610100850151909150612710906121129061ffff1682614e4f565b61211c9083615146565b612126919061515d565b9750878061214a57604051638c4fcd9360e01b815260040161098891815260200190565b5050505050505050919050565b5f5f61216289610c7a565b5f8a8152600d602052604090205490915060ff16600481600681111561218a5761218a614693565b148a6004839091926121b2576040516337e1404160e01b815260040161098893929190614e1a565b5050505f8a8152600e602090815260409182902082516060810184528154815260018201549281019290925260020154918101829052908b9042811015612215576040516308f3034360e31b815260048101929092526024820152604401610988565b50505f8b8152600860205260409020600c016122328a8c83614ef0565b505f8b8152600d6020526040902080546005919060ff191660018302179055508261010001516001600160a01b0316635bf48e3a8b8b60405161227692919061507f565b6040519081900381206001600160e01b031960e084901b1682526122a4918c908c908c908c906004016151a6565b602060405180830381865afa1580156122bf573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122e391906150ba565b935089898561230757604051632f9f8ab960e01b81526004016109889291906150d5565b50506123128b613cba565b8a7f3a140076c461ebc41d74833ae0ee8bbc8079a135a63392098cd381e84350b69b8b8b8b8b60405161234894939291906151de565b60405180910390a28a5f5160206159d95f395f51905f5260046005604051612371929190614e62565b60405180910390a2505050979650505050505050565b5f546001600160a01b03163314806123a957506003546001600160a01b031633145b6123c657604051639e75a8b560e01b815260040160405180910390fd5b5f8160ff161180156123dc5750600d60ff821611155b6124215760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b2103330b4b63ab932903932b0b9b7b760511b6044820152606401610988565b61243f828260ff16600d81111561243a5761243a614693565b614126565b5050565b61244b61384e565b6001600160a01b0381166124a15760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420536c617368696e674d616e616765722061646472657373006044820152606401610988565b600380546001600160a01b0319166001600160a01b0383169081179091556040517f4ccc8ed483c7c44c3602c3c38afc2c014a8f1d2dc210dfe58ebeeeead230f8e0905f90a250565b6003546001600160a01b03163314612515576040516357d6948d60e11b815260040160405180910390fd5b60025460405163c1ab0f1f60e01b815260048101849052602481018390526001600160a01b039091169063c1ab0f1f906044015f604051808303815f87803b15801561255f575f5ffd5b505af1158015612571573d5f5f3e3d5ffd5b50505050817f4f41a3b0a032ebcae925f2ace77d507435840ca4b2dbaffdd7723fa8d72ee5428260405161147c91815260200190565b6125af61384e565b6001600160a01b038116158015906125e057505f828152600960205260409020546001600160a01b03828116911614155b8290612602576040516381c4951960e01b815260040161098891815260200190565b505f8281526009602090815260409182902080546001600160a01b0319166001600160a01b03851617905590518381527ff4041a3f914dac3bc9bf5f003ba41f28dbb84abe42f4e07c76266f5c8ceecb69910160405180910390a15050565b61266961384e565b60058190556040518181527fba0716ba1ee2ea8ecc4c64119b4537cdb42a99d82acf92af5b87607b8b52355290602001610ab0565b6126a661384e565b6127106126bb61012083016101008401615229565b61ffff1611156126d361012083016101008401615229565b906126f8576040516301027fc160e21b815261ffff9091166004820152602401610988565b5061271061270e61014083016101208401615229565b61ffff16111561272661014083016101208401615229565b9061274b576040516301027fc160e21b815261ffff9091166004820152602401610988565b5061271061276161016083016101408401615229565b61ffff16111561277961016083016101408401615229565b9061279e57604051633239953960e01b815261ffff9091166004820152602401610988565b506127106127b461018083016101608401615229565b61ffff1611156127cc61018083016101608401615229565b906127f157604051633239953960e01b815261ffff9091166004820152602401610988565b506127106128076101a083016101808401615229565b61ffff16111561281f6101a083016101808401615229565b9061284457604051633239953960e01b815261ffff9091166004820152602401610988565b5061285761014082016101208301615229565b61ffff16158061288057505f612874610100830160e084016145d4565b6001600160a01b031614155b61289d5760405163015f92ff60e51b815260040160405180910390fd5b6128af6101e082016101c08301615260565b63ffffffff166128c76101c083016101a08401615260565b63ffffffff1610156128ec576040516392f55c6560e01b815260040160405180910390fd5b8060186128f9828261529f565b9050507fbf3951313e980027eb48ce363fdb707286195ec6a0f802ac153927cf929c3fc681604051610ab0919061545d565b61293361384e565b6001600160a01b0381161580159061295957506001546001600160a01b03828116911614155b8190612979576040516320252f0b60e01b8152600401610988919061461a565b50600180546001600160a01b0319166001600160a01b0383161790556040517fad4055f18cdad6f4bdd71afe3a72cbeee964217943e1bde38f138289e981a9a790610ab090839061461a565b6129cd61384e565b6129da6020820182615260565b63ffffffff166129f06040830160208401615260565b63ffffffff1610158015612a1557505f612a0d6020830183615260565b63ffffffff16115b612a3257604051634564ab9b60e01b815260040160405180910390fd5b604080516101e0810182526018548152601954602080830191909152601a5492820192909252601b546060820152601c546080820152601d5460a0820152601e5460c0820152601f546001600160a01b03811660e083015261ffff600160a01b82048116610100840152600160b01b82048116610120840152600160c01b82048116610140840152600160d01b82048116610160840152600160e01b90910416610180820152905463ffffffff8082166101a08401819052640100000000909204166101c083015215612b6b576101a081015163ffffffff16612b1b6040840160208501615260565b63ffffffff161015612b336040840160208501615260565b826101a001519091612b6857604051633ccc4c2160e21b815263ffffffff928316600482015291166024820152604401610988565b50505b6101c081015163ffffffff1615612be2576101c081015163ffffffff16612b956020840184615260565b63ffffffff161015612baa6020840184615260565b826101c001519091612bdf5760405163156c4e5b60e11b815263ffffffff928316600482015291166024820152604401610988565b50505b8160125f856003811115612bf857612bf8614693565b6003811115612c0957612c09614693565b815260208101919091526040015f20612c239160026144bf565b50826003811115612c3657612c36614693565b7f8b56fae526eee054f0849759a99fc7d4ff3823824ebf097a56f7d78adb6b34fa83604051612c659190615567565b60405180910390a2505050565b612c7a61384e565b6001600160a01b038116612ca3575f604051631e4fbdf760e01b8152600401610988919061461a565b610acc81613978565b5f612cb5614442565b5f601281612cc6602087018761511f565b6003811115612cd757612cd7614693565b6003811115612ce857612ce8614693565b8152602081019190915260409081015f20815180830190925260028282826020028201915f905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411612d0f579050505050505090505f81600160028110612d6657612d6661506b565b602002015163ffffffff1611845f016020810190612d84919061511f565b90612da35760405163286c068d60e11b81526004016109889190615138565b50602084013542811015612dcd57604051630b99e87960e01b815260040161098891815260200190565b5060408401356020850135811015612dfb5760405163174b5a0760e21b815260040161098891815260200190565b506017546016545f9190612e13426040890135615193565b612e1d9190614e4f565b612e279190614e4f565b905060055481108190612e50576040516313b783af60e21b815260040161098891815260200190565b5060075f612e6460808801606089016145d4565b6001600160a01b0316815260208101919091526040015f205460ff16612e9060808701606088016145d4565b90612eaf5760405163295a6a6f60e11b8152600401610988919061461a565b505f612eba86611b82565b60068054965090915085905f612ecf836155a7565b9091555050604080514460208201529081018690525f9060600160408051601f1981840301815291815281516020928301205f898152600c84528281208690556004546011855283822080546001600160a01b03199081166001600160a01b0393841617909155601f805460138852868520805461ffff191661ffff600160b01b909304929092169190911790555460148752858420805483169190931617909155600d8552838220805460ff191660011790556010909452829020805433941693909317909255601654919250612faa9190890135614e4f565b5f878152600e6020908152604090912060010191909155818652612fd09088018861511f565b85602001906003811115612fe657612fe6614693565b90816003811115612ff957612ff9614693565b905250436040808701919091528051808201825290602089019060029083908390808284375f92019190915250505060608087019190915261304190608089019089016145d4565b6001600160a01b031660a08087019190915261306290880160808901614994565b60ff1660c08087019190915261307a908801886155bf565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050505060e0808701919091526130c7906101008901908901615601565b15156101c08601525f610140860181905261016086018190526040805160208101909152908152610180860152336101a08601819052600454613117916001600160a01b03909116903085614281565b5f600b8161312b60a08b0160808c01614994565b60ff1660ff1681526020019081526020015f20805461314990614de8565b80601f016020809104026020016040519081016040528092919081815260200182805461317590614de8565b80156131c05780601f10613197576101008083540402835291602001916131c0565b820191905f5260205f20905b8154815290600101906020018083116131a357829003601f168201915b505050505090505f8151116131e75760405162461bcd60e51b8152600401610988906150e8565b5f6131f860808a0160608b016145d4565b6001600160a01b031663fefd9a8b89858561321660a08f018f6155bf565b8f8060c0019061322691906155bf565b6040518863ffffffff1660e01b8152600401613248979695949392919061561c565b6020604051808303815f875af1158015613264573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613288919061517c565b5f818152600960205260409020549091506001600160a01b031681816132c4576040516381c4951960e01b815260040161098891815260200190565b505f828152600a60205260409020546001600160a01b031682816132fe576040516381c4951960e01b815260040161098891815260200190565b50608089018390526001600160a01b038083166101008b015281166101208a01525f8a81526008602090815260409091208a518155908a0151600180830180548d94939260ff19919091169083600381111561335c5761335c614693565b021790555060408201518160020155606082015181600301906002613382929190614560565b506080820151600582015560a082015160068201805460c085015160ff16600160a01b026001600160a81b03199091166001600160a01b039093169290921791909117905560e082015160078201906133db9082615670565b506101008201516008820180546001600160a01b039283166001600160a01b031991821617909155610120840151600984018054919093169116179055610140820151600a820155610160820151600b820155610180820151600c8201906134439082615670565b506101a0820151600d90910180546101c0909301511515600160a01b026001600160a81b03199093166001600160a01b0392831617929092179091555f5460405163291a691b60e01b815291169063291a691b906134a9908d9089908d90600401615725565b6020604051808303815f875af11580156134c5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906134e991906150ba565b61350657604051630d8dbe2560e01b815260040160405180910390fd5b61351660808c0160608d016145d4565b6001600160a01b03167f5090c9764b5cd13df7afc0013f733dfbe6eaf1b6ddc22a5e291fa387efd4c15e8b8b604051613550929190614dc8565b60405180910390a2895f5160206159d95f395f51905f525f6001604051613578929190614e62565b60405180910390a25050505050505050915091565b5f818152600d602052604081205460ff16818160068111156135b1576135b1614693565b036135d657826001826040516337e1404160e01b815260040161098893929190614e1a565b60058160068111156135ea576135ea614693565b0361360b5760405163462c7bed60e01b815260048101849052602401610988565b600681600681111561361f5761361f614693565b0361364057604051633de16e3560e11b815260048101849052602401610988565b5f61364b8483613b32565b935090508061367057604051639f65d93560e01b815260048101859052602401610988565b5f848152600d6020526040902080546006919060ff191660018302179055505f848152600f60205260409020805484919060ff1916600183600d8111156136b9576136b9614693565b0217905550835f5160206159d95f395f51905f528360066040516136de929190614e62565b60405180910390a2837fe20209be7caae6e76291267cfa711353981274bf127e94f16eb9ec44b68582bb838560405161371892919061576a565b60405180910390a25050919050565b61372f61384e565b6001600160a01b0381161580159061375457505f546001600160a01b03828116911614155b8190613774576040516375ac4eb760e11b8152600401610988919061461a565b505f80546001600160a01b0319166001600160a01b0383161790556040517f80052b810d39120cf6c976cca504a21703f585521dc7a41c6d241090e6c579b690610ab090839061461a565b6001600160a01b0381165f90815260076020526040902054819060ff16156137fb5760405163b29d459560e01b8152600401610988919061461a565b506001600160a01b0381165f9081526007602052604090819020805460ff19166001179055517fb8d368517268f297fff00825d67d098763117d061360d31027be5b2e1a59d46790610ab090839061461a565b33613857611688565b6001600160a01b0316146112fe573360405163118cdaa760e01b8152600401610988919061461a565b803561389f5760405163055f269d60e01b815260040160405180910390fd5b5f8160200135116138c35760405163055f269d60e01b815260040160405180910390fd5b5f8160400135116138e75760405163055f269d60e01b815260040160405180910390fd5b80356015819055602080830135601681905560408085013560178190558151948552928401919091528201527f7e86ba16b805e2835af5c5b7aa5a942ced8bcc1fb95a05fbe42dae3862350a1690606001610ab0565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005b92915050565b61396f6142c0565b610acc816142e5565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f818152600f602052604090205460609060ff16600181600d811115613a1057613a10614693565b1480613a2d5750600281600d811115613a2b57613a2b614693565b145b15613a65575f5b604051908082528060200260200182016040528015613a5d578160200160208202803683370190505b509392505050565b5f5460405162beb08960e51b8152600481018590526001600160a01b03909116906317d61120906024015f60405180830381865afa925050508015613acb57506040513d5f823e601f3d908101601f19168201604052613ac89190810190615841565b60015b613a5d575f613a34565b613b2d83846001600160a01b031663a9059cbb8585604051602401613afb929190615906565b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506142ed565b505050565b5f828152600e60209081526040808320815160608101835281548152600182015493810193909352600201548282015282549051632800d82960e01b81526004810186905283929183916001600160a01b0390911690632800d82990602401602060405180830381865afa158015613bac573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613bd0919061517c565b90506001856006811115613be657613be6614693565b148015613bf257508042115b15613c0557600180935093505050613cb3565b6002856006811115613c1957613c19614693565b148015613c265750815142115b15613c3a5760016003935093505050613cb3565b6003856006811115613c4e57613c4e614693565b148015613c5e5750816020015142115b15613c725760016006935093505050613cb3565b6004856006811115613c8657613c86614693565b148015613c965750816040015142115b15613caa576001600a935093505050613cb3565b5f5f9350935050505b9250929050565b5f805460405162beb08960e51b8152600481018490526001600160a01b03909116906317d61120906024015f60405180830381865afa158015613cff573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052613d269190810190615841565b5080515f848152600c60209081526040808320805490849055601190925282205493945091926001600160a01b031690829003613dc5576002546040516341489f1560e01b81526001600160a01b03909116906341489f1590613d919088908890869060040161591f565b5f604051808303815f87803b158015613da8575f5ffd5b505af1158015613dba573d5f5f3e3d5ffd5b505050505050505050565b825f03613e66575f858152601060205260409020546001600160a01b03168015613dfd57613dfd6001600160a01b0383168285613ad5565b6002546040516341489f1560e01b81526001600160a01b03909116906341489f1590613e319089908990879060040161591f565b5f604051808303815f87803b158015613e48575f5ffd5b505af1158015613e5a573d5f5f3e3d5ffd5b50505050505050505050565b5f85815260136020908152604080832054601490925282205461ffff909116906001600160a01b03168115801590613ea657506001600160a01b03811615155b15613ee257612710613ebc61ffff841687615146565b613ec6919061515d565b92508215613ee257613ee26001600160a01b0385168285613ad5565b5f613eed8487615193565b90505f876001600160401b03811115613f0857613f08614e7d565b604051908082528060200260200182016040528015613f31578160200160208202803683370190505b5090505f613f3f898461515d565b90505f805b8a811015613f7e5782848281518110613f5f57613f5f61506b565b6020908102919091010152613f748383614e4f565b9150600101613f44565b505f613f8a8286615193565b90508015613fc7578084613f9f60018e615193565b81518110613faf57613faf61506b565b60200260200101818151613fc39190614e4f565b9052505b600154613fe1906001600160a01b038b8116911687614350565b60015f9054906101000a90046001600160a01b03166001600160a01b031663dd8c818e8a8e876040518463ffffffff1660e01b81526004016140259392919061597f565b5f604051808303815f87803b15801561403c575f5ffd5b505af115801561404e573d5f5f3e3d5ffd5b505060015461406c92506001600160a01b038c81169250165f614350565b8c7fac9fe8ad7f55eac03284399116ecafc104f10459773f4cdf47063c46e5be335a8d8660405161409e9291906159b4565b60405180910390a260025f9054906101000a90046001600160a01b03166001600160a01b03166341489f158e8e8c6040518463ffffffff1660e01b81526004016140ea9392919061591f565b5f604051808303815f87803b158015614101575f5ffd5b505af1158015614113573d5f5f3e3d5ffd5b5050505050505050505050505050505050565b5f828152600d602052604081205460ff169081600681111561414a5761414a614693565b0361416f57826001826040516337e1404160e01b815260040161098893929190614e1a565b600581600681111561418357614183614693565b036141a45760405163462c7bed60e01b815260048101849052602401610988565b60068160068111156141b8576141b8614693565b036141d957604051633de16e3560e11b815260048101849052602401610988565b5f838152600d6020526040902080546006919060ff191660018302179055505f838152600f60205260409020805483919060ff1916600183600d81111561422257614222614693565b0217905550825f5160206159d95f395f51905f52826006604051614247929190614e62565b60405180910390a2827fe20209be7caae6e76291267cfa711353981274bf127e94f16eb9ec44b68582bb8284604051612c6592919061576a565b6040516001600160a01b0384811660248301528381166044830152606482018390526142ba9186918216906323b872dd90608401613afb565b50505050565b6142c86143e0565b6112fe57604051631afcd79f60e31b815260040160405180910390fd5b612c7a6142c0565b5f5f60205f8451602086015f885af18061430c576040513d5f823e3d81fd5b50505f513d91508115614323578060011415614330565b6001600160a01b0384163b155b156142ba5783604051635274afe760e01b8152600401610988919061461a565b5f836001600160a01b031663095ea7b38484604051602401614373929190615906565b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505090506143ac84826143f9565b6142ba576143d684856001600160a01b031663095ea7b3865f604051602401613afb929190615906565b6142ba84826142ed565b5f6143e961393d565b54600160401b900460ff16919050565b5f5f5f5f60205f8651602088015f8a5af192503d91505f5190508280156144385750811561442a5780600114614438565b5f866001600160a01b03163b115b9695505050505050565b604080516101e081019091525f808252602082019081526020015f815260200161446a61458e565b81525f602082018190526040820181905260608083018290526080830181905260a0830182905260c0830182905260e08301829052610100830182905261012083015261014082018190526101609091015290565b600183019183908215614550579160200282015f5b8382111561451e57833563ffffffff1683826101000a81548163ffffffff021916908363ffffffff16021790555092602001926004016020816003010492830192600103026144d4565b801561454e5782816101000a81549063ffffffff021916905560040160208160030104928301926001030261451e565b505b5061455c9291506145ac565b5090565b8260028101928215614550579160200282015b82811115614550578251825591602001919060010190614573565b60405180604001604052806002906020820280368337509192915050565b5b8082111561455c575f81556001016145ad565b6001600160a01b0381168114610acc575f5ffd5b5f602082840312156145e4575f5ffd5b81356145ef816145c0565b9392505050565b5f60208284031215614606575f5ffd5b5035919050565b6001600160a01b03169052565b6001600160a01b0391909116815260200190565b80356004811061463c575f5ffd5b919050565b5f5f60408385031215614652575f5ffd5b61465b8361462e565b946020939093013593505050565b5f60608284031215610ef1575f5ffd5b5f60608284031215614689575f5ffd5b6145ef8383614669565b634e487b7160e01b5f52602160045260245ffd5b600e81106146b7576146b7614693565b9052565b6020810161396182846146a7565b600481106146b7576146b7614693565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b8e8152614717602082018f6146c9565b8c60408201528b6060820152614730608082018c61460d565b60ff8a1660a08201526101c060c08201525f6147506101c083018b6146d9565b61475d60e084018b61460d565b61476b61010084018a61460d565b876101208401528661014084015282810361016084015261478c81876146d9565b91505061479d61018083018561460d565b8215156101a08301529f9e505050505050505050505050505050565b805f5b60028110156142ba5781518452602093840193909101906001016147bc565b805182525f60208201516147f260208501826146c9565b5060408201516040840152606082015161480f60608501826147b9565b50608082015160a084015260a082015161482c60c085018261460d565b5060c082015160ff811660e08501525060e08201516102006101008501526148586102008501826146d9565b905061010083015161486e61012086018261460d565b5061012083015161488361014086018261460d565b506101408301516101608501526101608301516101808501526101808301518482036101a08601526148b582826146d9565b9150506101a08301516148cc6101c086018261460d565b506101c08301518015156101e0860152613a5d565b602081525f6145ef60208301846147db565b803561463c816145c0565b5f5f5f5f5f5f5f610120888a031215614915575f5ffd5b8735614920816145c0565b96506020880135614930816145c0565b95506040880135614940816145c0565b94506060880135614950816145c0565b93506080880135614960816145c0565b925060a088013591506149768960c08a01614669565b905092959891949750929550565b803560ff8116811461463c575f5ffd5b5f602082840312156149a4575f5ffd5b6145ef82614984565b602081525f6145ef60208301846146d9565b5f5f604083850312156149d0575f5ffd5b8235915060208301356149e2816145c0565b809150509250929050565b5f5f604083850312156149fe575f5ffd5b50508035926020909101359150565b5f5f83601f840112614a1d575f5ffd5b5081356001600160401b03811115614a33575f5ffd5b602083019150836020828501011115613cb3575f5ffd5b5f5f5f60408486031215614a5c575f5ffd5b614a6584614984565b925060208401356001600160401b03811115614a7f575f5ffd5b614a8b86828701614a0d565b9497909650939450505050565b81518152602080830151908201526040808301519082015260608101613961565b8215158152604081016145ef60208301846146a7565b5f5f5f5f5f60608688031215614ae3575f5ffd5b8535945060208601356001600160401b03811115614aff575f5ffd5b614b0b88828901614a0d565b90955093505060408601356001600160401b03811115614b29575f5ffd5b614b3588828901614a0d565b969995985093965092949392505050565b5f60208284031215614b56575f5ffd5b81356001600160401b03811115614b6b575f5ffd5b820161010081850312156145ef575f5ffd5b5f6101e082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e0830151614bd760e084018261460d565b50610100830151614bef61010084018261ffff169052565b50610120830151614c0761012084018261ffff169052565b50610140830151614c1f61014084018261ffff169052565b50610160830151614c3761016084018261ffff169052565b50610180830151614c4f61018084018261ffff169052565b506101a0830151614c696101a084018263ffffffff169052565b506101c0830151614c836101c084018263ffffffff169052565b5092915050565b5f5f5f5f5f5f5f6080888a031215614ca0575f5ffd5b8735965060208801356001600160401b03811115614cbc575f5ffd5b614cc88a828b01614a0d565b90975095505060408801356001600160401b03811115614ce6575f5ffd5b614cf28a828b01614a0d565b90955093505060608801356001600160401b03811115614d10575f5ffd5b614d1c8a828b01614a0d565b989b979a50959850939692959293505050565b5f5f60408385031215614d40575f5ffd5b82359150614d5060208401614984565b90509250929050565b600781106146b7576146b7614693565b602081016139618284614d59565b5f6101e0828403128015614d89575f5ffd5b509092915050565b5f5f60608385031215614da2575f5ffd5b614dab8361462e565b915083606084011115614dbc575f5ffd5b50926020919091019150565b828152604060208201525f614de060408301846147db565b949350505050565b600181811c90821680614dfc57607f821691505b602082108103610ef157634e487b7160e01b5f52602260045260245ffd5b83815260608101614e2e6020830185614d59565b614de06040830184614d59565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561396157613961614e3b565b60408101614e708285614d59565b6145ef6020830184614d59565b634e487b7160e01b5f52604160045260245ffd5b601f821115613b2d57805f5260205f20601f840160051c81016020851015614eb65750805b601f840160051c820191505b81811015614ed5575f8155600101614ec2565b5050505050565b5f19600383901b1c191660019190911b1790565b6001600160401b03831115614f0757614f07614e7d565b614f1b83614f158354614de8565b83614e91565b5f601f841160018114614f47575f8515614f355750838201355b614f3f8682614edc565b845550614ed5565b5f83815260208120601f198716915b82811015614f765786850135825560209485019460019092019101614f56565b5086821015614f92575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60ff84168152604060208201525f614fe8604083018486614fa4565b95945050505050565b5f8151808452602084019350602083015f5b8281101561502a5781516001600160a01b0316865260209586019590910190600101615003565b5093949350505050565b848152836020820152608060408201525f6150526080830185614ff1565b905060018060a01b038316606083015295945050505050565b634e487b7160e01b5f52603260045260245ffd5b818382375f9101908152919050565b848152836020820152606060408201525f614438606083018486614fa4565b8015158114610acc575f5ffd5b5f602082840312156150ca575f5ffd5b81516145ef816150ad565b602081525f614de0602083018486614fa4565b6020808252601c908201527f42465620706172616d20736574206e6f74207265676973746572656400000000604082015260600190565b5f6020828403121561512f575f5ffd5b6145ef8261462e565b6020810161396182846146c9565b808202811582820484141761396157613961614e3b565b5f8261517757634e487b7160e01b5f52601260045260245ffd5b500490565b5f6020828403121561518c575f5ffd5b5051919050565b8181038181111561396157613961614e3b565b858152606060208201525f6151bf606083018688614fa4565b82810360408401526151d2818587614fa4565b98975050505050505050565b604081525f6151f1604083018688614fa4565b8281036020840152615204818587614fa4565b979650505050505050565b61ffff81168114610acc575f5ffd5b803561463c8161520f565b5f60208284031215615239575f5ffd5b81356145ef8161520f565b63ffffffff81168114610acc575f5ffd5b803561463c81615244565b5f60208284031215615270575f5ffd5b81356145ef81615244565b5f8135613961816145c0565b5f81356139618161520f565b5f813561396181615244565b813581556020820135600182015560408201356002820155606082013560038201556080820135600482015560a0820135600582015560c082013560068201556007810161530f6152f260e0850161527b565b82546001600160a01b0319166001600160a01b0391909116178255565b61533f61531f6101008501615287565b82805461ffff60a01b191660a09290921b61ffff60a01b16919091179055565b61536f61534f6101208501615287565b82805461ffff60b01b191660b09290921b61ffff60b01b16919091179055565b61539f61537f6101408501615287565b82805461ffff60c01b191660c09290921b61ffff60c01b16919091179055565b6153cf6153af6101608501615287565b82805461ffff60d01b191660d09290921b61ffff60d01b16919091179055565b6153ff6153df6101808501615287565b82805461ffff60e01b191660e09290921b61ffff60e01b16919091179055565b506008810161542b6154146101a08501615293565b825463ffffffff191663ffffffff91909116178255565b613b2d61543b6101c08501615293565b825467ffffffff00000000191660209190911b67ffffffff0000000016178255565b813581526020808301359082015260408083013590820152606080830135908201526080808301359082015260a0808301359082015260c080830135908201526101e081016154ae60e084016148f3565b6154bb60e084018261460d565b506154c9610100840161521e565b61ffff166101008301526154e0610120840161521e565b61ffff166101208301526154f7610140840161521e565b61ffff1661014083015261550e610160840161521e565b61ffff16610160830152615525610180840161521e565b61ffff1661018083015261553c6101a08401615255565b63ffffffff166101a08301526155556101c08401615255565b63ffffffff81166101c0840152614c83565b6040810181835f5b600281101561559e57813561558381615244565b63ffffffff168352602092830192919091019060010161556f565b50505092915050565b5f600182016155b8576155b8614e3b565b5060010190565b5f5f8335601e198436030181126155d4575f5ffd5b8301803591506001600160401b038211156155ed575f5ffd5b602001915036819003821315613cb3575f5ffd5b5f60208284031215615611575f5ffd5b81356145ef816150ad565b87815286602082015260a060408201525f61563a60a08301886146d9565b828103606084015261564d818789614fa4565b90508281036080840152615662818587614fa4565b9a9950505050505050505050565b81516001600160401b0381111561568957615689614e7d565b61569d816156978454614de8565b84614e91565b6020601f8211600181146156ca575f83156156b85750848201515b6156c28482614edc565b855550614ed5565b5f84815260208120601f198516915b828110156156f957878501518255602094850194600190920191016156d9565b508482101561571657868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b838152602081018390526080810160408201835f5b600281101561575f57815163ffffffff1683526020928301929091019060010161573a565b505050949350505050565b604081016157788285614d59565b6145ef60208301846146a7565b604051601f8201601f191681016001600160401b03811182821017156157ad576157ad614e7d565b604052919050565b5f6001600160401b038211156157cd576157cd614e7d565b5060051b60200190565b5f82601f8301126157e6575f5ffd5b81516157f96157f4826157b5565b615785565b8082825260208201915060208360051b86010192508583111561581a575f5ffd5b602085015b8381101561583757805183526020928301920161581f565b5095945050505050565b5f5f60408385031215615852575f5ffd5b82516001600160401b03811115615867575f5ffd5b8301601f81018513615877575f5ffd5b80516158856157f4826157b5565b8082825260208201915060208360051b8501019250878311156158a6575f5ffd5b6020840193505b828410156158d15783516158c0816145c0565b8252602093840193909101906158ad565b8095505050505060208301516001600160401b038111156158f0575f5ffd5b6158fc858286016157d7565b9150509250929050565b6001600160a01b03929092168252602082015260400190565b838152606060208201525f6159376060830185614ff1565b905060018060a01b0383166040830152949350505050565b5f8151808452602084019350602083015f5b8281101561502a578151865260209586019590910190600101615961565b6001600160a01b03841681526060602082018190525f906159a290830185614ff1565b8281036040840152614438818561594f565b604081525f6159c66040830185614ff1565b8281036020840152614fe8818561594f56fe1b418a230a21d37a078bf8f16decbde8ccceacd77159371f62f0d4ea00d19967a164736f6c634300081c000a", + "bytecode": "0x6080604052348015600e575f5ffd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b615a13806100d65f395ff3fe608060405234801561000f575f5ffd5b50600436106102ce575f3560e01c80639117173c11610182578063cb649617116100e0578063f0691cba1161008f578063f0691cba14610886578063f2fde38b14610899578063f3ceba3a146108ac578063f81b8ef6146108cd578063fad8e111146108e0578063fbdb3237146108f3578063fd2f3d011461091b575f5ffd5b8063cb649617146107ef578063cbd16872146107f8578063cf0f34c41461080b578063cfbdc98d1461081e578063d8afed3e1461084d578063e59e469514610860578063ea71aa5714610873575f5ffd5b8063a87f4ab91161013c578063a87f4ab914610607578063ac3d2f4214610759578063b27392d514610781578063bb2d1b8214610794578063bff232c1146107a7578063c1ab0f1f146107ba578063c4ccafa2146107cd575f5ffd5b80639117173c146105625780639231238614610575578063929a8faf1461058857806399c6679d146105a95780639c8570c8146105d15780639e57b934146105f4575f5ffd5b80635d1684181161022f57806381476ec2116101e957806381476ec2146104e7578063830d7181146104fa578063858142431461050d5780638da5cb5b146105205780638dcdd86b146105285780638e5ce3ad1461053a57806390173a411461054d575f5ffd5b80635d1684181461047d578063647846a51461049d5780636db5c8fd146104b0578063715018a6146104b95780637c8c3b4d146104c15780637cfa9d74146104d4575f5ffd5b806336c5d38a1161028b57806336c5d38a1461039b5780634017daf0146103ca578063406ed35c146103f75780634147a360146104175780634d600e5d146104445780634e92ec63146104575780634fc772641461046a575f5ffd5b806302a3a9c9146102d25780630ef81b2f146102e757806310bc62811461032557806311bd61d91461034d57806315cce224146103755780631ba7294514610388575b5f5ffd5b6102e56102e03660046145e2565b61092e565b005b61030f6102f5366004614604565b5f908152600960205260409020546001600160a01b031690565b60405161031c9190614628565b60405180910390f35b61030f610333366004614604565b60096020525f90815260409020546001600160a01b031681565b61036061035b36600461464f565b6109da565b60405163ffffffff909116815260200161031c565b6102e56103833660046145e2565b610a16565b6102e5610396366004614687565b610abb565b6103bd6103a9366004614604565b5f908152600f602052604090205460ff1690565b60405161031c91906146c9565b6103dd6103d8366004614604565b610acf565b60405161031c9e9d9c9b9a99989796959493929190614715565b61040a610405366004614604565b610c7a565b60405161031c91906148ef565b610436610425366004614604565b600c6020525f908152604090205481565b60405190815260200161031c565b6102e561045236600461490c565b610ef7565b6102e5610465366004614604565b611134565b6102e56104783660046145e2565b6111c3565b61049061048b3660046149a2565b611256565b60405161031c91906149bb565b60045461030f906001600160a01b031681565b61043660055481565b6102e56112ed565b6102e56104cf3660046149cd565b611300565b6102e56104e2366004614604565b611389565b6102e56104f53660046149fb565b611488565b6102e5610508366004614a58565b61157c565b60015461030f906001600160a01b031681565b61030f611688565b5f5461030f906001600160a01b031681565b60035461030f906001600160a01b031681565b6105556116b6565b60405161031c9190614aa6565b6102e5610570366004614604565b6116fc565b610555610583366004614604565b61186a565b61059b610596366004614604565b6118c3565b60405161031c929190614ac7565b61030f6105b7366004614604565b5f908152601060205260409020546001600160a01b031690565b6105e46105df366004614add565b6118ea565b604051901515815260200161031c565b610436610602366004614b54565b611b82565b61074c604080516101e0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081019190915250604080516101e0810182526018548152601954602080830191909152601a5492820192909252601b546060820152601c546080820152601d5460a0820152601e5460c0820152601f546001600160a01b03811660e083015261ffff600160a01b82048116610100840152600160b01b82048116610120840152600160c01b82048116610140840152600160d01b82048116610160840152600160e01b90910416610180820152905463ffffffff8082166101a0840152640100000000909104166101c082015290565b60405161031c9190614b8b565b61030f610767366004614604565b5f908152600a60205260409020546001600160a01b031690565b6105e461078f366004614c98565b612157565b6102e56107a2366004614d3d565b612395565b6102e56107b53660046145e2565b612451565b6102e56107c83660046149fb565b6124f8565b6105e46107db3660046145e2565b60076020525f908152604090205460ff1681565b61043660065481565b6102e56108063660046149cd565b6125b5565b6102e5610819366004614604565b61266f565b61084061082c366004614604565b5f908152600d602052604090205460ff1690565b60405161031c9190614d77565b6102e561085b366004614d85565b6126ac565b6102e561086e3660046145e2565b612939565b6102e5610881366004614d9f565b6129d3565b60025461030f906001600160a01b031681565b6102e56108a73660046145e2565b612c80565b6108bf6108ba366004614b54565b612cba565b60405161031c929190614dd6565b6103bd6108db366004614604565b61359b565b6102e56108ee3660046145e2565b613735565b61030f610901366004614604565b600a6020525f90815260409020546001600160a01b031681565b6102e56109293660046145e2565b6137cd565b61093661385c565b6001600160a01b0381166109915760405162461bcd60e51b815260206004820152601f60248201527f496e76616c6964204533526566756e644d616e6167657220616464726573730060448201526064015b60405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040517f9557d04c1c0b16f93f13b69aed23b3b6ab935bff3c53ac81d17896d3583542ed905f90a250565b6012602052815f5260405f2081600281106109f3575f80fd5b60089182820401919006600402915091509054906101000a900463ffffffff1681565b610a1e61385c565b6001600160a01b03811615801590610a4457506004546001600160a01b03828116911614155b8190610a645760405163eddf07f560e01b81526004016109889190614628565b50600480546001600160a01b0319166001600160a01b0383161790556040517f722ff84c1234b2482061def5c82c6b5080c117b3cbb69d686844a051e4b8e7f390610ab0908390614628565b60405180910390a150565b610ac361385c565b610acc8161388e565b50565b60086020525f9081526040902080546001820154600283015460058401546006850154600786018054959660ff95861696949593946001600160a01b03841694600160a01b90940490931692909190610b2790614df6565b80601f0160208091040260200160405190810160405280929190818152602001828054610b5390614df6565b8015610b9e5780601f10610b7557610100808354040283529160200191610b9e565b820191905f5260205f20905b815481529060010190602001808311610b8157829003601f168201915b50505060088401546009850154600a860154600b870154600c8801805497986001600160a01b03958616989490951696509194509291610bdd90614df6565b80601f0160208091040260200160405190810160405280929190818152602001828054610c0990614df6565b8015610c545780601f10610c2b57610100808354040283529160200191610c54565b820191905f5260205f20905b815481529060010190602001808311610c3757829003601f168201915b505050600d90930154919250506001600160a01b0381169060ff600160a01b909104168e565b610c82614450565b5f8281526008602090815260409182902082516101e08101909352805483526001810154909183019060ff166003811115610cbf57610cbf6146a1565b6003811115610cd057610cd06146a1565b8152600282810154602083015260408051808201808352919093019291600385019182845b815481526020019060010190808311610cf55750505091835250506005820154602082015260068201546001600160a01b0381166040830152600160a01b900460ff166060820152600782018054608090920191610d5290614df6565b80601f0160208091040260200160405190810160405280929190818152602001828054610d7e90614df6565b8015610dc95780601f10610da057610100808354040283529160200191610dc9565b820191905f5260205f20905b815481529060010190602001808311610dac57829003601f168201915b505050918352505060088201546001600160a01b0390811660208301526009830154166040820152600a8201546060820152600b8201546080820152600c8201805460a090920191610e1a90614df6565b80601f0160208091040260200160405190810160405280929190818152602001828054610e4690614df6565b8015610e915780601f10610e6857610100808354040283529160200191610e91565b820191905f5260205f20905b815481529060010190602001808311610e7457829003601f168201915b5050509183525050600d91909101546001600160a01b038082166020840152600160a01b90910460ff16151560409092019190915260a0820151919250839116610ef15760405163cd6f4a4f60e01b815260040161098891815260200190565b50919050565b5f610f0061394b565b805490915060ff600160401b82041615906001600160401b03165f81158015610f265750825b90505f826001600160401b03166001148015610f415750303b155b905081158015610f4f575080155b15610f6d5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610f9757845460ff60401b1916600160401b1785555b610fa033613975565b610fa98761266f565b610fb28b613735565b610fbb8a612939565b610fc48961092e565b610fcd88610a16565b610fd68661388e565b604080516101e08101825261c3508082526161a86020808401829052611388948401859052601460608501819052620249f0608086018190526207a12060a087018190526107d060c088018190525f60e089018190526103e86101008a015261012089018190526109c46101408a018190526101608a018b90526101808a01526101a089018190526101c090980197909752601895909555601993909355601a95909555601b94909455601c55601d55601e55601f80546001600160f01b031916690138827101388000007d60a31b179055805467ffffffffffffffff191690556110bf611688565b6001600160a01b03168c6001600160a01b0316146110e0576110e08c612c80565b831561112657845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050505050565b61113c61385c565b5f8181526009602052604090205481906001600160a01b0316611175576040516381c4951960e01b815260040161098891815260200190565b505f818152600960205260409081902080546001600160a01b0319169055517f104eb329a192aef26eddea07c2af5ad2587792e62b37ed4045b6ba59bc5540fc90610ab09083815260200190565b6111cb61385c565b6001600160a01b0381165f90815260076020526040902054819060ff16611206576040516321ac7c5f60e01b81526004016109889190614628565b506001600160a01b0381165f9081526007602052604090819020805460ff19169055517f56070b80bd617fcd2f7a284861edb488830a38f9dedcd77b2cb2f4eac17743e790610ab0908390614628565b600b6020525f90815260409020805461126e90614df6565b80601f016020809104026020016040519081016040528092919081815260200182805461129a90614df6565b80156112e55780601f106112bc576101008083540402835291602001916112e5565b820191905f5260205f20905b8154815290600101906020018083116112c857829003601f168201915b505050505081565b6112f561385c565b6112fe5f613986565b565b61130861385c565b6001600160a01b0381161580159061133957505f828152600a60205260409020546001600160a01b03828116911614155b829061135b576040516381c4951960e01b815260040161098891815260200190565b505f918252600a602052604090912080546001600160a01b0319166001600160a01b03909216919091179055565b5f546001600160a01b031633146113b35760405163b56831db60e01b815260040160405180910390fd5b5f818152600d602052604090205460ff1660018160068111156113d8576113d86146a1565b146113fd57816001826040516337e1404160e01b815260040161098893929190614e28565b5f828152600d60205260409020805460ff191660021790556015546114229042614e5d565b5f838152600e602052604080822092909255905183917fc44405af9078047712501f519e1fb900c2896c62b488336f84529c72ae16e6f191a2815f5160206159e75f395f51905f526001600260405161147c929190614e70565b60405180910390a25050565b5f546001600160a01b031633146114b25760405163b56831db60e01b815260040160405180910390fd5b5f828152600860209081526040808320600d9092529091205460ff1660028160068111156114e2576114e26146a1565b1461150757836002826040516337e1404160e01b815260040161098893929190614e28565b5f848152600d6020526040808220805460ff19166003179055600a84018590555185917f11df18edb9bc9cd90a79068e0e208b630202148643d797d6150e7bacb733e63c91a2835f5160206159e75f395f51905f526002600360405161156e929190614e70565b60405180910390a250505050565b61158461385c565b806115c05760405162461bcd60e51b815260206004820152600c60248201526b456d70747920706172616d7360a01b6044820152606401610988565b60ff83165f908152600b6020526040902080546115dc90614df6565b15905061162b5760405162461bcd60e51b815260206004820152601b60248201527f506172616d53657420616c7265616479207265676973746572656400000000006044820152606401610988565b60ff83165f908152600b60205260409020611647828483614efe565b507f6e4a4ea7f38fc775e616080b155744337e6216848e886a69c918b4ab84da219583838360405161167b93929190614fda565b60405180910390a1505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6116d760405180606001604052805f81526020015f81526020015f81525090565b5060408051606081018252601554815260165460208201526017549181019190915290565b5f818152600d602052604090205460ff166006816006811115611721576117216146a1565b14829061174457604051637cb2d48360e11b815260040161098891815260200190565b505f828152600c60205260409020548281611775576040516345ba89d560e11b815260040161098891815260200190565b505f838152600c6020526040812081905561178f846139f6565b5f858152601160205260409020546002549192506001600160a01b03908116916117bc9183911685613ae3565b60025460405163da19b69760e01b81526001600160a01b039091169063da19b697906117f2908890879087908790600401615042565b5f604051808303815f87803b158015611809575f5ffd5b505af115801561181b573d5f5f3e3d5ffd5b50505050847f5297818f48a66292b8b3e2caab83eec531b669bb20807fd38cf006adb2a0731784845160405161185b929190918252602082015260400190565b60405180910390a25050505050565b61188b60405180606001604052805f81526020015f81526020015f81525090565b505f908152600e6020908152604091829020825160608101845281548152600182015492810192909252600201549181019190915290565b5f818152600d6020526040812054819060ff166118e08482613b40565b9250925050915091565b5f5f6118f587610c7a565b5f888152600d602052604090205490915060ff16600381600681111561191d5761191d6146a1565b1488600383909192611945576040516337e1404160e01b815260040161098893929190614e28565b5050505f888152600e60209081526040918290208251606081018452815481526001820154928101839052600290910154928101929092528990428110156119a9576040516308f3034360e31b815260048101929092526024820152604401610988565b50506060830151602001518990428111156119e05760405163017e35e560e71b815260048101929092526024820152604401610988565b5050610160830151899015611a0b57604051637eb9cea960e11b815260040161098891815260200190565b505f8888604051611a1d92919061508d565b60408051918290039091205f8c815260086020908152838220600b01839055600d905291909120805460ff19166004179055601754909150611a5f9042614e5d565b5f8b8152600e6020526040908190206002019190915560a08501519051632f0e1bbf60e01b81526001600160a01b0390911690632f0e1bbf90611aac908d9085908c908c9060040161509c565b6020604051808303815f875af1158015611ac8573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611aec91906150c8565b9450888886611b1057604051632f9f8ab960e01b81526004016109889291906150e3565b5050897f7cc27e4a5626cbc4f8ba1a927b0448de55e6a114bc87660331270c5109ade0718a8a604051611b449291906150e3565b60405180910390a2895f5160206159e75f395f51905f5260036004604051611b6d929190614e70565b60405180910390a25050505095945050505050565b5f80600b81611b9760a08601608087016149a2565b60ff1660ff1681526020019081526020015f208054611bb590614df6565b905011611bd45760405162461bcd60e51b8152600401610988906150f6565b5f601281611be5602086018661512d565b6003811115611bf657611bf66146a1565b6003811115611c0757611c076146a1565b8152602081019190915260409081015f20815180830190925260028282826020028201915f905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411611c2e579050505050505090505f81600160028110611c8557611c85615079565b602002015163ffffffff1611835f016020810190611ca3919061512d565b90611cc25760405163286c068d60e11b81526004016109889190615146565b506020808201518251604080516101e081018252601854815260195481860152601a5491810191909152601b546060820152601c546080820152601d5460a0820152601e5460c0820152601f546001600160a01b03811660e0830152600160a01b810461ffff908116610100840152600160b01b82048116610120840152600160c01b82048116610140840152600160d01b82048116610160840152600160e01b90910416610180820152925463ffffffff8181166101a0860181905264010000000090920481166101c086015292831693919092169115611ded576101a081015163ffffffff16846001602002015163ffffffff161015865f016020810190611dcc919061512d565b90611deb5760405163010b971d60e31b81526004016109889190615146565b505b6101c081015163ffffffff1615611e3c576101c081015184519063ffffffff9081169082161015611e3a57604051630a4b6b6360e11b815263ffffffff9091166004820152602401610988565b505b60408601356020870135811015611e695760405163174b5a0760e21b815260040161098891815260200190565b506101808101516017545f9161271091611e879161ffff1690615154565b611e91919061516b565b61271061ffff1683610160015161ffff16601560010154611eb29190615154565b611ebc919061516b565b61271061ffff1684610140015161ffff1660155f0154611edc9190615154565b611ee6919061516b565b5f5460408051634f87c3a560e11b8152815160208e81013594938f0135936001600160a01b031692639f0f874a92600480830193928290030181865afa158015611f32573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f56919061518a565b611f609190614e5d565b611f6a91906151a1565b611f749190614e5d565b611f7e9190614e5d565b611f889190614e5d565b90505f611f966001866151a1565b611fa1906002615154565b611fac906002615154565b611fb7906006614e5d565b90505f85845f0151611fc99190615154565b905081868560200151611fdc9190615154565b611fe69190615154565b611ff09082614e5d565b905060018611156120385760026120086001886151a1565b6120129088615154565b85604001516120219190615154565b61202b919061516b565b6120359082614e5d565b90505b81868560c001516120499190615154565b6120539190615154565b61205d9082614e5d565b9050828685606001516120709190615154565b61207a9190615154565b6120849082614e5d565b90508484608001516120969190615154565b6120a09082614e5d565b905060018511156120e85760026120b86001876151a1565b6120c29087615154565b85604001516120d19190615154565b6120db919061516b565b6120e59082614e5d565b90505b60a08401516120f79082614e5d565b610100850151909150612710906121129061ffff1682614e5d565b61211c9083615154565b612126919061516b565b9750878061214a57604051638c4fcd9360e01b815260040161098891815260200190565b5050505050505050919050565b5f5f61216289610c7a565b5f8a8152600d602052604090205490915060ff16600481600681111561218a5761218a6146a1565b148a6004839091926121b2576040516337e1404160e01b815260040161098893929190614e28565b5050505f8a8152600e602090815260409182902082516060810184528154815260018201549281019290925260020154918101829052908b9042811015612215576040516308f3034360e31b815260048101929092526024820152604401610988565b50505f8b8152600860205260409020600c016122328a8c83614efe565b505f8b8152600d60205260409020805460ff191660051790556101c083015115612312578261010001516001600160a01b0316635bf48e3a8b8b60405161227a92919061508d565b6040519081900381206001600160e01b031960e084901b1682526122a8918c908c908c908c906004016151b4565b602060405180830381865afa1580156122c3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122e791906150c8565b935089898561230b57604051632f9f8ab960e01b81526004016109889291906150e3565b5050612317565b600193505b6123208b613cc8565b8a7f3a140076c461ebc41d74833ae0ee8bbc8079a135a63392098cd381e84350b69b8b8b8b8b60405161235694939291906151ec565b60405180910390a28a5f5160206159e75f395f51905f526004600560405161237f929190614e70565b60405180910390a2505050979650505050505050565b5f546001600160a01b03163314806123b757506003546001600160a01b031633145b6123d457604051639e75a8b560e01b815260040160405180910390fd5b5f8160ff161180156123ea5750600d60ff821611155b61242f5760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b2103330b4b63ab932903932b0b9b7b760511b6044820152606401610988565b61244d828260ff16600d811115612448576124486146a1565b614134565b5050565b61245961385c565b6001600160a01b0381166124af5760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420536c617368696e674d616e616765722061646472657373006044820152606401610988565b600380546001600160a01b0319166001600160a01b0383169081179091556040517f4ccc8ed483c7c44c3602c3c38afc2c014a8f1d2dc210dfe58ebeeeead230f8e0905f90a250565b6003546001600160a01b03163314612523576040516357d6948d60e11b815260040160405180910390fd5b60025460405163c1ab0f1f60e01b815260048101849052602481018390526001600160a01b039091169063c1ab0f1f906044015f604051808303815f87803b15801561256d575f5ffd5b505af115801561257f573d5f5f3e3d5ffd5b50505050817f4f41a3b0a032ebcae925f2ace77d507435840ca4b2dbaffdd7723fa8d72ee5428260405161147c91815260200190565b6125bd61385c565b6001600160a01b038116158015906125ee57505f828152600960205260409020546001600160a01b03828116911614155b8290612610576040516381c4951960e01b815260040161098891815260200190565b505f8281526009602090815260409182902080546001600160a01b0319166001600160a01b03851617905590518381527ff4041a3f914dac3bc9bf5f003ba41f28dbb84abe42f4e07c76266f5c8ceecb69910160405180910390a15050565b61267761385c565b60058190556040518181527fba0716ba1ee2ea8ecc4c64119b4537cdb42a99d82acf92af5b87607b8b52355290602001610ab0565b6126b461385c565b6127106126c961012083016101008401615237565b61ffff1611156126e161012083016101008401615237565b90612706576040516301027fc160e21b815261ffff9091166004820152602401610988565b5061271061271c61014083016101208401615237565b61ffff16111561273461014083016101208401615237565b90612759576040516301027fc160e21b815261ffff9091166004820152602401610988565b5061271061276f61016083016101408401615237565b61ffff16111561278761016083016101408401615237565b906127ac57604051633239953960e01b815261ffff9091166004820152602401610988565b506127106127c261018083016101608401615237565b61ffff1611156127da61018083016101608401615237565b906127ff57604051633239953960e01b815261ffff9091166004820152602401610988565b506127106128156101a083016101808401615237565b61ffff16111561282d6101a083016101808401615237565b9061285257604051633239953960e01b815261ffff9091166004820152602401610988565b5061286561014082016101208301615237565b61ffff16158061288e57505f612882610100830160e084016145e2565b6001600160a01b031614155b6128ab5760405163015f92ff60e51b815260040160405180910390fd5b6128bd6101e082016101c0830161526e565b63ffffffff166128d56101c083016101a0840161526e565b63ffffffff1610156128fa576040516392f55c6560e01b815260040160405180910390fd5b80601861290782826152ad565b9050507fbf3951313e980027eb48ce363fdb707286195ec6a0f802ac153927cf929c3fc681604051610ab0919061546b565b61294161385c565b6001600160a01b0381161580159061296757506001546001600160a01b03828116911614155b8190612987576040516320252f0b60e01b81526004016109889190614628565b50600180546001600160a01b0319166001600160a01b0383161790556040517fad4055f18cdad6f4bdd71afe3a72cbeee964217943e1bde38f138289e981a9a790610ab0908390614628565b6129db61385c565b6129e8602082018261526e565b63ffffffff166129fe604083016020840161526e565b63ffffffff1610158015612a2357505f612a1b602083018361526e565b63ffffffff16115b612a4057604051634564ab9b60e01b815260040160405180910390fd5b604080516101e0810182526018548152601954602080830191909152601a5492820192909252601b546060820152601c546080820152601d5460a0820152601e5460c0820152601f546001600160a01b03811660e083015261ffff600160a01b82048116610100840152600160b01b82048116610120840152600160c01b82048116610140840152600160d01b82048116610160840152600160e01b90910416610180820152905463ffffffff8082166101a08401819052640100000000909204166101c083015215612b79576101a081015163ffffffff16612b29604084016020850161526e565b63ffffffff161015612b41604084016020850161526e565b826101a001519091612b7657604051633ccc4c2160e21b815263ffffffff928316600482015291166024820152604401610988565b50505b6101c081015163ffffffff1615612bf0576101c081015163ffffffff16612ba3602084018461526e565b63ffffffff161015612bb8602084018461526e565b826101c001519091612bed5760405163156c4e5b60e11b815263ffffffff928316600482015291166024820152604401610988565b50505b8160125f856003811115612c0657612c066146a1565b6003811115612c1757612c176146a1565b815260208101919091526040015f20612c319160026144cd565b50826003811115612c4457612c446146a1565b7f8b56fae526eee054f0849759a99fc7d4ff3823824ebf097a56f7d78adb6b34fa83604051612c739190615575565b60405180910390a2505050565b612c8861385c565b6001600160a01b038116612cb1575f604051631e4fbdf760e01b81526004016109889190614628565b610acc81613986565b5f612cc3614450565b5f601281612cd4602087018761512d565b6003811115612ce557612ce56146a1565b6003811115612cf657612cf66146a1565b8152602081019190915260409081015f20815180830190925260028282826020028201915f905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411612d1d579050505050505090505f81600160028110612d7457612d74615079565b602002015163ffffffff1611845f016020810190612d92919061512d565b90612db15760405163286c068d60e11b81526004016109889190615146565b50602084013542811015612ddb57604051630b99e87960e01b815260040161098891815260200190565b5060408401356020850135811015612e095760405163174b5a0760e21b815260040161098891815260200190565b506017546016545f9190612e214260408901356151a1565b612e2b9190614e5d565b612e359190614e5d565b905060055481108190612e5e576040516313b783af60e21b815260040161098891815260200190565b5060075f612e7260808801606089016145e2565b6001600160a01b0316815260208101919091526040015f205460ff16612e9e60808701606088016145e2565b90612ebd5760405163295a6a6f60e11b81526004016109889190614628565b505f612ec886611b82565b60068054965090915085905f612edd836155b5565b9091555050604080514460208201529081018690525f9060600160408051601f1981840301815291815281516020928301205f898152600c84528281208690556004546011855283822080546001600160a01b03199081166001600160a01b0393841617909155601f805460138852868520805461ffff191661ffff600160b01b909304929092169190911790555460148752858420805483169190931617909155600d8552838220805460ff191660011790556010909452829020805433941693909317909255601654919250612fb89190890135614e5d565b5f878152600e6020908152604090912060010191909155818652612fde9088018861512d565b85602001906003811115612ff457612ff46146a1565b90816003811115613007576130076146a1565b905250436040808701919091528051808201825290602089019060029083908390808284375f92019190915250505060608087019190915261304f90608089019089016145e2565b6001600160a01b031660a080870191909152613070908801608089016149a2565b60ff1660c080870191909152613088908801886155cd565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050505060e0808701919091526130d590610100890190890161560f565b15156101c08601525f610140860181905261016086018190526040805160208101909152908152610180860152336101a08601819052600454613125916001600160a01b0390911690308561428f565b5f600b8161313960a08b0160808c016149a2565b60ff1660ff1681526020019081526020015f20805461315790614df6565b80601f016020809104026020016040519081016040528092919081815260200182805461318390614df6565b80156131ce5780601f106131a5576101008083540402835291602001916131ce565b820191905f5260205f20905b8154815290600101906020018083116131b157829003601f168201915b505050505090505f8151116131f55760405162461bcd60e51b8152600401610988906150f6565b5f61320660808a0160608b016145e2565b6001600160a01b031663fefd9a8b89858561322460a08f018f6155cd565b8f8060c0019061323491906155cd565b6040518863ffffffff1660e01b8152600401613256979695949392919061562a565b6020604051808303815f875af1158015613272573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613296919061518a565b5f818152600960205260409020549091506001600160a01b031681816132d2576040516381c4951960e01b815260040161098891815260200190565b505f828152600a60205260409020546001600160a01b0316828161330c576040516381c4951960e01b815260040161098891815260200190565b50608089018390526001600160a01b038083166101008b015281166101208a01525f8a81526008602090815260409091208a518155908a0151600180830180548d94939260ff19919091169083600381111561336a5761336a6146a1565b02179055506040820151816002015560608201518160030190600261339092919061456e565b506080820151600582015560a082015160068201805460c085015160ff16600160a01b026001600160a81b03199091166001600160a01b039093169290921791909117905560e082015160078201906133e9908261567e565b506101008201516008820180546001600160a01b039283166001600160a01b031991821617909155610120840151600984018054919093169116179055610140820151600a820155610160820151600b820155610180820151600c820190613451908261567e565b506101a0820151600d90910180546101c0909301511515600160a01b026001600160a81b03199093166001600160a01b0392831617929092179091555f5460405163291a691b60e01b815291169063291a691b906134b7908d9089908d90600401615733565b6020604051808303815f875af11580156134d3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906134f791906150c8565b61351457604051630d8dbe2560e01b815260040160405180910390fd5b61352460808c0160608d016145e2565b6001600160a01b03167f5090c9764b5cd13df7afc0013f733dfbe6eaf1b6ddc22a5e291fa387efd4c15e8b8b60405161355e929190614dd6565b60405180910390a2895f5160206159e75f395f51905f525f6001604051613586929190614e70565b60405180910390a25050505050505050915091565b5f818152600d602052604081205460ff16818160068111156135bf576135bf6146a1565b036135e457826001826040516337e1404160e01b815260040161098893929190614e28565b60058160068111156135f8576135f86146a1565b036136195760405163462c7bed60e01b815260048101849052602401610988565b600681600681111561362d5761362d6146a1565b0361364e57604051633de16e3560e11b815260048101849052602401610988565b5f6136598483613b40565b935090508061367e57604051639f65d93560e01b815260048101859052602401610988565b5f848152600d6020526040902080546006919060ff191660018302179055505f848152600f60205260409020805484919060ff1916600183600d8111156136c7576136c76146a1565b0217905550835f5160206159e75f395f51905f528360066040516136ec929190614e70565b60405180910390a2837fe20209be7caae6e76291267cfa711353981274bf127e94f16eb9ec44b68582bb8385604051613726929190615778565b60405180910390a25050919050565b61373d61385c565b6001600160a01b0381161580159061376257505f546001600160a01b03828116911614155b8190613782576040516375ac4eb760e11b81526004016109889190614628565b505f80546001600160a01b0319166001600160a01b0383161790556040517f80052b810d39120cf6c976cca504a21703f585521dc7a41c6d241090e6c579b690610ab0908390614628565b6001600160a01b0381165f90815260076020526040902054819060ff16156138095760405163b29d459560e01b81526004016109889190614628565b506001600160a01b0381165f9081526007602052604090819020805460ff19166001179055517fb8d368517268f297fff00825d67d098763117d061360d31027be5b2e1a59d46790610ab0908390614628565b33613865611688565b6001600160a01b0316146112fe573360405163118cdaa760e01b81526004016109889190614628565b80356138ad5760405163055f269d60e01b815260040160405180910390fd5b5f8160200135116138d15760405163055f269d60e01b815260040160405180910390fd5b5f8160400135116138f55760405163055f269d60e01b815260040160405180910390fd5b80356015819055602080830135601681905560408085013560178190558151948552928401919091528201527f7e86ba16b805e2835af5c5b7aa5a942ced8bcc1fb95a05fbe42dae3862350a1690606001610ab0565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005b92915050565b61397d6142ce565b610acc816142f3565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f818152600f602052604090205460609060ff16600181600d811115613a1e57613a1e6146a1565b1480613a3b5750600281600d811115613a3957613a396146a1565b145b15613a73575f5b604051908082528060200260200182016040528015613a6b578160200160208202803683370190505b509392505050565b5f5460405162beb08960e51b8152600481018590526001600160a01b03909116906317d61120906024015f60405180830381865afa925050508015613ad957506040513d5f823e601f3d908101601f19168201604052613ad6919081019061584f565b60015b613a6b575f613a42565b613b3b83846001600160a01b031663a9059cbb8585604051602401613b09929190615914565b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506142fb565b505050565b5f828152600e60209081526040808320815160608101835281548152600182015493810193909352600201548282015282549051632800d82960e01b81526004810186905283929183916001600160a01b0390911690632800d82990602401602060405180830381865afa158015613bba573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613bde919061518a565b90506001856006811115613bf457613bf46146a1565b148015613c0057508042115b15613c1357600180935093505050613cc1565b6002856006811115613c2757613c276146a1565b148015613c345750815142115b15613c485760016003935093505050613cc1565b6003856006811115613c5c57613c5c6146a1565b148015613c6c5750816020015142115b15613c805760016006935093505050613cc1565b6004856006811115613c9457613c946146a1565b148015613ca45750816040015142115b15613cb8576001600a935093505050613cc1565b5f5f9350935050505b9250929050565b5f805460405162beb08960e51b8152600481018490526001600160a01b03909116906317d61120906024015f60405180830381865afa158015613d0d573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052613d34919081019061584f565b5080515f848152600c60209081526040808320805490849055601190925282205493945091926001600160a01b031690829003613dd3576002546040516341489f1560e01b81526001600160a01b03909116906341489f1590613d9f9088908890869060040161592d565b5f604051808303815f87803b158015613db6575f5ffd5b505af1158015613dc8573d5f5f3e3d5ffd5b505050505050505050565b825f03613e74575f858152601060205260409020546001600160a01b03168015613e0b57613e0b6001600160a01b0383168285613ae3565b6002546040516341489f1560e01b81526001600160a01b03909116906341489f1590613e3f9089908990879060040161592d565b5f604051808303815f87803b158015613e56575f5ffd5b505af1158015613e68573d5f5f3e3d5ffd5b50505050505050505050565b5f85815260136020908152604080832054601490925282205461ffff909116906001600160a01b03168115801590613eb457506001600160a01b03811615155b15613ef057612710613eca61ffff841687615154565b613ed4919061516b565b92508215613ef057613ef06001600160a01b0385168285613ae3565b5f613efb84876151a1565b90505f876001600160401b03811115613f1657613f16614e8b565b604051908082528060200260200182016040528015613f3f578160200160208202803683370190505b5090505f613f4d898461516b565b90505f805b8a811015613f8c5782848281518110613f6d57613f6d615079565b6020908102919091010152613f828383614e5d565b9150600101613f52565b505f613f9882866151a1565b90508015613fd5578084613fad60018e6151a1565b81518110613fbd57613fbd615079565b60200260200101818151613fd19190614e5d565b9052505b600154613fef906001600160a01b038b811691168761435e565b60015f9054906101000a90046001600160a01b03166001600160a01b031663dd8c818e8a8e876040518463ffffffff1660e01b81526004016140339392919061598d565b5f604051808303815f87803b15801561404a575f5ffd5b505af115801561405c573d5f5f3e3d5ffd5b505060015461407a92506001600160a01b038c81169250165f61435e565b8c7fac9fe8ad7f55eac03284399116ecafc104f10459773f4cdf47063c46e5be335a8d866040516140ac9291906159c2565b60405180910390a260025f9054906101000a90046001600160a01b03166001600160a01b03166341489f158e8e8c6040518463ffffffff1660e01b81526004016140f89392919061592d565b5f604051808303815f87803b15801561410f575f5ffd5b505af1158015614121573d5f5f3e3d5ffd5b5050505050505050505050505050505050565b5f828152600d602052604081205460ff1690816006811115614158576141586146a1565b0361417d57826001826040516337e1404160e01b815260040161098893929190614e28565b6005816006811115614191576141916146a1565b036141b25760405163462c7bed60e01b815260048101849052602401610988565b60068160068111156141c6576141c66146a1565b036141e757604051633de16e3560e11b815260048101849052602401610988565b5f838152600d6020526040902080546006919060ff191660018302179055505f838152600f60205260409020805483919060ff1916600183600d811115614230576142306146a1565b0217905550825f5160206159e75f395f51905f52826006604051614255929190614e70565b60405180910390a2827fe20209be7caae6e76291267cfa711353981274bf127e94f16eb9ec44b68582bb8284604051612c73929190615778565b6040516001600160a01b0384811660248301528381166044830152606482018390526142c89186918216906323b872dd90608401613b09565b50505050565b6142d66143ee565b6112fe57604051631afcd79f60e31b815260040160405180910390fd5b612c886142ce565b5f5f60205f8451602086015f885af18061431a576040513d5f823e3d81fd5b50505f513d9150811561433157806001141561433e565b6001600160a01b0384163b155b156142c85783604051635274afe760e01b81526004016109889190614628565b5f836001600160a01b031663095ea7b38484604051602401614381929190615914565b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505090506143ba8482614407565b6142c8576143e484856001600160a01b031663095ea7b3865f604051602401613b09929190615914565b6142c884826142fb565b5f6143f761394b565b54600160401b900460ff16919050565b5f5f5f5f60205f8651602088015f8a5af192503d91505f519050828015614446575081156144385780600114614446565b5f866001600160a01b03163b115b9695505050505050565b604080516101e081019091525f808252602082019081526020015f815260200161447861459c565b81525f602082018190526040820181905260608083018290526080830181905260a0830182905260c0830182905260e08301829052610100830182905261012083015261014082018190526101609091015290565b60018301918390821561455e579160200282015f5b8382111561452c57833563ffffffff1683826101000a81548163ffffffff021916908363ffffffff16021790555092602001926004016020816003010492830192600103026144e2565b801561455c5782816101000a81549063ffffffff021916905560040160208160030104928301926001030261452c565b505b5061456a9291506145ba565b5090565b826002810192821561455e579160200282015b8281111561455e578251825591602001919060010190614581565b60405180604001604052806002906020820280368337509192915050565b5b8082111561456a575f81556001016145bb565b6001600160a01b0381168114610acc575f5ffd5b5f602082840312156145f2575f5ffd5b81356145fd816145ce565b9392505050565b5f60208284031215614614575f5ffd5b5035919050565b6001600160a01b03169052565b6001600160a01b0391909116815260200190565b80356004811061464a575f5ffd5b919050565b5f5f60408385031215614660575f5ffd5b6146698361463c565b946020939093013593505050565b5f60608284031215610ef1575f5ffd5b5f60608284031215614697575f5ffd5b6145fd8383614677565b634e487b7160e01b5f52602160045260245ffd5b600e81106146c5576146c56146a1565b9052565b6020810161396f82846146b5565b600481106146c5576146c56146a1565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b8e8152614725602082018f6146d7565b8c60408201528b606082015261473e608082018c61461b565b60ff8a1660a08201526101c060c08201525f61475e6101c083018b6146e7565b61476b60e084018b61461b565b61477961010084018a61461b565b876101208401528661014084015282810361016084015261479a81876146e7565b9150506147ab61018083018561461b565b8215156101a08301529f9e505050505050505050505050505050565b805f5b60028110156142c85781518452602093840193909101906001016147ca565b805182525f602082015161480060208501826146d7565b5060408201516040840152606082015161481d60608501826147c7565b50608082015160a084015260a082015161483a60c085018261461b565b5060c082015160ff811660e08501525060e08201516102006101008501526148666102008501826146e7565b905061010083015161487c61012086018261461b565b5061012083015161489161014086018261461b565b506101408301516101608501526101608301516101808501526101808301518482036101a08601526148c382826146e7565b9150506101a08301516148da6101c086018261461b565b506101c08301518015156101e0860152613a6b565b602081525f6145fd60208301846147e9565b803561464a816145ce565b5f5f5f5f5f5f5f610120888a031215614923575f5ffd5b873561492e816145ce565b9650602088013561493e816145ce565b9550604088013561494e816145ce565b9450606088013561495e816145ce565b9350608088013561496e816145ce565b925060a088013591506149848960c08a01614677565b905092959891949750929550565b803560ff8116811461464a575f5ffd5b5f602082840312156149b2575f5ffd5b6145fd82614992565b602081525f6145fd60208301846146e7565b5f5f604083850312156149de575f5ffd5b8235915060208301356149f0816145ce565b809150509250929050565b5f5f60408385031215614a0c575f5ffd5b50508035926020909101359150565b5f5f83601f840112614a2b575f5ffd5b5081356001600160401b03811115614a41575f5ffd5b602083019150836020828501011115613cc1575f5ffd5b5f5f5f60408486031215614a6a575f5ffd5b614a7384614992565b925060208401356001600160401b03811115614a8d575f5ffd5b614a9986828701614a1b565b9497909650939450505050565b8151815260208083015190820152604080830151908201526060810161396f565b8215158152604081016145fd60208301846146b5565b5f5f5f5f5f60608688031215614af1575f5ffd5b8535945060208601356001600160401b03811115614b0d575f5ffd5b614b1988828901614a1b565b90955093505060408601356001600160401b03811115614b37575f5ffd5b614b4388828901614a1b565b969995985093965092949392505050565b5f60208284031215614b64575f5ffd5b81356001600160401b03811115614b79575f5ffd5b820161010081850312156145fd575f5ffd5b5f6101e082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e0830151614be560e084018261461b565b50610100830151614bfd61010084018261ffff169052565b50610120830151614c1561012084018261ffff169052565b50610140830151614c2d61014084018261ffff169052565b50610160830151614c4561016084018261ffff169052565b50610180830151614c5d61018084018261ffff169052565b506101a0830151614c776101a084018263ffffffff169052565b506101c0830151614c916101c084018263ffffffff169052565b5092915050565b5f5f5f5f5f5f5f6080888a031215614cae575f5ffd5b8735965060208801356001600160401b03811115614cca575f5ffd5b614cd68a828b01614a1b565b90975095505060408801356001600160401b03811115614cf4575f5ffd5b614d008a828b01614a1b565b90955093505060608801356001600160401b03811115614d1e575f5ffd5b614d2a8a828b01614a1b565b989b979a50959850939692959293505050565b5f5f60408385031215614d4e575f5ffd5b82359150614d5e60208401614992565b90509250929050565b600781106146c5576146c56146a1565b6020810161396f8284614d67565b5f6101e0828403128015614d97575f5ffd5b509092915050565b5f5f60608385031215614db0575f5ffd5b614db98361463c565b915083606084011115614dca575f5ffd5b50926020919091019150565b828152604060208201525f614dee60408301846147e9565b949350505050565b600181811c90821680614e0a57607f821691505b602082108103610ef157634e487b7160e01b5f52602260045260245ffd5b83815260608101614e3c6020830185614d67565b614dee6040830184614d67565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561396f5761396f614e49565b60408101614e7e8285614d67565b6145fd6020830184614d67565b634e487b7160e01b5f52604160045260245ffd5b601f821115613b3b57805f5260205f20601f840160051c81016020851015614ec45750805b601f840160051c820191505b81811015614ee3575f8155600101614ed0565b5050505050565b5f19600383901b1c191660019190911b1790565b6001600160401b03831115614f1557614f15614e8b565b614f2983614f238354614df6565b83614e9f565b5f601f841160018114614f55575f8515614f435750838201355b614f4d8682614eea565b845550614ee3565b5f83815260208120601f198716915b82811015614f845786850135825560209485019460019092019101614f64565b5086821015614fa0575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60ff84168152604060208201525f614ff6604083018486614fb2565b95945050505050565b5f8151808452602084019350602083015f5b828110156150385781516001600160a01b0316865260209586019590910190600101615011565b5093949350505050565b848152836020820152608060408201525f6150606080830185614fff565b905060018060a01b038316606083015295945050505050565b634e487b7160e01b5f52603260045260245ffd5b818382375f9101908152919050565b848152836020820152606060408201525f614446606083018486614fb2565b8015158114610acc575f5ffd5b5f602082840312156150d8575f5ffd5b81516145fd816150bb565b602081525f614dee602083018486614fb2565b6020808252601c908201527f42465620706172616d20736574206e6f74207265676973746572656400000000604082015260600190565b5f6020828403121561513d575f5ffd5b6145fd8261463c565b6020810161396f82846146d7565b808202811582820484141761396f5761396f614e49565b5f8261518557634e487b7160e01b5f52601260045260245ffd5b500490565b5f6020828403121561519a575f5ffd5b5051919050565b8181038181111561396f5761396f614e49565b858152606060208201525f6151cd606083018688614fb2565b82810360408401526151e0818587614fb2565b98975050505050505050565b604081525f6151ff604083018688614fb2565b8281036020840152615212818587614fb2565b979650505050505050565b61ffff81168114610acc575f5ffd5b803561464a8161521d565b5f60208284031215615247575f5ffd5b81356145fd8161521d565b63ffffffff81168114610acc575f5ffd5b803561464a81615252565b5f6020828403121561527e575f5ffd5b81356145fd81615252565b5f813561396f816145ce565b5f813561396f8161521d565b5f813561396f81615252565b813581556020820135600182015560408201356002820155606082013560038201556080820135600482015560a0820135600582015560c082013560068201556007810161531d61530060e08501615289565b82546001600160a01b0319166001600160a01b0391909116178255565b61534d61532d6101008501615295565b82805461ffff60a01b191660a09290921b61ffff60a01b16919091179055565b61537d61535d6101208501615295565b82805461ffff60b01b191660b09290921b61ffff60b01b16919091179055565b6153ad61538d6101408501615295565b82805461ffff60c01b191660c09290921b61ffff60c01b16919091179055565b6153dd6153bd6101608501615295565b82805461ffff60d01b191660d09290921b61ffff60d01b16919091179055565b61540d6153ed6101808501615295565b82805461ffff60e01b191660e09290921b61ffff60e01b16919091179055565b50600881016154396154226101a085016152a1565b825463ffffffff191663ffffffff91909116178255565b613b3b6154496101c085016152a1565b825467ffffffff00000000191660209190911b67ffffffff0000000016178255565b813581526020808301359082015260408083013590820152606080830135908201526080808301359082015260a0808301359082015260c080830135908201526101e081016154bc60e08401614901565b6154c960e084018261461b565b506154d7610100840161522c565b61ffff166101008301526154ee610120840161522c565b61ffff16610120830152615505610140840161522c565b61ffff1661014083015261551c610160840161522c565b61ffff16610160830152615533610180840161522c565b61ffff1661018083015261554a6101a08401615263565b63ffffffff166101a08301526155636101c08401615263565b63ffffffff81166101c0840152614c91565b6040810181835f5b60028110156155ac57813561559181615252565b63ffffffff168352602092830192919091019060010161557d565b50505092915050565b5f600182016155c6576155c6614e49565b5060010190565b5f5f8335601e198436030181126155e2575f5ffd5b8301803591506001600160401b038211156155fb575f5ffd5b602001915036819003821315613cc1575f5ffd5b5f6020828403121561561f575f5ffd5b81356145fd816150bb565b87815286602082015260a060408201525f61564860a08301886146e7565b828103606084015261565b818789614fb2565b90508281036080840152615670818587614fb2565b9a9950505050505050505050565b81516001600160401b0381111561569757615697614e8b565b6156ab816156a58454614df6565b84614e9f565b6020601f8211600181146156d8575f83156156c65750848201515b6156d08482614eea565b855550614ee3565b5f84815260208120601f198516915b8281101561570757878501518255602094850194600190920191016156e7565b508482101561572457868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b838152602081018390526080810160408201835f5b600281101561576d57815163ffffffff16835260209283019290910190600101615748565b505050949350505050565b604081016157868285614d67565b6145fd60208301846146b5565b604051601f8201601f191681016001600160401b03811182821017156157bb576157bb614e8b565b604052919050565b5f6001600160401b038211156157db576157db614e8b565b5060051b60200190565b5f82601f8301126157f4575f5ffd5b8151615807615802826157c3565b615793565b8082825260208201915060208360051b860101925085831115615828575f5ffd5b602085015b8381101561584557805183526020928301920161582d565b5095945050505050565b5f5f60408385031215615860575f5ffd5b82516001600160401b03811115615875575f5ffd5b8301601f81018513615885575f5ffd5b8051615893615802826157c3565b8082825260208201915060208360051b8501019250878311156158b4575f5ffd5b6020840193505b828410156158df5783516158ce816145ce565b8252602093840193909101906158bb565b8095505050505060208301516001600160401b038111156158fe575f5ffd5b61590a858286016157e5565b9150509250929050565b6001600160a01b03929092168252602082015260400190565b838152606060208201525f6159456060830185614fff565b905060018060a01b0383166040830152949350505050565b5f8151808452602084019350602083015f5b8281101561503857815186526020958601959091019060010161596f565b6001600160a01b03841681526060602082018190525f906159b090830185614fff565b8281036040840152614446818561595d565b604081525f6159d46040830185614fff565b8281036020840152614ff6818561595d56fe1b418a230a21d37a078bf8f16decbde8ccceacd77159371f62f0d4ea00d19967a164736f6c634300081c000a", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b50600436106102ce575f3560e01c80639117173c11610182578063cb649617116100e0578063f0691cba1161008f578063f0691cba14610886578063f2fde38b14610899578063f3ceba3a146108ac578063f81b8ef6146108cd578063fad8e111146108e0578063fbdb3237146108f3578063fd2f3d011461091b575f5ffd5b8063cb649617146107ef578063cbd16872146107f8578063cf0f34c41461080b578063cfbdc98d1461081e578063d8afed3e1461084d578063e59e469514610860578063ea71aa5714610873575f5ffd5b8063a87f4ab91161013c578063a87f4ab914610607578063ac3d2f4214610759578063b27392d514610781578063bb2d1b8214610794578063bff232c1146107a7578063c1ab0f1f146107ba578063c4ccafa2146107cd575f5ffd5b80639117173c146105625780639231238614610575578063929a8faf1461058857806399c6679d146105a95780639c8570c8146105d15780639e57b934146105f4575f5ffd5b80635d1684181161022f57806381476ec2116101e957806381476ec2146104e7578063830d7181146104fa578063858142431461050d5780638da5cb5b146105205780638dcdd86b146105285780638e5ce3ad1461053a57806390173a411461054d575f5ffd5b80635d1684181461047d578063647846a51461049d5780636db5c8fd146104b0578063715018a6146104b95780637c8c3b4d146104c15780637cfa9d74146104d4575f5ffd5b806336c5d38a1161028b57806336c5d38a1461039b5780634017daf0146103ca578063406ed35c146103f75780634147a360146104175780634d600e5d146104445780634e92ec63146104575780634fc772641461046a575f5ffd5b806302a3a9c9146102d25780630ef81b2f146102e757806310bc62811461032557806311bd61d91461034d57806315cce224146103755780631ba7294514610388575b5f5ffd5b6102e56102e03660046145e2565b61092e565b005b61030f6102f5366004614604565b5f908152600960205260409020546001600160a01b031690565b60405161031c9190614628565b60405180910390f35b61030f610333366004614604565b60096020525f90815260409020546001600160a01b031681565b61036061035b36600461464f565b6109da565b60405163ffffffff909116815260200161031c565b6102e56103833660046145e2565b610a16565b6102e5610396366004614687565b610abb565b6103bd6103a9366004614604565b5f908152600f602052604090205460ff1690565b60405161031c91906146c9565b6103dd6103d8366004614604565b610acf565b60405161031c9e9d9c9b9a99989796959493929190614715565b61040a610405366004614604565b610c7a565b60405161031c91906148ef565b610436610425366004614604565b600c6020525f908152604090205481565b60405190815260200161031c565b6102e561045236600461490c565b610ef7565b6102e5610465366004614604565b611134565b6102e56104783660046145e2565b6111c3565b61049061048b3660046149a2565b611256565b60405161031c91906149bb565b60045461030f906001600160a01b031681565b61043660055481565b6102e56112ed565b6102e56104cf3660046149cd565b611300565b6102e56104e2366004614604565b611389565b6102e56104f53660046149fb565b611488565b6102e5610508366004614a58565b61157c565b60015461030f906001600160a01b031681565b61030f611688565b5f5461030f906001600160a01b031681565b60035461030f906001600160a01b031681565b6105556116b6565b60405161031c9190614aa6565b6102e5610570366004614604565b6116fc565b610555610583366004614604565b61186a565b61059b610596366004614604565b6118c3565b60405161031c929190614ac7565b61030f6105b7366004614604565b5f908152601060205260409020546001600160a01b031690565b6105e46105df366004614add565b6118ea565b604051901515815260200161031c565b610436610602366004614b54565b611b82565b61074c604080516101e0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081019190915250604080516101e0810182526018548152601954602080830191909152601a5492820192909252601b546060820152601c546080820152601d5460a0820152601e5460c0820152601f546001600160a01b03811660e083015261ffff600160a01b82048116610100840152600160b01b82048116610120840152600160c01b82048116610140840152600160d01b82048116610160840152600160e01b90910416610180820152905463ffffffff8082166101a0840152640100000000909104166101c082015290565b60405161031c9190614b8b565b61030f610767366004614604565b5f908152600a60205260409020546001600160a01b031690565b6105e461078f366004614c98565b612157565b6102e56107a2366004614d3d565b612395565b6102e56107b53660046145e2565b612451565b6102e56107c83660046149fb565b6124f8565b6105e46107db3660046145e2565b60076020525f908152604090205460ff1681565b61043660065481565b6102e56108063660046149cd565b6125b5565b6102e5610819366004614604565b61266f565b61084061082c366004614604565b5f908152600d602052604090205460ff1690565b60405161031c9190614d77565b6102e561085b366004614d85565b6126ac565b6102e561086e3660046145e2565b612939565b6102e5610881366004614d9f565b6129d3565b60025461030f906001600160a01b031681565b6102e56108a73660046145e2565b612c80565b6108bf6108ba366004614b54565b612cba565b60405161031c929190614dd6565b6103bd6108db366004614604565b61359b565b6102e56108ee3660046145e2565b613735565b61030f610901366004614604565b600a6020525f90815260409020546001600160a01b031681565b6102e56109293660046145e2565b6137cd565b61093661385c565b6001600160a01b0381166109915760405162461bcd60e51b815260206004820152601f60248201527f496e76616c6964204533526566756e644d616e6167657220616464726573730060448201526064015b60405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040517f9557d04c1c0b16f93f13b69aed23b3b6ab935bff3c53ac81d17896d3583542ed905f90a250565b6012602052815f5260405f2081600281106109f3575f80fd5b60089182820401919006600402915091509054906101000a900463ffffffff1681565b610a1e61385c565b6001600160a01b03811615801590610a4457506004546001600160a01b03828116911614155b8190610a645760405163eddf07f560e01b81526004016109889190614628565b50600480546001600160a01b0319166001600160a01b0383161790556040517f722ff84c1234b2482061def5c82c6b5080c117b3cbb69d686844a051e4b8e7f390610ab0908390614628565b60405180910390a150565b610ac361385c565b610acc8161388e565b50565b60086020525f9081526040902080546001820154600283015460058401546006850154600786018054959660ff95861696949593946001600160a01b03841694600160a01b90940490931692909190610b2790614df6565b80601f0160208091040260200160405190810160405280929190818152602001828054610b5390614df6565b8015610b9e5780601f10610b7557610100808354040283529160200191610b9e565b820191905f5260205f20905b815481529060010190602001808311610b8157829003601f168201915b50505060088401546009850154600a860154600b870154600c8801805497986001600160a01b03958616989490951696509194509291610bdd90614df6565b80601f0160208091040260200160405190810160405280929190818152602001828054610c0990614df6565b8015610c545780601f10610c2b57610100808354040283529160200191610c54565b820191905f5260205f20905b815481529060010190602001808311610c3757829003601f168201915b505050600d90930154919250506001600160a01b0381169060ff600160a01b909104168e565b610c82614450565b5f8281526008602090815260409182902082516101e08101909352805483526001810154909183019060ff166003811115610cbf57610cbf6146a1565b6003811115610cd057610cd06146a1565b8152600282810154602083015260408051808201808352919093019291600385019182845b815481526020019060010190808311610cf55750505091835250506005820154602082015260068201546001600160a01b0381166040830152600160a01b900460ff166060820152600782018054608090920191610d5290614df6565b80601f0160208091040260200160405190810160405280929190818152602001828054610d7e90614df6565b8015610dc95780601f10610da057610100808354040283529160200191610dc9565b820191905f5260205f20905b815481529060010190602001808311610dac57829003601f168201915b505050918352505060088201546001600160a01b0390811660208301526009830154166040820152600a8201546060820152600b8201546080820152600c8201805460a090920191610e1a90614df6565b80601f0160208091040260200160405190810160405280929190818152602001828054610e4690614df6565b8015610e915780601f10610e6857610100808354040283529160200191610e91565b820191905f5260205f20905b815481529060010190602001808311610e7457829003601f168201915b5050509183525050600d91909101546001600160a01b038082166020840152600160a01b90910460ff16151560409092019190915260a0820151919250839116610ef15760405163cd6f4a4f60e01b815260040161098891815260200190565b50919050565b5f610f0061394b565b805490915060ff600160401b82041615906001600160401b03165f81158015610f265750825b90505f826001600160401b03166001148015610f415750303b155b905081158015610f4f575080155b15610f6d5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610f9757845460ff60401b1916600160401b1785555b610fa033613975565b610fa98761266f565b610fb28b613735565b610fbb8a612939565b610fc48961092e565b610fcd88610a16565b610fd68661388e565b604080516101e08101825261c3508082526161a86020808401829052611388948401859052601460608501819052620249f0608086018190526207a12060a087018190526107d060c088018190525f60e089018190526103e86101008a015261012089018190526109c46101408a018190526101608a018b90526101808a01526101a089018190526101c090980197909752601895909555601993909355601a95909555601b94909455601c55601d55601e55601f80546001600160f01b031916690138827101388000007d60a31b179055805467ffffffffffffffff191690556110bf611688565b6001600160a01b03168c6001600160a01b0316146110e0576110e08c612c80565b831561112657845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050505050565b61113c61385c565b5f8181526009602052604090205481906001600160a01b0316611175576040516381c4951960e01b815260040161098891815260200190565b505f818152600960205260409081902080546001600160a01b0319169055517f104eb329a192aef26eddea07c2af5ad2587792e62b37ed4045b6ba59bc5540fc90610ab09083815260200190565b6111cb61385c565b6001600160a01b0381165f90815260076020526040902054819060ff16611206576040516321ac7c5f60e01b81526004016109889190614628565b506001600160a01b0381165f9081526007602052604090819020805460ff19169055517f56070b80bd617fcd2f7a284861edb488830a38f9dedcd77b2cb2f4eac17743e790610ab0908390614628565b600b6020525f90815260409020805461126e90614df6565b80601f016020809104026020016040519081016040528092919081815260200182805461129a90614df6565b80156112e55780601f106112bc576101008083540402835291602001916112e5565b820191905f5260205f20905b8154815290600101906020018083116112c857829003601f168201915b505050505081565b6112f561385c565b6112fe5f613986565b565b61130861385c565b6001600160a01b0381161580159061133957505f828152600a60205260409020546001600160a01b03828116911614155b829061135b576040516381c4951960e01b815260040161098891815260200190565b505f918252600a602052604090912080546001600160a01b0319166001600160a01b03909216919091179055565b5f546001600160a01b031633146113b35760405163b56831db60e01b815260040160405180910390fd5b5f818152600d602052604090205460ff1660018160068111156113d8576113d86146a1565b146113fd57816001826040516337e1404160e01b815260040161098893929190614e28565b5f828152600d60205260409020805460ff191660021790556015546114229042614e5d565b5f838152600e602052604080822092909255905183917fc44405af9078047712501f519e1fb900c2896c62b488336f84529c72ae16e6f191a2815f5160206159e75f395f51905f526001600260405161147c929190614e70565b60405180910390a25050565b5f546001600160a01b031633146114b25760405163b56831db60e01b815260040160405180910390fd5b5f828152600860209081526040808320600d9092529091205460ff1660028160068111156114e2576114e26146a1565b1461150757836002826040516337e1404160e01b815260040161098893929190614e28565b5f848152600d6020526040808220805460ff19166003179055600a84018590555185917f11df18edb9bc9cd90a79068e0e208b630202148643d797d6150e7bacb733e63c91a2835f5160206159e75f395f51905f526002600360405161156e929190614e70565b60405180910390a250505050565b61158461385c565b806115c05760405162461bcd60e51b815260206004820152600c60248201526b456d70747920706172616d7360a01b6044820152606401610988565b60ff83165f908152600b6020526040902080546115dc90614df6565b15905061162b5760405162461bcd60e51b815260206004820152601b60248201527f506172616d53657420616c7265616479207265676973746572656400000000006044820152606401610988565b60ff83165f908152600b60205260409020611647828483614efe565b507f6e4a4ea7f38fc775e616080b155744337e6216848e886a69c918b4ab84da219583838360405161167b93929190614fda565b60405180910390a1505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6116d760405180606001604052805f81526020015f81526020015f81525090565b5060408051606081018252601554815260165460208201526017549181019190915290565b5f818152600d602052604090205460ff166006816006811115611721576117216146a1565b14829061174457604051637cb2d48360e11b815260040161098891815260200190565b505f828152600c60205260409020548281611775576040516345ba89d560e11b815260040161098891815260200190565b505f838152600c6020526040812081905561178f846139f6565b5f858152601160205260409020546002549192506001600160a01b03908116916117bc9183911685613ae3565b60025460405163da19b69760e01b81526001600160a01b039091169063da19b697906117f2908890879087908790600401615042565b5f604051808303815f87803b158015611809575f5ffd5b505af115801561181b573d5f5f3e3d5ffd5b50505050847f5297818f48a66292b8b3e2caab83eec531b669bb20807fd38cf006adb2a0731784845160405161185b929190918252602082015260400190565b60405180910390a25050505050565b61188b60405180606001604052805f81526020015f81526020015f81525090565b505f908152600e6020908152604091829020825160608101845281548152600182015492810192909252600201549181019190915290565b5f818152600d6020526040812054819060ff166118e08482613b40565b9250925050915091565b5f5f6118f587610c7a565b5f888152600d602052604090205490915060ff16600381600681111561191d5761191d6146a1565b1488600383909192611945576040516337e1404160e01b815260040161098893929190614e28565b5050505f888152600e60209081526040918290208251606081018452815481526001820154928101839052600290910154928101929092528990428110156119a9576040516308f3034360e31b815260048101929092526024820152604401610988565b50506060830151602001518990428111156119e05760405163017e35e560e71b815260048101929092526024820152604401610988565b5050610160830151899015611a0b57604051637eb9cea960e11b815260040161098891815260200190565b505f8888604051611a1d92919061508d565b60408051918290039091205f8c815260086020908152838220600b01839055600d905291909120805460ff19166004179055601754909150611a5f9042614e5d565b5f8b8152600e6020526040908190206002019190915560a08501519051632f0e1bbf60e01b81526001600160a01b0390911690632f0e1bbf90611aac908d9085908c908c9060040161509c565b6020604051808303815f875af1158015611ac8573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611aec91906150c8565b9450888886611b1057604051632f9f8ab960e01b81526004016109889291906150e3565b5050897f7cc27e4a5626cbc4f8ba1a927b0448de55e6a114bc87660331270c5109ade0718a8a604051611b449291906150e3565b60405180910390a2895f5160206159e75f395f51905f5260036004604051611b6d929190614e70565b60405180910390a25050505095945050505050565b5f80600b81611b9760a08601608087016149a2565b60ff1660ff1681526020019081526020015f208054611bb590614df6565b905011611bd45760405162461bcd60e51b8152600401610988906150f6565b5f601281611be5602086018661512d565b6003811115611bf657611bf66146a1565b6003811115611c0757611c076146a1565b8152602081019190915260409081015f20815180830190925260028282826020028201915f905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411611c2e579050505050505090505f81600160028110611c8557611c85615079565b602002015163ffffffff1611835f016020810190611ca3919061512d565b90611cc25760405163286c068d60e11b81526004016109889190615146565b506020808201518251604080516101e081018252601854815260195481860152601a5491810191909152601b546060820152601c546080820152601d5460a0820152601e5460c0820152601f546001600160a01b03811660e0830152600160a01b810461ffff908116610100840152600160b01b82048116610120840152600160c01b82048116610140840152600160d01b82048116610160840152600160e01b90910416610180820152925463ffffffff8181166101a0860181905264010000000090920481166101c086015292831693919092169115611ded576101a081015163ffffffff16846001602002015163ffffffff161015865f016020810190611dcc919061512d565b90611deb5760405163010b971d60e31b81526004016109889190615146565b505b6101c081015163ffffffff1615611e3c576101c081015184519063ffffffff9081169082161015611e3a57604051630a4b6b6360e11b815263ffffffff9091166004820152602401610988565b505b60408601356020870135811015611e695760405163174b5a0760e21b815260040161098891815260200190565b506101808101516017545f9161271091611e879161ffff1690615154565b611e91919061516b565b61271061ffff1683610160015161ffff16601560010154611eb29190615154565b611ebc919061516b565b61271061ffff1684610140015161ffff1660155f0154611edc9190615154565b611ee6919061516b565b5f5460408051634f87c3a560e11b8152815160208e81013594938f0135936001600160a01b031692639f0f874a92600480830193928290030181865afa158015611f32573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f56919061518a565b611f609190614e5d565b611f6a91906151a1565b611f749190614e5d565b611f7e9190614e5d565b611f889190614e5d565b90505f611f966001866151a1565b611fa1906002615154565b611fac906002615154565b611fb7906006614e5d565b90505f85845f0151611fc99190615154565b905081868560200151611fdc9190615154565b611fe69190615154565b611ff09082614e5d565b905060018611156120385760026120086001886151a1565b6120129088615154565b85604001516120219190615154565b61202b919061516b565b6120359082614e5d565b90505b81868560c001516120499190615154565b6120539190615154565b61205d9082614e5d565b9050828685606001516120709190615154565b61207a9190615154565b6120849082614e5d565b90508484608001516120969190615154565b6120a09082614e5d565b905060018511156120e85760026120b86001876151a1565b6120c29087615154565b85604001516120d19190615154565b6120db919061516b565b6120e59082614e5d565b90505b60a08401516120f79082614e5d565b610100850151909150612710906121129061ffff1682614e5d565b61211c9083615154565b612126919061516b565b9750878061214a57604051638c4fcd9360e01b815260040161098891815260200190565b5050505050505050919050565b5f5f61216289610c7a565b5f8a8152600d602052604090205490915060ff16600481600681111561218a5761218a6146a1565b148a6004839091926121b2576040516337e1404160e01b815260040161098893929190614e28565b5050505f8a8152600e602090815260409182902082516060810184528154815260018201549281019290925260020154918101829052908b9042811015612215576040516308f3034360e31b815260048101929092526024820152604401610988565b50505f8b8152600860205260409020600c016122328a8c83614efe565b505f8b8152600d60205260409020805460ff191660051790556101c083015115612312578261010001516001600160a01b0316635bf48e3a8b8b60405161227a92919061508d565b6040519081900381206001600160e01b031960e084901b1682526122a8918c908c908c908c906004016151b4565b602060405180830381865afa1580156122c3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122e791906150c8565b935089898561230b57604051632f9f8ab960e01b81526004016109889291906150e3565b5050612317565b600193505b6123208b613cc8565b8a7f3a140076c461ebc41d74833ae0ee8bbc8079a135a63392098cd381e84350b69b8b8b8b8b60405161235694939291906151ec565b60405180910390a28a5f5160206159e75f395f51905f526004600560405161237f929190614e70565b60405180910390a2505050979650505050505050565b5f546001600160a01b03163314806123b757506003546001600160a01b031633145b6123d457604051639e75a8b560e01b815260040160405180910390fd5b5f8160ff161180156123ea5750600d60ff821611155b61242f5760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b2103330b4b63ab932903932b0b9b7b760511b6044820152606401610988565b61244d828260ff16600d811115612448576124486146a1565b614134565b5050565b61245961385c565b6001600160a01b0381166124af5760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420536c617368696e674d616e616765722061646472657373006044820152606401610988565b600380546001600160a01b0319166001600160a01b0383169081179091556040517f4ccc8ed483c7c44c3602c3c38afc2c014a8f1d2dc210dfe58ebeeeead230f8e0905f90a250565b6003546001600160a01b03163314612523576040516357d6948d60e11b815260040160405180910390fd5b60025460405163c1ab0f1f60e01b815260048101849052602481018390526001600160a01b039091169063c1ab0f1f906044015f604051808303815f87803b15801561256d575f5ffd5b505af115801561257f573d5f5f3e3d5ffd5b50505050817f4f41a3b0a032ebcae925f2ace77d507435840ca4b2dbaffdd7723fa8d72ee5428260405161147c91815260200190565b6125bd61385c565b6001600160a01b038116158015906125ee57505f828152600960205260409020546001600160a01b03828116911614155b8290612610576040516381c4951960e01b815260040161098891815260200190565b505f8281526009602090815260409182902080546001600160a01b0319166001600160a01b03851617905590518381527ff4041a3f914dac3bc9bf5f003ba41f28dbb84abe42f4e07c76266f5c8ceecb69910160405180910390a15050565b61267761385c565b60058190556040518181527fba0716ba1ee2ea8ecc4c64119b4537cdb42a99d82acf92af5b87607b8b52355290602001610ab0565b6126b461385c565b6127106126c961012083016101008401615237565b61ffff1611156126e161012083016101008401615237565b90612706576040516301027fc160e21b815261ffff9091166004820152602401610988565b5061271061271c61014083016101208401615237565b61ffff16111561273461014083016101208401615237565b90612759576040516301027fc160e21b815261ffff9091166004820152602401610988565b5061271061276f61016083016101408401615237565b61ffff16111561278761016083016101408401615237565b906127ac57604051633239953960e01b815261ffff9091166004820152602401610988565b506127106127c261018083016101608401615237565b61ffff1611156127da61018083016101608401615237565b906127ff57604051633239953960e01b815261ffff9091166004820152602401610988565b506127106128156101a083016101808401615237565b61ffff16111561282d6101a083016101808401615237565b9061285257604051633239953960e01b815261ffff9091166004820152602401610988565b5061286561014082016101208301615237565b61ffff16158061288e57505f612882610100830160e084016145e2565b6001600160a01b031614155b6128ab5760405163015f92ff60e51b815260040160405180910390fd5b6128bd6101e082016101c0830161526e565b63ffffffff166128d56101c083016101a0840161526e565b63ffffffff1610156128fa576040516392f55c6560e01b815260040160405180910390fd5b80601861290782826152ad565b9050507fbf3951313e980027eb48ce363fdb707286195ec6a0f802ac153927cf929c3fc681604051610ab0919061546b565b61294161385c565b6001600160a01b0381161580159061296757506001546001600160a01b03828116911614155b8190612987576040516320252f0b60e01b81526004016109889190614628565b50600180546001600160a01b0319166001600160a01b0383161790556040517fad4055f18cdad6f4bdd71afe3a72cbeee964217943e1bde38f138289e981a9a790610ab0908390614628565b6129db61385c565b6129e8602082018261526e565b63ffffffff166129fe604083016020840161526e565b63ffffffff1610158015612a2357505f612a1b602083018361526e565b63ffffffff16115b612a4057604051634564ab9b60e01b815260040160405180910390fd5b604080516101e0810182526018548152601954602080830191909152601a5492820192909252601b546060820152601c546080820152601d5460a0820152601e5460c0820152601f546001600160a01b03811660e083015261ffff600160a01b82048116610100840152600160b01b82048116610120840152600160c01b82048116610140840152600160d01b82048116610160840152600160e01b90910416610180820152905463ffffffff8082166101a08401819052640100000000909204166101c083015215612b79576101a081015163ffffffff16612b29604084016020850161526e565b63ffffffff161015612b41604084016020850161526e565b826101a001519091612b7657604051633ccc4c2160e21b815263ffffffff928316600482015291166024820152604401610988565b50505b6101c081015163ffffffff1615612bf0576101c081015163ffffffff16612ba3602084018461526e565b63ffffffff161015612bb8602084018461526e565b826101c001519091612bed5760405163156c4e5b60e11b815263ffffffff928316600482015291166024820152604401610988565b50505b8160125f856003811115612c0657612c066146a1565b6003811115612c1757612c176146a1565b815260208101919091526040015f20612c319160026144cd565b50826003811115612c4457612c446146a1565b7f8b56fae526eee054f0849759a99fc7d4ff3823824ebf097a56f7d78adb6b34fa83604051612c739190615575565b60405180910390a2505050565b612c8861385c565b6001600160a01b038116612cb1575f604051631e4fbdf760e01b81526004016109889190614628565b610acc81613986565b5f612cc3614450565b5f601281612cd4602087018761512d565b6003811115612ce557612ce56146a1565b6003811115612cf657612cf66146a1565b8152602081019190915260409081015f20815180830190925260028282826020028201915f905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411612d1d579050505050505090505f81600160028110612d7457612d74615079565b602002015163ffffffff1611845f016020810190612d92919061512d565b90612db15760405163286c068d60e11b81526004016109889190615146565b50602084013542811015612ddb57604051630b99e87960e01b815260040161098891815260200190565b5060408401356020850135811015612e095760405163174b5a0760e21b815260040161098891815260200190565b506017546016545f9190612e214260408901356151a1565b612e2b9190614e5d565b612e359190614e5d565b905060055481108190612e5e576040516313b783af60e21b815260040161098891815260200190565b5060075f612e7260808801606089016145e2565b6001600160a01b0316815260208101919091526040015f205460ff16612e9e60808701606088016145e2565b90612ebd5760405163295a6a6f60e11b81526004016109889190614628565b505f612ec886611b82565b60068054965090915085905f612edd836155b5565b9091555050604080514460208201529081018690525f9060600160408051601f1981840301815291815281516020928301205f898152600c84528281208690556004546011855283822080546001600160a01b03199081166001600160a01b0393841617909155601f805460138852868520805461ffff191661ffff600160b01b909304929092169190911790555460148752858420805483169190931617909155600d8552838220805460ff191660011790556010909452829020805433941693909317909255601654919250612fb89190890135614e5d565b5f878152600e6020908152604090912060010191909155818652612fde9088018861512d565b85602001906003811115612ff457612ff46146a1565b90816003811115613007576130076146a1565b905250436040808701919091528051808201825290602089019060029083908390808284375f92019190915250505060608087019190915261304f90608089019089016145e2565b6001600160a01b031660a080870191909152613070908801608089016149a2565b60ff1660c080870191909152613088908801886155cd565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050505060e0808701919091526130d590610100890190890161560f565b15156101c08601525f610140860181905261016086018190526040805160208101909152908152610180860152336101a08601819052600454613125916001600160a01b0390911690308561428f565b5f600b8161313960a08b0160808c016149a2565b60ff1660ff1681526020019081526020015f20805461315790614df6565b80601f016020809104026020016040519081016040528092919081815260200182805461318390614df6565b80156131ce5780601f106131a5576101008083540402835291602001916131ce565b820191905f5260205f20905b8154815290600101906020018083116131b157829003601f168201915b505050505090505f8151116131f55760405162461bcd60e51b8152600401610988906150f6565b5f61320660808a0160608b016145e2565b6001600160a01b031663fefd9a8b89858561322460a08f018f6155cd565b8f8060c0019061323491906155cd565b6040518863ffffffff1660e01b8152600401613256979695949392919061562a565b6020604051808303815f875af1158015613272573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613296919061518a565b5f818152600960205260409020549091506001600160a01b031681816132d2576040516381c4951960e01b815260040161098891815260200190565b505f828152600a60205260409020546001600160a01b0316828161330c576040516381c4951960e01b815260040161098891815260200190565b50608089018390526001600160a01b038083166101008b015281166101208a01525f8a81526008602090815260409091208a518155908a0151600180830180548d94939260ff19919091169083600381111561336a5761336a6146a1565b02179055506040820151816002015560608201518160030190600261339092919061456e565b506080820151600582015560a082015160068201805460c085015160ff16600160a01b026001600160a81b03199091166001600160a01b039093169290921791909117905560e082015160078201906133e9908261567e565b506101008201516008820180546001600160a01b039283166001600160a01b031991821617909155610120840151600984018054919093169116179055610140820151600a820155610160820151600b820155610180820151600c820190613451908261567e565b506101a0820151600d90910180546101c0909301511515600160a01b026001600160a81b03199093166001600160a01b0392831617929092179091555f5460405163291a691b60e01b815291169063291a691b906134b7908d9089908d90600401615733565b6020604051808303815f875af11580156134d3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906134f791906150c8565b61351457604051630d8dbe2560e01b815260040160405180910390fd5b61352460808c0160608d016145e2565b6001600160a01b03167f5090c9764b5cd13df7afc0013f733dfbe6eaf1b6ddc22a5e291fa387efd4c15e8b8b60405161355e929190614dd6565b60405180910390a2895f5160206159e75f395f51905f525f6001604051613586929190614e70565b60405180910390a25050505050505050915091565b5f818152600d602052604081205460ff16818160068111156135bf576135bf6146a1565b036135e457826001826040516337e1404160e01b815260040161098893929190614e28565b60058160068111156135f8576135f86146a1565b036136195760405163462c7bed60e01b815260048101849052602401610988565b600681600681111561362d5761362d6146a1565b0361364e57604051633de16e3560e11b815260048101849052602401610988565b5f6136598483613b40565b935090508061367e57604051639f65d93560e01b815260048101859052602401610988565b5f848152600d6020526040902080546006919060ff191660018302179055505f848152600f60205260409020805484919060ff1916600183600d8111156136c7576136c76146a1565b0217905550835f5160206159e75f395f51905f528360066040516136ec929190614e70565b60405180910390a2837fe20209be7caae6e76291267cfa711353981274bf127e94f16eb9ec44b68582bb8385604051613726929190615778565b60405180910390a25050919050565b61373d61385c565b6001600160a01b0381161580159061376257505f546001600160a01b03828116911614155b8190613782576040516375ac4eb760e11b81526004016109889190614628565b505f80546001600160a01b0319166001600160a01b0383161790556040517f80052b810d39120cf6c976cca504a21703f585521dc7a41c6d241090e6c579b690610ab0908390614628565b6001600160a01b0381165f90815260076020526040902054819060ff16156138095760405163b29d459560e01b81526004016109889190614628565b506001600160a01b0381165f9081526007602052604090819020805460ff19166001179055517fb8d368517268f297fff00825d67d098763117d061360d31027be5b2e1a59d46790610ab0908390614628565b33613865611688565b6001600160a01b0316146112fe573360405163118cdaa760e01b81526004016109889190614628565b80356138ad5760405163055f269d60e01b815260040160405180910390fd5b5f8160200135116138d15760405163055f269d60e01b815260040160405180910390fd5b5f8160400135116138f55760405163055f269d60e01b815260040160405180910390fd5b80356015819055602080830135601681905560408085013560178190558151948552928401919091528201527f7e86ba16b805e2835af5c5b7aa5a942ced8bcc1fb95a05fbe42dae3862350a1690606001610ab0565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005b92915050565b61397d6142ce565b610acc816142f3565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f818152600f602052604090205460609060ff16600181600d811115613a1e57613a1e6146a1565b1480613a3b5750600281600d811115613a3957613a396146a1565b145b15613a73575f5b604051908082528060200260200182016040528015613a6b578160200160208202803683370190505b509392505050565b5f5460405162beb08960e51b8152600481018590526001600160a01b03909116906317d61120906024015f60405180830381865afa925050508015613ad957506040513d5f823e601f3d908101601f19168201604052613ad6919081019061584f565b60015b613a6b575f613a42565b613b3b83846001600160a01b031663a9059cbb8585604051602401613b09929190615914565b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506142fb565b505050565b5f828152600e60209081526040808320815160608101835281548152600182015493810193909352600201548282015282549051632800d82960e01b81526004810186905283929183916001600160a01b0390911690632800d82990602401602060405180830381865afa158015613bba573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613bde919061518a565b90506001856006811115613bf457613bf46146a1565b148015613c0057508042115b15613c1357600180935093505050613cc1565b6002856006811115613c2757613c276146a1565b148015613c345750815142115b15613c485760016003935093505050613cc1565b6003856006811115613c5c57613c5c6146a1565b148015613c6c5750816020015142115b15613c805760016006935093505050613cc1565b6004856006811115613c9457613c946146a1565b148015613ca45750816040015142115b15613cb8576001600a935093505050613cc1565b5f5f9350935050505b9250929050565b5f805460405162beb08960e51b8152600481018490526001600160a01b03909116906317d61120906024015f60405180830381865afa158015613d0d573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052613d34919081019061584f565b5080515f848152600c60209081526040808320805490849055601190925282205493945091926001600160a01b031690829003613dd3576002546040516341489f1560e01b81526001600160a01b03909116906341489f1590613d9f9088908890869060040161592d565b5f604051808303815f87803b158015613db6575f5ffd5b505af1158015613dc8573d5f5f3e3d5ffd5b505050505050505050565b825f03613e74575f858152601060205260409020546001600160a01b03168015613e0b57613e0b6001600160a01b0383168285613ae3565b6002546040516341489f1560e01b81526001600160a01b03909116906341489f1590613e3f9089908990879060040161592d565b5f604051808303815f87803b158015613e56575f5ffd5b505af1158015613e68573d5f5f3e3d5ffd5b50505050505050505050565b5f85815260136020908152604080832054601490925282205461ffff909116906001600160a01b03168115801590613eb457506001600160a01b03811615155b15613ef057612710613eca61ffff841687615154565b613ed4919061516b565b92508215613ef057613ef06001600160a01b0385168285613ae3565b5f613efb84876151a1565b90505f876001600160401b03811115613f1657613f16614e8b565b604051908082528060200260200182016040528015613f3f578160200160208202803683370190505b5090505f613f4d898461516b565b90505f805b8a811015613f8c5782848281518110613f6d57613f6d615079565b6020908102919091010152613f828383614e5d565b9150600101613f52565b505f613f9882866151a1565b90508015613fd5578084613fad60018e6151a1565b81518110613fbd57613fbd615079565b60200260200101818151613fd19190614e5d565b9052505b600154613fef906001600160a01b038b811691168761435e565b60015f9054906101000a90046001600160a01b03166001600160a01b031663dd8c818e8a8e876040518463ffffffff1660e01b81526004016140339392919061598d565b5f604051808303815f87803b15801561404a575f5ffd5b505af115801561405c573d5f5f3e3d5ffd5b505060015461407a92506001600160a01b038c81169250165f61435e565b8c7fac9fe8ad7f55eac03284399116ecafc104f10459773f4cdf47063c46e5be335a8d866040516140ac9291906159c2565b60405180910390a260025f9054906101000a90046001600160a01b03166001600160a01b03166341489f158e8e8c6040518463ffffffff1660e01b81526004016140f89392919061592d565b5f604051808303815f87803b15801561410f575f5ffd5b505af1158015614121573d5f5f3e3d5ffd5b5050505050505050505050505050505050565b5f828152600d602052604081205460ff1690816006811115614158576141586146a1565b0361417d57826001826040516337e1404160e01b815260040161098893929190614e28565b6005816006811115614191576141916146a1565b036141b25760405163462c7bed60e01b815260048101849052602401610988565b60068160068111156141c6576141c66146a1565b036141e757604051633de16e3560e11b815260048101849052602401610988565b5f838152600d6020526040902080546006919060ff191660018302179055505f838152600f60205260409020805483919060ff1916600183600d811115614230576142306146a1565b0217905550825f5160206159e75f395f51905f52826006604051614255929190614e70565b60405180910390a2827fe20209be7caae6e76291267cfa711353981274bf127e94f16eb9ec44b68582bb8284604051612c73929190615778565b6040516001600160a01b0384811660248301528381166044830152606482018390526142c89186918216906323b872dd90608401613b09565b50505050565b6142d66143ee565b6112fe57604051631afcd79f60e31b815260040160405180910390fd5b612c886142ce565b5f5f60205f8451602086015f885af18061431a576040513d5f823e3d81fd5b50505f513d9150811561433157806001141561433e565b6001600160a01b0384163b155b156142c85783604051635274afe760e01b81526004016109889190614628565b5f836001600160a01b031663095ea7b38484604051602401614381929190615914565b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505090506143ba8482614407565b6142c8576143e484856001600160a01b031663095ea7b3865f604051602401613b09929190615914565b6142c884826142fb565b5f6143f761394b565b54600160401b900460ff16919050565b5f5f5f5f60205f8651602088015f8a5af192503d91505f519050828015614446575081156144385780600114614446565b5f866001600160a01b03163b115b9695505050505050565b604080516101e081019091525f808252602082019081526020015f815260200161447861459c565b81525f602082018190526040820181905260608083018290526080830181905260a0830182905260c0830182905260e08301829052610100830182905261012083015261014082018190526101609091015290565b60018301918390821561455e579160200282015f5b8382111561452c57833563ffffffff1683826101000a81548163ffffffff021916908363ffffffff16021790555092602001926004016020816003010492830192600103026144e2565b801561455c5782816101000a81549063ffffffff021916905560040160208160030104928301926001030261452c565b505b5061456a9291506145ba565b5090565b826002810192821561455e579160200282015b8281111561455e578251825591602001919060010190614581565b60405180604001604052806002906020820280368337509192915050565b5b8082111561456a575f81556001016145bb565b6001600160a01b0381168114610acc575f5ffd5b5f602082840312156145f2575f5ffd5b81356145fd816145ce565b9392505050565b5f60208284031215614614575f5ffd5b5035919050565b6001600160a01b03169052565b6001600160a01b0391909116815260200190565b80356004811061464a575f5ffd5b919050565b5f5f60408385031215614660575f5ffd5b6146698361463c565b946020939093013593505050565b5f60608284031215610ef1575f5ffd5b5f60608284031215614697575f5ffd5b6145fd8383614677565b634e487b7160e01b5f52602160045260245ffd5b600e81106146c5576146c56146a1565b9052565b6020810161396f82846146b5565b600481106146c5576146c56146a1565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b8e8152614725602082018f6146d7565b8c60408201528b606082015261473e608082018c61461b565b60ff8a1660a08201526101c060c08201525f61475e6101c083018b6146e7565b61476b60e084018b61461b565b61477961010084018a61461b565b876101208401528661014084015282810361016084015261479a81876146e7565b9150506147ab61018083018561461b565b8215156101a08301529f9e505050505050505050505050505050565b805f5b60028110156142c85781518452602093840193909101906001016147ca565b805182525f602082015161480060208501826146d7565b5060408201516040840152606082015161481d60608501826147c7565b50608082015160a084015260a082015161483a60c085018261461b565b5060c082015160ff811660e08501525060e08201516102006101008501526148666102008501826146e7565b905061010083015161487c61012086018261461b565b5061012083015161489161014086018261461b565b506101408301516101608501526101608301516101808501526101808301518482036101a08601526148c382826146e7565b9150506101a08301516148da6101c086018261461b565b506101c08301518015156101e0860152613a6b565b602081525f6145fd60208301846147e9565b803561464a816145ce565b5f5f5f5f5f5f5f610120888a031215614923575f5ffd5b873561492e816145ce565b9650602088013561493e816145ce565b9550604088013561494e816145ce565b9450606088013561495e816145ce565b9350608088013561496e816145ce565b925060a088013591506149848960c08a01614677565b905092959891949750929550565b803560ff8116811461464a575f5ffd5b5f602082840312156149b2575f5ffd5b6145fd82614992565b602081525f6145fd60208301846146e7565b5f5f604083850312156149de575f5ffd5b8235915060208301356149f0816145ce565b809150509250929050565b5f5f60408385031215614a0c575f5ffd5b50508035926020909101359150565b5f5f83601f840112614a2b575f5ffd5b5081356001600160401b03811115614a41575f5ffd5b602083019150836020828501011115613cc1575f5ffd5b5f5f5f60408486031215614a6a575f5ffd5b614a7384614992565b925060208401356001600160401b03811115614a8d575f5ffd5b614a9986828701614a1b565b9497909650939450505050565b8151815260208083015190820152604080830151908201526060810161396f565b8215158152604081016145fd60208301846146b5565b5f5f5f5f5f60608688031215614af1575f5ffd5b8535945060208601356001600160401b03811115614b0d575f5ffd5b614b1988828901614a1b565b90955093505060408601356001600160401b03811115614b37575f5ffd5b614b4388828901614a1b565b969995985093965092949392505050565b5f60208284031215614b64575f5ffd5b81356001600160401b03811115614b79575f5ffd5b820161010081850312156145fd575f5ffd5b5f6101e082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e0830151614be560e084018261461b565b50610100830151614bfd61010084018261ffff169052565b50610120830151614c1561012084018261ffff169052565b50610140830151614c2d61014084018261ffff169052565b50610160830151614c4561016084018261ffff169052565b50610180830151614c5d61018084018261ffff169052565b506101a0830151614c776101a084018263ffffffff169052565b506101c0830151614c916101c084018263ffffffff169052565b5092915050565b5f5f5f5f5f5f5f6080888a031215614cae575f5ffd5b8735965060208801356001600160401b03811115614cca575f5ffd5b614cd68a828b01614a1b565b90975095505060408801356001600160401b03811115614cf4575f5ffd5b614d008a828b01614a1b565b90955093505060608801356001600160401b03811115614d1e575f5ffd5b614d2a8a828b01614a1b565b989b979a50959850939692959293505050565b5f5f60408385031215614d4e575f5ffd5b82359150614d5e60208401614992565b90509250929050565b600781106146c5576146c56146a1565b6020810161396f8284614d67565b5f6101e0828403128015614d97575f5ffd5b509092915050565b5f5f60608385031215614db0575f5ffd5b614db98361463c565b915083606084011115614dca575f5ffd5b50926020919091019150565b828152604060208201525f614dee60408301846147e9565b949350505050565b600181811c90821680614e0a57607f821691505b602082108103610ef157634e487b7160e01b5f52602260045260245ffd5b83815260608101614e3c6020830185614d67565b614dee6040830184614d67565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561396f5761396f614e49565b60408101614e7e8285614d67565b6145fd6020830184614d67565b634e487b7160e01b5f52604160045260245ffd5b601f821115613b3b57805f5260205f20601f840160051c81016020851015614ec45750805b601f840160051c820191505b81811015614ee3575f8155600101614ed0565b5050505050565b5f19600383901b1c191660019190911b1790565b6001600160401b03831115614f1557614f15614e8b565b614f2983614f238354614df6565b83614e9f565b5f601f841160018114614f55575f8515614f435750838201355b614f4d8682614eea565b845550614ee3565b5f83815260208120601f198716915b82811015614f845786850135825560209485019460019092019101614f64565b5086821015614fa0575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60ff84168152604060208201525f614ff6604083018486614fb2565b95945050505050565b5f8151808452602084019350602083015f5b828110156150385781516001600160a01b0316865260209586019590910190600101615011565b5093949350505050565b848152836020820152608060408201525f6150606080830185614fff565b905060018060a01b038316606083015295945050505050565b634e487b7160e01b5f52603260045260245ffd5b818382375f9101908152919050565b848152836020820152606060408201525f614446606083018486614fb2565b8015158114610acc575f5ffd5b5f602082840312156150d8575f5ffd5b81516145fd816150bb565b602081525f614dee602083018486614fb2565b6020808252601c908201527f42465620706172616d20736574206e6f74207265676973746572656400000000604082015260600190565b5f6020828403121561513d575f5ffd5b6145fd8261463c565b6020810161396f82846146d7565b808202811582820484141761396f5761396f614e49565b5f8261518557634e487b7160e01b5f52601260045260245ffd5b500490565b5f6020828403121561519a575f5ffd5b5051919050565b8181038181111561396f5761396f614e49565b858152606060208201525f6151cd606083018688614fb2565b82810360408401526151e0818587614fb2565b98975050505050505050565b604081525f6151ff604083018688614fb2565b8281036020840152615212818587614fb2565b979650505050505050565b61ffff81168114610acc575f5ffd5b803561464a8161521d565b5f60208284031215615247575f5ffd5b81356145fd8161521d565b63ffffffff81168114610acc575f5ffd5b803561464a81615252565b5f6020828403121561527e575f5ffd5b81356145fd81615252565b5f813561396f816145ce565b5f813561396f8161521d565b5f813561396f81615252565b813581556020820135600182015560408201356002820155606082013560038201556080820135600482015560a0820135600582015560c082013560068201556007810161531d61530060e08501615289565b82546001600160a01b0319166001600160a01b0391909116178255565b61534d61532d6101008501615295565b82805461ffff60a01b191660a09290921b61ffff60a01b16919091179055565b61537d61535d6101208501615295565b82805461ffff60b01b191660b09290921b61ffff60b01b16919091179055565b6153ad61538d6101408501615295565b82805461ffff60c01b191660c09290921b61ffff60c01b16919091179055565b6153dd6153bd6101608501615295565b82805461ffff60d01b191660d09290921b61ffff60d01b16919091179055565b61540d6153ed6101808501615295565b82805461ffff60e01b191660e09290921b61ffff60e01b16919091179055565b50600881016154396154226101a085016152a1565b825463ffffffff191663ffffffff91909116178255565b613b3b6154496101c085016152a1565b825467ffffffff00000000191660209190911b67ffffffff0000000016178255565b813581526020808301359082015260408083013590820152606080830135908201526080808301359082015260a0808301359082015260c080830135908201526101e081016154bc60e08401614901565b6154c960e084018261461b565b506154d7610100840161522c565b61ffff166101008301526154ee610120840161522c565b61ffff16610120830152615505610140840161522c565b61ffff1661014083015261551c610160840161522c565b61ffff16610160830152615533610180840161522c565b61ffff1661018083015261554a6101a08401615263565b63ffffffff166101a08301526155636101c08401615263565b63ffffffff81166101c0840152614c91565b6040810181835f5b60028110156155ac57813561559181615252565b63ffffffff168352602092830192919091019060010161557d565b50505092915050565b5f600182016155c6576155c6614e49565b5060010190565b5f5f8335601e198436030181126155e2575f5ffd5b8301803591506001600160401b038211156155fb575f5ffd5b602001915036819003821315613cc1575f5ffd5b5f6020828403121561561f575f5ffd5b81356145fd816150bb565b87815286602082015260a060408201525f61564860a08301886146e7565b828103606084015261565b818789614fb2565b90508281036080840152615670818587614fb2565b9a9950505050505050505050565b81516001600160401b0381111561569757615697614e8b565b6156ab816156a58454614df6565b84614e9f565b6020601f8211600181146156d8575f83156156c65750848201515b6156d08482614eea565b855550614ee3565b5f84815260208120601f198516915b8281101561570757878501518255602094850194600190920191016156e7565b508482101561572457868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b838152602081018390526080810160408201835f5b600281101561576d57815163ffffffff16835260209283019290910190600101615748565b505050949350505050565b604081016157868285614d67565b6145fd60208301846146b5565b604051601f8201601f191681016001600160401b03811182821017156157bb576157bb614e8b565b604052919050565b5f6001600160401b038211156157db576157db614e8b565b5060051b60200190565b5f82601f8301126157f4575f5ffd5b8151615807615802826157c3565b615793565b8082825260208201915060208360051b860101925085831115615828575f5ffd5b602085015b8381101561584557805183526020928301920161582d565b5095945050505050565b5f5f60408385031215615860575f5ffd5b82516001600160401b03811115615875575f5ffd5b8301601f81018513615885575f5ffd5b8051615893615802826157c3565b8082825260208201915060208360051b8501019250878311156158b4575f5ffd5b6020840193505b828410156158df5783516158ce816145ce565b8252602093840193909101906158bb565b8095505050505060208301516001600160401b038111156158fe575f5ffd5b61590a858286016157e5565b9150509250929050565b6001600160a01b03929092168252602082015260400190565b838152606060208201525f6159456060830185614fff565b905060018060a01b0383166040830152949350505050565b5f8151808452602084019350602083015f5b8281101561503857815186526020958601959091019060010161596f565b6001600160a01b03841681526060602082018190525f906159b090830185614fff565b8281036040840152614446818561595d565b604081525f6159d46040830185614fff565b8281036020840152614ff6818561595d56fe1b418a230a21d37a078bf8f16decbde8ccceacd77159371f62f0d4ea00d19967a164736f6c634300081c000a", "linkReferences": {}, "deployedLinkReferences": {}, "immutableReferences": {}, "inputSourceName": "project/contracts/Enclave.sol", - "buildInfoId": "solc-0_8_28-450dba89e3316019924fd97da52afa696f4be931" + "buildInfoId": "solc-0_8_28-ad0ab271a39c8d6cc271ed8cba75fab865dc3973" } \ No newline at end of file diff --git a/packages/enclave-contracts/artifacts/contracts/registry/CiphernodeRegistryOwnable.sol/CiphernodeRegistryOwnable.json b/packages/enclave-contracts/artifacts/contracts/registry/CiphernodeRegistryOwnable.sol/CiphernodeRegistryOwnable.json index bb462308d4..b218563f66 100644 --- a/packages/enclave-contracts/artifacts/contracts/registry/CiphernodeRegistryOwnable.sol/CiphernodeRegistryOwnable.json +++ b/packages/enclave-contracts/artifacts/contracts/registry/CiphernodeRegistryOwnable.sol/CiphernodeRegistryOwnable.json @@ -1264,30 +1264,30 @@ "type": "function" } ], - "bytecode": "0x6080604052348015600e575f5ffd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b613ec6806100d65f395ff3fe608060405234801561000f575f5ffd5b506004361061023f575f3560e01c80639f0f874a11610135578063e59e4695116100b4578063f26ef74e11610079578063f26ef74e1461057f578063f2fde38b14610592578063f379b0df146105a5578063f52fd803146105df578063f6fc05d514610651575f5ffd5b8063e59e469514610524578063e6745e1314610537578063e82f3b701461054a578063ebf0c7171461055d578063f165053614610565575f5ffd5b8063c3a0ec30116100fa578063c3a0ec30146104bc578063ca2869a0146104cd578063cd6dc687146104ec578063da881e5a146104ff578063dbb06c9314610512575f5ffd5b80639f0f874a1461044e578063a016493014610457578063a8a4d69b14610477578063bff232c11461048a578063c2b40ae41461049d575f5ffd5b8063715018a6116101c15780638d1ddfb1116101865780638d1ddfb1146103ce5780638da5cb5b146103e45780638e5ce3ad146103ec5780639015d371146103ff5780639a7a2ffc14610412575f5ffd5b8063715018a6146103475780637c92f5241461034f578063858142431461037c5780638a78bb151461039c5780638cb89ecb146103af575f5ffd5b80632e7b716d116102075780632e7b716d146102d95780634d6861a6146102ec57806350e6d94c146102ff5780635d5047761461032157806370e36bbe14610334575f5ffd5b8063096b810a146102435780630f3e34121461025857806317d611201461026b5780632800d82914610295578063291a691b146102b6575b5f5ffd5b6102566102513660046132aa565b61065a565b005b6102566102663660046132c5565b6107a6565b61027e6102793660046132c5565b6107e9565b60405161028c92919061334f565b60405180910390f35b6102a86102a33660046132c5565b610993565b60405190815260200161028c565b6102c96102c436600461337c565b6109df565b604051901515815260200161028c565b6102c96102e73660046132aa565b610bb9565b6102c96102fa3660046132c5565b610c6c565b6102c961030d3660046132aa565b60066020525f908152604090205460ff1681565b6102c961032f3660046133b5565b610cab565b6102566103423660046132aa565b610cef565b610256610d65565b61036261035d3660046133e3565b610d78565b6040805192835263ffffffff90911660208301520161028c565b60015461038f906001600160a01b031681565b60405161028c9190613418565b6102566103aa3660046132aa565b610f1f565b6102a86103bd3660046132c5565b60096020525f908152604090205481565b600454600160281b900464ffffffffff166102a8565b61038f61105d565b600b5461038f906001600160a01b031681565b6102c961040d3660046132aa565b61108b565b6104386104203660046132aa565b60076020525f908152604090205464ffffffffff1681565b60405164ffffffffff909116815260200161028c565b6102a860035481565b61046a6104653660046132c5565b6110a8565b60405161028c919061342c565b6102c96104853660046133b5565b61113e565b6102566104983660046132aa565b611182565b6102a86104ab3660046132c5565b60086020525f908152604090205481565b6001546001600160a01b031661038f565b6102a86104db3660046132c5565b5f9081526008602052604090205490565b6102566104fa36600461343e565b6111d3565b6102c961050d3660046132c5565b611330565b5f5461038f906001600160a01b031681565b6102566105323660046132aa565b61160a565b610256610545366004613468565b611682565b6102a86105583660046132c5565b611845565b6102a8611876565b61056d601481565b60405160ff909116815260200161028c565b61025661058d3660046134cc565b611888565b6102566105a03660046132aa565b611b7a565b6004546105c19064ffffffffff80821691600160281b90041682565b6040805164ffffffffff93841681529290911660208301520161028c565b6106226105ed3660046132c5565b5f908152600a6020819052604090912090810154600590910154909163ffffffff80831692600160201b900416908284101590565b60405161028c949392919093845263ffffffff9283166020850152911660408301521515606082015260800190565b6102a860025481565b61066261105d565b6001600160a01b0316336001600160a01b0316148061068b57506001546001600160a01b031633145b6106a857604051632864c4e160e01b815260040160405180910390fd5b6106b18161108b565b81906106da576040516381e5828960e01b81526004016106d19190613418565b60405180910390fd5b506001600160a01b0381165f9081526007602052604081205464ffffffffff16906107089060049083611bb4565b6001600160a01b0382165f908152600660205260408120805460ff191690556002805491610735836135e6565b90915550506002546004546040805164ffffffffff80861682526020820194909452600160281b909204909216918101919091526001600160a01b038316907f8c008e3835f6c79bfcdb89f0f6ca8705e0b01049ee84a90b0e4da1c7ba9405d5906060015b60405180910390a25050565b6107ae611e56565b60038190556040518181527fbe772dc189863d512fa01e489c8eac204975aef1a8662d8b5a333804b5207ab79060200160405180910390a150565b5f818152600a60208190526040909120600681015491810154606092839291806001600160401b03811115610820576108206135fb565b604051908082528060200260200182016040528015610849578160200160208202803683370190505b509450806001600160401b03811115610864576108646135fb565b60405190808252806020026020018201604052801561088d578160200160208202803683370190505b5093505f805b83811015610989575f8560060182815481106108b1576108b161360f565b5f918252602090912001546001600160a01b0316905060016001600160a01b0382165f90815260098801602052604090205460ff1660028111156108f7576108f7613623565b03610980578088848151811061090f5761090f61360f565b60200260200101906001600160a01b031690816001600160a01b031681525050856008015f826001600160a01b03166001600160a01b031681526020019081526020015f20548784815181106109675761096761360f565b60209081029190910101528261097c81613637565b9350505b50600101610893565b5050505050915091565b5f818152600a6020526040812081815460ff1660038111156109b7576109b7613623565b036109d557604051630d4c1d9760e41b815260040160405180910390fd5b6003015492915050565b5f80546001600160a01b03163314610a0a5760405163e4c2a7eb60e01b815260040160405180910390fd5b5f848152600a6020526040812090815460ff166003811115610a2e57610a2e613623565b14610a4c576040516374ff462560e11b815260040160405180910390fd5b60015460408051630cc37d8f60e11b815290515f926001600160a01b031691631986fb1e9160048083019260209291908290030181865afa158015610a93573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab7919061364f565b905080610aca6040860160208701613679565b63ffffffff161115610ae26040860160208701613679565b829091610b10576040516344ec930f60e01b815263ffffffff909216600483015260248201526044016106d1565b5050815460ff1916600190811783558201859055436002830155600354610b379042613692565b6003830155610b4b600583018560026131e1565b50610b54611876565b5f87815260086020526040908190209190915560028301546003840154915188927f381d281d32f95ef8fe4e5f3b263ea6a32d03d331e1a141ae1da996dc02a7a17092610ba5928a928a92916136a5565b60405180910390a250600195945050505050565b5f610bc38261108b565b610bce57505f919050565b6001546001600160a01b0316610bf7576040516350ca893360e01b815260040160405180910390fd5b600154604051639f8a13d760e01b81526001600160a01b0390911690639f8a13d790610c27908590600401613418565b602060405180830381865afa158015610c42573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c669190613704565b92915050565b5f818152600a602052604081206001815460ff166003811115610c9157610c91613623565b14610c9e57505f92915050565b6003015442111592915050565b5f60015f848152600a602090815260408083206001600160a01b038716845260090190915290205460ff166002811115610ce757610ce7613623565b149392505050565b610cf7611e56565b6001600160a01b038116610d1e5760405163d92e233d60e01b815260040160405180910390fd5b5f80546001600160a01b0319166001600160a01b038316908117825560405190917f2c8267accd82e977550ed2349c73311183cd22e306347be4453c8d130995e3c991a250565b610d6d611e56565b610d765f611e88565b565b600b545f9081906001600160a01b03163314610da75760405163fcef374960e01b815260040160405180910390fd5b5f858152600a602052604090206002815460ff166003811115610dcc57610dcc613623565b14610dea57604051634f4b461f60e11b815260040160405180910390fd5b60058101546001600160a01b0386165f90815260098301602052604090205463ffffffff909116925060019060ff166002811115610e2a57610e2a613623565b14610e3a57600a01549150610f17565b6001600160a01b0385165f9081526009820160205260408120805460ff19166002179055600a8201805491610e6e836135e6565b919050555080600a01549250846001600160a01b0316867f6c783b92374361b4d6efaf29673b89437ee969bb3c9d2d5d86b143ad5447b8498686604051610ebf929190918252602082015260400190565b60405180910390a36040805184815263ffffffff84166020820181905285101591810182905287907f119cb11dd0a68c257d6dc9b06dcb37dd422ce276eb8bf3cd0b7079a116b8e2989060600160405180910390a250505b935093915050565b610f2761105d565b6001600160a01b0316336001600160a01b03161480610f5057506001546001600160a01b031633145b610f6d57604051632864c4e160e01b815260040160405180910390fd5b610f768161108b565b61105a5760048054600160281b900464ffffffffff1690610fa0906001600160a01b038416611ef8565b6001600160a01b0382165f908152600660209081526040808320805460ff1916600117905560079091528120805464ffffffffff841664ffffffffff199091161790556002805491610ff183613637565b90915550506002546004546040805164ffffffffff80861682526020820194909452600160281b909204909216918101919091526001600160a01b038316907f3318d261fe14a5761d2d1e21555652f623d2134c430a9883c9ad6e958bb0db539060600161079a565b50565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b03165f9081526006602052604090205460ff1690565b5f818152600a602052604090206004810154606091906110db576040516322e679e360e11b815260040160405180910390fd5b8060060180548060200260200160405190810160405280929190818152602001828054801561113157602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611113575b5050505050915050919050565b5f805f848152600a602090815260408083206001600160a01b038716845260090190915290205460ff16600281111561117957611179613623565b14159392505050565b61118a611e56565b6001600160a01b0381166111b15760405163d92e233d60e01b815260040160405180910390fd5b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b5f6111dc6120ce565b805490915060ff600160401b82041615906001600160401b03165f811580156112025750825b90505f826001600160401b0316600114801561121d5750303b155b90508115801561122b575080155b156112495760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561127357845460ff60401b1916600160401b1785555b6001600160a01b03871661129a5760405163d92e233d60e01b815260040160405180910390fd5b6112a3336120f6565b6112af60046014612107565b6112b8866107a6565b6112c061105d565b6001600160a01b0316876001600160a01b0316146112e1576112e187611b7a565b831561132757845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b5f818152600a6020526040812081815460ff16600381111561135457611354613623565b0361137257604051630d4c1d9760e41b815260040160405180910390fd5b6001815460ff16600381111561138a5761138a613623565b146113a857604051631860f69960e31b815260040160405180910390fd5b806003015442116113cc57604051632f021e8d60e11b815260040160405180910390fd5b60058101546006820154600160201b90910463ffffffff161115806114b1578154600360ff199091161782556006820154600583015460408051928352600160201b90910463ffffffff16602083015285917fecc4a9fb7e28d074cba7f5b227e9b5827823c850a385539b9a2f98a08f8c203d910160405180910390a25f54604051635d968dc160e11b815260048101869052600260248201526001600160a01b039091169063bb2d1b82906044015f604051808303815f87803b158015611492575f5ffd5b505af11580156114a4573d5f5f3e3d5ffd5b505f979650505050505050565b815460ff191660021782556006820154600a83018190555f816001600160401b038111156114e1576114e16135fb565b60405190808252806020026020018201604052801561150a578160200160208202803683370190505b5090505f5b8281101561157c57846008015f8660060183815481106115315761153161360f565b5f9182526020808320909101546001600160a01b0316835282019290925260400190205482518390839081106115695761156961360f565b602090810291909101015260010161150f565b505f54604051631f3ea75d60e21b8152600481018890526001600160a01b0390911690637cfa9d74906024015f604051808303815f87803b1580156115bf575f5ffd5b505af11580156115d1573d5f5f3e3d5ffd5b50505050857f4f1f5b329c741a8ba15e9645e301061294d0c1fdd455448ffd5e76ff255929d78560060183604051610ba592919061371d565b611612611e56565b6001600160a01b0381166116395760405163d92e233d60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040517fad4055f18cdad6f4bdd71afe3a72cbeee964217943e1bde38f138289e981a9a7905f90a250565b5f828152600a6020526040812090815460ff1660038111156116a6576116a6613623565b036116c457604051630d4c1d9760e41b815260040160405180910390fd5b6001815460ff1660038111156116dc576116dc613623565b146116fa57604051631860f69960e31b815260040160405180910390fd5b806003015442111561171f57604051639a19114d60e01b815260040160405180910390fd5b335f90815260078201602052604090205460ff16156117515760405163257309f160e11b815260040160405180910390fd5b61175a33610bb9565b6117775760405163149fbcfd60e11b815260040160405180910390fd5b611782338385612186565b6001810154604080516bffffffffffffffffffffffff193360601b16602080830191909152603482018690526054820187905260748083019490945282518083039094018452609490910190915281519101205f90335f8181526007850160205260409020805460ff1916600117905590915061180190839083612357565b506040805184815260208101839052339186917f52999628fb1cb05707e842278833b22e511f11746202cecdf221968b0b89e8bd910160405180910390a350505050565b5f8181526009602052604090205480611871576040516322e679e360e11b815260040160405180910390fd5b919050565b5f61188360046014612558565b905090565b5f898152600a602052604090206002815460ff1660038111156118ad576118ad613623565b146118cb57604051634f4b461f60e11b815260040160405180910390fd5b6004810154156118ee5760405163632a22bb60e01b815260040160405180910390fd5b600681015488146119375760405162461bcd60e51b815260206004820152601360248201527209cdec8ca40c6deeadce840dad2e6dac2e8c6d606b1b60448201526064016106d1565b5f61194485870187613874565b9150505f81511161198e5760405162461bcd60e51b815260206004820152601460248201527343353a206e6f207075626c696320696e7075747360601b60448201526064016106d1565b5f816001835161199e9190613917565b815181106119ae576119ae61360f565b602002602001015190505f5f5f9054906101000a90046001600160a01b03166001600160a01b031663406ed35c8e6040518263ffffffff1660e01b81526004016119fa91815260200190565b5f60405180830381865afa158015611a14573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611a3b9190810190613a0c565b610120810151604051637bf41d7760e11b81529192506001600160a01b03169063f7e83aee90611a75908b908b908b908b90600401613b92565b602060405180830381865afa158015611a90573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ab4919061364f565b5060048085018390555f8e815260096020526040808220859055905490516340a3b76160e11b81529182018f9052602482018490526001600160a01b0316906381476ec2906044015f604051808303815f87803b158015611b13575f5ffd5b505af1158015611b25573d5f5f3e3d5ffd5b505050508c7f49ac1dd411942113d1c5e6799c6379ce341afe85a4175fb562cf2a5fb886c27d8d8d8d8d8d8d604051611b6396959493929190613bc3565b60405180910390a250505050505050505050505050565b611b82611e56565b6001600160a01b038116611bab575f604051631e4fbdf760e01b81526004016106d19190613418565b61105a81611e88565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018210611bf35760405162461bcd60e51b81526004016106d190613c3c565b825464ffffffffff600160281b90910481169082168111611c515760405162461bcd60e51b815260206004820152601860248201527713185e9e5253550e881b195859881b5d5cdd08195e1a5cdd60421b60448201526064016106d1565b825f5b81866001015f611c648488612651565b64ffffffffff1681526020019081526020015f20819055505f816001611c8a9190613c86565b60ff168464ffffffffff16901c64ffffffffff16905060018564ffffffffff16901c64ffffffffff168111611cbf5750611e4e565b600185165f03611d86575f611cde83611cd9886001613c9f565b612651565b60408051808201825286815264ffffffffff83165f90815260018c0160209081529083902054908201529051632b0aac7f60e11b815291925073__$078c82ddf6c95d34ea184ef1dd6130d136$__9163561558fe91611d3f91600401613cbc565b602060405180830381865af4158015611d5a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d7e919061364f565b935050611e3a565b5f611d9683611cd9600189613cec565b60408051808201825264ffffffffff83165f90815260018c0160209081529083902054825281018790529051632b0aac7f60e11b815291925073__$078c82ddf6c95d34ea184ef1dd6130d136$__9163561558fe91611df791600401613cbc565b602060405180830381865af4158015611e12573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e36919061364f565b9350505b50647fffffffff600194851c169301611c54565b505050505050565b33611e5f61105d565b6001600160a01b031614610d76573360405163118cdaa760e01b81526004016106d19190613418565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b8154600160281b900464ffffffffff167f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018210611f475760405162461bcd60e51b81526004016106d190613c3c565b825464ffffffffff90811690821610611f9a5760405162461bcd60e51b815260206004820152601560248201527413185e9e5253550e881d1c9959481a5cc8199d5b1b605a1b60448201526064016106d1565b611fa5816001613c9f565b835464ffffffffff91909116600160281b0269ffffffffff000000000019909116178355815f5b81856001015f611fdc8487612651565b64ffffffffff16815260208101919091526040015f205560018316156120c7575f61200c82611cd9600187613cec565b60408051808201825264ffffffffff83165f90815260018a0160209081529083902054825281018690529051632b0aac7f60e11b815291925073__$078c82ddf6c95d34ea184ef1dd6130d136$__9163561558fe9161206d91600401613cbc565b602060405180830381865af4158015612088573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120ac919061364f565b647fffffffff600195861c1694909350919091019050611fcc565b5050505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610c66565b6120fe61266e565b61105a81612693565b602060ff821611156121555760405162461bcd60e51b81526020600482015260176024820152764c617a79494d543a205472656520746f6f206c6172676560481b60448201526064016106d1565b612166600160ff831681901b613917565b825469ffffffffffffffffffff191664ffffffffff919091161790915550565b5f82116121a65760405163aeaddff160e01b815260040160405180910390fd5b6001546001600160a01b03166121cf576040516350ca893360e01b815260040160405180910390fd5b5f818152600a602052604081206001805460028301549293926001600160a01b039091169163bb03bd7191889161220591613917565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381865afa15801561224c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612270919061364f565b90505f60015f9054906101000a90046001600160a01b03166001600160a01b0316631209b1f66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122c3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122e7919061364f565b90505f81116123095760405163aeaddff160e01b815260040160405180910390fd5b5f6123148284613d09565b90505f81116123365760405163149fbcfd60e11b815260040160405180910390fd5b808611156113275760405163aeaddff160e01b815260040160405180910390fd5b60058301546006840180545f92600160201b900463ffffffff16908111156123d557508054600180820183555f928352602080842090920180546001600160a01b0319166001600160a01b03881690811790915583526008870182526040808420869055600988019092529120805460ff1916821790559050612551565b5f5f90505f876008015f855f815481106123f1576123f161360f565b5f9182526020808320909101546001600160a01b03168352820192909252604001902054905060015b8454811015612479575f896008015f87848154811061243b5761243b61360f565b5f9182526020808320909101546001600160a01b03168352820192909252604001902054905082811115612470578092508193505b5060010161241a565b5080861061248d575f945050505050612551565b5f886009015f8685815481106124a5576124a561360f565b5f9182526020808320909101546001600160a01b031683528201929092526040019020805460ff191660018360028111156124e2576124e2613623565b0217905550868483815481106124fa576124fa61360f565b5f91825260208083209190910180546001600160a01b0319166001600160a01b03948516179055918916815260088a018252604080822089905560098b0190925220805460ff191660019081179091559450505050505b9392505050565b5f5f8260ff16116125ab5760405162461bcd60e51b815260206004820152601a60248201527f4c617a79494d543a206465707468206d757374206265203e203000000000000060448201526064016106d1565b602060ff831611156125cf5760405162461bcd60e51b81526004016106d190613d28565b8254600160281b900464ffffffffff16806125ee60ff85166002613e79565b64ffffffffff16101561263e5760405162461bcd60e51b8152602060048201526018602482015277098c2f4f2929aa87440c2dac4d2ceeadeeae640c8cae0e8d60431b60448201526064016106d1565b61264984828561269b565b949350505050565b5f8161266460ff851663ffffffff613e92565b6125519190613c9f565b612676612763565b610d7657604051631afcd79f60e31b815260040160405180910390fd5b611b8261266e565b5f602060ff831611156126c05760405162461bcd60e51b81526004016106d190613d28565b8264ffffffffff165f036126de576126d78261277c565b9050612551565b5f6126ea836001613c86565b60ff166001600160401b03811115612704576127046135fb565b60405190808252806020026020018201604052801561272d578160200160208202803683370190505b50905061273c85858584612e16565b808360ff16815181106127515761275161360f565b60200260200101519150509392505050565b5f61276c6120ce565b54600160401b900460ff16919050565b5f8160ff165f0361278e57505f919050565b8160ff166001036127c057507f2098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864919050565b8160ff166002036127f257507f1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1919050565b8160ff1660030361282457507f18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238919050565b8160ff1660040361285657507f07f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a919050565b8160ff1660050361288857507f2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55919050565b8160ff166006036128ba57507f2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78919050565b8160ff166007036128ec57507f078295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d919050565b8160ff1660080361291e57507f2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61919050565b8160ff1660090361295057507f0e884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747919050565b8160ff16600a0361298257507f1b7201da72494f1e28717ad1a52eb469f95892f957713533de6175e5da190af2919050565b8160ff16600b036129b457507f1f8d8822725e36385200c0b201249819a6e6e1e4650808b5bebc6bface7d7636919050565b8160ff16600c036129e657507f2c5d82f66c914bafb9701589ba8cfcfb6162b0a12acf88a8d0879a0471b5f85a919050565b8160ff16600d03612a1857507f14c54148a0940bb820957f5adf3fa1134ef5c4aaa113f4646458f270e0bfbfd0919050565b8160ff16600e03612a4a57507f190d33b12f986f961e10c0ee44d8b9af11be25588cad89d416118e4bf4ebe80c919050565b8160ff16600f03612a7c57507f22f98aa9ce704152ac17354914ad73ed1167ae6596af510aa5b3649325e06c92919050565b8160ff16601003612aae57507f2a7c7c9b6ce5880b9f6f228d72bf6a575a526f29c66ecceef8b753d38bba7323919050565b8160ff16601103612ae057507f2e8186e558698ec1c67af9c14d463ffc470043c9c2988b954d75dd643f36b992919050565b8160ff16601203612b1257507f0f57c5571e9a4eab49e2c8cf050dae948aef6ead647392273546249d1c1ff10f919050565b8160ff16601303612b4457507f1830ee67b5fb554ad5f63d4388800e1cfe78e310697d46e43c9ce36134f72cca919050565b8160ff16601403612b7657507f2134e76ac5d21aab186c2be1dd8f84ee880a1e46eaf712f9d371b6df22191f3e919050565b8160ff16601503612ba857507f19df90ec844ebc4ffeebd866f33859b0c051d8c958ee3aa88f8f8df3db91a5b1919050565b8160ff16601603612bda57507f18cca2a66b5c0787981e69aefd84852d74af0e93ef4912b4648c05f722efe52b919050565b8160ff16601703612c0c57507f2388909415230d1b4d1304d2d54f473a628338f2efad83fadf05644549d2538d919050565b8160ff16601803612c3e57507f27171fb4a97b6cc0e9e8f543b5294de866a2af2c9c8d0b1d96e673e4529ed540919050565b8160ff16601903612c7057507f2ff6650540f629fd5711a0bc74fc0d28dcb230b9392583e5f8d59696dde6ae21919050565b8160ff16601a03612ca257507f120c58f143d491e95902f7f5277778a2e0ad5168f6add75669932630ce611518919050565b8160ff16601b03612cd457507f1f21feb70d3f21b07bf853d5e5db03071ec495a0a565a21da2d665d279483795919050565b8160ff16601c03612d0657507f24be905fa71335e14c638cc0f66a8623a826e768068a9e968bb1a1dde18a72d2919050565b8160ff16601d03612d3857507f0f8666b62ed17491c50ceadead57d4cd597ef3821d65c328744c74e553dac26d919050565b8160ff16601e03612d6a57507f0918d46bf52d98b034413f4a1a1c41594e7a7a3f6ae08cb43d1a2a230e1959ef919050565b8160ff16601f03612d9c57507f1bbeb01b4c479ecde76917645e404dfa2e26f90d0afc5a65128513ad375c5ff2919050565b8160ff16602003612dce57507f2f68a1c58e257e42a17a6c61dff5551ed560b9922ab119d5ac8e184c9734ead9919050565b60405162461bcd60e51b815260206004820152601e60248201527f4c617a79494d543a2064656661756c745a65726f2062616420696e646578000060448201526064016106d1565b602060ff83161115612e3a5760405162461bcd60e51b81526004016106d190613d28565b5f8364ffffffffff1611612e9e5760405162461bcd60e51b815260206004820152602560248201527f4c617a79494d543a206e756d626572206f66206c6561766573206d7573742062604482015264065203e20360dc1b60648201526084016106d1565b5f612eaa600185613cec565b9050600181165f03612efd57846001015f612ec55f84612651565b64ffffffffff1681526020019081526020015f2054825f81518110612eec57612eec61360f565b602002602001018181525050612f25565b612f065f61277c565b825f81518110612f1857612f1861360f565b6020026020010181815250505b5f5b8360ff168160ff161015611e4e57600182165f0361301d5773__$078c82ddf6c95d34ea184ef1dd6130d136$__63561558fe6040518060400160405280868560ff1681518110612f7957612f7961360f565b60200260200101518152602001612f8f8561277c565b8152506040518263ffffffff1660e01b8152600401612fae9190613cbc565b602060405180830381865af4158015612fc9573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612fed919061364f565b83612ff9836001613c86565b60ff168151811061300c5761300c61360f565b6020026020010181815250506131ce565b5f613029826001613c86565b60ff168664ffffffffff16901c64ffffffffff16905060018364ffffffffff16901c64ffffffffff168111156130cb575f876001015f61308085600161306f9190613c86565b60018864ffffffffff16901c612651565b64ffffffffff1681526020019081526020015f2054905080858460016130a69190613c86565b60ff16815181106130b9576130b961360f565b602002602001018181525050506131cc565b5f876001015f6130e285600188611cd99190613cec565b64ffffffffff1681526020019081526020015f2054905073__$078c82ddf6c95d34ea184ef1dd6130d136$__63561558fe6040518060400160405280848152602001888760ff16815181106131395761313961360f565b60200260200101518152506040518263ffffffff1660e01b81526004016131609190613cbc565b602060405180830381865af415801561317b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061319f919061364f565b856131ab856001613c86565b60ff16815181106131be576131be61360f565b602002602001018181525050505b505b647fffffffff600192831c169101612f27565b600183019183908215613272579160200282015f5b8382111561324057833563ffffffff1683826101000a81548163ffffffff021916908363ffffffff16021790555092602001926004016020816003010492830192600103026131f6565b80156132705782816101000a81549063ffffffff0219169055600401602081600301049283019260010302613240565b505b5061327e929150613282565b5090565b5b8082111561327e575f8155600101613283565b6001600160a01b038116811461105a575f5ffd5b5f602082840312156132ba575f5ffd5b813561255181613296565b5f602082840312156132d5575f5ffd5b5035919050565b5f8151808452602084019350602083015f5b828110156133155781516001600160a01b03168652602095860195909101906001016132ee565b5093949350505050565b5f8151808452602084019350602083015f5b82811015613315578151865260209586019590910190600101613331565b604081525f61336160408301856132dc565b8281036020840152613373818561331f565b95945050505050565b5f5f5f6080848603121561338e575f5ffd5b8335925060208401359150608084018510156133a8575f5ffd5b6040840190509250925092565b5f5f604083850312156133c6575f5ffd5b8235915060208301356133d881613296565b809150509250929050565b5f5f5f606084860312156133f5575f5ffd5b83359250602084013561340781613296565b929592945050506040919091013590565b6001600160a01b0391909116815260200190565b602081525f61255160208301846132dc565b5f5f6040838503121561344f575f5ffd5b823561345a81613296565b946020939093013593505050565b5f5f60408385031215613479575f5ffd5b50508035926020909101359150565b5f5f83601f840112613498575f5ffd5b5081356001600160401b038111156134ae575f5ffd5b6020830191508360208285010111156134c5575f5ffd5b9250929050565b5f5f5f5f5f5f5f5f5f60a08a8c0312156134e4575f5ffd5b8935985060208a01356001600160401b03811115613500575f5ffd5b8a01601f81018c13613510575f5ffd5b80356001600160401b03811115613525575f5ffd5b8c60208260051b8401011115613539575f5ffd5b6020919091019850965060408a01356001600160401b0381111561355b575f5ffd5b6135678c828d01613488565b90975095505060608a01356001600160401b03811115613585575f5ffd5b6135918c828d01613488565b90955093505060808a01356001600160401b038111156135af575f5ffd5b6135bb8c828d01613488565b915080935050809150509295985092959850929598565b634e487b7160e01b5f52601160045260245ffd5b5f816135f4576135f46135d2565b505f190190565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52602160045260245ffd5b5f60018201613648576136486135d2565b5060010190565b5f6020828403121561365f575f5ffd5b5051919050565b803563ffffffff81168114611871575f5ffd5b5f60208284031215613689575f5ffd5b61255182613666565b80820180821115610c6657610c666135d2565b84815260a0810160208201855f5b60028110156136e05763ffffffff6136ca83613666565b16835260209283019291909101906001016136b3565b50505060608201939093526080015292915050565b80518015158114611871575f5ffd5b5f60208284031215613714575f5ffd5b612551826136f5565b604080825283549082018190525f8481526020812090916060840190835b818110156137625783546001600160a01b031683526001938401936020909301920161373b565b50508381036020850152613776818661331f565b9695505050505050565b6040516101e081016001600160401b03811182821017156137a3576137a36135fb565b60405290565b604051601f8201601f191681016001600160401b03811182821017156137d1576137d16135fb565b604052919050565b5f6001600160401b038211156137f1576137f16135fb565b50601f01601f191660200190565b5f82601f83011261380e575f5ffd5b81356001600160401b03811115613827576138276135fb565b8060051b613837602082016137a9565b91825260208185018101929081019086841115613852575f5ffd5b6020860192505b83831015613776578235825260209283019290910190613859565b5f5f60408385031215613885575f5ffd5b82356001600160401b0381111561389a575f5ffd5b8301601f810185136138aa575f5ffd5b80356138bd6138b8826137d9565b6137a9565b8181528660208385010111156138d1575f5ffd5b816020840160208301375f6020838301015280945050505060208301356001600160401b03811115613901575f5ffd5b61390d858286016137ff565b9150509250929050565b81810381811115610c6657610c666135d2565b805160048110611871575f5ffd5b5f82601f830112613947575f5ffd5b604080519081016001600160401b0381118282101715613969576139696135fb565b806040525080604084018581111561397f575f5ffd5b845b81811015613999578051835260209283019201613981565b509195945050505050565b805161187181613296565b805160ff81168114611871575f5ffd5b5f82601f8301126139ce575f5ffd5b81516139dc6138b8826137d9565b8181528460208386010111156139f0575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b5f60208284031215613a1c575f5ffd5b81516001600160401b03811115613a31575f5ffd5b82016102008185031215613a43575f5ffd5b613a4b613780565b81518152613a5b6020830161392a565b602082015260408281015190820152613a778560608401613938565b606082015260a08201516080820152613a9260c083016139a4565b60a0820152613aa360e083016139af565b60c08201526101008201516001600160401b03811115613ac1575f5ffd5b613acd868285016139bf565b60e083015250613ae061012083016139a4565b610100820152613af361014083016139a4565b61012082015261016082810151610140830152610180830151908201526101a08201516001600160401b03811115613b29575f5ffd5b613b35868285016139bf565b61018083015250613b496101c083016139a4565b6101a0820152613b5c6101e083016136f5565b6101c0820152949350505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f613ba5604083018688613b6a565b8281036020840152613bb8818587613b6a565b979650505050505050565b606080825281018690525f8760808301825b89811015613c05578235613be881613296565b6001600160a01b0316825260209283019290910190600101613bd5565b508381036020850152613c1981888a613b6a565b9150508281036040840152613c2f818587613b6a565b9998505050505050505050565b6020808252602a908201527f4c617a79494d543a206c656166206d757374206265203c20534e41524b5f53436040820152691053105497d19251531160b21b606082015260800190565b60ff8181168382160190811115610c6657610c666135d2565b64ffffffffff8181168382160190811115610c6657610c666135d2565b6040810181835f5b6002811015613ce3578151835260209283019290910190600101613cc4565b50505092915050565b64ffffffffff8281168282160390811115610c6657610c666135d2565b5f82613d2357634e487b7160e01b5f52601260045260245ffd5b500490565b60208082526023908201527f4c617a79494d543a206465707468206d757374206265203c3d204d41585f44456040820152620a0a8960eb1b606082015260800190565b6001815b6001841115610f1757808504811115613d8a57613d8a6135d2565b6001841615613d9857908102905b60019390931c928002613d6f565b5f82613db457506001610c66565b81613dc057505f610c66565b8160018114613dd65760028114613de057613e12565b6001915050610c66565b60ff841115613df157613df16135d2565b6001841b915064ffffffffff821115613e0c57613e0c6135d2565b50610c66565b5060208310610133831016604e8410600b8410161715613e4a575081810a64ffffffffff811115613e4557613e456135d2565b610c66565b613e5a64ffffffffff8484613d6b565b8064ffffffffff04821115613e7157613e716135d2565b029392505050565b5f61255164ffffffffff841664ffffffffff8416613da6565b64ffffffffff8181168382160290811690818114613eb257613eb26135d2565b509291505056fea164736f6c634300081c000a", - "deployedBytecode": "0x608060405234801561000f575f5ffd5b506004361061023f575f3560e01c80639f0f874a11610135578063e59e4695116100b4578063f26ef74e11610079578063f26ef74e1461057f578063f2fde38b14610592578063f379b0df146105a5578063f52fd803146105df578063f6fc05d514610651575f5ffd5b8063e59e469514610524578063e6745e1314610537578063e82f3b701461054a578063ebf0c7171461055d578063f165053614610565575f5ffd5b8063c3a0ec30116100fa578063c3a0ec30146104bc578063ca2869a0146104cd578063cd6dc687146104ec578063da881e5a146104ff578063dbb06c9314610512575f5ffd5b80639f0f874a1461044e578063a016493014610457578063a8a4d69b14610477578063bff232c11461048a578063c2b40ae41461049d575f5ffd5b8063715018a6116101c15780638d1ddfb1116101865780638d1ddfb1146103ce5780638da5cb5b146103e45780638e5ce3ad146103ec5780639015d371146103ff5780639a7a2ffc14610412575f5ffd5b8063715018a6146103475780637c92f5241461034f578063858142431461037c5780638a78bb151461039c5780638cb89ecb146103af575f5ffd5b80632e7b716d116102075780632e7b716d146102d95780634d6861a6146102ec57806350e6d94c146102ff5780635d5047761461032157806370e36bbe14610334575f5ffd5b8063096b810a146102435780630f3e34121461025857806317d611201461026b5780632800d82914610295578063291a691b146102b6575b5f5ffd5b6102566102513660046132aa565b61065a565b005b6102566102663660046132c5565b6107a6565b61027e6102793660046132c5565b6107e9565b60405161028c92919061334f565b60405180910390f35b6102a86102a33660046132c5565b610993565b60405190815260200161028c565b6102c96102c436600461337c565b6109df565b604051901515815260200161028c565b6102c96102e73660046132aa565b610bb9565b6102c96102fa3660046132c5565b610c6c565b6102c961030d3660046132aa565b60066020525f908152604090205460ff1681565b6102c961032f3660046133b5565b610cab565b6102566103423660046132aa565b610cef565b610256610d65565b61036261035d3660046133e3565b610d78565b6040805192835263ffffffff90911660208301520161028c565b60015461038f906001600160a01b031681565b60405161028c9190613418565b6102566103aa3660046132aa565b610f1f565b6102a86103bd3660046132c5565b60096020525f908152604090205481565b600454600160281b900464ffffffffff166102a8565b61038f61105d565b600b5461038f906001600160a01b031681565b6102c961040d3660046132aa565b61108b565b6104386104203660046132aa565b60076020525f908152604090205464ffffffffff1681565b60405164ffffffffff909116815260200161028c565b6102a860035481565b61046a6104653660046132c5565b6110a8565b60405161028c919061342c565b6102c96104853660046133b5565b61113e565b6102566104983660046132aa565b611182565b6102a86104ab3660046132c5565b60086020525f908152604090205481565b6001546001600160a01b031661038f565b6102a86104db3660046132c5565b5f9081526008602052604090205490565b6102566104fa36600461343e565b6111d3565b6102c961050d3660046132c5565b611330565b5f5461038f906001600160a01b031681565b6102566105323660046132aa565b61160a565b610256610545366004613468565b611682565b6102a86105583660046132c5565b611845565b6102a8611876565b61056d601481565b60405160ff909116815260200161028c565b61025661058d3660046134cc565b611888565b6102566105a03660046132aa565b611b7a565b6004546105c19064ffffffffff80821691600160281b90041682565b6040805164ffffffffff93841681529290911660208301520161028c565b6106226105ed3660046132c5565b5f908152600a6020819052604090912090810154600590910154909163ffffffff80831692600160201b900416908284101590565b60405161028c949392919093845263ffffffff9283166020850152911660408301521515606082015260800190565b6102a860025481565b61066261105d565b6001600160a01b0316336001600160a01b0316148061068b57506001546001600160a01b031633145b6106a857604051632864c4e160e01b815260040160405180910390fd5b6106b18161108b565b81906106da576040516381e5828960e01b81526004016106d19190613418565b60405180910390fd5b506001600160a01b0381165f9081526007602052604081205464ffffffffff16906107089060049083611bb4565b6001600160a01b0382165f908152600660205260408120805460ff191690556002805491610735836135e6565b90915550506002546004546040805164ffffffffff80861682526020820194909452600160281b909204909216918101919091526001600160a01b038316907f8c008e3835f6c79bfcdb89f0f6ca8705e0b01049ee84a90b0e4da1c7ba9405d5906060015b60405180910390a25050565b6107ae611e56565b60038190556040518181527fbe772dc189863d512fa01e489c8eac204975aef1a8662d8b5a333804b5207ab79060200160405180910390a150565b5f818152600a60208190526040909120600681015491810154606092839291806001600160401b03811115610820576108206135fb565b604051908082528060200260200182016040528015610849578160200160208202803683370190505b509450806001600160401b03811115610864576108646135fb565b60405190808252806020026020018201604052801561088d578160200160208202803683370190505b5093505f805b83811015610989575f8560060182815481106108b1576108b161360f565b5f918252602090912001546001600160a01b0316905060016001600160a01b0382165f90815260098801602052604090205460ff1660028111156108f7576108f7613623565b03610980578088848151811061090f5761090f61360f565b60200260200101906001600160a01b031690816001600160a01b031681525050856008015f826001600160a01b03166001600160a01b031681526020019081526020015f20548784815181106109675761096761360f565b60209081029190910101528261097c81613637565b9350505b50600101610893565b5050505050915091565b5f818152600a6020526040812081815460ff1660038111156109b7576109b7613623565b036109d557604051630d4c1d9760e41b815260040160405180910390fd5b6003015492915050565b5f80546001600160a01b03163314610a0a5760405163e4c2a7eb60e01b815260040160405180910390fd5b5f848152600a6020526040812090815460ff166003811115610a2e57610a2e613623565b14610a4c576040516374ff462560e11b815260040160405180910390fd5b60015460408051630cc37d8f60e11b815290515f926001600160a01b031691631986fb1e9160048083019260209291908290030181865afa158015610a93573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab7919061364f565b905080610aca6040860160208701613679565b63ffffffff161115610ae26040860160208701613679565b829091610b10576040516344ec930f60e01b815263ffffffff909216600483015260248201526044016106d1565b5050815460ff1916600190811783558201859055436002830155600354610b379042613692565b6003830155610b4b600583018560026131e1565b50610b54611876565b5f87815260086020526040908190209190915560028301546003840154915188927f381d281d32f95ef8fe4e5f3b263ea6a32d03d331e1a141ae1da996dc02a7a17092610ba5928a928a92916136a5565b60405180910390a250600195945050505050565b5f610bc38261108b565b610bce57505f919050565b6001546001600160a01b0316610bf7576040516350ca893360e01b815260040160405180910390fd5b600154604051639f8a13d760e01b81526001600160a01b0390911690639f8a13d790610c27908590600401613418565b602060405180830381865afa158015610c42573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c669190613704565b92915050565b5f818152600a602052604081206001815460ff166003811115610c9157610c91613623565b14610c9e57505f92915050565b6003015442111592915050565b5f60015f848152600a602090815260408083206001600160a01b038716845260090190915290205460ff166002811115610ce757610ce7613623565b149392505050565b610cf7611e56565b6001600160a01b038116610d1e5760405163d92e233d60e01b815260040160405180910390fd5b5f80546001600160a01b0319166001600160a01b038316908117825560405190917f2c8267accd82e977550ed2349c73311183cd22e306347be4453c8d130995e3c991a250565b610d6d611e56565b610d765f611e88565b565b600b545f9081906001600160a01b03163314610da75760405163fcef374960e01b815260040160405180910390fd5b5f858152600a602052604090206002815460ff166003811115610dcc57610dcc613623565b14610dea57604051634f4b461f60e11b815260040160405180910390fd5b60058101546001600160a01b0386165f90815260098301602052604090205463ffffffff909116925060019060ff166002811115610e2a57610e2a613623565b14610e3a57600a01549150610f17565b6001600160a01b0385165f9081526009820160205260408120805460ff19166002179055600a8201805491610e6e836135e6565b919050555080600a01549250846001600160a01b0316867f6c783b92374361b4d6efaf29673b89437ee969bb3c9d2d5d86b143ad5447b8498686604051610ebf929190918252602082015260400190565b60405180910390a36040805184815263ffffffff84166020820181905285101591810182905287907f119cb11dd0a68c257d6dc9b06dcb37dd422ce276eb8bf3cd0b7079a116b8e2989060600160405180910390a250505b935093915050565b610f2761105d565b6001600160a01b0316336001600160a01b03161480610f5057506001546001600160a01b031633145b610f6d57604051632864c4e160e01b815260040160405180910390fd5b610f768161108b565b61105a5760048054600160281b900464ffffffffff1690610fa0906001600160a01b038416611ef8565b6001600160a01b0382165f908152600660209081526040808320805460ff1916600117905560079091528120805464ffffffffff841664ffffffffff199091161790556002805491610ff183613637565b90915550506002546004546040805164ffffffffff80861682526020820194909452600160281b909204909216918101919091526001600160a01b038316907f3318d261fe14a5761d2d1e21555652f623d2134c430a9883c9ad6e958bb0db539060600161079a565b50565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b03165f9081526006602052604090205460ff1690565b5f818152600a602052604090206004810154606091906110db576040516322e679e360e11b815260040160405180910390fd5b8060060180548060200260200160405190810160405280929190818152602001828054801561113157602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611113575b5050505050915050919050565b5f805f848152600a602090815260408083206001600160a01b038716845260090190915290205460ff16600281111561117957611179613623565b14159392505050565b61118a611e56565b6001600160a01b0381166111b15760405163d92e233d60e01b815260040160405180910390fd5b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b5f6111dc6120ce565b805490915060ff600160401b82041615906001600160401b03165f811580156112025750825b90505f826001600160401b0316600114801561121d5750303b155b90508115801561122b575080155b156112495760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561127357845460ff60401b1916600160401b1785555b6001600160a01b03871661129a5760405163d92e233d60e01b815260040160405180910390fd5b6112a3336120f6565b6112af60046014612107565b6112b8866107a6565b6112c061105d565b6001600160a01b0316876001600160a01b0316146112e1576112e187611b7a565b831561132757845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b5f818152600a6020526040812081815460ff16600381111561135457611354613623565b0361137257604051630d4c1d9760e41b815260040160405180910390fd5b6001815460ff16600381111561138a5761138a613623565b146113a857604051631860f69960e31b815260040160405180910390fd5b806003015442116113cc57604051632f021e8d60e11b815260040160405180910390fd5b60058101546006820154600160201b90910463ffffffff161115806114b1578154600360ff199091161782556006820154600583015460408051928352600160201b90910463ffffffff16602083015285917fecc4a9fb7e28d074cba7f5b227e9b5827823c850a385539b9a2f98a08f8c203d910160405180910390a25f54604051635d968dc160e11b815260048101869052600260248201526001600160a01b039091169063bb2d1b82906044015f604051808303815f87803b158015611492575f5ffd5b505af11580156114a4573d5f5f3e3d5ffd5b505f979650505050505050565b815460ff191660021782556006820154600a83018190555f816001600160401b038111156114e1576114e16135fb565b60405190808252806020026020018201604052801561150a578160200160208202803683370190505b5090505f5b8281101561157c57846008015f8660060183815481106115315761153161360f565b5f9182526020808320909101546001600160a01b0316835282019290925260400190205482518390839081106115695761156961360f565b602090810291909101015260010161150f565b505f54604051631f3ea75d60e21b8152600481018890526001600160a01b0390911690637cfa9d74906024015f604051808303815f87803b1580156115bf575f5ffd5b505af11580156115d1573d5f5f3e3d5ffd5b50505050857f4f1f5b329c741a8ba15e9645e301061294d0c1fdd455448ffd5e76ff255929d78560060183604051610ba592919061371d565b611612611e56565b6001600160a01b0381166116395760405163d92e233d60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040517fad4055f18cdad6f4bdd71afe3a72cbeee964217943e1bde38f138289e981a9a7905f90a250565b5f828152600a6020526040812090815460ff1660038111156116a6576116a6613623565b036116c457604051630d4c1d9760e41b815260040160405180910390fd5b6001815460ff1660038111156116dc576116dc613623565b146116fa57604051631860f69960e31b815260040160405180910390fd5b806003015442111561171f57604051639a19114d60e01b815260040160405180910390fd5b335f90815260078201602052604090205460ff16156117515760405163257309f160e11b815260040160405180910390fd5b61175a33610bb9565b6117775760405163149fbcfd60e11b815260040160405180910390fd5b611782338385612186565b6001810154604080516bffffffffffffffffffffffff193360601b16602080830191909152603482018690526054820187905260748083019490945282518083039094018452609490910190915281519101205f90335f8181526007850160205260409020805460ff1916600117905590915061180190839083612357565b506040805184815260208101839052339186917f52999628fb1cb05707e842278833b22e511f11746202cecdf221968b0b89e8bd910160405180910390a350505050565b5f8181526009602052604090205480611871576040516322e679e360e11b815260040160405180910390fd5b919050565b5f61188360046014612558565b905090565b5f898152600a602052604090206002815460ff1660038111156118ad576118ad613623565b146118cb57604051634f4b461f60e11b815260040160405180910390fd5b6004810154156118ee5760405163632a22bb60e01b815260040160405180910390fd5b600681015488146119375760405162461bcd60e51b815260206004820152601360248201527209cdec8ca40c6deeadce840dad2e6dac2e8c6d606b1b60448201526064016106d1565b5f61194485870187613874565b9150505f81511161198e5760405162461bcd60e51b815260206004820152601460248201527343353a206e6f207075626c696320696e7075747360601b60448201526064016106d1565b5f816001835161199e9190613917565b815181106119ae576119ae61360f565b602002602001015190505f5f5f9054906101000a90046001600160a01b03166001600160a01b031663406ed35c8e6040518263ffffffff1660e01b81526004016119fa91815260200190565b5f60405180830381865afa158015611a14573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611a3b9190810190613a0c565b610120810151604051637bf41d7760e11b81529192506001600160a01b03169063f7e83aee90611a75908b908b908b908b90600401613b92565b602060405180830381865afa158015611a90573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ab4919061364f565b5060048085018390555f8e815260096020526040808220859055905490516340a3b76160e11b81529182018f9052602482018490526001600160a01b0316906381476ec2906044015f604051808303815f87803b158015611b13575f5ffd5b505af1158015611b25573d5f5f3e3d5ffd5b505050508c7f49ac1dd411942113d1c5e6799c6379ce341afe85a4175fb562cf2a5fb886c27d8d8d8d8d8d8d604051611b6396959493929190613bc3565b60405180910390a250505050505050505050505050565b611b82611e56565b6001600160a01b038116611bab575f604051631e4fbdf760e01b81526004016106d19190613418565b61105a81611e88565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018210611bf35760405162461bcd60e51b81526004016106d190613c3c565b825464ffffffffff600160281b90910481169082168111611c515760405162461bcd60e51b815260206004820152601860248201527713185e9e5253550e881b195859881b5d5cdd08195e1a5cdd60421b60448201526064016106d1565b825f5b81866001015f611c648488612651565b64ffffffffff1681526020019081526020015f20819055505f816001611c8a9190613c86565b60ff168464ffffffffff16901c64ffffffffff16905060018564ffffffffff16901c64ffffffffff168111611cbf5750611e4e565b600185165f03611d86575f611cde83611cd9886001613c9f565b612651565b60408051808201825286815264ffffffffff83165f90815260018c0160209081529083902054908201529051632b0aac7f60e11b815291925073__$078c82ddf6c95d34ea184ef1dd6130d136$__9163561558fe91611d3f91600401613cbc565b602060405180830381865af4158015611d5a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d7e919061364f565b935050611e3a565b5f611d9683611cd9600189613cec565b60408051808201825264ffffffffff83165f90815260018c0160209081529083902054825281018790529051632b0aac7f60e11b815291925073__$078c82ddf6c95d34ea184ef1dd6130d136$__9163561558fe91611df791600401613cbc565b602060405180830381865af4158015611e12573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e36919061364f565b9350505b50647fffffffff600194851c169301611c54565b505050505050565b33611e5f61105d565b6001600160a01b031614610d76573360405163118cdaa760e01b81526004016106d19190613418565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b8154600160281b900464ffffffffff167f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018210611f475760405162461bcd60e51b81526004016106d190613c3c565b825464ffffffffff90811690821610611f9a5760405162461bcd60e51b815260206004820152601560248201527413185e9e5253550e881d1c9959481a5cc8199d5b1b605a1b60448201526064016106d1565b611fa5816001613c9f565b835464ffffffffff91909116600160281b0269ffffffffff000000000019909116178355815f5b81856001015f611fdc8487612651565b64ffffffffff16815260208101919091526040015f205560018316156120c7575f61200c82611cd9600187613cec565b60408051808201825264ffffffffff83165f90815260018a0160209081529083902054825281018690529051632b0aac7f60e11b815291925073__$078c82ddf6c95d34ea184ef1dd6130d136$__9163561558fe9161206d91600401613cbc565b602060405180830381865af4158015612088573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120ac919061364f565b647fffffffff600195861c1694909350919091019050611fcc565b5050505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610c66565b6120fe61266e565b61105a81612693565b602060ff821611156121555760405162461bcd60e51b81526020600482015260176024820152764c617a79494d543a205472656520746f6f206c6172676560481b60448201526064016106d1565b612166600160ff831681901b613917565b825469ffffffffffffffffffff191664ffffffffff919091161790915550565b5f82116121a65760405163aeaddff160e01b815260040160405180910390fd5b6001546001600160a01b03166121cf576040516350ca893360e01b815260040160405180910390fd5b5f818152600a602052604081206001805460028301549293926001600160a01b039091169163bb03bd7191889161220591613917565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381865afa15801561224c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612270919061364f565b90505f60015f9054906101000a90046001600160a01b03166001600160a01b0316631209b1f66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122c3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122e7919061364f565b90505f81116123095760405163aeaddff160e01b815260040160405180910390fd5b5f6123148284613d09565b90505f81116123365760405163149fbcfd60e11b815260040160405180910390fd5b808611156113275760405163aeaddff160e01b815260040160405180910390fd5b60058301546006840180545f92600160201b900463ffffffff16908111156123d557508054600180820183555f928352602080842090920180546001600160a01b0319166001600160a01b03881690811790915583526008870182526040808420869055600988019092529120805460ff1916821790559050612551565b5f5f90505f876008015f855f815481106123f1576123f161360f565b5f9182526020808320909101546001600160a01b03168352820192909252604001902054905060015b8454811015612479575f896008015f87848154811061243b5761243b61360f565b5f9182526020808320909101546001600160a01b03168352820192909252604001902054905082811115612470578092508193505b5060010161241a565b5080861061248d575f945050505050612551565b5f886009015f8685815481106124a5576124a561360f565b5f9182526020808320909101546001600160a01b031683528201929092526040019020805460ff191660018360028111156124e2576124e2613623565b0217905550868483815481106124fa576124fa61360f565b5f91825260208083209190910180546001600160a01b0319166001600160a01b03948516179055918916815260088a018252604080822089905560098b0190925220805460ff191660019081179091559450505050505b9392505050565b5f5f8260ff16116125ab5760405162461bcd60e51b815260206004820152601a60248201527f4c617a79494d543a206465707468206d757374206265203e203000000000000060448201526064016106d1565b602060ff831611156125cf5760405162461bcd60e51b81526004016106d190613d28565b8254600160281b900464ffffffffff16806125ee60ff85166002613e79565b64ffffffffff16101561263e5760405162461bcd60e51b8152602060048201526018602482015277098c2f4f2929aa87440c2dac4d2ceeadeeae640c8cae0e8d60431b60448201526064016106d1565b61264984828561269b565b949350505050565b5f8161266460ff851663ffffffff613e92565b6125519190613c9f565b612676612763565b610d7657604051631afcd79f60e31b815260040160405180910390fd5b611b8261266e565b5f602060ff831611156126c05760405162461bcd60e51b81526004016106d190613d28565b8264ffffffffff165f036126de576126d78261277c565b9050612551565b5f6126ea836001613c86565b60ff166001600160401b03811115612704576127046135fb565b60405190808252806020026020018201604052801561272d578160200160208202803683370190505b50905061273c85858584612e16565b808360ff16815181106127515761275161360f565b60200260200101519150509392505050565b5f61276c6120ce565b54600160401b900460ff16919050565b5f8160ff165f0361278e57505f919050565b8160ff166001036127c057507f2098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864919050565b8160ff166002036127f257507f1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1919050565b8160ff1660030361282457507f18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238919050565b8160ff1660040361285657507f07f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a919050565b8160ff1660050361288857507f2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55919050565b8160ff166006036128ba57507f2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78919050565b8160ff166007036128ec57507f078295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d919050565b8160ff1660080361291e57507f2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61919050565b8160ff1660090361295057507f0e884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747919050565b8160ff16600a0361298257507f1b7201da72494f1e28717ad1a52eb469f95892f957713533de6175e5da190af2919050565b8160ff16600b036129b457507f1f8d8822725e36385200c0b201249819a6e6e1e4650808b5bebc6bface7d7636919050565b8160ff16600c036129e657507f2c5d82f66c914bafb9701589ba8cfcfb6162b0a12acf88a8d0879a0471b5f85a919050565b8160ff16600d03612a1857507f14c54148a0940bb820957f5adf3fa1134ef5c4aaa113f4646458f270e0bfbfd0919050565b8160ff16600e03612a4a57507f190d33b12f986f961e10c0ee44d8b9af11be25588cad89d416118e4bf4ebe80c919050565b8160ff16600f03612a7c57507f22f98aa9ce704152ac17354914ad73ed1167ae6596af510aa5b3649325e06c92919050565b8160ff16601003612aae57507f2a7c7c9b6ce5880b9f6f228d72bf6a575a526f29c66ecceef8b753d38bba7323919050565b8160ff16601103612ae057507f2e8186e558698ec1c67af9c14d463ffc470043c9c2988b954d75dd643f36b992919050565b8160ff16601203612b1257507f0f57c5571e9a4eab49e2c8cf050dae948aef6ead647392273546249d1c1ff10f919050565b8160ff16601303612b4457507f1830ee67b5fb554ad5f63d4388800e1cfe78e310697d46e43c9ce36134f72cca919050565b8160ff16601403612b7657507f2134e76ac5d21aab186c2be1dd8f84ee880a1e46eaf712f9d371b6df22191f3e919050565b8160ff16601503612ba857507f19df90ec844ebc4ffeebd866f33859b0c051d8c958ee3aa88f8f8df3db91a5b1919050565b8160ff16601603612bda57507f18cca2a66b5c0787981e69aefd84852d74af0e93ef4912b4648c05f722efe52b919050565b8160ff16601703612c0c57507f2388909415230d1b4d1304d2d54f473a628338f2efad83fadf05644549d2538d919050565b8160ff16601803612c3e57507f27171fb4a97b6cc0e9e8f543b5294de866a2af2c9c8d0b1d96e673e4529ed540919050565b8160ff16601903612c7057507f2ff6650540f629fd5711a0bc74fc0d28dcb230b9392583e5f8d59696dde6ae21919050565b8160ff16601a03612ca257507f120c58f143d491e95902f7f5277778a2e0ad5168f6add75669932630ce611518919050565b8160ff16601b03612cd457507f1f21feb70d3f21b07bf853d5e5db03071ec495a0a565a21da2d665d279483795919050565b8160ff16601c03612d0657507f24be905fa71335e14c638cc0f66a8623a826e768068a9e968bb1a1dde18a72d2919050565b8160ff16601d03612d3857507f0f8666b62ed17491c50ceadead57d4cd597ef3821d65c328744c74e553dac26d919050565b8160ff16601e03612d6a57507f0918d46bf52d98b034413f4a1a1c41594e7a7a3f6ae08cb43d1a2a230e1959ef919050565b8160ff16601f03612d9c57507f1bbeb01b4c479ecde76917645e404dfa2e26f90d0afc5a65128513ad375c5ff2919050565b8160ff16602003612dce57507f2f68a1c58e257e42a17a6c61dff5551ed560b9922ab119d5ac8e184c9734ead9919050565b60405162461bcd60e51b815260206004820152601e60248201527f4c617a79494d543a2064656661756c745a65726f2062616420696e646578000060448201526064016106d1565b602060ff83161115612e3a5760405162461bcd60e51b81526004016106d190613d28565b5f8364ffffffffff1611612e9e5760405162461bcd60e51b815260206004820152602560248201527f4c617a79494d543a206e756d626572206f66206c6561766573206d7573742062604482015264065203e20360dc1b60648201526084016106d1565b5f612eaa600185613cec565b9050600181165f03612efd57846001015f612ec55f84612651565b64ffffffffff1681526020019081526020015f2054825f81518110612eec57612eec61360f565b602002602001018181525050612f25565b612f065f61277c565b825f81518110612f1857612f1861360f565b6020026020010181815250505b5f5b8360ff168160ff161015611e4e57600182165f0361301d5773__$078c82ddf6c95d34ea184ef1dd6130d136$__63561558fe6040518060400160405280868560ff1681518110612f7957612f7961360f565b60200260200101518152602001612f8f8561277c565b8152506040518263ffffffff1660e01b8152600401612fae9190613cbc565b602060405180830381865af4158015612fc9573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612fed919061364f565b83612ff9836001613c86565b60ff168151811061300c5761300c61360f565b6020026020010181815250506131ce565b5f613029826001613c86565b60ff168664ffffffffff16901c64ffffffffff16905060018364ffffffffff16901c64ffffffffff168111156130cb575f876001015f61308085600161306f9190613c86565b60018864ffffffffff16901c612651565b64ffffffffff1681526020019081526020015f2054905080858460016130a69190613c86565b60ff16815181106130b9576130b961360f565b602002602001018181525050506131cc565b5f876001015f6130e285600188611cd99190613cec565b64ffffffffff1681526020019081526020015f2054905073__$078c82ddf6c95d34ea184ef1dd6130d136$__63561558fe6040518060400160405280848152602001888760ff16815181106131395761313961360f565b60200260200101518152506040518263ffffffff1660e01b81526004016131609190613cbc565b602060405180830381865af415801561317b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061319f919061364f565b856131ab856001613c86565b60ff16815181106131be576131be61360f565b602002602001018181525050505b505b647fffffffff600192831c169101612f27565b600183019183908215613272579160200282015f5b8382111561324057833563ffffffff1683826101000a81548163ffffffff021916908363ffffffff16021790555092602001926004016020816003010492830192600103026131f6565b80156132705782816101000a81549063ffffffff0219169055600401602081600301049283019260010302613240565b505b5061327e929150613282565b5090565b5b8082111561327e575f8155600101613283565b6001600160a01b038116811461105a575f5ffd5b5f602082840312156132ba575f5ffd5b813561255181613296565b5f602082840312156132d5575f5ffd5b5035919050565b5f8151808452602084019350602083015f5b828110156133155781516001600160a01b03168652602095860195909101906001016132ee565b5093949350505050565b5f8151808452602084019350602083015f5b82811015613315578151865260209586019590910190600101613331565b604081525f61336160408301856132dc565b8281036020840152613373818561331f565b95945050505050565b5f5f5f6080848603121561338e575f5ffd5b8335925060208401359150608084018510156133a8575f5ffd5b6040840190509250925092565b5f5f604083850312156133c6575f5ffd5b8235915060208301356133d881613296565b809150509250929050565b5f5f5f606084860312156133f5575f5ffd5b83359250602084013561340781613296565b929592945050506040919091013590565b6001600160a01b0391909116815260200190565b602081525f61255160208301846132dc565b5f5f6040838503121561344f575f5ffd5b823561345a81613296565b946020939093013593505050565b5f5f60408385031215613479575f5ffd5b50508035926020909101359150565b5f5f83601f840112613498575f5ffd5b5081356001600160401b038111156134ae575f5ffd5b6020830191508360208285010111156134c5575f5ffd5b9250929050565b5f5f5f5f5f5f5f5f5f60a08a8c0312156134e4575f5ffd5b8935985060208a01356001600160401b03811115613500575f5ffd5b8a01601f81018c13613510575f5ffd5b80356001600160401b03811115613525575f5ffd5b8c60208260051b8401011115613539575f5ffd5b6020919091019850965060408a01356001600160401b0381111561355b575f5ffd5b6135678c828d01613488565b90975095505060608a01356001600160401b03811115613585575f5ffd5b6135918c828d01613488565b90955093505060808a01356001600160401b038111156135af575f5ffd5b6135bb8c828d01613488565b915080935050809150509295985092959850929598565b634e487b7160e01b5f52601160045260245ffd5b5f816135f4576135f46135d2565b505f190190565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52602160045260245ffd5b5f60018201613648576136486135d2565b5060010190565b5f6020828403121561365f575f5ffd5b5051919050565b803563ffffffff81168114611871575f5ffd5b5f60208284031215613689575f5ffd5b61255182613666565b80820180821115610c6657610c666135d2565b84815260a0810160208201855f5b60028110156136e05763ffffffff6136ca83613666565b16835260209283019291909101906001016136b3565b50505060608201939093526080015292915050565b80518015158114611871575f5ffd5b5f60208284031215613714575f5ffd5b612551826136f5565b604080825283549082018190525f8481526020812090916060840190835b818110156137625783546001600160a01b031683526001938401936020909301920161373b565b50508381036020850152613776818661331f565b9695505050505050565b6040516101e081016001600160401b03811182821017156137a3576137a36135fb565b60405290565b604051601f8201601f191681016001600160401b03811182821017156137d1576137d16135fb565b604052919050565b5f6001600160401b038211156137f1576137f16135fb565b50601f01601f191660200190565b5f82601f83011261380e575f5ffd5b81356001600160401b03811115613827576138276135fb565b8060051b613837602082016137a9565b91825260208185018101929081019086841115613852575f5ffd5b6020860192505b83831015613776578235825260209283019290910190613859565b5f5f60408385031215613885575f5ffd5b82356001600160401b0381111561389a575f5ffd5b8301601f810185136138aa575f5ffd5b80356138bd6138b8826137d9565b6137a9565b8181528660208385010111156138d1575f5ffd5b816020840160208301375f6020838301015280945050505060208301356001600160401b03811115613901575f5ffd5b61390d858286016137ff565b9150509250929050565b81810381811115610c6657610c666135d2565b805160048110611871575f5ffd5b5f82601f830112613947575f5ffd5b604080519081016001600160401b0381118282101715613969576139696135fb565b806040525080604084018581111561397f575f5ffd5b845b81811015613999578051835260209283019201613981565b509195945050505050565b805161187181613296565b805160ff81168114611871575f5ffd5b5f82601f8301126139ce575f5ffd5b81516139dc6138b8826137d9565b8181528460208386010111156139f0575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b5f60208284031215613a1c575f5ffd5b81516001600160401b03811115613a31575f5ffd5b82016102008185031215613a43575f5ffd5b613a4b613780565b81518152613a5b6020830161392a565b602082015260408281015190820152613a778560608401613938565b606082015260a08201516080820152613a9260c083016139a4565b60a0820152613aa360e083016139af565b60c08201526101008201516001600160401b03811115613ac1575f5ffd5b613acd868285016139bf565b60e083015250613ae061012083016139a4565b610100820152613af361014083016139a4565b61012082015261016082810151610140830152610180830151908201526101a08201516001600160401b03811115613b29575f5ffd5b613b35868285016139bf565b61018083015250613b496101c083016139a4565b6101a0820152613b5c6101e083016136f5565b6101c0820152949350505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f613ba5604083018688613b6a565b8281036020840152613bb8818587613b6a565b979650505050505050565b606080825281018690525f8760808301825b89811015613c05578235613be881613296565b6001600160a01b0316825260209283019290910190600101613bd5565b508381036020850152613c1981888a613b6a565b9150508281036040840152613c2f818587613b6a565b9998505050505050505050565b6020808252602a908201527f4c617a79494d543a206c656166206d757374206265203c20534e41524b5f53436040820152691053105497d19251531160b21b606082015260800190565b60ff8181168382160190811115610c6657610c666135d2565b64ffffffffff8181168382160190811115610c6657610c666135d2565b6040810181835f5b6002811015613ce3578151835260209283019290910190600101613cc4565b50505092915050565b64ffffffffff8281168282160390811115610c6657610c666135d2565b5f82613d2357634e487b7160e01b5f52601260045260245ffd5b500490565b60208082526023908201527f4c617a79494d543a206465707468206d757374206265203c3d204d41585f44456040820152620a0a8960eb1b606082015260800190565b6001815b6001841115610f1757808504811115613d8a57613d8a6135d2565b6001841615613d9857908102905b60019390931c928002613d6f565b5f82613db457506001610c66565b81613dc057505f610c66565b8160018114613dd65760028114613de057613e12565b6001915050610c66565b60ff841115613df157613df16135d2565b6001841b915064ffffffffff821115613e0c57613e0c6135d2565b50610c66565b5060208310610133831016604e8410600b8410161715613e4a575081810a64ffffffffff811115613e4557613e456135d2565b610c66565b613e5a64ffffffffff8484613d6b565b8064ffffffffff04821115613e7157613e716135d2565b029392505050565b5f61255164ffffffffff841664ffffffffff8416613da6565b64ffffffffff8181168382160290811690818114613eb257613eb26135d2565b509291505056fea164736f6c634300081c000a", + "bytecode": "0x6080604052348015600e575f5ffd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b613ed1806100d65f395ff3fe608060405234801561000f575f5ffd5b506004361061023f575f3560e01c80639f0f874a11610135578063e59e4695116100b4578063f26ef74e11610079578063f26ef74e1461057f578063f2fde38b14610592578063f379b0df146105a5578063f52fd803146105df578063f6fc05d514610651575f5ffd5b8063e59e469514610524578063e6745e1314610537578063e82f3b701461054a578063ebf0c7171461055d578063f165053614610565575f5ffd5b8063c3a0ec30116100fa578063c3a0ec30146104bc578063ca2869a0146104cd578063cd6dc687146104ec578063da881e5a146104ff578063dbb06c9314610512575f5ffd5b80639f0f874a1461044e578063a016493014610457578063a8a4d69b14610477578063bff232c11461048a578063c2b40ae41461049d575f5ffd5b8063715018a6116101c15780638d1ddfb1116101865780638d1ddfb1146103ce5780638da5cb5b146103e45780638e5ce3ad146103ec5780639015d371146103ff5780639a7a2ffc14610412575f5ffd5b8063715018a6146103475780637c92f5241461034f578063858142431461037c5780638a78bb151461039c5780638cb89ecb146103af575f5ffd5b80632e7b716d116102075780632e7b716d146102d95780634d6861a6146102ec57806350e6d94c146102ff5780635d5047761461032157806370e36bbe14610334575f5ffd5b8063096b810a146102435780630f3e34121461025857806317d611201461026b5780632800d82914610295578063291a691b146102b6575b5f5ffd5b6102566102513660046132b5565b61065a565b005b6102566102663660046132d0565b6107a6565b61027e6102793660046132d0565b6107e9565b60405161028c92919061335a565b60405180910390f35b6102a86102a33660046132d0565b610993565b60405190815260200161028c565b6102c96102c4366004613387565b6109df565b604051901515815260200161028c565b6102c96102e73660046132b5565b610bb9565b6102c96102fa3660046132d0565b610c6c565b6102c961030d3660046132b5565b60066020525f908152604090205460ff1681565b6102c961032f3660046133c0565b610cab565b6102566103423660046132b5565b610cef565b610256610d65565b61036261035d3660046133ee565b610d78565b6040805192835263ffffffff90911660208301520161028c565b60015461038f906001600160a01b031681565b60405161028c9190613423565b6102566103aa3660046132b5565b610f1f565b6102a86103bd3660046132d0565b60096020525f908152604090205481565b600454600160281b900464ffffffffff166102a8565b61038f61105d565b600b5461038f906001600160a01b031681565b6102c961040d3660046132b5565b61108b565b6104386104203660046132b5565b60076020525f908152604090205464ffffffffff1681565b60405164ffffffffff909116815260200161028c565b6102a860035481565b61046a6104653660046132d0565b6110a8565b60405161028c9190613437565b6102c96104853660046133c0565b61113e565b6102566104983660046132b5565b611182565b6102a86104ab3660046132d0565b60086020525f908152604090205481565b6001546001600160a01b031661038f565b6102a86104db3660046132d0565b5f9081526008602052604090205490565b6102566104fa366004613449565b6111d3565b6102c961050d3660046132d0565b611330565b5f5461038f906001600160a01b031681565b6102566105323660046132b5565b61160a565b610256610545366004613473565b611682565b6102a86105583660046132d0565b611845565b6102a8611876565b61056d601481565b60405160ff909116815260200161028c565b61025661058d3660046134d7565b611888565b6102566105a03660046132b5565b611b85565b6004546105c19064ffffffffff80821691600160281b90041682565b6040805164ffffffffff93841681529290911660208301520161028c565b6106226105ed3660046132d0565b5f908152600a6020819052604090912090810154600590910154909163ffffffff80831692600160201b900416908284101590565b60405161028c949392919093845263ffffffff9283166020850152911660408301521515606082015260800190565b6102a860025481565b61066261105d565b6001600160a01b0316336001600160a01b0316148061068b57506001546001600160a01b031633145b6106a857604051632864c4e160e01b815260040160405180910390fd5b6106b18161108b565b81906106da576040516381e5828960e01b81526004016106d19190613423565b60405180910390fd5b506001600160a01b0381165f9081526007602052604081205464ffffffffff16906107089060049083611bbf565b6001600160a01b0382165f908152600660205260408120805460ff191690556002805491610735836135f1565b90915550506002546004546040805164ffffffffff80861682526020820194909452600160281b909204909216918101919091526001600160a01b038316907f8c008e3835f6c79bfcdb89f0f6ca8705e0b01049ee84a90b0e4da1c7ba9405d5906060015b60405180910390a25050565b6107ae611e61565b60038190556040518181527fbe772dc189863d512fa01e489c8eac204975aef1a8662d8b5a333804b5207ab79060200160405180910390a150565b5f818152600a60208190526040909120600681015491810154606092839291806001600160401b0381111561082057610820613606565b604051908082528060200260200182016040528015610849578160200160208202803683370190505b509450806001600160401b0381111561086457610864613606565b60405190808252806020026020018201604052801561088d578160200160208202803683370190505b5093505f805b83811015610989575f8560060182815481106108b1576108b161361a565b5f918252602090912001546001600160a01b0316905060016001600160a01b0382165f90815260098801602052604090205460ff1660028111156108f7576108f761362e565b03610980578088848151811061090f5761090f61361a565b60200260200101906001600160a01b031690816001600160a01b031681525050856008015f826001600160a01b03166001600160a01b031681526020019081526020015f20548784815181106109675761096761361a565b60209081029190910101528261097c81613642565b9350505b50600101610893565b5050505050915091565b5f818152600a6020526040812081815460ff1660038111156109b7576109b761362e565b036109d557604051630d4c1d9760e41b815260040160405180910390fd5b6003015492915050565b5f80546001600160a01b03163314610a0a5760405163e4c2a7eb60e01b815260040160405180910390fd5b5f848152600a6020526040812090815460ff166003811115610a2e57610a2e61362e565b14610a4c576040516374ff462560e11b815260040160405180910390fd5b60015460408051630cc37d8f60e11b815290515f926001600160a01b031691631986fb1e9160048083019260209291908290030181865afa158015610a93573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab7919061365a565b905080610aca6040860160208701613684565b63ffffffff161115610ae26040860160208701613684565b829091610b10576040516344ec930f60e01b815263ffffffff909216600483015260248201526044016106d1565b5050815460ff1916600190811783558201859055436002830155600354610b37904261369d565b6003830155610b4b600583018560026131ec565b50610b54611876565b5f87815260086020526040908190209190915560028301546003840154915188927f381d281d32f95ef8fe4e5f3b263ea6a32d03d331e1a141ae1da996dc02a7a17092610ba5928a928a92916136b0565b60405180910390a250600195945050505050565b5f610bc38261108b565b610bce57505f919050565b6001546001600160a01b0316610bf7576040516350ca893360e01b815260040160405180910390fd5b600154604051639f8a13d760e01b81526001600160a01b0390911690639f8a13d790610c27908590600401613423565b602060405180830381865afa158015610c42573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c66919061370f565b92915050565b5f818152600a602052604081206001815460ff166003811115610c9157610c9161362e565b14610c9e57505f92915050565b6003015442111592915050565b5f60015f848152600a602090815260408083206001600160a01b038716845260090190915290205460ff166002811115610ce757610ce761362e565b149392505050565b610cf7611e61565b6001600160a01b038116610d1e5760405163d92e233d60e01b815260040160405180910390fd5b5f80546001600160a01b0319166001600160a01b038316908117825560405190917f2c8267accd82e977550ed2349c73311183cd22e306347be4453c8d130995e3c991a250565b610d6d611e61565b610d765f611e93565b565b600b545f9081906001600160a01b03163314610da75760405163fcef374960e01b815260040160405180910390fd5b5f858152600a602052604090206002815460ff166003811115610dcc57610dcc61362e565b14610dea57604051634f4b461f60e11b815260040160405180910390fd5b60058101546001600160a01b0386165f90815260098301602052604090205463ffffffff909116925060019060ff166002811115610e2a57610e2a61362e565b14610e3a57600a01549150610f17565b6001600160a01b0385165f9081526009820160205260408120805460ff19166002179055600a8201805491610e6e836135f1565b919050555080600a01549250846001600160a01b0316867f6c783b92374361b4d6efaf29673b89437ee969bb3c9d2d5d86b143ad5447b8498686604051610ebf929190918252602082015260400190565b60405180910390a36040805184815263ffffffff84166020820181905285101591810182905287907f119cb11dd0a68c257d6dc9b06dcb37dd422ce276eb8bf3cd0b7079a116b8e2989060600160405180910390a250505b935093915050565b610f2761105d565b6001600160a01b0316336001600160a01b03161480610f5057506001546001600160a01b031633145b610f6d57604051632864c4e160e01b815260040160405180910390fd5b610f768161108b565b61105a5760048054600160281b900464ffffffffff1690610fa0906001600160a01b038416611f03565b6001600160a01b0382165f908152600660209081526040808320805460ff1916600117905560079091528120805464ffffffffff841664ffffffffff199091161790556002805491610ff183613642565b90915550506002546004546040805164ffffffffff80861682526020820194909452600160281b909204909216918101919091526001600160a01b038316907f3318d261fe14a5761d2d1e21555652f623d2134c430a9883c9ad6e958bb0db539060600161079a565b50565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b03165f9081526006602052604090205460ff1690565b5f818152600a602052604090206004810154606091906110db576040516322e679e360e11b815260040160405180910390fd5b8060060180548060200260200160405190810160405280929190818152602001828054801561113157602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611113575b5050505050915050919050565b5f805f848152600a602090815260408083206001600160a01b038716845260090190915290205460ff1660028111156111795761117961362e565b14159392505050565b61118a611e61565b6001600160a01b0381166111b15760405163d92e233d60e01b815260040160405180910390fd5b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b5f6111dc6120d9565b805490915060ff600160401b82041615906001600160401b03165f811580156112025750825b90505f826001600160401b0316600114801561121d5750303b155b90508115801561122b575080155b156112495760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561127357845460ff60401b1916600160401b1785555b6001600160a01b03871661129a5760405163d92e233d60e01b815260040160405180910390fd5b6112a333612101565b6112af60046014612112565b6112b8866107a6565b6112c061105d565b6001600160a01b0316876001600160a01b0316146112e1576112e187611b85565b831561132757845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b5f818152600a6020526040812081815460ff1660038111156113545761135461362e565b0361137257604051630d4c1d9760e41b815260040160405180910390fd5b6001815460ff16600381111561138a5761138a61362e565b146113a857604051631860f69960e31b815260040160405180910390fd5b806003015442116113cc57604051632f021e8d60e11b815260040160405180910390fd5b60058101546006820154600160201b90910463ffffffff161115806114b1578154600360ff199091161782556006820154600583015460408051928352600160201b90910463ffffffff16602083015285917fecc4a9fb7e28d074cba7f5b227e9b5827823c850a385539b9a2f98a08f8c203d910160405180910390a25f54604051635d968dc160e11b815260048101869052600260248201526001600160a01b039091169063bb2d1b82906044015f604051808303815f87803b158015611492575f5ffd5b505af11580156114a4573d5f5f3e3d5ffd5b505f979650505050505050565b815460ff191660021782556006820154600a83018190555f816001600160401b038111156114e1576114e1613606565b60405190808252806020026020018201604052801561150a578160200160208202803683370190505b5090505f5b8281101561157c57846008015f8660060183815481106115315761153161361a565b5f9182526020808320909101546001600160a01b0316835282019290925260400190205482518390839081106115695761156961361a565b602090810291909101015260010161150f565b505f54604051631f3ea75d60e21b8152600481018890526001600160a01b0390911690637cfa9d74906024015f604051808303815f87803b1580156115bf575f5ffd5b505af11580156115d1573d5f5f3e3d5ffd5b50505050857f4f1f5b329c741a8ba15e9645e301061294d0c1fdd455448ffd5e76ff255929d78560060183604051610ba5929190613728565b611612611e61565b6001600160a01b0381166116395760405163d92e233d60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040517fad4055f18cdad6f4bdd71afe3a72cbeee964217943e1bde38f138289e981a9a7905f90a250565b5f828152600a6020526040812090815460ff1660038111156116a6576116a661362e565b036116c457604051630d4c1d9760e41b815260040160405180910390fd5b6001815460ff1660038111156116dc576116dc61362e565b146116fa57604051631860f69960e31b815260040160405180910390fd5b806003015442111561171f57604051639a19114d60e01b815260040160405180910390fd5b335f90815260078201602052604090205460ff16156117515760405163257309f160e11b815260040160405180910390fd5b61175a33610bb9565b6117775760405163149fbcfd60e11b815260040160405180910390fd5b611782338385612191565b6001810154604080516bffffffffffffffffffffffff193360601b16602080830191909152603482018690526054820187905260748083019490945282518083039094018452609490910190915281519101205f90335f8181526007850160205260409020805460ff1916600117905590915061180190839083612362565b506040805184815260208101839052339186917f52999628fb1cb05707e842278833b22e511f11746202cecdf221968b0b89e8bd910160405180910390a350505050565b5f8181526009602052604090205480611871576040516322e679e360e11b815260040160405180910390fd5b919050565b5f61188360046014612563565b905090565b5f898152600a602052604090206002815460ff1660038111156118ad576118ad61362e565b146118cb57604051634f4b461f60e11b815260040160405180910390fd5b6004810154156118ee5760405163632a22bb60e01b815260040160405180910390fd5b600681015488146119375760405162461bcd60e51b815260206004820152601360248201527209cdec8ca40c6deeadce840dad2e6dac2e8c6d606b1b60448201526064016106d1565b5f6119448587018761387f565b9150505f81511161198e5760405162461bcd60e51b815260206004820152601460248201527343353a206e6f207075626c696320696e7075747360601b60448201526064016106d1565b5f816001835161199e9190613922565b815181106119ae576119ae61361a565b602002602001015190505f5f5f9054906101000a90046001600160a01b03166001600160a01b031663406ed35c8e6040518263ffffffff1660e01b81526004016119fa91815260200190565b5f60405180830381865afa158015611a14573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611a3b9190810190613a17565b9050806101c0015115611ac0578061012001516001600160a01b031663f7e83aee898989896040518563ffffffff1660e01b8152600401611a7f9493929190613b9d565b602060405180830381865afa158015611a9a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611abe919061365a565b505b60048085018390555f8e815260096020526040808220859055905490516340a3b76160e11b81529182018f9052602482018490526001600160a01b0316906381476ec2906044015f604051808303815f87803b158015611b1e575f5ffd5b505af1158015611b30573d5f5f3e3d5ffd5b505050508c7f49ac1dd411942113d1c5e6799c6379ce341afe85a4175fb562cf2a5fb886c27d8d8d8d8d8d8d604051611b6e96959493929190613bce565b60405180910390a250505050505050505050505050565b611b8d611e61565b6001600160a01b038116611bb6575f604051631e4fbdf760e01b81526004016106d19190613423565b61105a81611e93565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018210611bfe5760405162461bcd60e51b81526004016106d190613c47565b825464ffffffffff600160281b90910481169082168111611c5c5760405162461bcd60e51b815260206004820152601860248201527713185e9e5253550e881b195859881b5d5cdd08195e1a5cdd60421b60448201526064016106d1565b825f5b81866001015f611c6f848861265c565b64ffffffffff1681526020019081526020015f20819055505f816001611c959190613c91565b60ff168464ffffffffff16901c64ffffffffff16905060018564ffffffffff16901c64ffffffffff168111611cca5750611e59565b600185165f03611d91575f611ce983611ce4886001613caa565b61265c565b60408051808201825286815264ffffffffff83165f90815260018c0160209081529083902054908201529051632b0aac7f60e11b815291925073__$078c82ddf6c95d34ea184ef1dd6130d136$__9163561558fe91611d4a91600401613cc7565b602060405180830381865af4158015611d65573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d89919061365a565b935050611e45565b5f611da183611ce4600189613cf7565b60408051808201825264ffffffffff83165f90815260018c0160209081529083902054825281018790529051632b0aac7f60e11b815291925073__$078c82ddf6c95d34ea184ef1dd6130d136$__9163561558fe91611e0291600401613cc7565b602060405180830381865af4158015611e1d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e41919061365a565b9350505b50647fffffffff600194851c169301611c5f565b505050505050565b33611e6a61105d565b6001600160a01b031614610d76573360405163118cdaa760e01b81526004016106d19190613423565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b8154600160281b900464ffffffffff167f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018210611f525760405162461bcd60e51b81526004016106d190613c47565b825464ffffffffff90811690821610611fa55760405162461bcd60e51b815260206004820152601560248201527413185e9e5253550e881d1c9959481a5cc8199d5b1b605a1b60448201526064016106d1565b611fb0816001613caa565b835464ffffffffff91909116600160281b0269ffffffffff000000000019909116178355815f5b81856001015f611fe7848761265c565b64ffffffffff16815260208101919091526040015f205560018316156120d2575f61201782611ce4600187613cf7565b60408051808201825264ffffffffff83165f90815260018a0160209081529083902054825281018690529051632b0aac7f60e11b815291925073__$078c82ddf6c95d34ea184ef1dd6130d136$__9163561558fe9161207891600401613cc7565b602060405180830381865af4158015612093573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120b7919061365a565b647fffffffff600195861c1694909350919091019050611fd7565b5050505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610c66565b612109612679565b61105a8161269e565b602060ff821611156121605760405162461bcd60e51b81526020600482015260176024820152764c617a79494d543a205472656520746f6f206c6172676560481b60448201526064016106d1565b612171600160ff831681901b613922565b825469ffffffffffffffffffff191664ffffffffff919091161790915550565b5f82116121b15760405163aeaddff160e01b815260040160405180910390fd5b6001546001600160a01b03166121da576040516350ca893360e01b815260040160405180910390fd5b5f818152600a602052604081206001805460028301549293926001600160a01b039091169163bb03bd7191889161221091613922565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381865afa158015612257573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061227b919061365a565b90505f60015f9054906101000a90046001600160a01b03166001600160a01b0316631209b1f66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122ce573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122f2919061365a565b90505f81116123145760405163aeaddff160e01b815260040160405180910390fd5b5f61231f8284613d14565b90505f81116123415760405163149fbcfd60e11b815260040160405180910390fd5b808611156113275760405163aeaddff160e01b815260040160405180910390fd5b60058301546006840180545f92600160201b900463ffffffff16908111156123e057508054600180820183555f928352602080842090920180546001600160a01b0319166001600160a01b03881690811790915583526008870182526040808420869055600988019092529120805460ff191682179055905061255c565b5f5f90505f876008015f855f815481106123fc576123fc61361a565b5f9182526020808320909101546001600160a01b03168352820192909252604001902054905060015b8454811015612484575f896008015f8784815481106124465761244661361a565b5f9182526020808320909101546001600160a01b0316835282019290925260400190205490508281111561247b578092508193505b50600101612425565b50808610612498575f94505050505061255c565b5f886009015f8685815481106124b0576124b061361a565b5f9182526020808320909101546001600160a01b031683528201929092526040019020805460ff191660018360028111156124ed576124ed61362e565b0217905550868483815481106125055761250561361a565b5f91825260208083209190910180546001600160a01b0319166001600160a01b03948516179055918916815260088a018252604080822089905560098b0190925220805460ff191660019081179091559450505050505b9392505050565b5f5f8260ff16116125b65760405162461bcd60e51b815260206004820152601a60248201527f4c617a79494d543a206465707468206d757374206265203e203000000000000060448201526064016106d1565b602060ff831611156125da5760405162461bcd60e51b81526004016106d190613d33565b8254600160281b900464ffffffffff16806125f960ff85166002613e84565b64ffffffffff1610156126495760405162461bcd60e51b8152602060048201526018602482015277098c2f4f2929aa87440c2dac4d2ceeadeeae640c8cae0e8d60431b60448201526064016106d1565b6126548482856126a6565b949350505050565b5f8161266f60ff851663ffffffff613e9d565b61255c9190613caa565b61268161276e565b610d7657604051631afcd79f60e31b815260040160405180910390fd5b611b8d612679565b5f602060ff831611156126cb5760405162461bcd60e51b81526004016106d190613d33565b8264ffffffffff165f036126e9576126e282612787565b905061255c565b5f6126f5836001613c91565b60ff166001600160401b0381111561270f5761270f613606565b604051908082528060200260200182016040528015612738578160200160208202803683370190505b50905061274785858584612e21565b808360ff168151811061275c5761275c61361a565b60200260200101519150509392505050565b5f6127776120d9565b54600160401b900460ff16919050565b5f8160ff165f0361279957505f919050565b8160ff166001036127cb57507f2098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864919050565b8160ff166002036127fd57507f1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1919050565b8160ff1660030361282f57507f18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238919050565b8160ff1660040361286157507f07f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a919050565b8160ff1660050361289357507f2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55919050565b8160ff166006036128c557507f2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78919050565b8160ff166007036128f757507f078295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d919050565b8160ff1660080361292957507f2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61919050565b8160ff1660090361295b57507f0e884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747919050565b8160ff16600a0361298d57507f1b7201da72494f1e28717ad1a52eb469f95892f957713533de6175e5da190af2919050565b8160ff16600b036129bf57507f1f8d8822725e36385200c0b201249819a6e6e1e4650808b5bebc6bface7d7636919050565b8160ff16600c036129f157507f2c5d82f66c914bafb9701589ba8cfcfb6162b0a12acf88a8d0879a0471b5f85a919050565b8160ff16600d03612a2357507f14c54148a0940bb820957f5adf3fa1134ef5c4aaa113f4646458f270e0bfbfd0919050565b8160ff16600e03612a5557507f190d33b12f986f961e10c0ee44d8b9af11be25588cad89d416118e4bf4ebe80c919050565b8160ff16600f03612a8757507f22f98aa9ce704152ac17354914ad73ed1167ae6596af510aa5b3649325e06c92919050565b8160ff16601003612ab957507f2a7c7c9b6ce5880b9f6f228d72bf6a575a526f29c66ecceef8b753d38bba7323919050565b8160ff16601103612aeb57507f2e8186e558698ec1c67af9c14d463ffc470043c9c2988b954d75dd643f36b992919050565b8160ff16601203612b1d57507f0f57c5571e9a4eab49e2c8cf050dae948aef6ead647392273546249d1c1ff10f919050565b8160ff16601303612b4f57507f1830ee67b5fb554ad5f63d4388800e1cfe78e310697d46e43c9ce36134f72cca919050565b8160ff16601403612b8157507f2134e76ac5d21aab186c2be1dd8f84ee880a1e46eaf712f9d371b6df22191f3e919050565b8160ff16601503612bb357507f19df90ec844ebc4ffeebd866f33859b0c051d8c958ee3aa88f8f8df3db91a5b1919050565b8160ff16601603612be557507f18cca2a66b5c0787981e69aefd84852d74af0e93ef4912b4648c05f722efe52b919050565b8160ff16601703612c1757507f2388909415230d1b4d1304d2d54f473a628338f2efad83fadf05644549d2538d919050565b8160ff16601803612c4957507f27171fb4a97b6cc0e9e8f543b5294de866a2af2c9c8d0b1d96e673e4529ed540919050565b8160ff16601903612c7b57507f2ff6650540f629fd5711a0bc74fc0d28dcb230b9392583e5f8d59696dde6ae21919050565b8160ff16601a03612cad57507f120c58f143d491e95902f7f5277778a2e0ad5168f6add75669932630ce611518919050565b8160ff16601b03612cdf57507f1f21feb70d3f21b07bf853d5e5db03071ec495a0a565a21da2d665d279483795919050565b8160ff16601c03612d1157507f24be905fa71335e14c638cc0f66a8623a826e768068a9e968bb1a1dde18a72d2919050565b8160ff16601d03612d4357507f0f8666b62ed17491c50ceadead57d4cd597ef3821d65c328744c74e553dac26d919050565b8160ff16601e03612d7557507f0918d46bf52d98b034413f4a1a1c41594e7a7a3f6ae08cb43d1a2a230e1959ef919050565b8160ff16601f03612da757507f1bbeb01b4c479ecde76917645e404dfa2e26f90d0afc5a65128513ad375c5ff2919050565b8160ff16602003612dd957507f2f68a1c58e257e42a17a6c61dff5551ed560b9922ab119d5ac8e184c9734ead9919050565b60405162461bcd60e51b815260206004820152601e60248201527f4c617a79494d543a2064656661756c745a65726f2062616420696e646578000060448201526064016106d1565b602060ff83161115612e455760405162461bcd60e51b81526004016106d190613d33565b5f8364ffffffffff1611612ea95760405162461bcd60e51b815260206004820152602560248201527f4c617a79494d543a206e756d626572206f66206c6561766573206d7573742062604482015264065203e20360dc1b60648201526084016106d1565b5f612eb5600185613cf7565b9050600181165f03612f0857846001015f612ed05f8461265c565b64ffffffffff1681526020019081526020015f2054825f81518110612ef757612ef761361a565b602002602001018181525050612f30565b612f115f612787565b825f81518110612f2357612f2361361a565b6020026020010181815250505b5f5b8360ff168160ff161015611e5957600182165f036130285773__$078c82ddf6c95d34ea184ef1dd6130d136$__63561558fe6040518060400160405280868560ff1681518110612f8457612f8461361a565b60200260200101518152602001612f9a85612787565b8152506040518263ffffffff1660e01b8152600401612fb99190613cc7565b602060405180830381865af4158015612fd4573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ff8919061365a565b83613004836001613c91565b60ff16815181106130175761301761361a565b6020026020010181815250506131d9565b5f613034826001613c91565b60ff168664ffffffffff16901c64ffffffffff16905060018364ffffffffff16901c64ffffffffff168111156130d6575f876001015f61308b85600161307a9190613c91565b60018864ffffffffff16901c61265c565b64ffffffffff1681526020019081526020015f2054905080858460016130b19190613c91565b60ff16815181106130c4576130c461361a565b602002602001018181525050506131d7565b5f876001015f6130ed85600188611ce49190613cf7565b64ffffffffff1681526020019081526020015f2054905073__$078c82ddf6c95d34ea184ef1dd6130d136$__63561558fe6040518060400160405280848152602001888760ff16815181106131445761314461361a565b60200260200101518152506040518263ffffffff1660e01b815260040161316b9190613cc7565b602060405180830381865af4158015613186573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131aa919061365a565b856131b6856001613c91565b60ff16815181106131c9576131c961361a565b602002602001018181525050505b505b647fffffffff600192831c169101612f32565b60018301918390821561327d579160200282015f5b8382111561324b57833563ffffffff1683826101000a81548163ffffffff021916908363ffffffff1602179055509260200192600401602081600301049283019260010302613201565b801561327b5782816101000a81549063ffffffff021916905560040160208160030104928301926001030261324b565b505b5061328992915061328d565b5090565b5b80821115613289575f815560010161328e565b6001600160a01b038116811461105a575f5ffd5b5f602082840312156132c5575f5ffd5b813561255c816132a1565b5f602082840312156132e0575f5ffd5b5035919050565b5f8151808452602084019350602083015f5b828110156133205781516001600160a01b03168652602095860195909101906001016132f9565b5093949350505050565b5f8151808452602084019350602083015f5b8281101561332057815186526020958601959091019060010161333c565b604081525f61336c60408301856132e7565b828103602084015261337e818561332a565b95945050505050565b5f5f5f60808486031215613399575f5ffd5b8335925060208401359150608084018510156133b3575f5ffd5b6040840190509250925092565b5f5f604083850312156133d1575f5ffd5b8235915060208301356133e3816132a1565b809150509250929050565b5f5f5f60608486031215613400575f5ffd5b833592506020840135613412816132a1565b929592945050506040919091013590565b6001600160a01b0391909116815260200190565b602081525f61255c60208301846132e7565b5f5f6040838503121561345a575f5ffd5b8235613465816132a1565b946020939093013593505050565b5f5f60408385031215613484575f5ffd5b50508035926020909101359150565b5f5f83601f8401126134a3575f5ffd5b5081356001600160401b038111156134b9575f5ffd5b6020830191508360208285010111156134d0575f5ffd5b9250929050565b5f5f5f5f5f5f5f5f5f60a08a8c0312156134ef575f5ffd5b8935985060208a01356001600160401b0381111561350b575f5ffd5b8a01601f81018c1361351b575f5ffd5b80356001600160401b03811115613530575f5ffd5b8c60208260051b8401011115613544575f5ffd5b6020919091019850965060408a01356001600160401b03811115613566575f5ffd5b6135728c828d01613493565b90975095505060608a01356001600160401b03811115613590575f5ffd5b61359c8c828d01613493565b90955093505060808a01356001600160401b038111156135ba575f5ffd5b6135c68c828d01613493565b915080935050809150509295985092959850929598565b634e487b7160e01b5f52601160045260245ffd5b5f816135ff576135ff6135dd565b505f190190565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52602160045260245ffd5b5f60018201613653576136536135dd565b5060010190565b5f6020828403121561366a575f5ffd5b5051919050565b803563ffffffff81168114611871575f5ffd5b5f60208284031215613694575f5ffd5b61255c82613671565b80820180821115610c6657610c666135dd565b84815260a0810160208201855f5b60028110156136eb5763ffffffff6136d583613671565b16835260209283019291909101906001016136be565b50505060608201939093526080015292915050565b80518015158114611871575f5ffd5b5f6020828403121561371f575f5ffd5b61255c82613700565b604080825283549082018190525f8481526020812090916060840190835b8181101561376d5783546001600160a01b0316835260019384019360209093019201613746565b50508381036020850152613781818661332a565b9695505050505050565b6040516101e081016001600160401b03811182821017156137ae576137ae613606565b60405290565b604051601f8201601f191681016001600160401b03811182821017156137dc576137dc613606565b604052919050565b5f6001600160401b038211156137fc576137fc613606565b50601f01601f191660200190565b5f82601f830112613819575f5ffd5b81356001600160401b0381111561383257613832613606565b8060051b613842602082016137b4565b9182526020818501810192908101908684111561385d575f5ffd5b6020860192505b83831015613781578235825260209283019290910190613864565b5f5f60408385031215613890575f5ffd5b82356001600160401b038111156138a5575f5ffd5b8301601f810185136138b5575f5ffd5b80356138c86138c3826137e4565b6137b4565b8181528660208385010111156138dc575f5ffd5b816020840160208301375f6020838301015280945050505060208301356001600160401b0381111561390c575f5ffd5b6139188582860161380a565b9150509250929050565b81810381811115610c6657610c666135dd565b805160048110611871575f5ffd5b5f82601f830112613952575f5ffd5b604080519081016001600160401b038111828210171561397457613974613606565b806040525080604084018581111561398a575f5ffd5b845b818110156139a457805183526020928301920161398c565b509195945050505050565b8051611871816132a1565b805160ff81168114611871575f5ffd5b5f82601f8301126139d9575f5ffd5b81516139e76138c3826137e4565b8181528460208386010111156139fb575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b5f60208284031215613a27575f5ffd5b81516001600160401b03811115613a3c575f5ffd5b82016102008185031215613a4e575f5ffd5b613a5661378b565b81518152613a6660208301613935565b602082015260408281015190820152613a828560608401613943565b606082015260a08201516080820152613a9d60c083016139af565b60a0820152613aae60e083016139ba565b60c08201526101008201516001600160401b03811115613acc575f5ffd5b613ad8868285016139ca565b60e083015250613aeb61012083016139af565b610100820152613afe61014083016139af565b61012082015261016082810151610140830152610180830151908201526101a08201516001600160401b03811115613b34575f5ffd5b613b40868285016139ca565b61018083015250613b546101c083016139af565b6101a0820152613b676101e08301613700565b6101c0820152949350505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f613bb0604083018688613b75565b8281036020840152613bc3818587613b75565b979650505050505050565b606080825281018690525f8760808301825b89811015613c10578235613bf3816132a1565b6001600160a01b0316825260209283019290910190600101613be0565b508381036020850152613c2481888a613b75565b9150508281036040840152613c3a818587613b75565b9998505050505050505050565b6020808252602a908201527f4c617a79494d543a206c656166206d757374206265203c20534e41524b5f53436040820152691053105497d19251531160b21b606082015260800190565b60ff8181168382160190811115610c6657610c666135dd565b64ffffffffff8181168382160190811115610c6657610c666135dd565b6040810181835f5b6002811015613cee578151835260209283019290910190600101613ccf565b50505092915050565b64ffffffffff8281168282160390811115610c6657610c666135dd565b5f82613d2e57634e487b7160e01b5f52601260045260245ffd5b500490565b60208082526023908201527f4c617a79494d543a206465707468206d757374206265203c3d204d41585f44456040820152620a0a8960eb1b606082015260800190565b6001815b6001841115610f1757808504811115613d9557613d956135dd565b6001841615613da357908102905b60019390931c928002613d7a565b5f82613dbf57506001610c66565b81613dcb57505f610c66565b8160018114613de15760028114613deb57613e1d565b6001915050610c66565b60ff841115613dfc57613dfc6135dd565b6001841b915064ffffffffff821115613e1757613e176135dd565b50610c66565b5060208310610133831016604e8410600b8410161715613e55575081810a64ffffffffff811115613e5057613e506135dd565b610c66565b613e6564ffffffffff8484613d76565b8064ffffffffff04821115613e7c57613e7c6135dd565b029392505050565b5f61255c64ffffffffff841664ffffffffff8416613db1565b64ffffffffff8181168382160290811690818114613ebd57613ebd6135dd565b509291505056fea164736f6c634300081c000a", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b506004361061023f575f3560e01c80639f0f874a11610135578063e59e4695116100b4578063f26ef74e11610079578063f26ef74e1461057f578063f2fde38b14610592578063f379b0df146105a5578063f52fd803146105df578063f6fc05d514610651575f5ffd5b8063e59e469514610524578063e6745e1314610537578063e82f3b701461054a578063ebf0c7171461055d578063f165053614610565575f5ffd5b8063c3a0ec30116100fa578063c3a0ec30146104bc578063ca2869a0146104cd578063cd6dc687146104ec578063da881e5a146104ff578063dbb06c9314610512575f5ffd5b80639f0f874a1461044e578063a016493014610457578063a8a4d69b14610477578063bff232c11461048a578063c2b40ae41461049d575f5ffd5b8063715018a6116101c15780638d1ddfb1116101865780638d1ddfb1146103ce5780638da5cb5b146103e45780638e5ce3ad146103ec5780639015d371146103ff5780639a7a2ffc14610412575f5ffd5b8063715018a6146103475780637c92f5241461034f578063858142431461037c5780638a78bb151461039c5780638cb89ecb146103af575f5ffd5b80632e7b716d116102075780632e7b716d146102d95780634d6861a6146102ec57806350e6d94c146102ff5780635d5047761461032157806370e36bbe14610334575f5ffd5b8063096b810a146102435780630f3e34121461025857806317d611201461026b5780632800d82914610295578063291a691b146102b6575b5f5ffd5b6102566102513660046132b5565b61065a565b005b6102566102663660046132d0565b6107a6565b61027e6102793660046132d0565b6107e9565b60405161028c92919061335a565b60405180910390f35b6102a86102a33660046132d0565b610993565b60405190815260200161028c565b6102c96102c4366004613387565b6109df565b604051901515815260200161028c565b6102c96102e73660046132b5565b610bb9565b6102c96102fa3660046132d0565b610c6c565b6102c961030d3660046132b5565b60066020525f908152604090205460ff1681565b6102c961032f3660046133c0565b610cab565b6102566103423660046132b5565b610cef565b610256610d65565b61036261035d3660046133ee565b610d78565b6040805192835263ffffffff90911660208301520161028c565b60015461038f906001600160a01b031681565b60405161028c9190613423565b6102566103aa3660046132b5565b610f1f565b6102a86103bd3660046132d0565b60096020525f908152604090205481565b600454600160281b900464ffffffffff166102a8565b61038f61105d565b600b5461038f906001600160a01b031681565b6102c961040d3660046132b5565b61108b565b6104386104203660046132b5565b60076020525f908152604090205464ffffffffff1681565b60405164ffffffffff909116815260200161028c565b6102a860035481565b61046a6104653660046132d0565b6110a8565b60405161028c9190613437565b6102c96104853660046133c0565b61113e565b6102566104983660046132b5565b611182565b6102a86104ab3660046132d0565b60086020525f908152604090205481565b6001546001600160a01b031661038f565b6102a86104db3660046132d0565b5f9081526008602052604090205490565b6102566104fa366004613449565b6111d3565b6102c961050d3660046132d0565b611330565b5f5461038f906001600160a01b031681565b6102566105323660046132b5565b61160a565b610256610545366004613473565b611682565b6102a86105583660046132d0565b611845565b6102a8611876565b61056d601481565b60405160ff909116815260200161028c565b61025661058d3660046134d7565b611888565b6102566105a03660046132b5565b611b85565b6004546105c19064ffffffffff80821691600160281b90041682565b6040805164ffffffffff93841681529290911660208301520161028c565b6106226105ed3660046132d0565b5f908152600a6020819052604090912090810154600590910154909163ffffffff80831692600160201b900416908284101590565b60405161028c949392919093845263ffffffff9283166020850152911660408301521515606082015260800190565b6102a860025481565b61066261105d565b6001600160a01b0316336001600160a01b0316148061068b57506001546001600160a01b031633145b6106a857604051632864c4e160e01b815260040160405180910390fd5b6106b18161108b565b81906106da576040516381e5828960e01b81526004016106d19190613423565b60405180910390fd5b506001600160a01b0381165f9081526007602052604081205464ffffffffff16906107089060049083611bbf565b6001600160a01b0382165f908152600660205260408120805460ff191690556002805491610735836135f1565b90915550506002546004546040805164ffffffffff80861682526020820194909452600160281b909204909216918101919091526001600160a01b038316907f8c008e3835f6c79bfcdb89f0f6ca8705e0b01049ee84a90b0e4da1c7ba9405d5906060015b60405180910390a25050565b6107ae611e61565b60038190556040518181527fbe772dc189863d512fa01e489c8eac204975aef1a8662d8b5a333804b5207ab79060200160405180910390a150565b5f818152600a60208190526040909120600681015491810154606092839291806001600160401b0381111561082057610820613606565b604051908082528060200260200182016040528015610849578160200160208202803683370190505b509450806001600160401b0381111561086457610864613606565b60405190808252806020026020018201604052801561088d578160200160208202803683370190505b5093505f805b83811015610989575f8560060182815481106108b1576108b161361a565b5f918252602090912001546001600160a01b0316905060016001600160a01b0382165f90815260098801602052604090205460ff1660028111156108f7576108f761362e565b03610980578088848151811061090f5761090f61361a565b60200260200101906001600160a01b031690816001600160a01b031681525050856008015f826001600160a01b03166001600160a01b031681526020019081526020015f20548784815181106109675761096761361a565b60209081029190910101528261097c81613642565b9350505b50600101610893565b5050505050915091565b5f818152600a6020526040812081815460ff1660038111156109b7576109b761362e565b036109d557604051630d4c1d9760e41b815260040160405180910390fd5b6003015492915050565b5f80546001600160a01b03163314610a0a5760405163e4c2a7eb60e01b815260040160405180910390fd5b5f848152600a6020526040812090815460ff166003811115610a2e57610a2e61362e565b14610a4c576040516374ff462560e11b815260040160405180910390fd5b60015460408051630cc37d8f60e11b815290515f926001600160a01b031691631986fb1e9160048083019260209291908290030181865afa158015610a93573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab7919061365a565b905080610aca6040860160208701613684565b63ffffffff161115610ae26040860160208701613684565b829091610b10576040516344ec930f60e01b815263ffffffff909216600483015260248201526044016106d1565b5050815460ff1916600190811783558201859055436002830155600354610b37904261369d565b6003830155610b4b600583018560026131ec565b50610b54611876565b5f87815260086020526040908190209190915560028301546003840154915188927f381d281d32f95ef8fe4e5f3b263ea6a32d03d331e1a141ae1da996dc02a7a17092610ba5928a928a92916136b0565b60405180910390a250600195945050505050565b5f610bc38261108b565b610bce57505f919050565b6001546001600160a01b0316610bf7576040516350ca893360e01b815260040160405180910390fd5b600154604051639f8a13d760e01b81526001600160a01b0390911690639f8a13d790610c27908590600401613423565b602060405180830381865afa158015610c42573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c66919061370f565b92915050565b5f818152600a602052604081206001815460ff166003811115610c9157610c9161362e565b14610c9e57505f92915050565b6003015442111592915050565b5f60015f848152600a602090815260408083206001600160a01b038716845260090190915290205460ff166002811115610ce757610ce761362e565b149392505050565b610cf7611e61565b6001600160a01b038116610d1e5760405163d92e233d60e01b815260040160405180910390fd5b5f80546001600160a01b0319166001600160a01b038316908117825560405190917f2c8267accd82e977550ed2349c73311183cd22e306347be4453c8d130995e3c991a250565b610d6d611e61565b610d765f611e93565b565b600b545f9081906001600160a01b03163314610da75760405163fcef374960e01b815260040160405180910390fd5b5f858152600a602052604090206002815460ff166003811115610dcc57610dcc61362e565b14610dea57604051634f4b461f60e11b815260040160405180910390fd5b60058101546001600160a01b0386165f90815260098301602052604090205463ffffffff909116925060019060ff166002811115610e2a57610e2a61362e565b14610e3a57600a01549150610f17565b6001600160a01b0385165f9081526009820160205260408120805460ff19166002179055600a8201805491610e6e836135f1565b919050555080600a01549250846001600160a01b0316867f6c783b92374361b4d6efaf29673b89437ee969bb3c9d2d5d86b143ad5447b8498686604051610ebf929190918252602082015260400190565b60405180910390a36040805184815263ffffffff84166020820181905285101591810182905287907f119cb11dd0a68c257d6dc9b06dcb37dd422ce276eb8bf3cd0b7079a116b8e2989060600160405180910390a250505b935093915050565b610f2761105d565b6001600160a01b0316336001600160a01b03161480610f5057506001546001600160a01b031633145b610f6d57604051632864c4e160e01b815260040160405180910390fd5b610f768161108b565b61105a5760048054600160281b900464ffffffffff1690610fa0906001600160a01b038416611f03565b6001600160a01b0382165f908152600660209081526040808320805460ff1916600117905560079091528120805464ffffffffff841664ffffffffff199091161790556002805491610ff183613642565b90915550506002546004546040805164ffffffffff80861682526020820194909452600160281b909204909216918101919091526001600160a01b038316907f3318d261fe14a5761d2d1e21555652f623d2134c430a9883c9ad6e958bb0db539060600161079a565b50565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b03165f9081526006602052604090205460ff1690565b5f818152600a602052604090206004810154606091906110db576040516322e679e360e11b815260040160405180910390fd5b8060060180548060200260200160405190810160405280929190818152602001828054801561113157602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611113575b5050505050915050919050565b5f805f848152600a602090815260408083206001600160a01b038716845260090190915290205460ff1660028111156111795761117961362e565b14159392505050565b61118a611e61565b6001600160a01b0381166111b15760405163d92e233d60e01b815260040160405180910390fd5b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b5f6111dc6120d9565b805490915060ff600160401b82041615906001600160401b03165f811580156112025750825b90505f826001600160401b0316600114801561121d5750303b155b90508115801561122b575080155b156112495760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561127357845460ff60401b1916600160401b1785555b6001600160a01b03871661129a5760405163d92e233d60e01b815260040160405180910390fd5b6112a333612101565b6112af60046014612112565b6112b8866107a6565b6112c061105d565b6001600160a01b0316876001600160a01b0316146112e1576112e187611b85565b831561132757845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b5f818152600a6020526040812081815460ff1660038111156113545761135461362e565b0361137257604051630d4c1d9760e41b815260040160405180910390fd5b6001815460ff16600381111561138a5761138a61362e565b146113a857604051631860f69960e31b815260040160405180910390fd5b806003015442116113cc57604051632f021e8d60e11b815260040160405180910390fd5b60058101546006820154600160201b90910463ffffffff161115806114b1578154600360ff199091161782556006820154600583015460408051928352600160201b90910463ffffffff16602083015285917fecc4a9fb7e28d074cba7f5b227e9b5827823c850a385539b9a2f98a08f8c203d910160405180910390a25f54604051635d968dc160e11b815260048101869052600260248201526001600160a01b039091169063bb2d1b82906044015f604051808303815f87803b158015611492575f5ffd5b505af11580156114a4573d5f5f3e3d5ffd5b505f979650505050505050565b815460ff191660021782556006820154600a83018190555f816001600160401b038111156114e1576114e1613606565b60405190808252806020026020018201604052801561150a578160200160208202803683370190505b5090505f5b8281101561157c57846008015f8660060183815481106115315761153161361a565b5f9182526020808320909101546001600160a01b0316835282019290925260400190205482518390839081106115695761156961361a565b602090810291909101015260010161150f565b505f54604051631f3ea75d60e21b8152600481018890526001600160a01b0390911690637cfa9d74906024015f604051808303815f87803b1580156115bf575f5ffd5b505af11580156115d1573d5f5f3e3d5ffd5b50505050857f4f1f5b329c741a8ba15e9645e301061294d0c1fdd455448ffd5e76ff255929d78560060183604051610ba5929190613728565b611612611e61565b6001600160a01b0381166116395760405163d92e233d60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040517fad4055f18cdad6f4bdd71afe3a72cbeee964217943e1bde38f138289e981a9a7905f90a250565b5f828152600a6020526040812090815460ff1660038111156116a6576116a661362e565b036116c457604051630d4c1d9760e41b815260040160405180910390fd5b6001815460ff1660038111156116dc576116dc61362e565b146116fa57604051631860f69960e31b815260040160405180910390fd5b806003015442111561171f57604051639a19114d60e01b815260040160405180910390fd5b335f90815260078201602052604090205460ff16156117515760405163257309f160e11b815260040160405180910390fd5b61175a33610bb9565b6117775760405163149fbcfd60e11b815260040160405180910390fd5b611782338385612191565b6001810154604080516bffffffffffffffffffffffff193360601b16602080830191909152603482018690526054820187905260748083019490945282518083039094018452609490910190915281519101205f90335f8181526007850160205260409020805460ff1916600117905590915061180190839083612362565b506040805184815260208101839052339186917f52999628fb1cb05707e842278833b22e511f11746202cecdf221968b0b89e8bd910160405180910390a350505050565b5f8181526009602052604090205480611871576040516322e679e360e11b815260040160405180910390fd5b919050565b5f61188360046014612563565b905090565b5f898152600a602052604090206002815460ff1660038111156118ad576118ad61362e565b146118cb57604051634f4b461f60e11b815260040160405180910390fd5b6004810154156118ee5760405163632a22bb60e01b815260040160405180910390fd5b600681015488146119375760405162461bcd60e51b815260206004820152601360248201527209cdec8ca40c6deeadce840dad2e6dac2e8c6d606b1b60448201526064016106d1565b5f6119448587018761387f565b9150505f81511161198e5760405162461bcd60e51b815260206004820152601460248201527343353a206e6f207075626c696320696e7075747360601b60448201526064016106d1565b5f816001835161199e9190613922565b815181106119ae576119ae61361a565b602002602001015190505f5f5f9054906101000a90046001600160a01b03166001600160a01b031663406ed35c8e6040518263ffffffff1660e01b81526004016119fa91815260200190565b5f60405180830381865afa158015611a14573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611a3b9190810190613a17565b9050806101c0015115611ac0578061012001516001600160a01b031663f7e83aee898989896040518563ffffffff1660e01b8152600401611a7f9493929190613b9d565b602060405180830381865afa158015611a9a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611abe919061365a565b505b60048085018390555f8e815260096020526040808220859055905490516340a3b76160e11b81529182018f9052602482018490526001600160a01b0316906381476ec2906044015f604051808303815f87803b158015611b1e575f5ffd5b505af1158015611b30573d5f5f3e3d5ffd5b505050508c7f49ac1dd411942113d1c5e6799c6379ce341afe85a4175fb562cf2a5fb886c27d8d8d8d8d8d8d604051611b6e96959493929190613bce565b60405180910390a250505050505050505050505050565b611b8d611e61565b6001600160a01b038116611bb6575f604051631e4fbdf760e01b81526004016106d19190613423565b61105a81611e93565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018210611bfe5760405162461bcd60e51b81526004016106d190613c47565b825464ffffffffff600160281b90910481169082168111611c5c5760405162461bcd60e51b815260206004820152601860248201527713185e9e5253550e881b195859881b5d5cdd08195e1a5cdd60421b60448201526064016106d1565b825f5b81866001015f611c6f848861265c565b64ffffffffff1681526020019081526020015f20819055505f816001611c959190613c91565b60ff168464ffffffffff16901c64ffffffffff16905060018564ffffffffff16901c64ffffffffff168111611cca5750611e59565b600185165f03611d91575f611ce983611ce4886001613caa565b61265c565b60408051808201825286815264ffffffffff83165f90815260018c0160209081529083902054908201529051632b0aac7f60e11b815291925073__$078c82ddf6c95d34ea184ef1dd6130d136$__9163561558fe91611d4a91600401613cc7565b602060405180830381865af4158015611d65573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d89919061365a565b935050611e45565b5f611da183611ce4600189613cf7565b60408051808201825264ffffffffff83165f90815260018c0160209081529083902054825281018790529051632b0aac7f60e11b815291925073__$078c82ddf6c95d34ea184ef1dd6130d136$__9163561558fe91611e0291600401613cc7565b602060405180830381865af4158015611e1d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e41919061365a565b9350505b50647fffffffff600194851c169301611c5f565b505050505050565b33611e6a61105d565b6001600160a01b031614610d76573360405163118cdaa760e01b81526004016106d19190613423565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b8154600160281b900464ffffffffff167f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018210611f525760405162461bcd60e51b81526004016106d190613c47565b825464ffffffffff90811690821610611fa55760405162461bcd60e51b815260206004820152601560248201527413185e9e5253550e881d1c9959481a5cc8199d5b1b605a1b60448201526064016106d1565b611fb0816001613caa565b835464ffffffffff91909116600160281b0269ffffffffff000000000019909116178355815f5b81856001015f611fe7848761265c565b64ffffffffff16815260208101919091526040015f205560018316156120d2575f61201782611ce4600187613cf7565b60408051808201825264ffffffffff83165f90815260018a0160209081529083902054825281018690529051632b0aac7f60e11b815291925073__$078c82ddf6c95d34ea184ef1dd6130d136$__9163561558fe9161207891600401613cc7565b602060405180830381865af4158015612093573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120b7919061365a565b647fffffffff600195861c1694909350919091019050611fd7565b5050505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610c66565b612109612679565b61105a8161269e565b602060ff821611156121605760405162461bcd60e51b81526020600482015260176024820152764c617a79494d543a205472656520746f6f206c6172676560481b60448201526064016106d1565b612171600160ff831681901b613922565b825469ffffffffffffffffffff191664ffffffffff919091161790915550565b5f82116121b15760405163aeaddff160e01b815260040160405180910390fd5b6001546001600160a01b03166121da576040516350ca893360e01b815260040160405180910390fd5b5f818152600a602052604081206001805460028301549293926001600160a01b039091169163bb03bd7191889161221091613922565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381865afa158015612257573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061227b919061365a565b90505f60015f9054906101000a90046001600160a01b03166001600160a01b0316631209b1f66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122ce573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122f2919061365a565b90505f81116123145760405163aeaddff160e01b815260040160405180910390fd5b5f61231f8284613d14565b90505f81116123415760405163149fbcfd60e11b815260040160405180910390fd5b808611156113275760405163aeaddff160e01b815260040160405180910390fd5b60058301546006840180545f92600160201b900463ffffffff16908111156123e057508054600180820183555f928352602080842090920180546001600160a01b0319166001600160a01b03881690811790915583526008870182526040808420869055600988019092529120805460ff191682179055905061255c565b5f5f90505f876008015f855f815481106123fc576123fc61361a565b5f9182526020808320909101546001600160a01b03168352820192909252604001902054905060015b8454811015612484575f896008015f8784815481106124465761244661361a565b5f9182526020808320909101546001600160a01b0316835282019290925260400190205490508281111561247b578092508193505b50600101612425565b50808610612498575f94505050505061255c565b5f886009015f8685815481106124b0576124b061361a565b5f9182526020808320909101546001600160a01b031683528201929092526040019020805460ff191660018360028111156124ed576124ed61362e565b0217905550868483815481106125055761250561361a565b5f91825260208083209190910180546001600160a01b0319166001600160a01b03948516179055918916815260088a018252604080822089905560098b0190925220805460ff191660019081179091559450505050505b9392505050565b5f5f8260ff16116125b65760405162461bcd60e51b815260206004820152601a60248201527f4c617a79494d543a206465707468206d757374206265203e203000000000000060448201526064016106d1565b602060ff831611156125da5760405162461bcd60e51b81526004016106d190613d33565b8254600160281b900464ffffffffff16806125f960ff85166002613e84565b64ffffffffff1610156126495760405162461bcd60e51b8152602060048201526018602482015277098c2f4f2929aa87440c2dac4d2ceeadeeae640c8cae0e8d60431b60448201526064016106d1565b6126548482856126a6565b949350505050565b5f8161266f60ff851663ffffffff613e9d565b61255c9190613caa565b61268161276e565b610d7657604051631afcd79f60e31b815260040160405180910390fd5b611b8d612679565b5f602060ff831611156126cb5760405162461bcd60e51b81526004016106d190613d33565b8264ffffffffff165f036126e9576126e282612787565b905061255c565b5f6126f5836001613c91565b60ff166001600160401b0381111561270f5761270f613606565b604051908082528060200260200182016040528015612738578160200160208202803683370190505b50905061274785858584612e21565b808360ff168151811061275c5761275c61361a565b60200260200101519150509392505050565b5f6127776120d9565b54600160401b900460ff16919050565b5f8160ff165f0361279957505f919050565b8160ff166001036127cb57507f2098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864919050565b8160ff166002036127fd57507f1069673dcdb12263df301a6ff584a7ec261a44cb9dc68df067a4774460b1f1e1919050565b8160ff1660030361282f57507f18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238919050565b8160ff1660040361286157507f07f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a919050565b8160ff1660050361289357507f2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55919050565b8160ff166006036128c557507f2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78919050565b8160ff166007036128f757507f078295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d919050565b8160ff1660080361292957507f2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61919050565b8160ff1660090361295b57507f0e884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747919050565b8160ff16600a0361298d57507f1b7201da72494f1e28717ad1a52eb469f95892f957713533de6175e5da190af2919050565b8160ff16600b036129bf57507f1f8d8822725e36385200c0b201249819a6e6e1e4650808b5bebc6bface7d7636919050565b8160ff16600c036129f157507f2c5d82f66c914bafb9701589ba8cfcfb6162b0a12acf88a8d0879a0471b5f85a919050565b8160ff16600d03612a2357507f14c54148a0940bb820957f5adf3fa1134ef5c4aaa113f4646458f270e0bfbfd0919050565b8160ff16600e03612a5557507f190d33b12f986f961e10c0ee44d8b9af11be25588cad89d416118e4bf4ebe80c919050565b8160ff16600f03612a8757507f22f98aa9ce704152ac17354914ad73ed1167ae6596af510aa5b3649325e06c92919050565b8160ff16601003612ab957507f2a7c7c9b6ce5880b9f6f228d72bf6a575a526f29c66ecceef8b753d38bba7323919050565b8160ff16601103612aeb57507f2e8186e558698ec1c67af9c14d463ffc470043c9c2988b954d75dd643f36b992919050565b8160ff16601203612b1d57507f0f57c5571e9a4eab49e2c8cf050dae948aef6ead647392273546249d1c1ff10f919050565b8160ff16601303612b4f57507f1830ee67b5fb554ad5f63d4388800e1cfe78e310697d46e43c9ce36134f72cca919050565b8160ff16601403612b8157507f2134e76ac5d21aab186c2be1dd8f84ee880a1e46eaf712f9d371b6df22191f3e919050565b8160ff16601503612bb357507f19df90ec844ebc4ffeebd866f33859b0c051d8c958ee3aa88f8f8df3db91a5b1919050565b8160ff16601603612be557507f18cca2a66b5c0787981e69aefd84852d74af0e93ef4912b4648c05f722efe52b919050565b8160ff16601703612c1757507f2388909415230d1b4d1304d2d54f473a628338f2efad83fadf05644549d2538d919050565b8160ff16601803612c4957507f27171fb4a97b6cc0e9e8f543b5294de866a2af2c9c8d0b1d96e673e4529ed540919050565b8160ff16601903612c7b57507f2ff6650540f629fd5711a0bc74fc0d28dcb230b9392583e5f8d59696dde6ae21919050565b8160ff16601a03612cad57507f120c58f143d491e95902f7f5277778a2e0ad5168f6add75669932630ce611518919050565b8160ff16601b03612cdf57507f1f21feb70d3f21b07bf853d5e5db03071ec495a0a565a21da2d665d279483795919050565b8160ff16601c03612d1157507f24be905fa71335e14c638cc0f66a8623a826e768068a9e968bb1a1dde18a72d2919050565b8160ff16601d03612d4357507f0f8666b62ed17491c50ceadead57d4cd597ef3821d65c328744c74e553dac26d919050565b8160ff16601e03612d7557507f0918d46bf52d98b034413f4a1a1c41594e7a7a3f6ae08cb43d1a2a230e1959ef919050565b8160ff16601f03612da757507f1bbeb01b4c479ecde76917645e404dfa2e26f90d0afc5a65128513ad375c5ff2919050565b8160ff16602003612dd957507f2f68a1c58e257e42a17a6c61dff5551ed560b9922ab119d5ac8e184c9734ead9919050565b60405162461bcd60e51b815260206004820152601e60248201527f4c617a79494d543a2064656661756c745a65726f2062616420696e646578000060448201526064016106d1565b602060ff83161115612e455760405162461bcd60e51b81526004016106d190613d33565b5f8364ffffffffff1611612ea95760405162461bcd60e51b815260206004820152602560248201527f4c617a79494d543a206e756d626572206f66206c6561766573206d7573742062604482015264065203e20360dc1b60648201526084016106d1565b5f612eb5600185613cf7565b9050600181165f03612f0857846001015f612ed05f8461265c565b64ffffffffff1681526020019081526020015f2054825f81518110612ef757612ef761361a565b602002602001018181525050612f30565b612f115f612787565b825f81518110612f2357612f2361361a565b6020026020010181815250505b5f5b8360ff168160ff161015611e5957600182165f036130285773__$078c82ddf6c95d34ea184ef1dd6130d136$__63561558fe6040518060400160405280868560ff1681518110612f8457612f8461361a565b60200260200101518152602001612f9a85612787565b8152506040518263ffffffff1660e01b8152600401612fb99190613cc7565b602060405180830381865af4158015612fd4573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ff8919061365a565b83613004836001613c91565b60ff16815181106130175761301761361a565b6020026020010181815250506131d9565b5f613034826001613c91565b60ff168664ffffffffff16901c64ffffffffff16905060018364ffffffffff16901c64ffffffffff168111156130d6575f876001015f61308b85600161307a9190613c91565b60018864ffffffffff16901c61265c565b64ffffffffff1681526020019081526020015f2054905080858460016130b19190613c91565b60ff16815181106130c4576130c461361a565b602002602001018181525050506131d7565b5f876001015f6130ed85600188611ce49190613cf7565b64ffffffffff1681526020019081526020015f2054905073__$078c82ddf6c95d34ea184ef1dd6130d136$__63561558fe6040518060400160405280848152602001888760ff16815181106131445761314461361a565b60200260200101518152506040518263ffffffff1660e01b815260040161316b9190613cc7565b602060405180830381865af4158015613186573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131aa919061365a565b856131b6856001613c91565b60ff16815181106131c9576131c961361a565b602002602001018181525050505b505b647fffffffff600192831c169101612f32565b60018301918390821561327d579160200282015f5b8382111561324b57833563ffffffff1683826101000a81548163ffffffff021916908363ffffffff1602179055509260200192600401602081600301049283019260010302613201565b801561327b5782816101000a81549063ffffffff021916905560040160208160030104928301926001030261324b565b505b5061328992915061328d565b5090565b5b80821115613289575f815560010161328e565b6001600160a01b038116811461105a575f5ffd5b5f602082840312156132c5575f5ffd5b813561255c816132a1565b5f602082840312156132e0575f5ffd5b5035919050565b5f8151808452602084019350602083015f5b828110156133205781516001600160a01b03168652602095860195909101906001016132f9565b5093949350505050565b5f8151808452602084019350602083015f5b8281101561332057815186526020958601959091019060010161333c565b604081525f61336c60408301856132e7565b828103602084015261337e818561332a565b95945050505050565b5f5f5f60808486031215613399575f5ffd5b8335925060208401359150608084018510156133b3575f5ffd5b6040840190509250925092565b5f5f604083850312156133d1575f5ffd5b8235915060208301356133e3816132a1565b809150509250929050565b5f5f5f60608486031215613400575f5ffd5b833592506020840135613412816132a1565b929592945050506040919091013590565b6001600160a01b0391909116815260200190565b602081525f61255c60208301846132e7565b5f5f6040838503121561345a575f5ffd5b8235613465816132a1565b946020939093013593505050565b5f5f60408385031215613484575f5ffd5b50508035926020909101359150565b5f5f83601f8401126134a3575f5ffd5b5081356001600160401b038111156134b9575f5ffd5b6020830191508360208285010111156134d0575f5ffd5b9250929050565b5f5f5f5f5f5f5f5f5f60a08a8c0312156134ef575f5ffd5b8935985060208a01356001600160401b0381111561350b575f5ffd5b8a01601f81018c1361351b575f5ffd5b80356001600160401b03811115613530575f5ffd5b8c60208260051b8401011115613544575f5ffd5b6020919091019850965060408a01356001600160401b03811115613566575f5ffd5b6135728c828d01613493565b90975095505060608a01356001600160401b03811115613590575f5ffd5b61359c8c828d01613493565b90955093505060808a01356001600160401b038111156135ba575f5ffd5b6135c68c828d01613493565b915080935050809150509295985092959850929598565b634e487b7160e01b5f52601160045260245ffd5b5f816135ff576135ff6135dd565b505f190190565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52602160045260245ffd5b5f60018201613653576136536135dd565b5060010190565b5f6020828403121561366a575f5ffd5b5051919050565b803563ffffffff81168114611871575f5ffd5b5f60208284031215613694575f5ffd5b61255c82613671565b80820180821115610c6657610c666135dd565b84815260a0810160208201855f5b60028110156136eb5763ffffffff6136d583613671565b16835260209283019291909101906001016136be565b50505060608201939093526080015292915050565b80518015158114611871575f5ffd5b5f6020828403121561371f575f5ffd5b61255c82613700565b604080825283549082018190525f8481526020812090916060840190835b8181101561376d5783546001600160a01b0316835260019384019360209093019201613746565b50508381036020850152613781818661332a565b9695505050505050565b6040516101e081016001600160401b03811182821017156137ae576137ae613606565b60405290565b604051601f8201601f191681016001600160401b03811182821017156137dc576137dc613606565b604052919050565b5f6001600160401b038211156137fc576137fc613606565b50601f01601f191660200190565b5f82601f830112613819575f5ffd5b81356001600160401b0381111561383257613832613606565b8060051b613842602082016137b4565b9182526020818501810192908101908684111561385d575f5ffd5b6020860192505b83831015613781578235825260209283019290910190613864565b5f5f60408385031215613890575f5ffd5b82356001600160401b038111156138a5575f5ffd5b8301601f810185136138b5575f5ffd5b80356138c86138c3826137e4565b6137b4565b8181528660208385010111156138dc575f5ffd5b816020840160208301375f6020838301015280945050505060208301356001600160401b0381111561390c575f5ffd5b6139188582860161380a565b9150509250929050565b81810381811115610c6657610c666135dd565b805160048110611871575f5ffd5b5f82601f830112613952575f5ffd5b604080519081016001600160401b038111828210171561397457613974613606565b806040525080604084018581111561398a575f5ffd5b845b818110156139a457805183526020928301920161398c565b509195945050505050565b8051611871816132a1565b805160ff81168114611871575f5ffd5b5f82601f8301126139d9575f5ffd5b81516139e76138c3826137e4565b8181528460208386010111156139fb575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b5f60208284031215613a27575f5ffd5b81516001600160401b03811115613a3c575f5ffd5b82016102008185031215613a4e575f5ffd5b613a5661378b565b81518152613a6660208301613935565b602082015260408281015190820152613a828560608401613943565b606082015260a08201516080820152613a9d60c083016139af565b60a0820152613aae60e083016139ba565b60c08201526101008201516001600160401b03811115613acc575f5ffd5b613ad8868285016139ca565b60e083015250613aeb61012083016139af565b610100820152613afe61014083016139af565b61012082015261016082810151610140830152610180830151908201526101a08201516001600160401b03811115613b34575f5ffd5b613b40868285016139ca565b61018083015250613b546101c083016139af565b6101a0820152613b676101e08301613700565b6101c0820152949350505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f613bb0604083018688613b75565b8281036020840152613bc3818587613b75565b979650505050505050565b606080825281018690525f8760808301825b89811015613c10578235613bf3816132a1565b6001600160a01b0316825260209283019290910190600101613be0565b508381036020850152613c2481888a613b75565b9150508281036040840152613c3a818587613b75565b9998505050505050505050565b6020808252602a908201527f4c617a79494d543a206c656166206d757374206265203c20534e41524b5f53436040820152691053105497d19251531160b21b606082015260800190565b60ff8181168382160190811115610c6657610c666135dd565b64ffffffffff8181168382160190811115610c6657610c666135dd565b6040810181835f5b6002811015613cee578151835260209283019290910190600101613ccf565b50505092915050565b64ffffffffff8281168282160390811115610c6657610c666135dd565b5f82613d2e57634e487b7160e01b5f52601260045260245ffd5b500490565b60208082526023908201527f4c617a79494d543a206465707468206d757374206265203c3d204d41585f44456040820152620a0a8960eb1b606082015260800190565b6001815b6001841115610f1757808504811115613d9557613d956135dd565b6001841615613da357908102905b60019390931c928002613d7a565b5f82613dbf57506001610c66565b81613dcb57505f610c66565b8160018114613de15760028114613deb57613e1d565b6001915050610c66565b60ff841115613dfc57613dfc6135dd565b6001841b915064ffffffffff821115613e1757613e176135dd565b50610c66565b5060208310610133831016604e8410600b8410161715613e55575081810a64ffffffffff811115613e5057613e506135dd565b610c66565b613e6564ffffffffff8484613d76565b8064ffffffffff04821115613e7c57613e7c6135dd565b029392505050565b5f61255c64ffffffffff841664ffffffffff8416613db1565b64ffffffffff8181168382160290811690818114613ebd57613ebd6135dd565b509291505056fea164736f6c634300081c000a", "linkReferences": { "npm/poseidon-solidity@0.0.5/PoseidonT3.sol": { "PoseidonT3": [ { "length": 20, - "start": 7663 + "start": 7674 }, { "length": 20, - "start": 7847 + "start": 7858 }, { "length": 20, - "start": 8477 + "start": 8488 }, { "length": 20, - "start": 12311 + "start": 12322 }, { "length": 20, - "start": 12753 + "start": 12764 } ] } @@ -1297,28 +1297,28 @@ "PoseidonT3": [ { "length": 20, - "start": 7449 + "start": 7460 }, { "length": 20, - "start": 7633 + "start": 7644 }, { "length": 20, - "start": 8263 + "start": 8274 }, { "length": 20, - "start": 12097 + "start": 12108 }, { "length": 20, - "start": 12539 + "start": 12550 } ] } }, "immutableReferences": {}, "inputSourceName": "project/contracts/registry/CiphernodeRegistryOwnable.sol", - "buildInfoId": "solc-0_8_28-a5591f76a7a8353e3d0dd83e83c16479678f73a9" + "buildInfoId": "solc-0_8_28-ad0ab271a39c8d6cc271ed8cba75fab865dc3973" } \ No newline at end of file diff --git a/packages/enclave-contracts/contracts/Enclave.sol b/packages/enclave-contracts/contracts/Enclave.sol index 42cd3c06aa..0bea3166d8 100644 --- a/packages/enclave-contracts/contracts/Enclave.sol +++ b/packages/enclave-contracts/contracts/Enclave.sol @@ -412,12 +412,16 @@ contract Enclave is IEnclave, OwnableUpgradeable { e3s[e3Id].plaintextOutput = plaintextOutput; _e3Stages[e3Id] = E3Stage.Complete; - (success) = e3.decryptionVerifier.verify( - keccak256(plaintextOutput), - proof, - foldProof - ); - require(success, InvalidOutput(plaintextOutput)); + if (e3.proofAggregationEnabled) { + (success) = e3.decryptionVerifier.verify( + keccak256(plaintextOutput), + proof, + foldProof + ); + require(success, InvalidOutput(plaintextOutput)); + } else { + success = true; + } _distributeRewards(e3Id); @@ -660,7 +664,10 @@ contract Enclave is IEnclave, OwnableUpgradeable { bytes calldata encodedParams ) public onlyOwner { require(encodedParams.length > 0, "Empty params"); - require(paramSetRegistry[paramSet].length == 0, "ParamSet already registered"); + require( + paramSetRegistry[paramSet].length == 0, + "ParamSet already registered" + ); paramSetRegistry[paramSet] = encodedParams; emit ParamSetRegistered(paramSet, encodedParams); } diff --git a/packages/enclave-contracts/contracts/registry/CiphernodeRegistryOwnable.sol b/packages/enclave-contracts/contracts/registry/CiphernodeRegistryOwnable.sol index d5aeff1f90..d5b51f4ecc 100644 --- a/packages/enclave-contracts/contracts/registry/CiphernodeRegistryOwnable.sol +++ b/packages/enclave-contracts/contracts/registry/CiphernodeRegistryOwnable.sol @@ -220,7 +220,9 @@ contract CiphernodeRegistryOwnable is ICiphernodeRegistry, OwnableUpgradeable { bytes32 publicKeyHash = publicInputs[publicInputs.length - 1]; E3 memory e3 = enclave.getE3(e3Id); - e3.pkVerifier.verify(proof, foldProof); + if (e3.proofAggregationEnabled) { + e3.pkVerifier.verify(proof, foldProof); + } c.publicKey = publicKeyHash; publicKeyHashes[e3Id] = publicKeyHash; diff --git a/packages/enclave-contracts/tasks/enclave.ts b/packages/enclave-contracts/tasks/enclave.ts index 1ae4d1ec1e..384e7096e8 100644 --- a/packages/enclave-contracts/tasks/enclave.ts +++ b/packages/enclave-contracts/tasks/enclave.ts @@ -134,7 +134,7 @@ export const requestCommittee = task( inputWindowStart, inputWindowEnd, e3Address, - e3Params, + e3Params: _e3Params, computeParams, customParams, proofAggregationEnabled, diff --git a/packages/enclave-contracts/test/E3Lifecycle/E3Integration.spec.ts b/packages/enclave-contracts/test/E3Lifecycle/E3Integration.spec.ts index ebba4c6992..2d55af2125 100644 --- a/packages/enclave-contracts/test/E3Lifecycle/E3Integration.spec.ts +++ b/packages/enclave-contracts/test/E3Lifecycle/E3Integration.spec.ts @@ -314,7 +314,7 @@ describe("E3 Integration - Refund/Timeout Mechanism", function () { ["address"], ["0x1234567890123456789012345678901234567890"], ), - proofAggregationEnabled: true, + proofAggregationEnabled: false, }; const fee = await enclave.getE3Quote(requestParams); diff --git a/packages/enclave-contracts/test/Enclave.spec.ts b/packages/enclave-contracts/test/Enclave.spec.ts index 6885751758..8b206bfe14 100644 --- a/packages/enclave-contracts/test/Enclave.spec.ts +++ b/packages/enclave-contracts/test/Enclave.spec.ts @@ -293,7 +293,7 @@ describe("Enclave", function () { ["address"], ["0x1234567890123456789012345678901234567890"], ), - proofAggregationEnabled: true, + proofAggregationEnabled: false, }; // ── Return ──────────────────────────────────────────────────────────────── @@ -1095,6 +1095,7 @@ describe("Enclave", function () { await makeRequest(enclave, usdcToken, { ...request, inputWindow: [(await time.latest()) + 20, (await time.latest()) + 100], + proofAggregationEnabled: true, }); await setupAndPublishCommittee( diff --git a/packages/enclave-contracts/test/Registry/CiphernodeRegistryOwnable.spec.ts b/packages/enclave-contracts/test/Registry/CiphernodeRegistryOwnable.spec.ts index 02cc1a9843..5e073d63f8 100644 --- a/packages/enclave-contracts/test/Registry/CiphernodeRegistryOwnable.spec.ts +++ b/packages/enclave-contracts/test/Registry/CiphernodeRegistryOwnable.spec.ts @@ -252,13 +252,6 @@ describe("CiphernodeRegistryOwnable", function () { signer?: Signer, ) { const abiCoder = ethers.AbiCoder.defaultAbiCoder(); - const polynomial_degree = ethers.toBigInt(2048); - const plaintext_modulus = ethers.toBigInt(1032193); - const moduli = [ethers.toBigInt("18014398492704769")]; - const encodedE3ProgramParams = abiCoder.encode( - ["uint256", "uint256", "uint256[]"], - [polynomial_degree, plaintext_modulus, moduli], - ); const currentTime = await networkHelpers.time.latest(); const requestParams = { @@ -274,7 +267,7 @@ describe("CiphernodeRegistryOwnable", function () { ["address"], ["0x1234567890123456789012345678901234567890"], ), - proofAggregationEnabled: true, + proofAggregationEnabled: false, }; const fee = await enclave.getE3Quote(requestParams); diff --git a/packages/enclave-contracts/test/Slashing/CommitteeExpulsion.spec.ts b/packages/enclave-contracts/test/Slashing/CommitteeExpulsion.spec.ts index f799f6cd36..b88a3d3409 100644 --- a/packages/enclave-contracts/test/Slashing/CommitteeExpulsion.spec.ts +++ b/packages/enclave-contracts/test/Slashing/CommitteeExpulsion.spec.ts @@ -324,7 +324,7 @@ describe("Committee Expulsion & Fault Tolerance", function () { ["address"], ["0x1234567890123456789012345678901234567890"], ), - proofAggregationEnabled: true, + proofAggregationEnabled: false, }; const fee = await enclave.getE3Quote(requestParams); diff --git a/scripts/build-circuits.ts b/scripts/build-circuits.ts index 1de789ca76..6391ff7279 100644 --- a/scripts/build-circuits.ts +++ b/scripts/build-circuits.ts @@ -9,7 +9,16 @@ import { execSync } from 'child_process' import { createHash } from 'crypto' import { appendFileSync, copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from 'fs' import { basename, join, resolve } from 'path' -import { ALL_GROUPS, CIRCUIT_GROUPS, CIRCUIT_VARIANTS, type CircuitGroup } from './circuit-constants' +import { + ALL_GROUPS, + ALL_PRESETS, + CIRCUIT_GROUPS, + CIRCUIT_PRESETS, + CIRCUIT_VARIANTS, + PRESET_NOIR_CONFIG, + type CircuitGroup, + type CircuitPreset, +} from './circuit-constants' /** share_computation wrapper is shared by sk_share_computation and e_sm_share_computation. */ const SHARE_COMP_WRAPPER = { @@ -26,6 +35,7 @@ interface CircuitInfo { interface CompiledCircuit { name: string group: CircuitGroup + preset: string artifacts: { json?: string vk?: string @@ -53,6 +63,7 @@ interface BuildOptions { outputDir?: string clean?: boolean dryRun?: boolean + preset?: CircuitPreset | 'all' } interface BuildResult { success: boolean @@ -76,14 +87,77 @@ class NoirCircuitBuilder { outputDir: join(this.rootDir, 'dist', 'circuits'), clean: true, skipVk: false, + preset: CIRCUIT_PRESETS.INSECURE_512, ...options, } } async buildAll(): Promise { const result: BuildResult = { success: true, compiled: [], errors: [] } + const presets: CircuitPreset[] = this.options.preset === 'all' ? ALL_PRESETS : [this.options.preset!] - console.log('🔮 Building Noir circuits...') + console.log(`🔮 Building Noir circuits for preset(s): ${presets.join(', ')}...`) + + // Save original mod.nr content so we can restore it after building + const modNrPath = join(this.rootDir, 'circuits', 'lib', 'src', 'configs', 'default', 'mod.nr') + const originalModNr = readFileSync(modNrPath, 'utf-8') + + try { + if (this.options.clean && existsSync(this.options.outputDir!)) { + rmSync(this.options.outputDir!, { recursive: true }) + } + mkdirSync(this.options.outputDir!, { recursive: true }) + + for (const preset of presets) { + this.setNoirConfigPreset(modNrPath, preset) + const presetResult = await this.buildForPreset(preset) + result.compiled.push(...presetResult.compiled) + result.errors.push(...presetResult.errors) + if (!presetResult.success) result.success = false + if (presetResult.sourceHash && !result.sourceHash) result.sourceHash = presetResult.sourceHash + } + + if (!this.options.skipChecksums && result.compiled.length > 0) { + result.checksumFile = this.generateChecksumFile(result.compiled) + } + result.releaseDir = this.options.outputDir! + } finally { + // Restore original mod.nr + writeFileSync(modNrPath, originalModNr) + } + + return result + } + + private setNoirConfigPreset(modNrPath: string, preset: CircuitPreset): void { + const configModule = PRESET_NOIR_CONFIG[preset] + const content = [ + '// SPDX-License-Identifier: LGPL-3.0-only', + '//', + '// This file is provided WITHOUT ANY WARRANTY;', + '// without even the implied warranty of MERCHANTABILITY', + '// or FITNESS FOR A PARTICULAR PURPOSE.', + '//', + `// Auto-generated by build-circuits.ts for preset: ${preset}`, + '', + `pub use super::committee::micro::{H, N_PARTIES, T};`, + `pub use super::${configModule}::dkg;`, + `pub use super::${configModule}::threshold;`, + '', + '/// Max number of non-zero coefficients in the message polynomial.', + '/// This is a conservative estimate that should be okay for most use cases.', + 'pub global MAX_MSG_NON_ZERO_COEFFS: u32 = 100;', + '', + ].join('\n') + writeFileSync(modNrPath, content) + console.log(` 📋 Set Noir config to: ${configModule} (preset: ${preset})`) + } + + private async buildForPreset(preset: CircuitPreset): Promise { + const result: BuildResult = { success: true, compiled: [], errors: [] } + const presetOutputDir = join(this.options.outputDir!, preset) + + console.log(`\n🔮 Building preset: ${preset}...`) try { this.checkTool('nargo --version', 'nargo') @@ -102,31 +176,22 @@ class NoirCircuitBuilder { return result } - if (this.options.clean) { - if (existsSync(this.options.outputDir!)) { - rmSync(this.options.outputDir!, { recursive: true }) - } - this.cleanTargetDirs(circuits) - } - mkdirSync(this.options.outputDir!, { recursive: true }) + this.cleanTargetDirs(circuits) + mkdirSync(presetOutputDir, { recursive: true }) result.sourceHash = this.computeSourceHash() for (const circuit of circuits) { try { - result.compiled.push(this.buildCircuit(circuit)) + result.compiled.push(this.buildCircuit(circuit, preset)) } catch (error: any) { - result.errors.push(`${circuit.name}: ${error.message}`) + result.errors.push(`${preset}/${circuit.name}: ${error.message}`) result.success = false } } - if (!this.options.skipChecksums && result.compiled.length > 0) { - result.checksumFile = this.generateChecksumFile(result.compiled) - } - - result.releaseDir = this.copyArtifacts(result.compiled) - console.log(`\n✅ Built ${result.compiled.length} circuits`) + this.copyArtifacts(result.compiled, presetOutputDir, preset) + console.log(`\n✅ Built ${result.compiled.length} circuits for preset: ${preset}`) if (result.errors.length > 0) { console.error('\n❌ Failed circuits:') for (const err of result.errors) console.error(` ${err}`) @@ -227,11 +292,12 @@ class NoirCircuitBuilder { return dirs } - private buildCircuit(circuit: CircuitInfo): CompiledCircuit { + private buildCircuit(circuit: CircuitInfo, preset: string): CompiledCircuit { const packageName = this.getPackageName(circuit.path) const result: CompiledCircuit = { name: circuit.name, group: circuit.group, + preset, artifacts: {}, checksums: {}, } @@ -430,7 +496,7 @@ class NoirCircuitBuilder { // evm/ variant checksums (only for circuits that have an evm VK) if (c.checksums.vk && c.artifacts.vk) { - const evmPrefix = `${CIRCUIT_VARIANTS.EVM}/${c.group}/${c.name}` + const evmPrefix = `${c.preset}/${CIRCUIT_VARIANTS.EVM}/${c.group}/${c.name}` if (c.checksums.json && c.artifacts.json) { const f = `${evmPrefix}/${basename(c.artifacts.json)}` checksums[f] = c.checksums.json @@ -447,7 +513,7 @@ class NoirCircuitBuilder { } // default/ variant checksums - const defaultPrefix = `${CIRCUIT_VARIANTS.DEFAULT}/${c.group}/${c.name}` + const defaultPrefix = `${c.preset}/${CIRCUIT_VARIANTS.DEFAULT}/${c.group}/${c.name}` if (c.checksums.json && c.artifacts.json) { const f = `${defaultPrefix}/${basename(c.artifacts.json)}` checksums[f] = c.checksums.json @@ -467,7 +533,7 @@ class NoirCircuitBuilder { } // recursive/ variant checksums (noir-recursive VKs for inner proofs) if (c.checksums.vkNoir && c.artifacts.vkNoir) { - const recursivePrefix = `${CIRCUIT_VARIANTS.RECURSIVE}/${c.group}/${c.name}` + const recursivePrefix = `${c.preset}/${CIRCUIT_VARIANTS.RECURSIVE}/${c.group}/${c.name}` if (c.checksums.json && c.artifacts.json) { const f = `${recursivePrefix}/${basename(c.artifacts.json)}` checksums[f] = c.checksums.json @@ -486,17 +552,20 @@ class NoirCircuitBuilder { // share_computation wrapper aliases const wrapperPath = SHARE_COMP_WRAPPER.path.join('/') - for (const variant of SHARE_COMP_WRAPPER.variants) { - const shareCompPrefix = `${variant}/${wrapperPath}/share_computation` - const basePrefix = `${variant}/${wrapperPath}` - for (const alias of SHARE_COMP_WRAPPER.aliases) { - for (const suffix of ['.json', '.vk', '.vk_hash']) { - const srcKey = `${shareCompPrefix}/share_computation${suffix}` - const srcHash = checksums[srcKey] - if (srcHash) { - const aliasKey = `${basePrefix}/${alias}/${alias}${suffix}` - checksums[aliasKey] = srcHash - lines.push(`${srcHash} ${aliasKey}`) + const presets = Array.from(new Set(compiled.map((c) => c.preset))) + for (const preset of presets) { + for (const variant of SHARE_COMP_WRAPPER.variants) { + const shareCompPrefix = `${preset}/${variant}/${wrapperPath}/share_computation` + const basePrefix = `${preset}/${variant}/${wrapperPath}` + for (const alias of SHARE_COMP_WRAPPER.aliases) { + for (const suffix of ['.json', '.vk', '.vk_hash']) { + const srcKey = `${shareCompPrefix}/share_computation${suffix}` + const srcHash = checksums[srcKey] + if (srcHash) { + const aliasKey = `${basePrefix}/${alias}/${alias}${suffix}` + checksums[aliasKey] = srcHash + lines.push(`${srcHash} ${aliasKey}`) + } } } } @@ -511,8 +580,7 @@ class NoirCircuitBuilder { return join(outputDir, 'SHA256SUMS') } - private copyArtifacts(compiled: CompiledCircuit[]): string { - const outputDir = this.options.outputDir! + private copyArtifacts(compiled: CompiledCircuit[], outputDir: string, _preset: CircuitPreset | string): string { for (const c of compiled) { if (!c.artifacts.json && !c.artifacts.vk) continue const packageName = basename(c.artifacts.json ?? '', '.json') @@ -624,6 +692,14 @@ async function main() { else if (arg === '--group') options.groups = args[++i]?.split(',') as CircuitGroup[] else if (arg === '--circuit') (options.circuits ??= []).push(args[++i]) else if (arg === '-o' || arg === '--output') options.outputDir = resolve(args[++i]) + else if (arg === '--preset') { + const val = args[++i] + if (val !== 'all' && !ALL_PRESETS.includes(val as CircuitPreset)) { + console.error(`Unknown preset: ${val}. Valid values: ${ALL_PRESETS.join(', ')}, all`) + process.exit(1) + } + options.preset = val as CircuitPreset | 'all' + } else if (['hash', 'build'].includes(arg)) command = arg } @@ -649,6 +725,7 @@ Commands: build (default), hash Options: --group Circuit groups (comma-separated: dkg,threshold) --circuit Build specific circuit(s) + --preset Parameter preset: insecure-512 (default), secure-8192, or all --skip-vk Skip verification key generation --skip-checksums Skip checksum generation -o, --output

Output directory (default: dist/circuits) @@ -660,4 +737,14 @@ Options: if (require.main === module) main() -export { NoirCircuitBuilder, BuildOptions, BuildResult, CompiledCircuit, CircuitInfo, CircuitGroup, CIRCUIT_GROUPS } +export { + NoirCircuitBuilder, + BuildOptions, + BuildResult, + CompiledCircuit, + CircuitInfo, + CircuitGroup, + CIRCUIT_GROUPS, + CIRCUIT_PRESETS, + type CircuitPreset, +} diff --git a/scripts/circuit-constants.ts b/scripts/circuit-constants.ts index 3cdeccca28..544c6f2a62 100644 --- a/scripts/circuit-constants.ts +++ b/scripts/circuit-constants.ts @@ -34,3 +34,25 @@ export const CIRCUIT_VARIANTS = { export type CircuitVariant = (typeof CIRCUIT_VARIANTS)[keyof typeof CIRCUIT_VARIANTS] export const ALL_VARIANTS: CircuitVariant[] = [CIRCUIT_VARIANTS.DEFAULT, CIRCUIT_VARIANTS.RECURSIVE, CIRCUIT_VARIANTS.EVM] + +/** + * Circuit parameter presets identify which BFV parameter set the circuits were compiled for. + * Named as `{security_tier}-{degree}`. Threshold and DKG presets at the same degree share + * the same compiled circuit artifacts. + */ +export const CIRCUIT_PRESETS = { + INSECURE_512: 'insecure-512', + SECURE_8192: 'secure-8192', +} as const + +export type CircuitPreset = (typeof CIRCUIT_PRESETS)[keyof typeof CIRCUIT_PRESETS] + +export const ALL_PRESETS: CircuitPreset[] = [CIRCUIT_PRESETS.INSECURE_512, CIRCUIT_PRESETS.SECURE_8192] + +/** + * Maps each preset to the Noir config module it re-exports from `circuits/lib/src/configs/default/mod.nr`. + */ +export const PRESET_NOIR_CONFIG: Record = { + [CIRCUIT_PRESETS.INSECURE_512]: 'insecure', + [CIRCUIT_PRESETS.SECURE_8192]: 'secure', +} diff --git a/templates/default/client/src/pages/steps/RequestComputation.tsx b/templates/default/client/src/pages/steps/RequestComputation.tsx index b6141c3ba9..06f4916d1c 100644 --- a/templates/default/client/src/pages/steps/RequestComputation.tsx +++ b/templates/default/client/src/pages/steps/RequestComputation.tsx @@ -11,7 +11,6 @@ import Spinner from '../components/Spinner' import ErrorDisplay from '../components/ErrorDisplay' import { useWizard, WizardStep } from '../../context/WizardContext' import { - encodeBfvParams, encodeComputeProviderParams, DEFAULT_COMPUTE_PROVIDER_PARAMS, DEFAULT_E3_CONFIG, diff --git a/templates/default/tests/integration.spec.ts b/templates/default/tests/integration.spec.ts index 94a487efff..2080bc5407 100644 --- a/templates/default/tests/integration.spec.ts +++ b/templates/default/tests/integration.spec.ts @@ -8,7 +8,6 @@ import { EnclaveSDK, calculateInputWindow, DEFAULT_COMPUTE_PROVIDER_PARAMS, - encodeBfvParams, encodeComputeProviderParams, decodePlaintextOutput, CommitteeSize, diff --git a/tests/integration/persist.sh b/tests/integration/persist.sh index c7311fa327..8c7445dfca 100755 --- a/tests/integration/persist.sh +++ b/tests/integration/persist.sh @@ -67,7 +67,7 @@ pnpm committee:new \ --input-window-end "$INPUT_WINDOW_END" \ --e3-params "$ENCODED_PARAMS" \ --committee-size 0 \ - --proof-aggregation-enabled true + --proof-aggregation-enabled false wait_for_committee_pubkey 0 "$SCRIPT_DIR/output/pubkey.bin"