diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml index 9498e73b2..15f889f39 100644 --- a/.github/workflows/builds.yml +++ b/.github/workflows/builds.yml @@ -22,15 +22,10 @@ jobs: cargo make --profile ${{ matrix.profile }} build-xcc-docker - run: ls -lH bin/aurora-*${{ matrix.profile }}.wasm - name: Upload aurora-${{ matrix.profile }}.wasm artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: - name: aurora-${{ matrix.profile }}.wasm - path: bin/aurora-${{ matrix.profile }}.wasm - - name: Upload aurora-factory-${{ matrix.profile }}.wasm artifact - uses: actions/upload-artifact@v2 - with: - name: aurora-factory-${{ matrix.profile }}.wasm - path: bin/aurora-factory-${{ matrix.profile }}.wasm + name: contracts + path: bin/aurora*${{ matrix.profile }}.wasm publish: name: Publish contracts @@ -38,13 +33,13 @@ jobs: needs: build steps: - name: Download artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 + - run: ls -la contracts - name: Publish contracts for ${{ github.ref }} release uses: svenstaro/upload-release-action@v2 with: tag: ${{ github.ref }} - file: aurora*.wasm - overwrite: true + file: contracts/aurora*.wasm repo_token: ${{ secrets.GITHUB_TOKEN }} file_glob: true env: diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml index a096430aa..5d976701d 100644 --- a/.github/workflows/lints.yml +++ b/.github/workflows/lints.yml @@ -40,8 +40,6 @@ jobs: git checkout -f $(git -c user.name=x -c user.email=x@x commit-tree $(git hash-object -t tree /dev/null) < /dev/null) || : - name: Clone the repository uses: actions/checkout@v3 - - name: Update udeps - run: cargo install --force cargo-udeps - name: Run udeps run: cargo make udeps contracts: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index eeb33d278..6e0448ba1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -18,7 +18,7 @@ jobs: - name: Clone the repository uses: actions/checkout@v3 - name: Restore cache - run: cache-util restore cargo_git cargo_registry yarn_cache rocksdb:/root/rocksdb + run: cache-util restore cargo_git cargo_registry yarn_cache - name: Build contracts run: cargo make build-contracts - name: Test contracts diff --git a/CHANGES.md b/CHANGES.md index 6c5e77bf9..24c57d0a2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [2.10.2] 2023-08-10 + +### Changes + +- Added a view transaction `factory_get_wnear_address` for returning address for the `wNEAR` ERC-20 contract by [@aleksuss]. ([#807]) + +### Fixes + +- Fixed a bug where standalone engine can crash on tracing transactions with too large contract deployment by [@birchmd]. ([#817]) +- Fixed a bug and performance improvements with unusual exponents in the `engine-modexp` crate by [@guidovranken]. ([#814]) + +[#817]: https://github.com/aurora-is-near/aurora-engine/pull/817 +[#814]: https://github.com/aurora-is-near/aurora-engine/pull/814 +[#807]: https://github.com/aurora-is-near/aurora-engine/pull/807 + ## [2.10.1] 2023-07-27 ### Fixes @@ -449,7 +464,8 @@ struct SubmitResult { ## [1.0.0] - 2021-05-12 -[Unreleased]: https://github.com/aurora-is-near/aurora-engine/compare/2.10.1...develop +[Unreleased]: https://github.com/aurora-is-near/aurora-engine/compare/2.10.2...develop +[2.10.2]: https://github.com/aurora-is-near/aurora-engine/compare/2.10.1...2.10.2 [2.10.1]: https://github.com/aurora-is-near/aurora-engine/compare/2.10.0...2.10.1 [2.10.0]: https://github.com/aurora-is-near/aurora-engine/compare/2.9.3...2.10.0 [2.9.3]: https://github.com/aurora-is-near/aurora-engine/compare/2.9.2...2.9.3 @@ -492,12 +508,13 @@ struct SubmitResult { [@andrcmdr]: https://github.com/andrcmdr [@birchmd]: https://github.com/birchmd [@Casuso]: https://github.com/Casuso +[@guidovranken]: https://github.com/guidovranken [@hskang9]: https://github.com/hskang9 [@joshuajbouw]: https://github.com/joshuajbouw [@mandreyel]: https://github.com/mandreyel +[@matklad]: https://github.com/matklad [@mfornet]: https://github.com/mfornet [@mrLSD]: https://github.com/mrLSD +[@olonho]: https://github.com/olonho [@RomanHodulak]: https://github.com/RomanHodulak [@sept-en]: https://github.com/sept-en -[@matklad]: https://github.com/matklad -[@olonho]: https://github.com/olonho diff --git a/Cargo.lock b/Cargo.lock index 5a3a983cf..b83cb1194 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -327,7 +327,7 @@ dependencies = [ [[package]] name = "aurora-engine" -version = "2.10.0" +version = "2.10.1" dependencies = [ "aurora-engine-modexp", "aurora-engine-precompiles", @@ -1556,6 +1556,7 @@ dependencies = [ "rocksdb", "serde", "serde_json", + "strum 0.25.0", ] [[package]] @@ -3135,7 +3136,7 @@ dependencies = [ "opentelemetry-semantic-conventions", "prometheus", "serde", - "strum", + "strum 0.24.1", "thiserror", "tokio", "tracing", @@ -3169,7 +3170,7 @@ dependencies = [ "serde", "serde_json", "smart-default", - "strum", + "strum 0.24.1", "thiserror", ] @@ -3199,7 +3200,7 @@ dependencies = [ "serde", "serde_json", "smart-default", - "strum", + "strum 0.24.1", "thiserror", ] @@ -3234,7 +3235,7 @@ dependencies = [ "serde_with", "serde_yaml", "smart-default", - "strum", + "strum 0.24.1", "thiserror", "time 0.3.23", "tracing", @@ -3254,7 +3255,7 @@ dependencies = [ "num-rational 0.3.2", "serde", "sha2 0.10.7", - "strum", + "strum 0.24.1", ] [[package]] @@ -3272,7 +3273,7 @@ dependencies = [ "serde", "serde_repr", "sha2 0.10.7", - "strum", + "strum 0.24.1", ] [[package]] @@ -3293,7 +3294,7 @@ dependencies = [ "serde_repr", "serde_with", "sha2 0.10.7", - "strum", + "strum 0.24.1", "thiserror", ] @@ -3486,7 +3487,7 @@ dependencies = [ "near-account-id 0.15.0", "near-rpc-error-macro 0.15.0", "serde", - "strum", + "strum 0.24.1", ] [[package]] @@ -3499,7 +3500,7 @@ dependencies = [ "near-account-id 0.17.0", "near-rpc-error-macro 0.17.0", "serde", - "strum", + "strum 0.24.1", "thiserror", ] @@ -5226,7 +5227,16 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" dependencies = [ - "strum_macros", + "strum_macros 0.24.3", +] + +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +dependencies = [ + "strum_macros 0.25.1", ] [[package]] @@ -5242,6 +5252,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "strum_macros" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6069ca09d878a33f883cc06aaa9718ede171841d3832450354410b718b097232" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.26", +] + [[package]] name = "subtle" version = "2.5.0" diff --git a/Cargo.toml b/Cargo.toml index fea7dc915..e87602606 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,6 +59,7 @@ serde = { version = "1", default-features = false, features = ["alloc", "derive" serde_json = { version = "1", default-features = false, features = ["alloc"] } sha2 = { version = "0.10", default-features = false } sha3 = { version = "0.10", default-features = false } +strum = { version = "0.25", features = ["derive"] } tempfile = "3" tokio = { version = "1", default-features = false, features = ["macros"] } test-case = "3.1" diff --git a/Makefile.toml b/Makefile.toml index fb9d06409..d00ffcaa8 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -300,7 +300,7 @@ run_task = "build-engine-flow-docker" [tasks.build-docker] category = "Build" script = ''' -docker run --volume $PWD:/host -w /host -i --rm nearprotocol/contract-builder:master-1f62a6883f3b99094267f33f9045954ab29af1d8-amd64 ./scripts/docker-entrypoint.sh ${PROFILE} +docker run --volume $PWD:/host -w /host -i --rm nearprotocol/contract-builder:master-de975ed75e0f6a840c7aeb57e3414959cb59bc00-amd64 ./scripts/docker-entrypoint.sh ${PROFILE} ''' [tasks.build-xcc-router-docker-inner] @@ -312,7 +312,7 @@ run_task = "build-xcc-router-flow-docker" [tasks.build-xcc-docker] category = "Build" script = ''' -docker run --volume $PWD:/host -w /host -i --rm nearprotocol/contract-builder:master-1f62a6883f3b99094267f33f9045954ab29af1d8-amd64 ./scripts/docker-xcc-router-entrypoint.sh ${PROFILE} +docker run --volume $PWD:/host -w /host -i --rm nearprotocol/contract-builder:master-de975ed75e0f6a840c7aeb57e3414959cb59bc00-amd64 ./scripts/docker-xcc-router-entrypoint.sh ${PROFILE} ''' [tasks.test-contracts] diff --git a/VERSION b/VERSION index 8bbb6e406..c6436a853 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.10.1 +2.10.2 diff --git a/engine-modexp/Cargo.toml b/engine-modexp/Cargo.toml index 86ece67a6..0cf9de094 100644 --- a/engine-modexp/Cargo.toml +++ b/engine-modexp/Cargo.toml @@ -13,9 +13,9 @@ autobenches = false [dependencies] hex.workspace = true num.workspace = true -ibig.workspace = true +ibig = { workspace = true, optional = true } [features] default = ["std"] -std = ["num/std", "ibig/std", "hex/std"] -bench = [] +std = ["num/std", "hex/std"] +bench = ["ibig"] diff --git a/engine-modexp/src/arith.rs b/engine-modexp/src/arith.rs index ca0c7de69..04a0b0218 100644 --- a/engine-modexp/src/arith.rs +++ b/engine-modexp/src/arith.rs @@ -158,32 +158,6 @@ pub fn mod_inv(x: Word) -> Word { y } -// Given x odd, computes `x^(-1) mod 2^(WORD_BYTES*out.digits.len())`. -// See `MODULAR-INVERSE` in https://link.springer.com/content/pdf/10.1007/3-540-46877-3_21.pdf -pub fn big_mod_inv(x: &MPNat, out: &mut MPNat, scratch: &mut [Word]) { - let s = out.digits.len(); - out.digits[0] = mod_inv(x.digits[0]); - - for digit_index in 1..s { - for i in 1..WORD_BITS { - let mask = (1 << i) - 1; - big_wrapping_mul(x, out, scratch); - scratch[digit_index] &= mask; - let q = 1 << (i - 1); - if scratch[digit_index] >= q { - out.digits[digit_index] += q; - } - scratch.fill(0); - } - big_wrapping_mul(x, out, scratch); - let q = 1 << (WORD_BITS - 1); - if scratch[digit_index] >= q { - out.digits[digit_index] += q; - } - scratch.fill(0); - } -} - /// Computes R mod n, where R = 2^(WORD_BITS*k) and k = n.digits.len() /// Note that if R = qn + r, q must be smaller than 2^WORD_BITS since `2^(WORD_BITS) * n > R` /// (adding a whole additional word to n is too much). @@ -294,14 +268,22 @@ pub fn big_sq(x: &MPNat, out: &mut [Word]) { out[i + i] = product; let mut c = carry as DoubleWord; for j in (i + 1)..s { - let product = (x.digits[i] as DoubleWord) * (x.digits[j] as DoubleWord); - let (product, overflow) = product.overflowing_add(product); - let sum = (out[i + j] as DoubleWord) + product + c; - out[i + j] = sum as Word; - c = (sum >> WORD_BITS) as DoubleWord; + let mut new_c: DoubleWord = 0; + let res = (x.digits[i] as DoubleWord) * (x.digits[j] as DoubleWord); + let (res, overflow) = res.overflowing_add(res); if overflow { - c += BASE; + new_c += BASE; } + let (res, overflow) = (out[i + j] as DoubleWord).overflowing_add(res); + if overflow { + new_c += BASE; + } + let (res, overflow) = res.overflowing_add(c); + if overflow { + new_c += BASE; + } + out[i + j] = res as Word; + c = new_c + ((res >> WORD_BITS) as DoubleWord); } let (sum, carry) = carrying_add(out[i + s], c as Word, false); out[i + s] = sum; @@ -351,6 +333,11 @@ pub fn in_place_add(a: &mut [Word], b: &[Word]) -> bool { pub fn in_place_mul_sub(a: &mut [Word], x: &[Word], y: Word) -> Word { debug_assert!(a.len() == x.len()); + // a -= x*0 leaves a unchanged, so return early + if y == 0 { + return 0; + } + // carry is between -big_digit::MAX and 0, so to avoid overflow we store // offset_carry = carry + big_digit::MAX let mut offset_carry = Word::MAX; @@ -504,31 +491,6 @@ fn test_r_mod_n() { } } -#[test] -fn test_big_mod_inv() { - check_big_mod_inv(0x02_FF_FF_FF); - check_big_mod_inv(0x1234_0000_DDDD_FFFF); - check_big_mod_inv(0x52DA_9A91_F82D_6E17_FDF8_6743_2B58_7917); - - fn check_big_mod_inv(n: u128) { - let x = MPNat::from_big_endian(&n.to_be_bytes()); - let s = x.digits.len(); - let mut result = MPNat { digits: vec![0; s] }; - let mut scratch = vec![0; s]; - big_mod_inv(&x, &mut result, &mut scratch); - let n_inv = mp_nat_to_u128(&result); - if WORD_BITS * s < u128::BITS as usize { - assert_eq!( - n.wrapping_mul(n_inv) % (1 << (WORD_BITS * s)), - 1, - "{n} failed big_mod_inv check" - ); - } else { - assert_eq!(n.wrapping_mul(n_inv), 1, "{n} failed big_mod_inv check"); - } - } -} - #[test] fn test_in_place_shl() { check_in_place_shl(0, 0); @@ -655,6 +617,24 @@ fn test_big_sq() { }; assert_eq!(result, expected, "{a}^2 != {expected}"); } + + /* Test for addition overflows in the big_sq inner loop */ + { + let x = MPNat::from_big_endian(&[ + 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, + ]); + let mut out = vec![0; 2 * x.digits.len() + 1]; + big_sq(&x, &mut out); + let result = MPNat { digits: out }.to_big_endian(); + let expected = vec![ + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0xff, 0xff, 0xff, 0xfe, 0x40, 0x00, 0x00, 0x01, 0x90, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xbf, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + assert_eq!(result, expected); + } } #[test] diff --git a/engine-modexp/src/lib.rs b/engine-modexp/src/lib.rs index fbb5ff2ba..6bd08fa21 100644 --- a/engine-modexp/src/lib.rs +++ b/engine-modexp/src/lib.rs @@ -21,7 +21,7 @@ pub struct AuroraModExp; impl ModExpAlgorithm for AuroraModExp { fn modexp(base: &[u8], exp: &[u8], modulus: &[u8]) -> Vec { - modexp_ibig(base, exp, modulus) + modexp(base, exp, modulus) } } @@ -37,6 +37,7 @@ pub fn modexp(base: &[u8], exp: &[u8], modulus: &[u8]) -> Vec { result.to_big_endian() } +#[cfg(feature = "bench")] pub fn modexp_ibig(base: &[u8], exp: &[u8], modulus: &[u8]) -> Vec { use num::Zero; diff --git a/engine-modexp/src/mpnat.rs b/engine-modexp/src/mpnat.rs index 312b106aa..917030a6c 100644 --- a/engine-modexp/src/mpnat.rs +++ b/engine-modexp/src/mpnat.rs @@ -1,8 +1,8 @@ use crate::{ arith::{ - big_mod_inv, big_wrapping_mul, big_wrapping_pow, borrowing_sub, carrying_add, - compute_r_mod_n, in_place_add, in_place_mul_sub, in_place_shl, in_place_shr, - join_as_double, mod_inv, monpro, monsq, + big_wrapping_mul, big_wrapping_pow, borrowing_sub, carrying_add, compute_r_mod_n, + in_place_add, in_place_mul_sub, in_place_shl, in_place_shr, join_as_double, mod_inv, + monpro, monsq, }, maybe_std::{vec, Vec}, }; @@ -22,6 +22,72 @@ pub struct MPNat { } impl MPNat { + fn strip_leading_zeroes(a: &[u8]) -> (&[u8], bool) { + let len = a.len(); + let end = a.iter().position(|&x| x != 0).unwrap_or(len); + + if end == len { + (&[], true) + } else { + (&a[end..], false) + } + } + + // KoƧ's algorithm for inversion mod 2^k + // https://eprint.iacr.org/2017/411.pdf + fn koc_2017_inverse(aa: &Self, k: usize) -> Self { + debug_assert!(aa.is_odd()); + + let length = k / WORD_BITS; + let mut b = MPNat { + digits: vec![0; length + 1], + }; + b.digits[0] = 1; + + let mut a = MPNat { + digits: aa.digits.clone(), + }; + a.digits.resize(length + 1, 0); + + let mut neg: bool = false; + + let mut res = MPNat { + digits: vec![0; length + 1], + }; + + let (mut wordpos, mut bitpos) = (0, 0); + + for _ in 0..k { + let x = b.digits[0] & 1; + if x != 0 { + if !neg { + // b = a - b + let mut tmp = MPNat { + digits: a.digits.clone(), + }; + in_place_mul_sub(&mut tmp.digits, &b.digits, 1); + b = tmp; + neg = true; + } else { + // b = b - a + in_place_add(&mut b.digits, &a.digits); + } + } + + in_place_shr(&mut b.digits, 1); + + res.digits[wordpos] |= x << bitpos; + + bitpos += 1; + if bitpos == WORD_BITS { + bitpos = 0; + wordpos += 1; + } + } + + res + } + pub fn from_big_endian(bytes: &[u8]) -> Self { if bytes.is_empty() { return Self { digits: vec![0] }; @@ -88,8 +154,24 @@ impl MPNat { /// Computes `self ^ exp mod modulus`. `exp` must be given as big-endian bytes. pub fn modpow(&mut self, exp: &[u8], modulus: &Self) -> Self { - if exp.iter().all(|x| x == &0) { - return Self { digits: vec![1] }; + // exp must be stripped because it is iterated over in + // big_wrapping_pow and modpow_montgomery, and a large + // zero-padded exp leads to performance issues. + let (exp, exp_is_zero) = Self::strip_leading_zeroes(exp); + + // base^0 is always 1, regardless of base. + // Hence the result is 0 for (base^0) % 1, and 1 + // for every modulus larger than 1. + // + // The case of modulus being 0 should have already been + // handled in modexp(). + debug_assert!(!(modulus.digits.len() == 1 && modulus.digits[0] == 0)); + if exp_is_zero { + if modulus.digits.len() == 1 && modulus.digits[0] == 1 { + return Self { digits: vec![0] }; + } else { + return Self { digits: vec![1] }; + } } if exp.len() <= core::mem::size_of::() { @@ -174,14 +256,11 @@ impl MPNat { let x1 = base_copy.modpow_montgomery(exp, &odd); let x2 = self.modpow_with_power_of_two(exp, &power_of_two); + let odd_inv = + Self::koc_2017_inverse(&odd, trailing_zeros * WORD_BITS + additional_zero_bits); + let s = power_of_two.digits.len(); let mut scratch = vec![0; s]; - let odd_inv = { - let mut tmp = MPNat { digits: vec![0; s] }; - big_mod_inv(&odd, &mut tmp, &mut scratch); - *tmp.digits.last_mut().unwrap() &= power_of_two_mask; - tmp - }; let diff = { scratch.fill(0); let mut b = false; @@ -348,7 +427,7 @@ impl MPNat { return; } - let other_most_sig = *other.digits.last().unwrap(); + let other_most_sig = *other.digits.last().unwrap() as DoubleWord; if self.digits.len() == 2 { // This is the smallest case since `n >= 1` and `m > 0` @@ -357,7 +436,7 @@ impl MPNat { // to get the answer directly. let self_most_sig = self.digits.pop().unwrap(); let a = join_as_double(self_most_sig, self.digits[0]); - let b = other_most_sig as DoubleWord; + let b = other_most_sig; self.digits[0] = (a % b) as Word; return; } @@ -369,8 +448,7 @@ impl MPNat { for j in (0..k).rev() { let self_most_sig = self.digits.pop().unwrap(); let self_second_sig = self.digits[j]; - let r = - join_as_double(self_most_sig, self_second_sig) % (other_most_sig as DoubleWord); + let r = join_as_double(self_most_sig, self_second_sig) % other_most_sig; self.digits[j] = r as Word; } return; @@ -385,7 +463,7 @@ impl MPNat { // both numerator and denominator by a common factor // and run the algorithm on those numbers. // See Knuth The Art of Computer Programming vol. 2 section 4.3 for details. - let shift = other_most_sig.leading_zeros(); + let shift = (other_most_sig as Word).leading_zeros(); if shift > 0 { // Normalize self let overflow = in_place_shl(&mut self.digits, shift); @@ -410,34 +488,31 @@ impl MPNat { return; } - let other_second_sig = other.digits[n - 2]; + let other_second_sig = other.digits[n - 2] as DoubleWord; let mut self_most_sig: Word = 0; for j in (0..=m).rev() { let self_second_sig = *self.digits.last().unwrap(); let self_third_sig = self.digits[self.digits.len() - 2]; - let (mut q_hat, mut r_hat) = { - let a = join_as_double(self_most_sig, self_second_sig); - let mut q_hat = a / (other_most_sig as DoubleWord); - let mut r_hat = a % (other_most_sig as DoubleWord); + let a = join_as_double(self_most_sig, self_second_sig); + let mut q_hat = a / other_most_sig; + let mut r_hat = a % other_most_sig; - if q_hat == BASE { + loop { + let a = q_hat * other_second_sig; + let b = join_as_double(r_hat as Word, self_third_sig); + if q_hat >= BASE || a > b { q_hat -= 1; - r_hat += other_most_sig as DoubleWord; + r_hat += other_most_sig; + if BASE <= r_hat { + break; + } + } else { + break; } - - (q_hat as Word, r_hat) - }; - - while r_hat < BASE - && join_as_double(r_hat as Word, self_third_sig) - < (q_hat as DoubleWord) * (other_second_sig as DoubleWord) - { - q_hat -= 1; - r_hat += other_most_sig as DoubleWord; } - let mut borrow = in_place_mul_sub(&mut self.digits[j..], &other.digits, q_hat); + let mut borrow = in_place_mul_sub(&mut self.digits[j..], &other.digits, q_hat as Word); if borrow > self_most_sig { // q_hat was too large, add back one multiple of the modulus let carry = in_place_add(&mut self.digits[j..], &other.digits); @@ -556,6 +631,20 @@ fn test_modpow_even() { "023f4f762936eb0973d46b6eadb59d68d06101" ); + // Test empty exp + let base = hex::decode("00").unwrap(); + let exponent = hex::decode("").unwrap(); + let modulus = hex::decode("02").unwrap(); + let result = crate::modexp(&base, &exponent, &modulus); + assert_eq!(hex::encode(result), "01"); + + // Test zero exp + let base = hex::decode("00").unwrap(); + let exponent = hex::decode("00").unwrap(); + let modulus = hex::decode("02").unwrap(); + let result = crate::modexp(&base, &exponent, &modulus); + assert_eq!(hex::encode(result), "01"); + fn check_modpow_even(base: u128, exp: u128, modulus: u128, expected: u128) { let mut x = MPNat::from_big_endian(&base.to_be_bytes()); let m = MPNat::from_big_endian(&modulus.to_be_bytes()); @@ -660,6 +749,34 @@ fn test_sub_to_same_size() { let result = crate::arith::mp_nat_to_u128(&x); assert_eq!(result % n, a % n, "{a} % {n} failed sub_to_same_size check"); } + + /* Test that borrow equals self_most_sig at end of sub_to_same_size */ + { + let mut x = MPNat::from_big_endian(&[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x5f, 0xf0, 0x8b, 0xfc, 0x02, + 0x71, 0xa4, 0xfe, 0xe0, 0x49, 0x02, 0xc9, 0xd9, 0x12, 0x61, 0x8e, 0xf5, 0x02, 0x2c, + 0xa0, 0x00, 0x00, 0x00, + ]); + let y = MPNat::from_big_endian(&[ + 0xae, 0x5f, 0xf0, 0x8b, 0xfc, 0x02, 0x71, 0xa4, 0xfe, 0xe0, 0x49, 0x0f, 0x70, 0x00, + 0x00, 0x00, + ]); + x.sub_to_same_size(&y); + } + + /* Additional test for sub_to_same_size q_hat/r_hat adjustment logic */ + { + let mut x = MPNat::from_big_endian(&[ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]); + let y = MPNat::from_big_endian(&[ + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, + ]); + x.sub_to_same_size(&y); + } } #[test] diff --git a/engine-standalone-storage/Cargo.toml b/engine-standalone-storage/Cargo.toml index cacf5e388..c0cc78c1e 100644 --- a/engine-standalone-storage/Cargo.toml +++ b/engine-standalone-storage/Cargo.toml @@ -26,6 +26,7 @@ rocksdb.workspace = true postgres.workspace = true serde = { workspace = true, features = ["std"] } serde_json = { workspace = true, features = ["std"] } +strum.workspace = true [features] default = ["snappy", "lz4", "zstd", "zlib"] diff --git a/engine-standalone-storage/src/error.rs b/engine-standalone-storage/src/error.rs index 39ff93f21..75481cb75 100644 --- a/engine-standalone-storage/src/error.rs +++ b/engine-standalone-storage/src/error.rs @@ -1,6 +1,6 @@ +use crate::{sync::types::TransactionKindTag, TransactionIncluded}; use aurora_engine_types::H256; - -use crate::TransactionIncluded; +use std::fmt; #[derive(Debug, PartialEq, Clone)] pub enum Error { @@ -25,3 +25,47 @@ impl From for Error { Self::Borsh(e.to_string()) } } + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ParseTransactionKindError { + UnknownMethodName { + name: String, + }, + FailedDeserialization { + transaction_kind_tag: TransactionKindTag, + error_message: String, + }, +} + +impl ParseTransactionKindError { + pub fn failed_deserialization( + tag: TransactionKindTag, + error: Option, + ) -> Self { + Self::FailedDeserialization { + transaction_kind_tag: tag, + error_message: error.map(|e| format!("{e:?}")).unwrap_or_default(), + } + } +} + +impl fmt::Display for ParseTransactionKindError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::UnknownMethodName { name } => { + write!( + f, + "Error parsing transaction kind: Unknown method name {name}" + ) + } + Self::FailedDeserialization { + transaction_kind_tag, + error_message, + } => { + write!(f, "Error deserializing args for transaction of kind {transaction_kind_tag:?}. Error message: {error_message:?}") + } + } + } +} + +impl std::error::Error for ParseTransactionKindError {} diff --git a/engine-standalone-storage/src/sync/mod.rs b/engine-standalone-storage/src/sync/mod.rs index 0f32b33ba..407804dc8 100644 --- a/engine-standalone-storage/src/sync/mod.rs +++ b/engine-standalone-storage/src/sync/mod.rs @@ -2,21 +2,229 @@ use aurora_engine::parameters::SubmitArgs; use aurora_engine::pausables::{ EnginePrecompilesPauser, PausedPrecompilesManager, PrecompileFlags, }; -use aurora_engine::{connector, engine, parameters::SubmitResult, state, xcc}; +use aurora_engine::{ + connector, engine, + parameters::{self, SubmitResult}, + state, xcc, +}; use aurora_engine_modexp::ModExpAlgorithm; use aurora_engine_sdk::env::{self, Env, DEFAULT_PREPAID_GAS}; +use aurora_engine_transactions::EthTransactionKind; use aurora_engine_types::{ account_id::AccountId, + borsh::BorshDeserialize, parameters::PromiseWithCallbackArgs, types::{Address, Yocto}, H256, }; +use std::{io, str::FromStr}; pub mod types; use crate::engine_state::EngineStateAccess; -use crate::{BlockMetadata, Diff, Storage}; -use types::{Message, TransactionKind, TransactionMessage}; +use crate::{error::ParseTransactionKindError, BlockMetadata, Diff, Storage}; +use types::{Message, TransactionKind, TransactionKindTag, TransactionMessage}; + +/// Try to parse an Aurora transaction from raw information available in a Near action +/// (method name, input bytes, data returned from promises). +#[allow(clippy::too_many_lines)] +pub fn parse_transaction_kind( + method_name: &str, + bytes: Vec, + promise_data: &[Option>], +) -> Result { + let tx_kind_tag = TransactionKindTag::from_str(method_name).map_err(|_| { + ParseTransactionKindError::UnknownMethodName { + name: method_name.into(), + } + })?; + let f = |e: io::Error| ParseTransactionKindError::failed_deserialization(tx_kind_tag, Some(e)); + + let tx_kind = match tx_kind_tag { + TransactionKindTag::Submit => { + let eth_tx = EthTransactionKind::try_from(bytes.as_slice()).map_err(|e| { + ParseTransactionKindError::failed_deserialization(tx_kind_tag, Some(e)) + })?; + TransactionKind::Submit(eth_tx) + } + TransactionKindTag::SubmitWithArgs => { + let args = parameters::SubmitArgs::try_from_slice(&bytes).map_err(f)?; + TransactionKind::SubmitWithArgs(args) + } + TransactionKindTag::Call => { + let call_args = parameters::CallArgs::deserialize(&bytes).ok_or_else(|| { + ParseTransactionKindError::failed_deserialization::(tx_kind_tag, None) + })?; + TransactionKind::Call(call_args) + } + TransactionKindTag::PausePrecompiles => { + let args = parameters::PausePrecompilesCallArgs::try_from_slice(&bytes).map_err(f)?; + TransactionKind::PausePrecompiles(args) + } + TransactionKindTag::ResumePrecompiles => { + let args = parameters::PausePrecompilesCallArgs::try_from_slice(&bytes).map_err(f)?; + TransactionKind::ResumePrecompiles(args) + } + TransactionKindTag::SetOwner => { + let args = parameters::SetOwnerArgs::try_from_slice(&bytes).map_err(f)?; + TransactionKind::SetOwner(args) + } + TransactionKindTag::Deploy => TransactionKind::Deploy(bytes), + TransactionKindTag::DeployErc20 => { + let deploy_args = + parameters::DeployErc20TokenArgs::try_from_slice(&bytes).map_err(f)?; + TransactionKind::DeployErc20(deploy_args) + } + TransactionKindTag::FtOnTransfer => { + let transfer_args: parameters::NEP141FtOnTransferArgs = + serde_json::from_slice(bytes.as_slice()).map_err(|e| { + ParseTransactionKindError::failed_deserialization(tx_kind_tag, Some(e)) + })?; + + TransactionKind::FtOnTransfer(transfer_args) + } + TransactionKindTag::Deposit => TransactionKind::Deposit(bytes), + TransactionKindTag::FtTransferCall => { + let transfer_args: parameters::TransferCallCallArgs = + serde_json::from_slice(bytes.as_slice()).map_err(|e| { + ParseTransactionKindError::failed_deserialization(tx_kind_tag, Some(e)) + })?; + + TransactionKind::FtTransferCall(transfer_args) + } + TransactionKindTag::FinishDeposit => { + let args = parameters::FinishDepositCallArgs::try_from_slice(&bytes).map_err(f)?; + TransactionKind::FinishDeposit(args) + } + TransactionKindTag::ResolveTransfer => { + let args = parameters::ResolveTransferCallArgs::try_from_slice(&bytes).map_err(f)?; + let promise_result = promise_data + .first() + .and_then(Option::as_ref) + .map_or(aurora_engine_types::types::PromiseResult::Failed, |bytes| { + aurora_engine_types::types::PromiseResult::Successful(bytes.clone()) + }); + TransactionKind::ResolveTransfer(args, promise_result) + } + TransactionKindTag::FtTransfer => { + let args: parameters::TransferCallArgs = serde_json::from_slice(bytes.as_slice()) + .map_err(|e| { + ParseTransactionKindError::failed_deserialization(tx_kind_tag, Some(e)) + })?; + + TransactionKind::FtTransfer(args) + } + TransactionKindTag::Withdraw => { + let args = aurora_engine_types::parameters::WithdrawCallArgs::try_from_slice(&bytes) + .map_err(f)?; + TransactionKind::Withdraw(args) + } + TransactionKindTag::StorageDeposit => { + let args: parameters::StorageDepositCallArgs = serde_json::from_slice(bytes.as_slice()) + .map_err(|e| { + ParseTransactionKindError::failed_deserialization(tx_kind_tag, Some(e)) + })?; + + TransactionKind::StorageDeposit(args) + } + TransactionKindTag::StorageUnregister => { + let json_args: serde_json::Value = + serde_json::from_slice(bytes.as_slice()).map_err(|e| { + ParseTransactionKindError::failed_deserialization(tx_kind_tag, Some(e)) + })?; + let force = json_args + .as_object() + .and_then(|x| x.get("force")) + .and_then(serde_json::Value::as_bool); + + TransactionKind::StorageUnregister(force) + } + TransactionKindTag::StorageWithdraw => { + let args: parameters::StorageWithdrawCallArgs = + serde_json::from_slice(bytes.as_slice()).map_err(|e| { + ParseTransactionKindError::failed_deserialization(tx_kind_tag, Some(e)) + })?; + + TransactionKind::StorageWithdraw(args) + } + TransactionKindTag::SetPausedFlags => { + let args = parameters::PauseEthConnectorCallArgs::try_from_slice(&bytes).map_err(f)?; + TransactionKind::SetPausedFlags(args) + } + TransactionKindTag::RegisterRelayer => { + let address = Address::try_from_slice(&bytes).map_err(|e| { + ParseTransactionKindError::failed_deserialization(tx_kind_tag, Some(e)) + })?; + TransactionKind::RegisterRelayer(address) + } + TransactionKindTag::RefundOnError => match promise_data.first().and_then(Option::as_ref) { + None => TransactionKind::RefundOnError(None), + Some(_) => { + let args = aurora_engine_types::parameters::RefundCallArgs::try_from_slice(&bytes) + .map_err(f)?; + TransactionKind::RefundOnError(Some(args)) + } + }, + TransactionKindTag::SetConnectorData => { + let args = parameters::SetContractDataCallArgs::try_from_slice(&bytes).map_err(f)?; + TransactionKind::SetConnectorData(args) + } + TransactionKindTag::NewConnector => { + let args = parameters::InitCallArgs::try_from_slice(&bytes).map_err(f)?; + TransactionKind::NewConnector(args) + } + TransactionKindTag::NewEngine => { + let args = parameters::NewCallArgs::deserialize(&bytes).map_err(|e| { + ParseTransactionKindError::failed_deserialization(tx_kind_tag, Some(e)) + })?; + TransactionKind::NewEngine(args) + } + TransactionKindTag::FactoryUpdate => TransactionKind::FactoryUpdate(bytes), + TransactionKindTag::FactoryUpdateAddressVersion => { + let args = + aurora_engine::xcc::AddressVersionUpdateArgs::try_from_slice(&bytes).map_err(f)?; + TransactionKind::FactoryUpdateAddressVersion(args) + } + TransactionKindTag::FactorySetWNearAddress => { + let address = Address::try_from_slice(&bytes).map_err(|e| { + ParseTransactionKindError::failed_deserialization(tx_kind_tag, Some(e)) + })?; + TransactionKind::FactorySetWNearAddress(address) + } + TransactionKindTag::SetUpgradeDelayBlocks => { + let args = aurora_engine::parameters::SetUpgradeDelayBlocksArgs::try_from_slice(&bytes) + .map_err(f)?; + TransactionKind::SetUpgradeDelayBlocks(args) + } + TransactionKindTag::FundXccSubAccound => { + let args = aurora_engine::xcc::FundXccArgs::try_from_slice(&bytes).map_err(f)?; + TransactionKind::FundXccSubAccound(args) + } + TransactionKindTag::PauseContract => TransactionKind::PauseContract, + TransactionKindTag::ResumeContract => TransactionKind::ResumeContract, + TransactionKindTag::SetKeyManager => { + let args = aurora_engine::parameters::RelayerKeyManagerArgs::try_from_slice(&bytes) + .map_err(f)?; + TransactionKind::SetKeyManager(args) + } + TransactionKindTag::AddRelayerKey => { + let args = + aurora_engine::parameters::RelayerKeyArgs::try_from_slice(&bytes).map_err(f)?; + TransactionKind::AddRelayerKey(args) + } + TransactionKindTag::RemoveRelayerKey => { + let args = + aurora_engine::parameters::RelayerKeyArgs::try_from_slice(&bytes).map_err(f)?; + TransactionKind::RemoveRelayerKey(args) + } + TransactionKindTag::Unknown => { + return Err(ParseTransactionKindError::UnknownMethodName { + name: method_name.into(), + }); + } + }; + Ok(tx_kind) +} pub fn consume_message( storage: &mut Storage, diff --git a/engine-standalone-storage/src/sync/types.rs b/engine-standalone-storage/src/sync/types.rs index 1c702aa8b..cab2209a8 100644 --- a/engine-standalone-storage/src/sync/types.rs +++ b/engine-standalone-storage/src/sync/types.rs @@ -10,6 +10,7 @@ use aurora_engine_types::{ H256, U256, }; use std::borrow::Cow; +use strum::EnumString; /// Type describing the format of messages sent to the storage layer for keeping /// it in sync with the blockchain. @@ -407,6 +408,122 @@ impl TransactionKind { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, EnumString)] +pub enum TransactionKindTag { + #[strum(serialize = "submit")] + Submit, + #[strum(serialize = "call")] + Call, + #[strum(serialize = "pause_precompiles")] + PausePrecompiles, + #[strum(serialize = "resume_precompiles")] + ResumePrecompiles, + #[strum(serialize = "deploy_code")] + Deploy, + #[strum(serialize = "deploy_erc20_token")] + DeployErc20, + #[strum(serialize = "ft_on_transfer")] + FtOnTransfer, + #[strum(serialize = "deposit")] + Deposit, + #[strum(serialize = "ft_transfer_call")] + FtTransferCall, + #[strum(serialize = "finish_deposit")] + FinishDeposit, + #[strum(serialize = "ft_resolve_transfer")] + ResolveTransfer, + #[strum(serialize = "ft_transfer")] + FtTransfer, + #[strum(serialize = "withdraw")] + Withdraw, + #[strum(serialize = "storage_deposit")] + StorageDeposit, + #[strum(serialize = "storage_unregister")] + StorageUnregister, + #[strum(serialize = "storage_withdraw")] + StorageWithdraw, + #[strum(serialize = "set_paused_flags")] + SetPausedFlags, + #[strum(serialize = "register_relayer")] + RegisterRelayer, + #[strum(serialize = "refund_on_error")] + RefundOnError, + #[strum(serialize = "set_eth_connector_contract_data")] + SetConnectorData, + #[strum(serialize = "new_eth_connector")] + NewConnector, + #[strum(serialize = "new")] + NewEngine, + #[strum(serialize = "factory_update")] + FactoryUpdate, + #[strum(serialize = "factory_update_address_version")] + FactoryUpdateAddressVersion, + #[strum(serialize = "factory_set_wnear_address")] + FactorySetWNearAddress, + #[strum(serialize = "set_owner")] + SetOwner, + #[strum(serialize = "submit_with_args")] + SubmitWithArgs, + #[strum(serialize = "set_upgrade_delay_blocks")] + SetUpgradeDelayBlocks, + #[strum(serialize = "fund_xcc_sub_account")] + FundXccSubAccound, + #[strum(serialize = "pause_contract")] + PauseContract, + #[strum(serialize = "resume_contract")] + ResumeContract, + #[strum(serialize = "set_key_manager")] + SetKeyManager, + #[strum(serialize = "add_relayer_key")] + AddRelayerKey, + #[strum(serialize = "remove_relayer_key")] + RemoveRelayerKey, + Unknown, +} + +/// Used to make sure `TransactionKindTag` is kept in sync with `TransactionKind` +impl From<&TransactionKind> for TransactionKindTag { + fn from(tx: &TransactionKind) -> Self { + match tx { + TransactionKind::Submit(_) => Self::Submit, + TransactionKind::Call(_) => Self::Call, + TransactionKind::PausePrecompiles(_) => Self::PausePrecompiles, + TransactionKind::ResumePrecompiles(_) => Self::ResumePrecompiles, + TransactionKind::Deploy(_) => Self::Deploy, + TransactionKind::DeployErc20(_) => Self::DeployErc20, + TransactionKind::FtOnTransfer(_) => Self::FtOnTransfer, + TransactionKind::Deposit(_) => Self::Deposit, + TransactionKind::FtTransferCall(_) => Self::FtTransferCall, + TransactionKind::FinishDeposit(_) => Self::FinishDeposit, + TransactionKind::ResolveTransfer(_, _) => Self::ResolveTransfer, + TransactionKind::FtTransfer(_) => Self::FtTransfer, + TransactionKind::Withdraw(_) => Self::Withdraw, + TransactionKind::StorageDeposit(_) => Self::StorageDeposit, + TransactionKind::StorageUnregister(_) => Self::StorageUnregister, + TransactionKind::StorageWithdraw(_) => Self::StorageWithdraw, + TransactionKind::SetPausedFlags(_) => Self::SetPausedFlags, + TransactionKind::RegisterRelayer(_) => Self::RegisterRelayer, + TransactionKind::RefundOnError(_) => Self::RefundOnError, + TransactionKind::SetConnectorData(_) => Self::SetConnectorData, + TransactionKind::NewConnector(_) => Self::NewConnector, + TransactionKind::NewEngine(_) => Self::NewEngine, + TransactionKind::FactoryUpdate(_) => Self::FactoryUpdate, + TransactionKind::FactoryUpdateAddressVersion(_) => Self::FactoryUpdateAddressVersion, + TransactionKind::FactorySetWNearAddress(_) => Self::FactorySetWNearAddress, + TransactionKind::SetOwner(_) => Self::SetOwner, + TransactionKind::SubmitWithArgs(_) => Self::SubmitWithArgs, + TransactionKind::SetUpgradeDelayBlocks(_) => Self::SetUpgradeDelayBlocks, + TransactionKind::FundXccSubAccound(_) => Self::FundXccSubAccound, + TransactionKind::PauseContract => Self::PauseContract, + TransactionKind::ResumeContract => Self::ResumeContract, + TransactionKind::SetKeyManager(_) => Self::SetKeyManager, + TransactionKind::AddRelayerKey(_) => Self::AddRelayerKey, + TransactionKind::RemoveRelayerKey(_) => Self::RemoveRelayerKey, + TransactionKind::Unknown => Self::Unknown, + } + } +} + /// This data type represents `TransactionMessage` above in the way consistent with how it is /// stored on disk (in the DB). This type implements borsh (de)serialization. The purpose of /// having a private struct for borsh, which is separate from the main `TransactionMessage` diff --git a/engine-standalone-tracing/src/types/call_tracer.rs b/engine-standalone-tracing/src/types/call_tracer.rs index 97237ccc8..22bdadf0c 100644 --- a/engine-standalone-tracing/src/types/call_tracer.rs +++ b/engine-standalone-tracing/src/types/call_tracer.rs @@ -20,10 +20,37 @@ pub struct CallFrame { #[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct CallTracer { pub call_stack: Vec, + pub top_level_transact: Option, } impl CallTracer { fn end(&mut self, output: Vec, error: Option<&evm::ExitReason>) { + if self.call_stack.is_empty() { + debug_assert!( + error.is_some(), + "Empty stack can only occur if there is an early error" + ); + debug_assert!( + self.top_level_transact.is_some(), + "Top level transact events always come before any exit event" + ); + let frame = self.top_level_transact.take().unwrap_or_else(|| CallFrame { + call_type: CallType::Call, + from: Address::default(), + to: None, + value: U256::zero(), + gas: 0, + gas_used: 0, + input: Vec::new(), + output: Vec::new(), + error: Some("Tracing bug: Exit before Enter".into()), + calls: Vec::new(), + }); + self.call_stack.push(frame); + } + + // unwrap is safe because we push a new frame if the + // stack was empty at the start of this method. let frame = self.call_stack.first_mut().unwrap(); match error { None => { @@ -161,6 +188,7 @@ impl evm_runtime::tracing::EventListener for CallTracer { } impl evm::tracing::EventListener for CallTracer { + #[allow(clippy::too_many_lines)] fn event(&mut self, event: evm::tracing::Event) { match event { evm::tracing::Event::Call { @@ -255,11 +283,75 @@ impl evm::tracing::EventListener for CallTracer { self.exit(return_value.to_vec(), error); } + evm::tracing::Event::TransactCall { + caller, + address, + value, + data, + gas_limit, + } => { + let frame = CallFrame { + call_type: CallType::Call, + from: Address::new(caller), + to: Some(Address::new(address)), + value, + gas: gas_limit, + gas_used: 0, + input: data.to_vec(), + output: Vec::new(), + error: None, + calls: Vec::new(), + }; + self.top_level_transact = Some(frame); + } + + evm::tracing::Event::TransactCreate { + caller, + value, + init_code, + gas_limit, + address, + } => { + let frame = CallFrame { + call_type: CallType::Create, + from: Address::new(caller), + to: Some(Address::new(address)), + value, + gas: gas_limit, + gas_used: 0, + input: init_code.to_vec(), + output: Vec::new(), + error: None, + calls: Vec::new(), + }; + self.top_level_transact = Some(frame); + } + + evm::tracing::Event::TransactCreate2 { + caller, + value, + init_code, + gas_limit, + address, + .. + } => { + let frame = CallFrame { + call_type: CallType::Create2, + from: Address::new(caller), + to: Some(Address::new(address)), + value, + gas: gas_limit, + gas_used: 0, + input: init_code.to_vec(), + output: Vec::new(), + error: None, + calls: Vec::new(), + }; + self.top_level_transact = Some(frame); + } + // not useful - evm::tracing::Event::PrecompileSubcall { .. } - | evm::tracing::Event::TransactCall { .. } - | evm::tracing::Event::TransactCreate { .. } - | evm::tracing::Event::TransactCreate2 { .. } => (), + evm::tracing::Event::PrecompileSubcall { .. } => (), } } } diff --git a/engine-tests/src/tests/contract_call.rs b/engine-tests/src/tests/contract_call.rs index d061059f5..f8856cb79 100644 --- a/engine-tests/src/tests/contract_call.rs +++ b/engine-tests/src/tests/contract_call.rs @@ -2,7 +2,7 @@ use crate::prelude::{parameters::SubmitResult, vec, Address, Wei, H256, U256}; use crate::utils::solidity::exit_precompile::{ Tester, TesterConstructor, DEST_ACCOUNT, DEST_ADDRESS, }; -use crate::utils::{self, AuroraRunner, Signer, ORIGIN}; +use crate::utils::{self, AuroraRunner, Signer, DEFAULT_AURORA_ACCOUNT_ID}; fn setup_test() -> (AuroraRunner, Signer, Address, Tester) { let mut runner = AuroraRunner::new(); @@ -26,7 +26,12 @@ fn setup_test() -> (AuroraRunner, Signer, Address, Tester) { .into(); runner - .mint(token, tester.contract.address, 1_000_000_000, ORIGIN) + .mint( + token, + tester.contract.address, + 1_000_000_000, + DEFAULT_AURORA_ACCOUNT_ID, + ) .unwrap(); (runner, signer, token, tester) diff --git a/engine-tests/src/tests/erc20_connector.rs b/engine-tests/src/tests/erc20_connector.rs index 9bddd2305..8578ece1b 100644 --- a/engine-tests/src/tests/erc20_connector.rs +++ b/engine-tests/src/tests/erc20_connector.rs @@ -1,5 +1,5 @@ use crate::prelude::{Address, Balance, Wei, WeiU256, U256}; -use crate::utils::{self, create_eth_transaction, AuroraRunner, ORIGIN}; +use crate::utils::{self, create_eth_transaction, AuroraRunner, DEFAULT_AURORA_ACCOUNT_ID}; use aurora_engine::engine::EngineError; use aurora_engine::parameters::{CallArgs, FunctionCallArgsV2}; use aurora_engine_transactions::legacy::LegacyEthSignedTransaction; @@ -92,7 +92,11 @@ impl AuroraRunner { pub fn deploy_erc20_token(&mut self, nep141: &str) -> Address { let result = self - .make_call("deploy_erc20_token", ORIGIN, nep141.try_to_vec().unwrap()) + .make_call( + "deploy_erc20_token", + DEFAULT_AURORA_ACCOUNT_ID, + nep141.try_to_vec().unwrap(), + ) .unwrap(); Vec::try_from_slice(&result.return_data.as_value().unwrap()) @@ -217,11 +221,11 @@ fn test_mint() { let mut runner = AuroraRunner::new(); let token = runner.deploy_erc20_token("tt.testnet"); let address = runner.create_account().address; - let balance = runner.balance_of(token, address, ORIGIN); + let balance = runner.balance_of(token, address, DEFAULT_AURORA_ACCOUNT_ID); assert_eq!(balance, U256::from(0)); let amount = 10; - let _result = runner.mint(token, address, amount, ORIGIN); - let balance = runner.balance_of(token, address, ORIGIN); + let _result = runner.mint(token, address, amount, DEFAULT_AURORA_ACCOUNT_ID); + let balance = runner.balance_of(token, address, DEFAULT_AURORA_ACCOUNT_ID); assert_eq!(balance, U256::from(amount)); } @@ -230,11 +234,11 @@ fn test_mint_not_admin() { let mut runner = AuroraRunner::new(); let token = runner.deploy_erc20_token("tt.testnet"); let address = runner.create_account().address; - let balance = runner.balance_of(token, address, ORIGIN); + let balance = runner.balance_of(token, address, DEFAULT_AURORA_ACCOUNT_ID); assert_eq!(balance, U256::from(0)); let amount = 10; runner.mint(token, address, amount, "not_admin").unwrap(); - let balance = runner.balance_of(token, address, ORIGIN); + let balance = runner.balance_of(token, address, DEFAULT_AURORA_ACCOUNT_ID); assert_eq!(balance, U256::from(0)); } @@ -249,14 +253,14 @@ fn test_ft_on_transfer() { let amount = Balance::new(10); let recipient = runner.create_account().address; - let balance = runner.balance_of(token, recipient, ORIGIN); + let balance = runner.balance_of(token, recipient, DEFAULT_AURORA_ACCOUNT_ID); assert_eq!(balance, U256::from(0)); let res = runner.ft_on_transfer(nep141, alice, alice, amount, &recipient.encode()); // Transaction should succeed so return amount is 0 assert_eq!(res, "\"0\""); - let balance = runner.balance_of(token, recipient, ORIGIN); + let balance = runner.balance_of(token, recipient, DEFAULT_AURORA_ACCOUNT_ID); assert_eq!(balance, U256::from(amount.as_u128())); } @@ -294,7 +298,7 @@ fn test_relayer_charge_fee() { let relayer_balance = runner.get_balance(relayer); assert_eq!(relayer_balance, Wei::zero()); - let balance = runner.balance_of(token, recipient, ORIGIN); + let balance = runner.balance_of(token, recipient, DEFAULT_AURORA_ACCOUNT_ID); assert_eq!(balance, U256::from(0)); let fee_encoded = &mut [0; 32]; @@ -316,7 +320,7 @@ fn test_relayer_charge_fee() { let relayer_balance = runner.get_balance(relayer); assert_eq!(relayer_balance, Wei::new_u64(fee)); - let balance = runner.balance_of(token, recipient, ORIGIN); + let balance = runner.balance_of(token, recipient, DEFAULT_AURORA_ACCOUNT_ID); assert_eq!(balance, U256::from(amount.as_u128())); } @@ -331,31 +335,39 @@ fn test_transfer_erc20_token() { let to_transfer = 43; assert_eq!( - runner.balance_of(token, peer0.address, ORIGIN), + runner.balance_of(token, peer0.address, DEFAULT_AURORA_ACCOUNT_ID), U256::zero() ); assert_eq!( - runner.balance_of(token, peer1.address, ORIGIN), + runner.balance_of(token, peer1.address, DEFAULT_AURORA_ACCOUNT_ID), U256::zero() ); - runner.mint(token, peer0.address, to_mint, ORIGIN).unwrap(); + runner + .mint(token, peer0.address, to_mint, DEFAULT_AURORA_ACCOUNT_ID) + .unwrap(); assert_eq!( - runner.balance_of(token, peer0.address, ORIGIN), + runner.balance_of(token, peer0.address, DEFAULT_AURORA_ACCOUNT_ID), U256::from(to_mint) ); runner - .transfer_erc20(token, peer0.secret_key, peer1.address, to_transfer, ORIGIN) + .transfer_erc20( + token, + peer0.secret_key, + peer1.address, + to_transfer, + DEFAULT_AURORA_ACCOUNT_ID, + ) .unwrap(); assert_eq!( - runner.balance_of(token, peer0.address, ORIGIN), + runner.balance_of(token, peer0.address, DEFAULT_AURORA_ACCOUNT_ID), U256::from(to_mint - to_transfer) ); assert_eq!( - runner.balance_of(token, peer1.address, ORIGIN), + runner.balance_of(token, peer1.address, DEFAULT_AURORA_ACCOUNT_ID), U256::from(to_transfer) ); } diff --git a/engine-tests/src/tests/modexp.rs b/engine-tests/src/tests/modexp.rs index 83eae40ac..07c1bc4f8 100644 --- a/engine-tests/src/tests/modexp.rs +++ b/engine-tests/src/tests/modexp.rs @@ -128,18 +128,18 @@ fn bench_modexp_standalone() { // These contracts run the modexp precompile in an infinite loop using strategically selecting // input that can take a long time to run with some modexp implementations. It should be - // possible to burn 30M EVM gas (the GAS_LIMIT for this transactions) within 1 second. + // possible to burn 30M EVM gas (the GAS_LIMIT for these transactions) within 1 second. // This test checks this is case for these specially chosen modexp inputs. do_bench( &mut standalone, &mut signer, "../etc/tests/modexp-bench/res/evm_contract_1.hex", ); - /*do_bench( // TODO: re-enable this in the future + do_bench( &mut standalone, &mut signer, "../etc/tests/modexp-bench/res/evm_contract_2.hex", - );*/ + ); } #[test] @@ -318,6 +318,8 @@ impl Default for ModExpBenchContext { std::fs::read(output_path).unwrap() }; + // Standalone not relevant here because this is not an Aurora Engine instance + inner.standalone_runner = None; inner.wasm_config.limit_config.max_gas_burnt = u64::MAX; inner.code = ContractCode::new(bench_contract_bytes, None); diff --git a/engine-tests/src/tests/pausable_precompiles.rs b/engine-tests/src/tests/pausable_precompiles.rs index 7d86820c1..bd975d9e3 100644 --- a/engine-tests/src/tests/pausable_precompiles.rs +++ b/engine-tests/src/tests/pausable_precompiles.rs @@ -1,7 +1,8 @@ use crate::prelude::{Address, U256}; use crate::utils::solidity::exit_precompile::{Tester, TesterConstructor}; use crate::utils::{ - self, AuroraRunner, Signer, ORIGIN, PAUSED_PRECOMPILES, PAUSE_PRECOMPILES, RESUME_PRECOMPILES, + self, AuroraRunner, Signer, DEFAULT_AURORA_ACCOUNT_ID, PAUSED_PRECOMPILES, PAUSE_PRECOMPILES, + RESUME_PRECOMPILES, }; use aurora_engine::engine::EngineErrorKind; use aurora_engine::parameters::{PausePrecompilesCallArgs, TransactionStatus}; @@ -24,6 +25,7 @@ fn test_paused_precompile_is_shown_when_viewing() { let _res = runner.call(PAUSE_PRECOMPILES, CALLED_ACCOUNT_ID, input.clone()); let result = runner + .one_shot() .call(PAUSED_PRECOMPILES, CALLED_ACCOUNT_ID, Vec::new()) .unwrap(); let output = result.return_data.as_value().unwrap(); @@ -130,7 +132,12 @@ fn setup_test() -> (AuroraRunner, Signer, Address, Tester) { .into(); runner - .mint(token, tester.contract.address, 1_000_000_000, ORIGIN) + .mint( + token, + tester.contract.address, + 1_000_000_000, + DEFAULT_AURORA_ACCOUNT_ID, + ) .unwrap(); (runner, signer, token, tester) diff --git a/engine-tests/src/tests/pause_contract.rs b/engine-tests/src/tests/pause_contract.rs index 5d810f6b2..ce068ab72 100644 --- a/engine-tests/src/tests/pause_contract.rs +++ b/engine-tests/src/tests/pause_contract.rs @@ -73,7 +73,9 @@ fn test_pause_contract() { .unwrap(); // contract is running by default, gets and sets should work - let result = runner.call("get_upgrade_delay_blocks", &aurora_account_id, vec![]); + let result = runner + .one_shot() + .call("get_upgrade_delay_blocks", &aurora_account_id, vec![]); assert!(result.is_ok()); let result = runner.call("set_upgrade_delay_blocks", &aurora_account_id, set.clone()); @@ -84,7 +86,9 @@ fn test_pause_contract() { assert!(result.is_ok()); // contract is paused, gets should still work but sets should fail - let result = runner.call("get_upgrade_delay_blocks", &aurora_account_id, vec![]); + let result = runner + .one_shot() + .call("get_upgrade_delay_blocks", &aurora_account_id, vec![]); assert!(result.is_ok()); let result = runner.call("set_upgrade_delay_blocks", &aurora_account_id, set); @@ -110,7 +114,9 @@ fn test_resume_contract() { assert!(result.is_ok()); // contract is running again, gets and sets should work - let result = runner.call("get_upgrade_delay_blocks", &aurora_account_id, vec![]); + let result = runner + .one_shot() + .call("get_upgrade_delay_blocks", &aurora_account_id, vec![]); assert!(result.is_ok()); let result = runner.call("set_upgrade_delay_blocks", &aurora_account_id, set); diff --git a/engine-tests/src/tests/repro.rs b/engine-tests/src/tests/repro.rs index d69bdbf0d..a113826fb 100644 --- a/engine-tests/src/tests/repro.rs +++ b/engine-tests/src/tests/repro.rs @@ -1,7 +1,6 @@ //! A module containing tests which reproduce transactions sent to live networks. -use crate::utils::{standalone, ORIGIN}; -use crate::utils::{AuroraRunner, ExecutionProfile}; +use crate::utils::{standalone, AuroraRunner, ExecutionProfile}; use aurora_engine::parameters::SubmitResult; use aurora_engine_types::borsh::{BorshDeserialize, BorshSerialize}; use engine_standalone_storage::json_snapshot; @@ -126,7 +125,7 @@ fn repro_Emufid2() { block_timestamp: 1_662_118_048_636_713_538, input_path: "src/tests/res/input_Emufid2.hex", evm_gas_used: 1_156_364, - near_gas_used: 285, + near_gas_used: 282, }); } @@ -142,7 +141,10 @@ fn repro_common(context: &ReproContext) { let snapshot = json_snapshot::types::JsonSnapshot::load_from_file(snapshot_path).unwrap(); - let mut runner = AuroraRunner::default(); + let mut runner = AuroraRunner { + standalone_runner: None, // Turn off standalone here, validated separately below + ..Default::default() + }; runner.wasm_config.limit_config.max_gas_burnt = 3_000_000_000_000_000; runner.context.storage_usage = 1_000_000_000; runner.consume_json_snapshot(snapshot.clone()); @@ -167,10 +169,6 @@ fn repro_common(context: &ReproContext) { // Also validate the SubmitResult in the standalone engine let mut standalone = standalone::StandaloneRunner::default(); - standalone - .storage - .set_engine_account_id(&ORIGIN.parse().unwrap()) - .unwrap(); json_snapshot::initialize_engine_state(&mut standalone.storage, snapshot).unwrap(); let standalone_result = standalone .submit_raw("submit", &runner.context, &[]) diff --git a/engine-tests/src/tests/res/contract_data_too_large.hex b/engine-tests/src/tests/res/contract_data_too_large.hex new file mode 100644 index 000000000..efe711297 --- /dev/null +++ b/engine-tests/src/tests/res/contract_data_too_large.hex @@ -0,0 +1 @@ +0x61418a62007b4860003961418a60006000f0506143b56200bcd26000396143b560006000f05061438b6200005460003961438b60006000f050613769620043df60003961376960006000f05033ff60006000f3fe617a69600a5561437356600436101561000d576133dd565b60046000601c3760005163029b2f34811861002c57336104a052610047565b63cb495064811861077a5760a4358060a01c614364576104a0525b60005461436457600160005561005e6104e061346c565b6104e0516104c0526006546104e052600754610500526008546105205260095461054052600f5461056052601054610580526011546105a0526012546105c0526105605161028052610580516102a0526105a0516102c0526105c0516102e0526104e051610300526105005161032052610520516103405261054051610360526104c051610380526100f16106006138be565b610600516105e052601a54610600526104e051610620526105005161064052610520516106605261054051610680526106a060006004818352015b60206106a05102600401356106c052610600516101505760006106c0511115614364575b6106206106a0516004811015614364576020020180516106c05181818301106143645780820190509050815250815160010180835281141561012c5750506105605161028052610580516102a0526105a0516102c0526105c0516102e05261062051610300526106405161032052610660516103405261068051610360526104c051610380526101e16106c06138be565b6106c0516106a0526105e0516106a05111156143645760a0366106c0376000610600511161023257610620516006556106405160075561066051600855610680516009556106a05161074052610498565b600a5460048082028215828483041417156143645790509050600c808204905090506107605261078060006004818352015b6106a0516104e061078051600481101561436457602002015180820282158284830414171561436457905090506105e051808015614364578204905090506107a05260006107c0526106206107805160048110156143645760200201516107e0526107e0516107a051116102f1576107e0516107a05180821061436457808203905090506107c05261030c565b6107a0516107e05180821061436457808203905090506107c0525b610760516107c05180820282158284830414171561436457905090506402540be400808204905090506106c06107805160048110156143645760200201526107e0516106c061078051600481101561436457602002015164012a05f20080820282158284830414171561436457905090506402540be4008082049050905080821061436457808203905090506001610780516004811015614364570260060155610620610780516004811015614364576020020180516106c0610780516004811015614364576020020151808210614364578082039050905081525081516001018083528114156102645750506105605161028052610580516102a0526105a0516102c0526105c0516102e05261062051610300526106405161032052610660516103405261068051610360526104c0516103805261044c6107a06138be565b6107a0516107805261060051610780516105e051808210614364578082039050905080820282158284830414171561436457905090506105e05180801561436457820490509050610740525b60843561074051101561051c576014610760527f536c697070616765207363726577656420796f750000000000000000000000006107805261076050610760518061078001818260206001820306601f82010390500336823750506308c379a0610720526020610740526107605160206001820306601f820103905060440161073cfd5b60043534186143645761076060016003818352015b602061076051026004013561078052600061078051111561065e57600060046107e0527f23b872dd00000000000000000000000000000000000000000000000000000000610800526107e06004806020846108200101826020850160045afa5050805182019150503360208261082001015260208101905030602082610820010152602081019050610780516020826108200101526020810190508061082052610820505060206108e061082051610840600060016107605160048110156143645702600201545af1610609573d600060003e3d6000fd5b6108c060203d80821161061c578161061e565b805b9050905081528051602001806107a0828460045afa9050505060006107a051111561065e576107c0516107a05181816020036008021c9050905015614364575b81516001018083528114156105315750506106008051610740518181830110614364578082019050905081525060186104a05160a05260805260406080208054610740518181830110614364578082019050905081555061060051601a556104a05160007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef61074051610760526020610760a3337f3f1915775e0c9a38a57a7bb7f1f9005f486fb904e1f84aa215364d567319a58d60043561076052602435610780526044356107a0526064356107c0526106c0516107e0526106e05161080052610700516108205261072051610840526106a051610860526106005161088052610140610760a2610740516107605260206107606000600055f35b633df02124811861078f57336104e0526107aa565b63ddc1f59d8118610e65576084358060a01c614364576104e0525b6004358060801d81607f1d18614364576104a0526024358060801d81607f1d18614364576104c052600054614364576001600055600f5461050052601054610520526011546105405260125461056052600654610580526007546105a0526008546105c0526009546105e0526105005160e05261052051610100526105405161012052610560516101405261058051610160526105a051610180526105c0516101a0526105e0516101c0526108606106806135a7565b610680805161060052806020015161062052806040015161064052806060015161066052506106006104a05160048110156143645760200201516044356105006104a05160048110156143645760200201518082028215828483041417156143645790509050670de0b6b3a76400008082049050905081818301106143645780820190509050610680526104a051610280526104c0516102a052610680516102c052610600516102e05261062051610300526106405161032052610660516103405261092d6106c0613968565b6106c0516106a0526106006104c05160048110156143645760200201516106a0518082106143645780820390509050600180821061436457808203905090506106c0526106c051600a5480820282158284830414171561436457905090506402540be400808204905090506106e0526106c0516106e0518082106143645780820390509050670de0b6b3a764000080820282158284830414171561436457905090506105006104c0516004811015614364576020020151808015614364578204905090506106c0526064356106c0511015610a9e57602e610700527f45786368616e676520726573756c74656420696e20666577657220636f696e73610720527f207468616e2065787065637465640000000000000000000000000000000000006107405261070050610700518061072001818260206001820306601f82010390500336823750506308c379a06106c05260206106e0526107005160206001820306601f82010390506044016106dcfd5b6106e05164012a05f20080820282158284830414171561436457905090506402540be400808204905090506107005261070051670de0b6b3a764000080820282158284830414171561436457905090506105006104c051600481101561436457602002015180801561436457820490509050610700526105806104a05160048110156143645760200201516044358181830110614364578082019050905060016104a05160048110156143645702600601556105806104c05160048110156143645760200201516106c051808210614364578082039050905061070051808210614364578082039050905060016104c05160048110156143645702600601556104a05115610cc057346143645760006004610760527f23b872dd00000000000000000000000000000000000000000000000000000000610780526107606004806020846107a00101826020850160045afa505080518201915050336020826107a0010152602081019050306020826107a00101526020810190506044356020826107a0010152602081019050806107a0526107a0505060206108606107a0516107c0600060016104a05160048110156143645702600201545af1610c67573d600060003e3d6000fd5b61084060203d808211610c7a5781610c7c565b805b905090508152805160200180610720828460045afa905050506000610720511115610cca57610740516107205181816020036008021c905090501561436457610cca565b6044353418614364575b6104c05115610ddc5760006004610760527fa9059cbb00000000000000000000000000000000000000000000000000000000610780526107606004806020846107a00101826020850160045afa5050805182019150506104e0516020826107a00101526020810190506106c0516020826107a0010152602081019050806107a0526107a0505060206108406107a0516107c0600060016104c05160048110156143645702600201545af1610d83573d600060003e3d6000fd5b61082060203d808211610d965781610d98565b805b905090508152805160200180610720828460045afa905050506000610720511115610e0a57610740516107205181816020036008021c905090501561436457610e0a565b6000610720526107205060006000610720516107406106c0516104e0515af1610e0a573d600060003e3d6000fd5b337f8b3e96f2b889fa771c53c981b40daf005f63f637f1869f707052d15a3dd971406104a05161072052604435610740526104c051610760526106c051610780526080610720a26106c0516107205260206107206000600055f35b346143645763a461b3c8811861121657600435600401602081351161436457808035602001808260e037505050602435600401600a813511614364578080356020018082610120375050506044358060a01c61436457610160526064358060a01c61436457610180526084358060a01c614364576101a05260a4358060a01c614364576101c052600a546143645773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee610160511861436457670de0b6b3a764000060c43518614364576101e060006004818352015b6101606101e05160048110156143645760200201516102005261020051610f5457610f9b565b6102005160016101e051600481101561436457026002015560206101e0510260c4013560016101e05160048110156143645702600f01558151600101808352811415610f2e575b505061014435606480820282158284830414171561436457905090506101e0526101e051600b556101e051600c5561016435600a553360015560006017610260527f43757276652e666920466163746f727920506f6f6c3a20000000000000000000610280526102606017806020846102a00101826020850160045afa50508051820191505060e06020806020846102a00101826020850160045afa505080518201915050806102a0526102a09050805160200180610200828460045afa90505050610200806013602082510160c060006003818352015b8260c0516020021115611085576110a4565b60c05160200285015160c0518501558151600101808352811415611073575b5050505050506000610120600a806020846102a00101826020850160045afa5050805182019150506002610260527f2d66000000000000000000000000000000000000000000000000000000000000610280526102606002806020846102a00101826020850160045afa505080518201915050806102a0526102a09050806016602082510160c060006002818352015b8260c051602002111561114657611165565b60c05160200285015160c0518501558151600101808352811415611134575b5050505050507f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61034052610200805160208201209050610360527f572f01d824885a118d5d21c74542f263b131d2897955c62a721594f1d7c3b2e261038052466103a052306103c05260a061032052610320805160208201209050601b553060007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6000610260526020610260a3005b63313ce567811861122c57601260e052602060e0f35b63a9059cbb811861126e576004358060a01c61436457610160523360e0526101605161010052602435610120526112616133e3565b6001610180526020610180f35b6323b872dd8118611342576004358060a01c61436457610160526024358060a01c61436457610180526101605160e0526101805161010052604435610120526112b56133e3565b60196101605160a05260805260406080203360a0526080526040608020546101a0527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101a05114611335576101a051604435808210614364578082039050905060196101605160a05260805260406080203360a0526080526040608020555b60016101c05260206101c0f35b63095ea7b381186113ba576004358060a01c6143645760e05260243560193360a052608052604060802060e05160a05260805260406080205560e051337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925602435610100526020610100a36001610100526020610100f35b63d505accf8118611727576004358060a01c6143645760e0526024358060a01c61436457610100526084358060081c6143645761012052600060e0511461436457606435421161436457601c60e05160a0526080526040608020546101405260006002610400527f1901000000000000000000000000000000000000000000000000000000000000610420526104006002806020846106000101826020850160045afa505080518201915050601b546020826106000101526020810190507f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c96105405260e0516105605261010051610580526044356105a052610140516105c0526064356105e05260c0610520526105208051602082012090506020826106000101526020810190508061060052610600905080516020820120905061016052600060e0513b1161153b5760e0516101605161018052610120516101a052604060a46101c03760206080608061018060015afa50608051186143645761169b565b600060a4356102205260c435610240526040610200526102006040806020846102c00101826020850160045afa505080518201915050601f60016020820661026001602082840111614364576020806102808261012060045afa5050818152905090506001806020846102c00101826020850160045afa505080518201915050806102c0526102c09050805160200180610180828460045afa905050507f1626ba7e00000000000000000000000000000000000000000000000000000000631626ba7e610200526102208060406101605182526020820191508082528083018061018080516020018083828460045afa905050508051806020830101818260206001820306601f8201039050033682375050805160200160206001820306601f820103905090509050810150505050602061020060c461021c60e0515afa611688573d600060003e3d6000fd5b601f3d1115614364576102005118614364575b604435601960e05160a05260805260406080206101005160a05260805260406080205561014051600181818301106143645780820190509050601c60e05160a0526080526040608020556101005160e0517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925604435610180526020610180a36001610180526020610180f35b6314f0597981186117535760065460e052600754610100526008546101205260095461014052608060e0f35b63fee3f7f9811861176d5764012a05f20060e052602060e0f35b63f446c1d0811861179b5761178361016061346c565b61016051606480820490509050610180526020610180f35b6376a2f0f081186117c0576117b161016061346c565b61016051610180526020610180f35b63bb7b8b8081186118bb576117d66102a061346c565b6102a05161028052600f5460e05260105461010052601154610120526012546101405260065461016052600754610180526008546101a0526009546101c0526118206103206135a7565b61032080516102a05280602001516102c05280604001516102e052806060015161030052506102a05160e0526102c051610100526102e0516101205261030051610140526102805161016052611877610340613651565b610340516103205261032051670de0b6b3a76400008082028215828483041417156143645790509050601a5480801561436457820490509050610340526020610340f35b63cf701ff78118611ac3576084358060011c614364576104a0526118e06104e061346c565b6104e0516104c0526006546104e052600754610500526008546105205260095461054052600f54610280526010546102a0526011546102c0526012546102e0526104e051610300526105005161032052610520516103405261054051610360526104c051610380526119536105806138be565b610580516105605261058060006004818352015b60206105805102600401356105a0526104a0516119ae576104e0610580516004811015614364576020020180516105a05180821061436457808203905090508152506119dc565b6104e0610580516004811015614364576020020180516105a051818183011061436457808201905090508152505b8151600101808352811415611967575050600f54610280526010546102a0526011546102c0526012546102e0526104e051610300526105005161032052610520516103405261054051610360526104c05161038052611a3c6105a06138be565b6105a0516105805260006105a0526104a051611a7157610560516105805180821061436457808203905090506105a052611a8c565b610580516105605180821061436457808203905090506105a0525b6105a051601a54808202821582848304141715614364579050905061056051808015614364578204905090506105c05260206105c0f35b635e0d443f8118611cf4576004358060801d81607f1d18614364576104a0526024358060801d81607f1d18614364576104c052600f546104e0526010546105005260115461052052601254610540526104e05160e05261050051610100526105205161012052610540516101405260065461016052600754610180526008546101a0526009546101c052611b586105e06135a7565b6105e080516105605280602001516105805280604001516105a05280606001516105c052506105606104a05160048110156143645760200201516044356104e06104a05160048110156143645760200201518082028215828483041417156143645790509050670de0b6b3a764000080820490509050818183011061436457808201905090506105e0526104a051610280526104c0516102a0526105e0516102c052610560516102e05261058051610300526105a051610320526105c05161034052611c25610620613968565b61062051610600526105606104c05160048110156143645760200201516106005180821061436457808203905090506001808210614364578082039050905061062052600a546106205180820282158284830414171561436457905090506402540be400808204905090506106405261062051610640518082106143645780820390509050670de0b6b3a764000080820282158284830414171561436457905090506104e06104c051600481101561436457602002015180801561436457820490509050610660526020610660f35b637d49d8758118611d08573360e052611d22565b63b2fdb76f81186120cc5760a4358060a01c6143645760e0525b600054614364576001600055601a5461010052608036610120376101a060006004818352015b60016101a05160048110156143645702600601546101c0526101c051600435808202821582848304141715614364579050905061010051808015614364578204905090506101e05260206101a05102602401356101e0511015611e41576030610200527f5769746864726177616c20726573756c74656420696e20666577657220636f69610220527f6e73207468616e206578706563746564000000000000000000000000000000006102405261020050610200518061022001818260206001820306601f82010390500336823750506308c379a06101c05260206101e0526102005160206001820306601f82010390506044016101dcfd5b6101c0516101e051808210614364578082039050905060016101a05160048110156143645702600601556101e0516101206101a05160048110156143645760200201526101a05115611f955760006004610240527fa9059cbb00000000000000000000000000000000000000000000000000000000610260526102406004806020846102800101826020850160045afa50508051820191505060e0516020826102800101526020810190506101e051602082610280010152602081019050806102805261028050506020610320610280516102a0600060016101a05160048110156143645702600201545af1611f3c573d600060003e3d6000fd5b61030060203d808211611f4f5781611f51565b805b905090508152805160200180610200828460045afa905050506000610200511115611fc257610220516102005181816020036008021c905090501561436457611fc2565b6000610200526102005060006000610200516102206101e05160e0515af1611fc2573d600060003e3d6000fd5b8151600101808352811415611d485750506101008051600435808210614364578082039050905081525060183360a05260805260406080208054600435808210614364578082039050905081555061010051601a556000337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6004356101a05260206101a0a3337f9878ca375e106f2a43c3b599fc624568131c4c9a4ba66a14563715763be9d59d610120516101a052610140516101c052610160516101e052610180516102005260803661022037610100516102a0526101206101a0a2610120516101a052610140516101c052610160516101e052610180516102005260806101a06000600055f35b6318a7bd7681186120e157336104a0526120fc565b634ab3a82b81186128005760a4358060a01c614364576104a0525b6000546143645760016000556121136104e061346c565b6104e0516104c052600f546104e05260105461050052601154610520526012546105405260065461056052600754610580526008546105a0526009546105c0526104e05161028052610500516102a052610520516102c052610540516102e052610560516103005261058051610320526105a051610340526105c051610360526104c051610380526121a66106006138be565b610600516105e052610560516106005261058051610620526105a051610640526105c0516106605261068060006004818352015b610600610680516004811015614364576020020180516020610680510260040135808210614364578082039050905081525081516001018083528114156121da5750506104e05161028052610500516102a052610520516102c052610540516102e05261060051610300526106205161032052610640516103405261066051610360526104c051610380526122706106a06138be565b6106a051610680526080366106a037600a5460048082028215828483041417156143645790509050600c808204905090506107205261074060006004818352015b6106805161056061074051600481101561436457602002015180820282158284830414171561436457905090506105e05180801561436457820490509050610760526000610780526106006107405160048110156143645760200201516107a0526107a051610760511161233e576107a05161076051808210614364578082039050905061078052612359565b610760516107a0518082106143645780820390509050610780525b610720516107805180820282158284830414171561436457905090506402540be400808204905090506106a06107405160048110156143645760200201526107a0516106a061074051600481101561436457602002015164012a05f20080820282158284830414171561436457905090506402540be4008082049050905080821061436457808203905090506001610740516004811015614364570260060155610600610740516004811015614364576020020180516106a0610740516004811015614364576020020151808210614364578082039050905081525081516001018083528114156122b15750506104e05161028052610500516102a052610520516102c052610540516102e05261060051610300526106205161032052610640516103405261066051610360526104c051610380526124996107606138be565b6107605161074052601a54610760526105e0516107405180821061436457808203905090506107605180820282158284830414171561436457905090506105e051808015614364578204905090506001818183011061436457808201905090506107805260016107805111156143645760843561078051111561258d5760146107a0527f536c697070616765207363726577656420796f750000000000000000000000006107c0526107a0506107a051806107c001818260206001820306601f82010390500336823750506308c379a0610760526020610780526107a05160206001820306601f820103905060440161077cfd5b610760805161078051808210614364578082039050905081525061076051601a5560183360a052608052604060802080546107805180821061436457808203905090508155506000337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef610780516107a05260206107a0a360006004351461263c5760006107a0526107a050600060006107a0516107c06004356104a0515af161263c573d600060003e3d6000fd5b6107a060016003818352015b600060206107a0510260040135146127665760006004610800527fa9059cbb00000000000000000000000000000000000000000000000000000000610820526108006004806020846108400101826020850160045afa5050805182019150506104a05160208261084001015260208101905060206107a05102600401356020826108400101526020810190508061084052610840505060206108e061084051610860600060016107a05160048110156143645702600201545af1612711573d600060003e3d6000fd5b6108c060203d8082116127245781612726565b805b9050905081528051602001806107c0828460045afa9050505060006107c0511115612766576107e0516107c05181816020036008021c9050905015614364575b8151600101808352811415612648575050337fb964b72f73f5ef5bf0fdc559b2fab9a7b12a39e47817a547f1f0aee47febd6026004356107a0526024356107c0526044356107e052606435610800526106a051610820526106c051610840526106e051610860526107005161088052610680516108a052610760516108c0526101406107a0a2610780516107a05260206107a06000600055f35b63cc2b27d78118612848576024358060801d81607f1d18614364576105a0526004356102c0526105a0516102e0526128396105c0613f58565b6105c051610600526020610600f35b631a4d01d2811861285d57336105c052612878565b63081579a58118612bb5576064358060a01c614364576105c0525b6024358060801d81607f1d18614364576105a0526000546143645760016000556004356102c0526105a0516102e0526128b2610620613f58565b61062080516105e052806020015161060052506044356105e0511015612949576018610620527f4e6f7420656e6f75676820636f696e732072656d6f76656400000000000000006106405261062050610620518061064001818260206001820306601f82010390500336823750506308c379a06105e0526020610600526106205160206001820306601f82010390506044016105fcfd5b60016105a0516004811015614364570260060180546105e0516106005164012a05f20080820282158284830414171561436457905090506402540be40080820490509050818183011061436457808201905090508082106143645780820390509050815550601a5460043580821061436457808203905090506106205261062051601a5560183360a0526080526040608020805460043580821061436457808203905090508155506000337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600435610640526020610640a36105a05115612b345760006004610680527fa9059cbb000000000000000000000000000000000000000000000000000000006106a0526106806004806020846106c00101826020850160045afa5050805182019150506105c0516020826106c00101526020810190506105e0516020826106c0010152602081019050806106c0526106c0505060206107606106c0516106e0600060016105a05160048110156143645702600201545af1612adb573d600060003e3d6000fd5b61074060203d808211612aee5781612af0565b805b905090508152805160200180610640828460045afa905050506000610640511115612b6257610660516106405181816020036008021c905090501561436457612b62565b6000610640526106405060006000610640516106606105e0516105c0515af1612b62573d600060003e3d6000fd5b337f5ad056f2e28a8cec232015406b843668c1e36cda598127ec3b8c59b8c72773a0600435610640526105e0516106605261062051610680526060610640a26105e0516106405260206106406000600055f35b633c157e648118612d395763f851a440610160526020610160600461017c6001545afa612be7573d600060003e3d6000fd5b601f3d11156143645761016051331861436457600d5462015180818183011061436457808201905090504210614364574262015180818183011061436457808201905090506024351061436457612c3f61018061346c565b61018051610160526004356064808202821582848304141715614364579050905061018052600060043511612c75576000612c7e565b620f4240600435105b1561436457610160516101805110612cb85761016051600a8082028215828483041417156143645790509050610180511161436457612cdc565b6101605161018051600a808202821582848304141715614364579050905010614364575b61016051600b5561018051600c5542600d55602435600e557fa2b71ec6df949300b59aab36b55e189697b750119dd349fcfa8c0f779e83c254610160516101a052610180516101c052426101e0526024356102005260806101a0a1005b63551a65888118612ddd5763f851a440610160526020610160600461017c6001545afa612d6b573d600060003e3d6000fd5b601f3d11156143645761016051331861436457612d8961018061346c565b610180516101605261016051600b5561016051600c5542600d5542600e557f46e22fb3709ad289f62ce63d469248536dbc78d82b84a3d7e74ad606dc2019386101605161018052426101a0526040610180a1005b63e2e7d2648118612e885760043515612e68576370a0823160e0523061010052602060e0602460fc600160043560048110156143645702600201545afa612e29573d600060003e3d6000fd5b601f3d11156143645760e051600160043560048110156143645702600601548082106143645780820390509050610120526020610120612e8656612e86565b47600654808210614364578082039050905060e052602060e0612e86565bf35b6330c54085811861304f5763154aa8f56101005230610120526020610100602461011c6001545afa612ebf573d600060003e3d6000fd5b601f3d111561436457610100518060a01c6143645760e052476006548082106143645780820390509050610100526000610120526101205060006000610120516101406101005160e0515af1612f1a573d600060003e3d6000fd5b61012060016003818352015b6001610120516004811015614364570260020154610140526370a082316101605230610180526020610160602461017c610140515afa612f6b573d600060003e3d6000fd5b601f3d11156143645761016051600161012051600481101561436457026006015480821061436457808203905090506101005260006004610160527fa9059cbb00000000000000000000000000000000000000000000000000000000610180526101606004806020846101a00101826020850160045afa50508051820191505060e0516020826101a0010152602081019050610100516020826101a0010152602081019050806101a0526101a05050600060006101a0516101c06000610140515af161303c573d600060003e3d6000fd5b8151600101808352811415612f26575050005b6354fd4d5081186130e957610120806020808252600660e0527f76352e302e3000000000000000000000000000000000000000000000000000006101005260e0818401808280516020018083828460045afa905050508051806020830101818260206001820306601f8201039050033682375050805160200160206001820306601f82010390509050905090508101905090509050610120f35b63c66106578118613110576001600435600481101561436457026002015460e052602060e0f35b634903b0d18118613137576001600435600481101561436457026006015460e052602060e0f35b63ddca3f43811861314e57600a5460e052602060e0f35b635409491a811861316557600b5460e052602060e0f35b63b4b577ad811861317c57600c5460e052602060e0f35b632081066c811861319357600d5460e052602060e0f35b631405228881186131aa57600e5460e052602060e0f35b6306fdde03811861324d5760e08060208082528083018060138082602082540160c060006003818352015b8260c05160200211156131e757613206565b60c05185015460c05160200285015281516001018083528114156131d5575b5050505050508051806020830101818260206001820306601f8201039050033682375050805160200160206001820306601f820103905090509050810190509050905060e0f35b6395d89b4181186132f05760e08060208082528083018060168082602082540160c060006002818352015b8260c051602002111561328a576132a9565b60c05185015460c0516020028501528151600101808352811415613278575b5050505050508051806020830101818260206001820306601f8201039050033682375050805160200160206001820306601f820103905090509050810190509050905060e0f35b6370a082318118613325576004358060a01c6143645760e052601860e05160a052608052604060802054610100526020610100f35b63dd62ed3e8118613378576004358060a01c6143645760e0526024358060a01c6143645761010052601960e05160a05260805260406080206101005160a052608052604060802054610120526020610120f35b6318160ddd811861338f57601a5460e052602060e0f35b633644e51581186133a657601b5460e052602060e0f35b637ecebe0081186133db576004358060a01c6143645760e052601c60e05160a052608052604060802054610100526020610100f35b505b60006000fd5b601860e05160a0526080526040608020805461012051808210614364578082039050905081555060186101005160a0526080526040608020805461012051818183011061436457808201905090508155506101005160e0517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef61012051610140526020610140a3565b600e5460e052600c546101005260e051421061349257610100518152506135a5566135a5565b600b5461012052600d546101405261012051610100511161352a57610120516101205161010051808210614364578082039050905042610140518082106143645780820390509050808202821582848304141715614364579050905060e0516101405180821061436457808203905090508080156143645782049050905080821061436457808203905090508152506135a5566135a5565b610120516101005161012051808210614364578082039050905042610140518082106143645780820390509050808202821582848304141715614364579050905060e05161014051808210614364578082039050905080801561436457820490509050818183011061436457808201905090508152506135a5565b565b6080366101e03761026060006004818352015b60e06102605160048110156143645760200201516101606102605160048110156143645760200201518082028215828483041417156143645790509050670de0b6b3a7640000808204905090506101e061026051600481101561436457602002015281516001018083528114156135ba5750506101e051815261020051816020015261022051816040015261024051816060015250565b604036610180376101e060006004818352015b60206101e0510260e001516101c05261018080516101c051818183011061436457808201905090508152508151600101808352811415613664575050610180516136b25760008152506138bc565b610180516101c05261016051600480820282158284830414171561436457905090506101e052610200600060ff818352015b6101c0516102205261026060006004818352015b6020610260510260e0015161024052610220516101c05180820282158284830414171561436457905090506102405160048082028215828483041417156143645790509050808015614364578204905090506102205281516001018083528114156136f85750506101c0516101a0526101e0516101805180820282158284830414171561436457905090506064808204905090506102205160048082028215828483041417156143645790509050818183011061436457808201905090506101c05180820282158284830414171561436457905090506101e051606480821061436457808203905090506101c0518082028215828483041417156143645790509050606480820490509050600561022051808202821582848304141715614364579050905081818301106143645780820190509050808015614364578204905090506101c0526101a0516101c0511161387a5760016101a0516101c0518082106143645780820390509050116138a55750506101c0518152506138bc566138a5565b60016101c0516101a0518082106143645780820390509050116138a55750506101c0518152506138bc565b81516001018083528114156136e457505060006000fd5b565b6102805160e0526102a051610100526102c051610120526102e0516101405261030051610160526103205161018052610340516101a052610360516101c0526139086104206135a7565b61042080516103a05280602001516103c05280604001516103e052806060015161040052506103a05160e0526103c051610100526103e051610120526104005161014052610380516101605261395f610420613651565b61042051815250565b6102a05161028051146143645760006102a051126143645760046102a05112156143645760006102805112614364576004610280511215614364576139ae61038061346c565b61038051610360526102e05160e05261030051610100526103205161012052610340516101405261036051610160526139e86103a0613651565b6103a051610380526060366103a037610380516104005261036051600480820282158284830414171561436457905090506104205261044060006004818352015b610280516104405118613a43576102c0516103c052613a74565b6102a051610440511415613a5a57613ad856613a74565b6102e06104405160048110156143645760200201516103c0525b6103a080516103c05181818301106143645780820190509050815250610400516103805180820282158284830414171561436457905090506103c0516004808202821582848304141715614364579050905080801561436457820490509050610400525b8151600101808352811415613a295750506104005161038051808202821582848304141715614364579050905060648082028215828483041417156143645790509050610420516004808202821582848304141715614364579050905080801561436457820490509050610400526103a0516103805160648082028215828483041417156143645790509050610420518080156143645782049050905081818301106143645780820190509050610440526103805161046052610480600060ff818352015b610460516103e0526104605161046051808202821582848304141715614364579050905061040051818183011061436457808201905090506002610460518082028215828483041417156143645790509050610440518181830110614364578082019050905061038051808210614364578082039050905080801561436457820490509050610460526103e0516104605111613c625760016103e05161046051808210614364578082039050905011613c8d57505061046051815250613ca456613c8d565b6001610460516103e051808210614364578082039050905011613c8d57505061046051815250613ca4565b8151600101808352811415613b9d57505060006000fd5b565b60006101005112614364576004610100511215614364576060366101c0376101a0516102205260e051600480820282158284830414171561436457905090506102405261026060006004818352015b61010051610260511415613d0c57613d8a56613d26565b6101206102605160048110156143645760200201516101e0525b6101c080516101e05181818301106143645780820190509050815250610220516101a05180820282158284830414171561436457905090506101e0516004808202821582848304141715614364579050905080801561436457820490509050610220525b8151600101808352811415613cf5575050610220516101a051808202821582848304141715614364579050905060648082028215828483041417156143645790509050610240516004808202821582848304141715614364579050905080801561436457820490509050610220526101c0516101a05160648082028215828483041417156143645790509050610240518080156143645782049050905081818301106143645780820190509050610260526101a051610280526102a0600060ff818352015b6102805161020052610280516102805180820282158284830414171561436457905090506102205181818301106143645780820190509050600261028051808202821582848304141715614364579050905061026051818183011061436457808201905090506101a05180821061436457808203905090508080156143645782049050905061028052610200516102805111613f145760016102005161028051808210614364578082039050905011613f3f57505061028051815250613f5656613f3f565b60016102805161020051808210614364578082039050905011613f3f57505061028051815250613f56565b8151600101808352811415613e4f57505060006000fd5b565b613f6361032061346c565b6103205161030052600f54610320526010546103405260115461036052601254610380526103205160e05261034051610100526103605161012052610380516101405260065461016052600754610180526008546101a0526009546101c052613fcd6104206135a7565b61042080516103a05280602001516103c05280604001516103e052806060015161040052506103a05160e0526103c051610100526103e0516101205261040051610140526103005161016052614024610440613651565b6104405161042052601a5461044052610420516102c05161042051808202821582848304141715614364579050905061044051808015614364578204905090508082106143645780820390509050610460526103005160e0526102e051610100526103a051610120526103c051610140526103e051610160526104005161018052610460516101a0526140b86104a0613ca6565b6104a05161048052600a5460048082028215828483041417156143645790509050600c808204905090506104a0526080366104c03761054060006004818352015b6000610560526103a0610540516004811015614364576020020151610580526102e051610540511861416d57610580516104605180820282158284830414171561436457905090506104205180801561436457820490509050610480518082106143645780820390509050610560526141b1565b610580516105805161046051808202821582848304141715614364579050905061042051808015614364578204905090508082106143645780820390509050610560525b610580516104a0516105605180820282158284830414171561436457905090506402540be4008082049050905080821061436457808203905090506104c061054051600481101561436457602002015281516001018083528114156140f95750506104c06102e05160048110156143645760200201516103005160e0526102e051610100526104c051610120526104e0516101405261050051610160526105205161018052610460516101a052614269610560613ca6565b610560518082106143645780820390509050610540526103a06102e0516004811015614364576020020151610480518082106143645780820390509050670de0b6b3a764000080820282158284830414171561436457905090506103206102e051600481101561436457602002015180801561436457820490509050610560526105405160018082106143645780820390509050670de0b6b3a764000080820282158284830414171561436457905090506103206102e0516004811015614364576020020151808015614364578204905090506105405261054051815261056051610540518082106143645780820390509050816020015250565b600080fd5b61000a6143730361000a60003961000a614373036000f3617a69600a5561375156600436101561000d576129f8565b60046000601c37600051346137425763a461b3c8811861039357600435600401602081351161374257808035602001808260e037505050602435600401600a813511613742578080356020018082610120375050506044358060a01c61374257610160526064358060a01c61374257610180526084358060a01c613742576101a05260a4358060a01c613742576101c052600a54613742576101e060006004818352015b6101606101e051600481101561374257602002015161020052610200516100d757610118565b6102005160016101e0516004811015613742570260020155670de0b6b3a764000060206101e0510260c40135186137425781516001018083528114156100b1575b505061014435606480820282158284830414171561374257905090506101e0526101e051600b556101e051600c5561016435600a55336001556000601d610260527f43757276652e666920466163746f727920506c61696e20506f6f6c3a2000000061028052610260601d806020846102a00101826020850160045afa50508051820191505060e06020806020846102a00101826020850160045afa505080518201915050806102a0526102a09050805160200180610200828460045afa9050505061020080600f602082510160c060006003818352015b8260c051602002111561020257610221565b60c05160200285015160c05185015581516001018083528114156101f0575b5050505050506000610120600a806020846102a00101826020850160045afa5050805182019150506002610260527f2d66000000000000000000000000000000000000000000000000000000000000610280526102606002806020846102a00101826020850160045afa505080518201915050806102a0526102a09050806012602082510160c060006002818352015b8260c05160200211156102c3576102e2565b60c05160200285015160c05185015581516001018083528114156102b1575b5050505050507f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61034052610200805160208201209050610360527f572f01d824885a118d5d21c74542f263b131d2897955c62a721594f1d7c3b2e261038052466103a052306103c05260a0610320526103208051602082012090506017553060007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6000610260526020610260a3005b63313ce56781186103a957601260e052602060e0f35b63a9059cbb81186103eb576004358060a01c61374257610160523360e0526101605161010052602435610120526103de6129fe565b6001610180526020610180f35b6323b872dd81186104bf576004358060a01c61374257610160526024358060a01c61374257610180526101605160e0526101805161010052604435610120526104326129fe565b60156101605160a05260805260406080203360a0526080526040608020546101a0527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101a051146104b2576101a051604435808210613742578082039050905060156101605160a05260805260406080203360a0526080526040608020555b60016101c05260206101c0f35b63095ea7b38118610537576004358060a01c6137425760e05260243560153360a052608052604060802060e05160a05260805260406080205560e051337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925602435610100526020610100a36001610100526020610100f35b63d505accf81186108a4576004358060a01c6137425760e0526024358060a01c61374257610100526084358060081c6137425761012052600060e0511461374257606435421161374257601860e05160a0526080526040608020546101405260006002610400527f1901000000000000000000000000000000000000000000000000000000000000610420526104006002806020846106000101826020850160045afa5050805182019150506017546020826106000101526020810190507f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c96105405260e0516105605261010051610580526044356105a052610140516105c0526064356105e05260c0610520526105208051602082012090506020826106000101526020810190508061060052610600905080516020820120905061016052600060e0513b116106b85760e0516101605161018052610120516101a052604060a46101c03760206080608061018060015afa506080511861374257610818565b600060a4356102205260c435610240526040610200526102006040806020846102c00101826020850160045afa505080518201915050601f60016020820661026001602082840111613742576020806102808261012060045afa5050818152905090506001806020846102c00101826020850160045afa505080518201915050806102c0526102c09050805160200180610180828460045afa905050507f1626ba7e00000000000000000000000000000000000000000000000000000000631626ba7e610200526102208060406101605182526020820191508082528083018061018080516020018083828460045afa905050508051806020830101818260206001820306601f8201039050033682375050805160200160206001820306601f820103905090509050810150505050602061020060c461021c60e0515afa610805573d600060003e3d6000fd5b601f3d1115613742576102005118613742575b604435601560e05160a05260805260406080206101005160a05260805260406080205561014051600181818301106137425780820190509050601860e05160a0526080526040608020556101005160e0517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925604435610180526020610180a36001610180526020610180f35b6314f0597981186108d05760065460e052600754610100526008546101205260095461014052608060e0f35b63fee3f7f981186108ea5764012a05f20060e052602060e0f35b63f446c1d0811861091857610900610160612a87565b61016051606480820490509050610180526020610180f35b6376a2f0f0811861093d5761092e610160612a87565b61016051610180526020610180f35b63bb7b8b8081186109cd576109536102a0612a87565b6102a0516102805260065460e05260075461010052600854610120526009546101405261028051610160526109896102c0612bc2565b6102c0516102a0526102a051670de0b6b3a76400008082028215828483041417156137425790509050601654808015613742578204905090506102c05260206102c0f35b63cf701ff78118610b9b576084358060011c61374257610280526109f26102c0612a87565b6102c0516102a0526006546102c0526007546102e05260085461030052600954610320526102c05160e0526102e05161010052610300516101205261032051610140526102a05161016052610a48610360612bc2565b610360516103405261036060006004818352015b60206103605102600401356103805261028051610aa3576102c061036051600481101561374257602002018051610380518082106137425780820390509050815250610ad1565b6102c06103605160048110156137425760200201805161038051818183011061374257808201905090508152505b8151600101808352811415610a5c5750506102c05160e0526102e05161010052610300516101205261032051610140526102a05161016052610b14610380612bc2565b610380516103605260006103805261028051610b49576103405161036051808210613742578082039050905061038052610b64565b61036051610340518082106137425780820390509050610380525b61038051601654808202821582848304141715613742579050905061034051808015613742578204905090506103a05260206103a0f35b63029b2f348118610bb0573361028052610bcb565b63cb49506481186111c35760a4358060a01c61374257610280525b600054613742576001600055610be26102c0612a87565b6102c0516102a0526006546102c0526007546102e05260085461030052600954610320526102c05160e0526102e05161010052610300516101205261032051610140526102a05161016052610c38610360612bc2565b6103605161034052601654610360526102c051610380526102e0516103a052610300516103c052610320516103e05261040060006004818352015b60206104005102600401356104205261036051610c97576000610420511115613742575b6103806104005160048110156137425760200201805161042051818183011061374257808201905090508152508151600101808352811415610c735750506103805160e0526103a051610100526103c051610120526103e051610140526102a05161016052610d07610420612bc2565b6104205161040052610340516104005111156137425760a0366104203760006103605111610d5857610380516006556103a0516007556103c0516008556103e051600955610400516104a052610f9d565b600a5460048082028215828483041417156137425790509050600c808204905090506104c0526104e060006004818352015b610400516102c06104e051600481101561374257602002015180820282158284830414171561374257905090506103405180801561374257820490509050610500526000610520526103806104e051600481101561374257602002015161054052610540516105005111610e17576105405161050051808210613742578082039050905061052052610e32565b61050051610540518082106137425780820390509050610520525b6104c0516105205180820282158284830414171561374257905090506402540be400808204905090506104206104e0516004811015613742576020020152610540516104206104e051600481101561374257602002015164012a05f20080820282158284830414171561374257905090506402540be40080820490509050808210613742578082039050905060016104e05160048110156137425702600601556103806104e0516004811015613742576020020180516104206104e051600481101561374257602002015180821061374257808203905090508152508151600101808352811415610d8a5750506103805160e0526103a051610100526103c051610120526103e051610140526102a05161016052610f51610500612bc2565b610500516104e052610360516104e051610340518082106137425780820390509050808202821582848304141715613742579050905061034051808015613742578204905090506104a0525b6084356104a05110156110215760146104c0527f536c697070616765207363726577656420796f750000000000000000000000006104e0526104c0506104c051806104e001818260206001820306601f82010390500336823750506308c379a06104805260206104a0526104c05160206001820306601f820103905060440161049cfd5b6104c060006004818352015b60206104c05102600401356104e05260006104e05111156110a7576323b872dd61050052336105205230610540526104e051610560526020610500606461051c600060016104c05160048110156137425702600201545af1611094573d600060003e3d6000fd5b601f3d1115613742576105005115613742575b815160010180835281141561102d57505061036080516104a0518181830110613742578082019050905081525060146102805160a052608052604060802080546104a05181818301106137425780820190509050815550610360516016556102805160007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6104a0516104c05260206104c0a3337f3f1915775e0c9a38a57a7bb7f1f9005f486fb904e1f84aa215364d567319a58d6004356104c0526024356104e0526044356105005260643561052052610420516105405261044051610560526104605161058052610480516105a052610400516105c052610360516105e0526101406104c0a26104a0516104c05260206104c06000600055f35b635e0d443f8118611311576004358060801d81607f1d18613742576104a0526024358060801d81607f1d18613742576104c0526006546104e0526007546105005260085461052052600954610540526104e06104a051600481101561374257602002015160443581818301106137425780820190509050610560526104a051610280526104c0516102a052610560516102c0526104e0516102e0526105005161030052610520516103205261054051610340526112816105a0612e2f565b6105a051610580526104e06104c0516004811015613742576020020151610580518082106137425780820390509050600180821061374257808203905090506105a052600a546105a05180820282158284830414171561374257905090506402540be400808204905090506105c0526105a0516105c05180821061374257808203905090506105e05260206105e0f35b633df02124811861132657336104e052611341565b63ddc1f59d81186116fe576084358060a01c613742576104e0525b6004358060801d81607f1d18613742576104a0526024358060801d81607f1d18613742576104c052600054613742576001600055600654610500526007546105205260085461054052600954610560526105006104a051600481101561374257602002015160443581818301106137425780820190509050610580526104a051610280526104c0516102a052610580516102c052610500516102e0526105205161030052610540516103205261056051610340526114006105c0612e2f565b6105c0516105a0526105006104c05160048110156137425760200201516105a0518082106137425780820390509050600180821061374257808203905090506105c0526105c051600a5480820282158284830414171561374257905090506402540be400808204905090506105e0526105c080516105e05180821061374257808203905090508152506064356105c051101561153257602e610600527f45786368616e676520726573756c74656420696e20666577657220636f696e73610620527f207468616e2065787065637465640000000000000000000000000000000000006106405261060050610600518061062001818260206001820306601f82010390500336823750506308c379a06105c05260206105e0526106005160206001820306601f82010390506044016105dcfd5b6105e05164012a05f20080820282158284830414171561374257905090506402540be40080820490509050610600526105006104a05160048110156137425760200201516044358181830110613742578082019050905060016104a05160048110156137425702600601556105006104c05160048110156137425760200201516105c051808210613742578082039050905061060051808210613742578082039050905060016104c05160048110156137425702600601556323b872dd6106205233610640523061066052604435610680526020610620606461063c600060016104a05160048110156137425702600201545af1611635573d600060003e3d6000fd5b601f3d11156137425761062051156137425763a9059cbb610620526104e051610640526105c051610660526020610620604461063c600060016104c05160048110156137425702600201545af1611691573d600060003e3d6000fd5b601f3d111561374257610620511561374257337f8b3e96f2b889fa771c53c981b40daf005f63f637f1869f707052d15a3dd971406104a05161062052604435610640526104c051610660526105c051610680526080610620a26105c0516106205260206106206000600055f35b637d49d8758118611712573360e05261172c565b63b2fdb76f81186119f35760a4358060a01c6137425760e0525b60005461374257600160005560165461010052608036610120376101a060006004818352015b60016101a05160048110156137425702600601546101c0526101c051600435808202821582848304141715613742579050905061010051808015613742578204905090506101e05260206101a05102602401356101e051101561184b576030610200527f5769746864726177616c20726573756c74656420696e20666577657220636f69610220527f6e73207468616e206578706563746564000000000000000000000000000000006102405261020050610200518061022001818260206001820306601f82010390500336823750506308c379a06101c05260206101e0526102005160206001820306601f82010390506044016101dcfd5b6101c0516101e051808210613742578082039050905060016101a05160048110156137425702600601556101e0516101206101a051600481101561374257602002015263a9059cbb6102005260e051610220526101e051610240526020610200604461021c600060016101a05160048110156137425702600201545af16118d7573d600060003e3d6000fd5b601f3d11156137425761020051156137425781516001018083528114156117525750506101008051600435808210613742578082039050905081525060143360a052608052604060802080546004358082106137425780820390509050815550610100516016556000337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6004356101a05260206101a0a3337f9878ca375e106f2a43c3b599fc624568131c4c9a4ba66a14563715763be9d59d610120516101a052610140516101c052610160516101e052610180516102005260803661022037610100516102a0526101206101a0a2610120516101a052610140516101c052610160516101e052610180516102005260806101a06000600055f35b6318a7bd768118611a08573361028052611a23565b634ab3a82b8118611fc95760a4358060a01c61374257610280525b600054613742576001600055611a3a6102c0612a87565b6102c0516102a0526006546102c0526007546102e05260085461030052600954610320526102c05160e0526102e05161010052610300516101205261032051610140526102a05161016052611a90610360612bc2565b61036051610340526102c051610360526102e05161038052610300516103a052610320516103c0526103e060006004818352015b6103606103e05160048110156137425760200201805160206103e051026004013580821061374257808203905090508152508151600101808352811415611ac45750506103605160e05261038051610100526103a051610120526103c051610140526102a05161016052611b39610400612bc2565b610400516103e05260803661040037600a5460048082028215828483041417156137425790509050600c80820490509050610480526104a060006004818352015b6103e0516102c06104a0516004811015613742576020020151808202821582848304141715613742579050905061034051808015613742578204905090506104c05260006104e0526103606104a051600481101561374257602002015161050052610500516104c05111611c0757610500516104c05180821061374257808203905090506104e052611c22565b6104c0516105005180821061374257808203905090506104e0525b610480516104e05180820282158284830414171561374257905090506402540be400808204905090506104006104a0516004811015613742576020020152610500516104006104a051600481101561374257602002015164012a05f20080820282158284830414171561374257905090506402540be40080820490509050808210613742578082039050905060016104a05160048110156137425702600601556103606104a0516004811015613742576020020180516104006104a051600481101561374257602002015180821061374257808203905090508152508151600101808352811415611b7a5750506103605160e05261038051610100526103a051610120526103c051610140526102a05161016052611d416104c0612bc2565b6104c0516104a0526016546104c052610340516104a05180821061374257808203905090506104c051808202821582848304141715613742579050905061034051808015613742578204905090506001818183011061374257808201905090506104e05260016104e0511115613742576084356104e0511115611e35576014610500527f536c697070616765207363726577656420796f750000000000000000000000006105205261050050610500518061052001818260206001820306601f82010390500336823750506308c379a06104c05260206104e0526105005160206001820306601f82010390506044016104dcfd5b6104c080516104e05180821061374257808203905090508152506104c05160165560143360a052608052604060802080546104e05180821061374257808203905090508155506000337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6104e051610500526020610500a361050060006004818352015b6000602061050051026004013514611f2f5763a9059cbb6105205261028051610540526020610500510260040135610560526020610520604461053c600060016105005160048110156137425702600201545af1611f1c573d600060003e3d6000fd5b601f3d1115613742576105205115613742575b8151600101808352811415611eb9575050337fb964b72f73f5ef5bf0fdc559b2fab9a7b12a39e47817a547f1f0aee47febd602600435610500526024356105205260443561054052606435610560526104005161058052610420516105a052610440516105c052610460516105e0526103e051610600526104c05161062052610140610500a26104e0516105005260206105006000600055f35b63cc2b27d78118612011576024358060801d81607f1d1861374257610520526004356102c052610520516102e05261200261054061341f565b61054051610580526020610580f35b631a4d01d28118612026573361054052612041565b63081579a5811861229a576064358060a01c61374257610540525b6024358060801d81607f1d1861374257610520526000546137425760016000556004356102c052610520516102e05261207b6105a061341f565b6105a0805161056052806020015161058052506044356105605110156121125760186105a0527f4e6f7420656e6f75676820636f696e732072656d6f76656400000000000000006105c0526105a0506105a051806105c001818260206001820306601f82010390500336823750506308c379a0610560526020610580526105a05160206001820306601f820103905060440161057cfd5b600161052051600481101561374257026006018054610560516105805164012a05f20080820282158284830414171561374257905090506402540be4008082049050905081818301106137425780820190509050808210613742578082039050905081555060165460043580821061374257808203905090506105a0526105a05160165560143360a0526080526040608020805460043580821061374257808203905090508155506000337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6004356105c05260206105c0a363a9059cbb6105c052610540516105e052610560516106005260206105c060446105dc600060016105205160048110156137425702600201545af1612235573d600060003e3d6000fd5b601f3d1115613742576105c0511561374257337f5ad056f2e28a8cec232015406b843668c1e36cda598127ec3b8c59b8c72773a06004356105c052610560516105e0526105a0516106005260606105c0a2610560516105c05260206105c06000600055f35b633c157e64811861241e5763f851a440610160526020610160600461017c6001545afa6122cc573d600060003e3d6000fd5b601f3d11156137425761016051331861374257600d5462015180818183011061374257808201905090504210613742574262015180818183011061374257808201905090506024351061374257612324610180612a87565b6101805161016052600435606480820282158284830414171561374257905090506101805260006004351161235a576000612363565b620f4240600435105b156137425761016051610180511061239d5761016051600a80820282158284830414171561374257905090506101805111613742576123c1565b6101605161018051600a808202821582848304141715613742579050905010613742575b61016051600b5561018051600c5542600d55602435600e557fa2b71ec6df949300b59aab36b55e189697b750119dd349fcfa8c0f779e83c254610160516101a052610180516101c052426101e0526024356102005260806101a0a1005b63551a658881186124c25763f851a440610160526020610160600461017c6001545afa612450573d600060003e3d6000fd5b601f3d1115613742576101605133186137425761246e610180612a87565b610180516101605261016051600b5561016051600c5542600d5542600e557f46e22fb3709ad289f62ce63d469248536dbc78d82b84a3d7e74ad606dc2019386101605161018052426101a0526040610180a1005b63e2e7d264811861253e576370a0823160e0523061010052602060e0602460fc600160043560048110156137425702600201545afa612506573d600060003e3d6000fd5b601f3d11156137425760e051600160043560048110156137425702600601548082106137425780820390509050610120526020610120f35b6330c54085811861266a5763154aa8f56101005230610120526020610100602461011c6001545afa612575573d600060003e3d6000fd5b601f3d111561374257610100518060a01c6137425760e05261010060006004818352015b6001610100516004811015613742570260020154610120526370a082316101605230610180526020610160602461017c610120515afa6125de573d600060003e3d6000fd5b601f3d11156137425761016051600161010051600481101561374257026006015480821061374257808203905090506101405263a9059cbb6101605260e05161018052610140516101a0526020610160604461017c6000610120515af161264a573d600060003e3d6000fd5b601f3d111561374257610160508151600101808352811415612599575050005b6354fd4d50811861270457610120806020808252600660e0527f76352e302e3000000000000000000000000000000000000000000000000000006101005260e0818401808280516020018083828460045afa905050508051806020830101818260206001820306601f8201039050033682375050805160200160206001820306601f82010390509050905090508101905090509050610120f35b63c6610657811861272b576001600435600481101561374257026002015460e052602060e0f35b634903b0d18118612752576001600435600481101561374257026006015460e052602060e0f35b63ddca3f43811861276957600a5460e052602060e0f35b635409491a811861278057600b5460e052602060e0f35b63b4b577ad811861279757600c5460e052602060e0f35b632081066c81186127ae57600d5460e052602060e0f35b631405228881186127c557600e5460e052602060e0f35b6306fdde0381186128685760e080602080825280830180600f8082602082540160c060006003818352015b8260c051602002111561280257612821565b60c05185015460c05160200285015281516001018083528114156127f0575b5050505050508051806020830101818260206001820306601f8201039050033682375050805160200160206001820306601f820103905090509050810190509050905060e0f35b6395d89b41811861290b5760e08060208082528083018060128082602082540160c060006002818352015b8260c05160200211156128a5576128c4565b60c05185015460c0516020028501528151600101808352811415612893575b5050505050508051806020830101818260206001820306601f8201039050033682375050805160200160206001820306601f820103905090509050810190509050905060e0f35b6370a082318118612940576004358060a01c6137425760e052601460e05160a052608052604060802054610100526020610100f35b63dd62ed3e8118612993576004358060a01c6137425760e0526024358060a01c6137425761010052601560e05160a05260805260406080206101005160a052608052604060802054610120526020610120f35b6318160ddd81186129aa5760165460e052602060e0f35b633644e51581186129c15760175460e052602060e0f35b637ecebe0081186129f6576004358060a01c6137425760e052601860e05160a052608052604060802054610100526020610100f35b505b60006000fd5b601460e05160a0526080526040608020805461012051808210613742578082039050905081555060146101005160a0526080526040608020805461012051818183011061374257808201905090508155506101005160e0517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef61012051610140526020610140a3565b600e5460e052600c546101005260e0514210612aad5761010051815250612bc056612bc0565b600b5461012052600d5461014052610120516101005111612b4557610120516101205161010051808210613742578082039050905042610140518082106137425780820390509050808202821582848304141715613742579050905060e051610140518082106137425780820390509050808015613742578204905090508082106137425780820390509050815250612bc056612bc0565b610120516101005161012051808210613742578082039050905042610140518082106137425780820390509050808202821582848304141715613742579050905060e0516101405180821061374257808203905090508080156137425782049050905081818301106137425780820190509050815250612bc0565b565b604036610180376101e060006004818352015b60206101e0510260e001516101c05261018080516101c051818183011061374257808201905090508152508151600101808352811415612bd557505061018051612c23576000815250612e2d565b610180516101c05261016051600480820282158284830414171561374257905090506101e052610200600060ff818352015b6101c0516102205261026060006004818352015b6020610260510260e0015161024052610220516101c0518082028215828483041417156137425790509050610240516004808202821582848304141715613742579050905080801561374257820490509050610220528151600101808352811415612c695750506101c0516101a0526101e0516101805180820282158284830414171561374257905090506064808204905090506102205160048082028215828483041417156137425790509050818183011061374257808201905090506101c05180820282158284830414171561374257905090506101e051606480821061374257808203905090506101c0518082028215828483041417156137425790509050606480820490509050600561022051808202821582848304141715613742579050905081818301106137425780820190509050808015613742578204905090506101c0526101a0516101c05111612deb5760016101a0516101c051808210613742578082039050905011612e165750506101c051815250612e2d56612e16565b60016101c0516101a051808210613742578082039050905011612e165750506101c051815250612e2d565b8151600101808352811415612c5557505060006000fd5b565b6102a05161028051146137425760006102a051126137425760046102a0511215613742576000610280511261374257600461028051121561374257612e75610380612a87565b61038051610360526102e05160e0526103005161010052610320516101205261034051610140526103605161016052612eaf6103a0612bc2565b6103a051610380526060366103a037610380516104005261036051600480820282158284830414171561374257905090506104205261044060006004818352015b610280516104405118612f0a576102c0516103c052612f3b565b6102a051610440511415612f2157612f9f56612f3b565b6102e06104405160048110156137425760200201516103c0525b6103a080516103c05181818301106137425780820190509050815250610400516103805180820282158284830414171561374257905090506103c0516004808202821582848304141715613742579050905080801561374257820490509050610400525b8151600101808352811415612ef05750506104005161038051808202821582848304141715613742579050905060648082028215828483041417156137425790509050610420516004808202821582848304141715613742579050905080801561374257820490509050610400526103a0516103805160648082028215828483041417156137425790509050610420518080156137425782049050905081818301106137425780820190509050610440526103805161046052610480600060ff818352015b610460516103e0526104605161046051808202821582848304141715613742579050905061040051818183011061374257808201905090506002610460518082028215828483041417156137425790509050610440518181830110613742578082019050905061038051808210613742578082039050905080801561374257820490509050610460526103e05161046051116131295760016103e051610460518082106137425780820390509050116131545750506104605181525061316b56613154565b6001610460516103e0518082106137425780820390509050116131545750506104605181525061316b565b815160010180835281141561306457505060006000fd5b565b60006101005112613742576004610100511215613742576060366101c0376101a0516102205260e051600480820282158284830414171561374257905090506102405261026060006004818352015b610100516102605114156131d357613251566131ed565b6101206102605160048110156137425760200201516101e0525b6101c080516101e05181818301106137425780820190509050815250610220516101a05180820282158284830414171561374257905090506101e0516004808202821582848304141715613742579050905080801561374257820490509050610220525b81516001018083528114156131bc575050610220516101a051808202821582848304141715613742579050905060648082028215828483041417156137425790509050610240516004808202821582848304141715613742579050905080801561374257820490509050610220526101c0516101a05160648082028215828483041417156137425790509050610240518080156137425782049050905081818301106137425780820190509050610260526101a051610280526102a0600060ff818352015b6102805161020052610280516102805180820282158284830414171561374257905090506102205181818301106137425780820190509050600261028051808202821582848304141715613742579050905061026051818183011061374257808201905090506101a051808210613742578082039050905080801561374257820490509050610280526102005161028051116133db57600161020051610280518082106137425780820390509050116134065750506102805181525061341d56613406565b600161028051610200518082106137425780820390509050116134065750506102805181525061341d565b815160010180835281141561331657505060006000fd5b565b61342a610320612a87565b6103205161030052600654610320526007546103405260085461036052600954610380526103205160e05261034051610100526103605161012052610380516101405261030051610160526134806103c0612bc2565b6103c0516103a0526016546103c0526103a0516102c0516103a05180820282158284830414171561374257905090506103c0518080156137425782049050905080821061374257808203905090506103e0526103005160e0526102e0516101005261032051610120526103405161014052610360516101605261038051610180526103e0516101a05261351461042061316d565b6104205161040052600a5460048082028215828483041417156137425790509050600c8082049050905061042052608036610440376104c060006004818352015b60006104e0526103206104c0516004811015613742576020020151610500526102e0516104c051186135c957610500516103e05180820282158284830414171561374257905090506103a051808015613742578204905090506104005180821061374257808203905090506104e05261360d565b61050051610500516103e05180820282158284830414171561374257905090506103a0518080156137425782049050905080821061374257808203905090506104e0525b61050051610420516104e05180820282158284830414171561374257905090506402540be4008082049050905080821061374257808203905090506104406104c051600481101561374257602002015281516001018083528114156135555750506104406102e05160048110156137425760200201516103005160e0526102e051610100526104405161012052610460516101405261048051610160526104a051610180526103e0516101a0526136c56104e061316d565b6104e05180821061374257808203905090506104c0526103206102e05160048110156137425760200201516104005180821061374257808203905090506104e0526104c051600180821061374257808203905090506104c0526104c05181526104e0516104c0518082106137425780820390509050816020015250565b600080fd5b61000a6137510361000a60003961000a613751036000f3617a69600a5561417256600436101561000d576131dc565b60046000601c37600051346141635763a461b3c8811861039957600435600401602081351161416357808035602001808260e037505050602435600401600a813511614163578080356020018082610120375050506044358060a01c61416357610160526064358060a01c61416357610180526084358060a01c614163576101a05260a4358060a01c614163576101c052600a54614163576101e060006004818352015b6101606101e051600481101561416357602002015161020052610200516100d75761011e565b6102005160016101e051600481101561416357026002015560206101e0510260c4013560016101e05160048110156141635702600f015581516001018083528114156100b1575b505061014435606480820282158284830414171561416357905090506101e0526101e051600b556101e051600c5561016435600a55336001556000601d610260527f43757276652e666920466163746f727920506c61696e20506f6f6c3a2000000061028052610260601d806020846102a00101826020850160045afa50508051820191505060e06020806020846102a00101826020850160045afa505080518201915050806102a0526102a09050805160200180610200828460045afa90505050610200806013602082510160c060006003818352015b8260c051602002111561020857610227565b60c05160200285015160c05185015581516001018083528114156101f6575b5050505050506000610120600a806020846102a00101826020850160045afa5050805182019150506002610260527f2d66000000000000000000000000000000000000000000000000000000000000610280526102606002806020846102a00101826020850160045afa505080518201915050806102a0526102a09050806016602082510160c060006002818352015b8260c05160200211156102c9576102e8565b60c05160200285015160c05185015581516001018083528114156102b7575b5050505050507f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61034052610200805160208201209050610360527f572f01d824885a118d5d21c74542f263b131d2897955c62a721594f1d7c3b2e261038052466103a052306103c05260a061032052610320805160208201209050601b553060007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6000610260526020610260a3005b63313ce56781186103af57601260e052602060e0f35b63a9059cbb81186103f1576004358060a01c61416357610160523360e0526101605161010052602435610120526103e46131e2565b6001610180526020610180f35b6323b872dd81186104c5576004358060a01c61416357610160526024358060a01c61416357610180526101605160e0526101805161010052604435610120526104386131e2565b60196101605160a05260805260406080203360a0526080526040608020546101a0527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101a051146104b8576101a051604435808210614163578082039050905060196101605160a05260805260406080203360a0526080526040608020555b60016101c05260206101c0f35b63095ea7b3811861053d576004358060a01c6141635760e05260243560193360a052608052604060802060e05160a05260805260406080205560e051337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925602435610100526020610100a36001610100526020610100f35b63d505accf81186108aa576004358060a01c6141635760e0526024358060a01c61416357610100526084358060081c6141635761012052600060e0511461416357606435421161416357601c60e05160a0526080526040608020546101405260006002610400527f1901000000000000000000000000000000000000000000000000000000000000610420526104006002806020846106000101826020850160045afa505080518201915050601b546020826106000101526020810190507f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c96105405260e0516105605261010051610580526044356105a052610140516105c0526064356105e05260c0610520526105208051602082012090506020826106000101526020810190508061060052610600905080516020820120905061016052600060e0513b116106be5760e0516101605161018052610120516101a052604060a46101c03760206080608061018060015afa50608051186141635761081e565b600060a4356102205260c435610240526040610200526102006040806020846102c00101826020850160045afa505080518201915050601f60016020820661026001602082840111614163576020806102808261012060045afa5050818152905090506001806020846102c00101826020850160045afa505080518201915050806102c0526102c09050805160200180610180828460045afa905050507f1626ba7e00000000000000000000000000000000000000000000000000000000631626ba7e610200526102208060406101605182526020820191508082528083018061018080516020018083828460045afa905050508051806020830101818260206001820306601f8201039050033682375050805160200160206001820306601f820103905090509050810150505050602061020060c461021c60e0515afa61080b573d600060003e3d6000fd5b601f3d1115614163576102005118614163575b604435601960e05160a05260805260406080206101005160a05260805260406080205561014051600181818301106141635780820190509050601c60e05160a0526080526040608020556101005160e0517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925604435610180526020610180a36001610180526020610180f35b6314f0597981186108d65760065460e052600754610100526008546101205260095461014052608060e0f35b63fee3f7f981186108f05764012a05f20060e052602060e0f35b63f446c1d0811861091e5761090661016061326b565b61016051606480820490509050610180526020610180f35b6376a2f0f081186109435761093461016061326b565b61016051610180526020610180f35b63bb7b8b808118610a3e576109596102a061326b565b6102a05161028052600f5460e05260105461010052601154610120526012546101405260065461016052600754610180526008546101a0526009546101c0526109a36103206133a6565b61032080516102a05280602001516102c05280604001516102e052806060015161030052506102a05160e0526102c051610100526102e05161012052610300516101405261028051610160526109fa610340613450565b610340516103205261032051670de0b6b3a76400008082028215828483041417156141635790509050601a5480801561416357820490509050610340526020610340f35b63cf701ff78118610c46576084358060011c614163576104a052610a636104e061326b565b6104e0516104c0526006546104e052600754610500526008546105205260095461054052600f54610280526010546102a0526011546102c0526012546102e0526104e051610300526105005161032052610520516103405261054051610360526104c05161038052610ad66105806136bd565b610580516105605261058060006004818352015b60206105805102600401356105a0526104a051610b31576104e0610580516004811015614163576020020180516105a0518082106141635780820390509050815250610b5f565b6104e0610580516004811015614163576020020180516105a051818183011061416357808201905090508152505b8151600101808352811415610aea575050600f54610280526010546102a0526011546102c0526012546102e0526104e051610300526105005161032052610520516103405261054051610360526104c05161038052610bbf6105a06136bd565b6105a0516105805260006105a0526104a051610bf457610560516105805180821061416357808203905090506105a052610c0f565b610580516105605180821061416357808203905090506105a0525b6105a051601a54808202821582848304141715614163579050905061056051808015614163578204905090506105c05260206105c0f35b63029b2f348118610c5b57336104a052610c76565b63cb495064811861136f5760a4358060a01c614163576104a0525b600054614163576001600055610c8d6104e061326b565b6104e0516104c0526006546104e052600754610500526008546105205260095461054052600f5461056052601054610580526011546105a0526012546105c0526105605161028052610580516102a0526105a0516102c0526105c0516102e0526104e051610300526105005161032052610520516103405261054051610360526104c05161038052610d206106006136bd565b610600516105e052601a54610600526104e051610620526105005161064052610520516106605261054051610680526106a060006004818352015b60206106a05102600401356106c05260006106c05111610d85576000610600511461416357610ec5565b60006004610720527f23b872dd00000000000000000000000000000000000000000000000000000000610740526107206004806020846107600101826020850160045afa50508051820191505033602082610760010152602081019050306020826107600101526020810190506106c05160208261076001015260208101905080610760526107605050602061082061076051610780600060016106a05160048110156141635702600201545af1610e42573d600060003e3d6000fd5b61080060203d808211610e555781610e57565b805b9050905081528051602001806106e0828460045afa9050505060006106e0511115610e9757610700516106e05181816020036008021c9050905015614163575b6106206106a0516004811015614163576020020180516106c051818183011061416357808201905090508152505b8151600101808352811415610d5b5750506105605161028052610580516102a0526105a0516102c0526105c0516102e05261062051610300526106405161032052610660516103405261068051610360526104c05161038052610f296106c06136bd565b6106c0516106a0526105e0516106a05111156141635760a0366106c03760006106005111610f7a57610620516006556106405160075561066051600855610680516009556106a051610740526111e0565b600a5460048082028215828483041417156141635790509050600c808204905090506107605261078060006004818352015b6106a0516104e061078051600481101561416357602002015180820282158284830414171561416357905090506105e051808015614163578204905090506107a05260006107c0526106206107805160048110156141635760200201516107e0526107e0516107a05111611039576107e0516107a05180821061416357808203905090506107c052611054565b6107a0516107e05180821061416357808203905090506107c0525b610760516107c05180820282158284830414171561416357905090506402540be400808204905090506106c06107805160048110156141635760200201526107e0516106c061078051600481101561416357602002015164012a05f20080820282158284830414171561416357905090506402540be4008082049050905080821061416357808203905090506001610780516004811015614163570260060155610620610780516004811015614163576020020180516106c061078051600481101561416357602002015180821061416357808203905090508152508151600101808352811415610fac5750506105605161028052610580516102a0526105a0516102c0526105c0516102e05261062051610300526106405161032052610660516103405261068051610360526104c051610380526111946107a06136bd565b6107a0516107805261060051610780516105e051808210614163578082039050905080820282158284830414171561416357905090506105e05180801561416357820490509050610740525b608435610740511015611264576014610760527f536c697070616765207363726577656420796f750000000000000000000000006107805261076050610760518061078001818260206001820306601f82010390500336823750506308c379a0610720526020610740526107605160206001820306601f820103905060440161073cfd5b6106008051610740518181830110614163578082019050905081525060186104a05160a05260805260406080208054610740518181830110614163578082019050905081555061060051601a556104a05160007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef61074051610760526020610760a3337f3f1915775e0c9a38a57a7bb7f1f9005f486fb904e1f84aa215364d567319a58d60043561076052602435610780526044356107a0526064356107c0526106c0516107e0526106e05161080052610700516108205261072051610840526106a051610860526106005161088052610140610760a2610740516107605260206107606000600055f35b635e0d443f81186115a0576004358060801d81607f1d18614163576104a0526024358060801d81607f1d18614163576104c052600f546104e0526010546105005260115461052052601254610540526104e05160e05261050051610100526105205161012052610540516101405260065461016052600754610180526008546101a0526009546101c0526114046105e06133a6565b6105e080516105605280602001516105805280604001516105a05280606001516105c052506105606104a05160048110156141635760200201516044356104e06104a05160048110156141635760200201518082028215828483041417156141635790509050670de0b6b3a764000080820490509050818183011061416357808201905090506105e0526104a051610280526104c0516102a0526105e0516102c052610560516102e05261058051610300526105a051610320526105c051610340526114d1610620613767565b61062051610600526105606104c05160048110156141635760200201516106005180821061416357808203905090506001808210614163578082039050905061062052600a546106205180820282158284830414171561416357905090506402540be400808204905090506106405261062051610640518082106141635780820390509050670de0b6b3a764000080820282158284830414171561416357905090506104e06104c051600481101561416357602002015180801561416357820490509050610660526020610660f35b633df0212481186115b557336104e0526115d0565b63ddc1f59d8118611c34576084358060a01c614163576104e0525b6004358060801d81607f1d18614163576104a0526024358060801d81607f1d18614163576104c052600054614163576001600055600f5461050052601054610520526011546105405260125461056052600654610580526007546105a0526008546105c0526009546105e0526105005160e05261052051610100526105405161012052610560516101405261058051610160526105a051610180526105c0516101a0526105e0516101c0526116866106806133a6565b610680805161060052806020015161062052806040015161064052806060015161066052506106006104a05160048110156141635760200201516044356105006104a05160048110156141635760200201518082028215828483041417156141635790509050670de0b6b3a76400008082049050905081818301106141635780820190509050610680526104a051610280526104c0516102a052610680516102c052610600516102e0526106205161030052610640516103205261066051610340526117536106c0613767565b6106c0516106a0526106006104c05160048110156141635760200201516106a0518082106141635780820390509050600180821061416357808203905090506106c0526106c051600a5480820282158284830414171561416357905090506402540be400808204905090506106e0526106c0516106e0518082106141635780820390509050670de0b6b3a764000080820282158284830414171561416357905090506105006104c0516004811015614163576020020151808015614163578204905090506106c0526064356106c05110156118c457602e610700527f45786368616e676520726573756c74656420696e20666577657220636f696e73610720527f207468616e2065787065637465640000000000000000000000000000000000006107405261070050610700518061072001818260206001820306601f82010390500336823750506308c379a06106c05260206106e0526107005160206001820306601f82010390506044016106dcfd5b6106e05164012a05f20080820282158284830414171561416357905090506402540be400808204905090506107005261070051670de0b6b3a764000080820282158284830414171561416357905090506105006104c051600481101561416357602002015180801561416357820490509050610700526105806104a05160048110156141635760200201516044358181830110614163578082019050905060016104a05160048110156141635702600601556105806104c05160048110156141635760200201516106c051808210614163578082039050905061070051808210614163578082039050905060016104c051600481101561416357026006015560006004610760527f23b872dd00000000000000000000000000000000000000000000000000000000610780526107606004806020846107a00101826020850160045afa505080518201915050336020826107a0010152602081019050306020826107a00101526020810190506044356020826107a0010152602081019050806107a0526107a0505060206108606107a0516107c0600060016104a05160048110156141635702600201545af1611a7f573d600060003e3d6000fd5b61084060203d808211611a925781611a94565b805b905090508152805160200180610720828460045afa905050506000610720511115611ad457610740516107205181816020036008021c9050905015614163575b60006004610760527fa9059cbb00000000000000000000000000000000000000000000000000000000610780526107606004806020846107a00101826020850160045afa5050805182019150506104e0516020826107a00101526020810190506106c0516020826107a0010152602081019050806107a0526107a0505060206108406107a0516107c0600060016104c05160048110156141635702600201545af1611b84573d600060003e3d6000fd5b61082060203d808211611b975781611b99565b805b905090508152805160200180610720828460045afa905050506000610720511115611bd957610740516107205181816020036008021c9050905015614163575b337f8b3e96f2b889fa771c53c981b40daf005f63f637f1869f707052d15a3dd971406104a05161076052604435610780526104c0516107a0526106c0516107c0526080610760a26106c0516107605260206107606000600055f35b637d49d8758118611c48573360e052611c62565b63b2fdb76f8118611fd25760a4358060a01c6141635760e0525b600054614163576001600055601a5461010052608036610120376101a060006004818352015b60016101a05160048110156141635702600601546101c0526101c051600435808202821582848304141715614163579050905061010051808015614163578204905090506101e05260206101a05102602401356101e0511015611d81576030610200527f5769746864726177616c20726573756c74656420696e20666577657220636f69610220527f6e73207468616e206578706563746564000000000000000000000000000000006102405261020050610200518061022001818260206001820306601f82010390500336823750506308c379a06101c05260206101e0526102005160206001820306601f82010390506044016101dcfd5b6101c0516101e051808210614163578082039050905060016101a05160048110156141635702600601556101e0516101206101a051600481101561416357602002015260006004610240527fa9059cbb00000000000000000000000000000000000000000000000000000000610260526102406004806020846102800101826020850160045afa50508051820191505060e0516020826102800101526020810190506101e051602082610280010152602081019050806102805261028050506020610320610280516102a0600060016101a05160048110156141635702600201545af1611e73573d600060003e3d6000fd5b61030060203d808211611e865781611e88565b805b905090508152805160200180610200828460045afa905050506000610200511115611ec857610220516102005181816020036008021c9050905015614163575b8151600101808352811415611c885750506101008051600435808210614163578082039050905081525060183360a05260805260406080208054600435808210614163578082039050905081555061010051601a556000337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6004356101a05260206101a0a3337f9878ca375e106f2a43c3b599fc624568131c4c9a4ba66a14563715763be9d59d610120516101a052610140516101c052610160516101e052610180516102005260803661022037610100516102a0526101206101a0a2610120516101a052610140516101c052610160516101e052610180516102005260806101a06000600055f35b6318a7bd768118611fe757336104a052612002565b634ab3a82b81186126ac5760a4358060a01c614163576104a0525b6000546141635760016000556120196104e061326b565b6104e0516104c052600f546104e05260105461050052601154610520526012546105405260065461056052600754610580526008546105a0526009546105c0526104e05161028052610500516102a052610520516102c052610540516102e052610560516103005261058051610320526105a051610340526105c051610360526104c051610380526120ac6106006136bd565b610600516105e052610560516106005261058051610620526105a051610640526105c0516106605261068060006004818352015b60206106805102600401356106a05260006106a0511461222a57610600610680516004811015614163576020020180516106a051808210614163578082039050905081525060006004610700527fa9059cbb00000000000000000000000000000000000000000000000000000000610720526107006004806020846107400101826020850160045afa5050805182019150506104a0516020826107400101526020810190506106a0516020826107400101526020810190508061074052610740505060206107e061074051610760600060016106805160048110156141635702600201545af16121d5573d600060003e3d6000fd5b6107c060203d8082116121e857816121ea565b805b9050905081528051602001806106c0828460045afa9050505060006106c051111561222a576106e0516106c05181816020036008021c9050905015614163575b81516001018083528114156120e05750506104e05161028052610500516102a052610520516102c052610540516102e05261060051610300526106205161032052610640516103405261066051610360526104c0516103805261228e6106a06136bd565b6106a051610680526080366106a037600a5460048082028215828483041417156141635790509050600c808204905090506107205261074060006004818352015b6106805161056061074051600481101561416357602002015180820282158284830414171561416357905090506105e05180801561416357820490509050610760526000610780526106006107405160048110156141635760200201516107a0526107a051610760511161235c576107a05161076051808210614163578082039050905061078052612377565b610760516107a0518082106141635780820390509050610780525b610720516107805180820282158284830414171561416357905090506402540be400808204905090506106a06107405160048110156141635760200201526107a0516106a061074051600481101561416357602002015164012a05f20080820282158284830414171561416357905090506402540be4008082049050905080821061416357808203905090506001610740516004811015614163570260060155610600610740516004811015614163576020020180516106a0610740516004811015614163576020020151808210614163578082039050905081525081516001018083528114156122cf5750506104e05161028052610500516102a052610520516102c052610540516102e05261060051610300526106205161032052610640516103405261066051610360526104c051610380526124b76107606136bd565b6107605161074052601a54610760526105e0516107405180821061416357808203905090506107605180820282158284830414171561416357905090506105e05180801561416357820490509050600181818301106141635780820190509050610780526001610780511115614163576084356107805111156125ab5760146107a0527f536c697070616765207363726577656420796f750000000000000000000000006107c0526107a0506107a051806107c001818260206001820306601f82010390500336823750506308c379a0610760526020610780526107a05160206001820306601f820103905060440161077cfd5b610760805161078051808210614163578082039050905081525061076051601a5560183360a052608052604060802080546107805180821061416357808203905090508155506000337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef610780516107a05260206107a0a3337fb964b72f73f5ef5bf0fdc559b2fab9a7b12a39e47817a547f1f0aee47febd6026004356107a0526024356107c0526044356107e052606435610800526106a051610820526106c051610840526106e051610860526107005161088052610680516108a052610760516108c0526101406107a0a2610780516107a05260206107a06000600055f35b63cc2b27d781186126f4576024358060801d81607f1d18614163576105a0526004356102c0526105a0516102e0526126e56105c0613d57565b6105c051610600526020610600f35b631a4d01d2811861270957336105c052612724565b63081579a58118612a26576064358060a01c614163576105c0525b6024358060801d81607f1d18614163576105a0526000546141635760016000556004356102c0526105a0516102e05261275e610620613d57565b61062080516105e052806020015161060052506044356105e05110156127f5576018610620527f4e6f7420656e6f75676820636f696e732072656d6f76656400000000000000006106405261062050610620518061064001818260206001820306601f82010390500336823750506308c379a06105e0526020610600526106205160206001820306601f82010390506044016105fcfd5b60016105a0516004811015614163570260060180546105e0516106005164012a05f20080820282158284830414171561416357905090506402540be40080820490509050818183011061416357808201905090508082106141635780820390509050815550601a5460043580821061416357808203905090506106205261062051601a5560183360a0526080526040608020805460043580821061416357808203905090508155506000337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600435610640526020610640a360006004610680527fa9059cbb000000000000000000000000000000000000000000000000000000006106a0526106806004806020846106c00101826020850160045afa5050805182019150506105c0516020826106c00101526020810190506105e0516020826106c0010152602081019050806106c0526106c0505060206107606106c0516106e0600060016105a05160048110156141635702600201545af161297e573d600060003e3d6000fd5b61074060203d8082116129915781612993565b805b905090508152805160200180610640828460045afa9050505060006106405111156129d357610660516106405181816020036008021c9050905015614163575b337f5ad056f2e28a8cec232015406b843668c1e36cda598127ec3b8c59b8c72773a0600435610680526105e0516106a052610620516106c0526060610680a26105e0516106805260206106806000600055f35b633c157e648118612baa5763f851a440610160526020610160600461017c6001545afa612a58573d600060003e3d6000fd5b601f3d11156141635761016051331861416357600d5462015180818183011061416357808201905090504210614163574262015180818183011061416357808201905090506024351061416357612ab061018061326b565b61018051610160526004356064808202821582848304141715614163579050905061018052600060043511612ae6576000612aef565b620f4240600435105b1561416357610160516101805110612b295761016051600a8082028215828483041417156141635790509050610180511161416357612b4d565b6101605161018051600a808202821582848304141715614163579050905010614163575b61016051600b5561018051600c5542600d55602435600e557fa2b71ec6df949300b59aab36b55e189697b750119dd349fcfa8c0f779e83c254610160516101a052610180516101c052426101e0526024356102005260806101a0a1005b63551a65888118612c4e5763f851a440610160526020610160600461017c6001545afa612bdc573d600060003e3d6000fd5b601f3d11156141635761016051331861416357612bfa61018061326b565b610180516101605261016051600b5561016051600c5542600d5542600e557f46e22fb3709ad289f62ce63d469248536dbc78d82b84a3d7e74ad606dc2019386101605161018052426101a0526040610180a1005b63e2e7d2648118612cca576370a0823160e0523061010052602060e0602460fc600160043560048110156141635702600201545afa612c92573d600060003e3d6000fd5b601f3d11156141635760e051600160043560048110156141635702600601548082106141635780820390509050610120526020610120f35b6330c540858118612e4e5763154aa8f56101005230610120526020610100602461011c6001545afa612d01573d600060003e3d6000fd5b601f3d111561416357610100518060a01c6141635760e05261010060006004818352015b6001610100516004811015614163570260020154610120526370a082316101605230610180526020610160602461017c610120515afa612d6a573d600060003e3d6000fd5b601f3d11156141635761016051600161010051600481101561416357026006015480821061416357808203905090506101405260006004610160527fa9059cbb00000000000000000000000000000000000000000000000000000000610180526101606004806020846101a00101826020850160045afa50508051820191505060e0516020826101a0010152602081019050610140516020826101a0010152602081019050806101a0526101a05050600060006101a0516101c06000610120515af1612e3b573d600060003e3d6000fd5b8151600101808352811415612d25575050005b6354fd4d508118612ee857610120806020808252600660e0527f76352e302e3000000000000000000000000000000000000000000000000000006101005260e0818401808280516020018083828460045afa905050508051806020830101818260206001820306601f8201039050033682375050805160200160206001820306601f82010390509050905090508101905090509050610120f35b63c66106578118612f0f576001600435600481101561416357026002015460e052602060e0f35b634903b0d18118612f36576001600435600481101561416357026006015460e052602060e0f35b63ddca3f438118612f4d57600a5460e052602060e0f35b635409491a8118612f6457600b5460e052602060e0f35b63b4b577ad8118612f7b57600c5460e052602060e0f35b632081066c8118612f9257600d5460e052602060e0f35b63140522888118612fa957600e5460e052602060e0f35b6306fdde03811861304c5760e08060208082528083018060138082602082540160c060006003818352015b8260c0516020021115612fe657613005565b60c05185015460c0516020028501528151600101808352811415612fd4575b5050505050508051806020830101818260206001820306601f8201039050033682375050805160200160206001820306601f820103905090509050810190509050905060e0f35b6395d89b4181186130ef5760e08060208082528083018060168082602082540160c060006002818352015b8260c0516020021115613089576130a8565b60c05185015460c0516020028501528151600101808352811415613077575b5050505050508051806020830101818260206001820306601f8201039050033682375050805160200160206001820306601f820103905090509050810190509050905060e0f35b6370a082318118613124576004358060a01c6141635760e052601860e05160a052608052604060802054610100526020610100f35b63dd62ed3e8118613177576004358060a01c6141635760e0526024358060a01c6141635761010052601960e05160a05260805260406080206101005160a052608052604060802054610120526020610120f35b6318160ddd811861318e57601a5460e052602060e0f35b633644e51581186131a557601b5460e052602060e0f35b637ecebe0081186131da576004358060a01c6141635760e052601c60e05160a052608052604060802054610100526020610100f35b505b60006000fd5b601860e05160a0526080526040608020805461012051808210614163578082039050905081555060186101005160a0526080526040608020805461012051818183011061416357808201905090508155506101005160e0517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef61012051610140526020610140a3565b600e5460e052600c546101005260e051421061329157610100518152506133a4566133a4565b600b5461012052600d546101405261012051610100511161332957610120516101205161010051808210614163578082039050905042610140518082106141635780820390509050808202821582848304141715614163579050905060e0516101405180821061416357808203905090508080156141635782049050905080821061416357808203905090508152506133a4566133a4565b610120516101005161012051808210614163578082039050905042610140518082106141635780820390509050808202821582848304141715614163579050905060e05161014051808210614163578082039050905080801561416357820490509050818183011061416357808201905090508152506133a4565b565b6080366101e03761026060006004818352015b60e06102605160048110156141635760200201516101606102605160048110156141635760200201518082028215828483041417156141635790509050670de0b6b3a7640000808204905090506101e061026051600481101561416357602002015281516001018083528114156133b95750506101e051815261020051816020015261022051816040015261024051816060015250565b604036610180376101e060006004818352015b60206101e0510260e001516101c05261018080516101c051818183011061416357808201905090508152508151600101808352811415613463575050610180516134b15760008152506136bb565b610180516101c05261016051600480820282158284830414171561416357905090506101e052610200600060ff818352015b6101c0516102205261026060006004818352015b6020610260510260e0015161024052610220516101c05180820282158284830414171561416357905090506102405160048082028215828483041417156141635790509050808015614163578204905090506102205281516001018083528114156134f75750506101c0516101a0526101e0516101805180820282158284830414171561416357905090506064808204905090506102205160048082028215828483041417156141635790509050818183011061416357808201905090506101c05180820282158284830414171561416357905090506101e051606480821061416357808203905090506101c0518082028215828483041417156141635790509050606480820490509050600561022051808202821582848304141715614163579050905081818301106141635780820190509050808015614163578204905090506101c0526101a0516101c051116136795760016101a0516101c0518082106141635780820390509050116136a45750506101c0518152506136bb566136a4565b60016101c0516101a0518082106141635780820390509050116136a45750506101c0518152506136bb565b81516001018083528114156134e357505060006000fd5b565b6102805160e0526102a051610100526102c051610120526102e0516101405261030051610160526103205161018052610340516101a052610360516101c0526137076104206133a6565b61042080516103a05280602001516103c05280604001516103e052806060015161040052506103a05160e0526103c051610100526103e051610120526104005161014052610380516101605261375e610420613450565b61042051815250565b6102a05161028051146141635760006102a051126141635760046102a05112156141635760006102805112614163576004610280511215614163576137ad61038061326b565b61038051610360526102e05160e05261030051610100526103205161012052610340516101405261036051610160526137e76103a0613450565b6103a051610380526060366103a037610380516104005261036051600480820282158284830414171561416357905090506104205261044060006004818352015b610280516104405118613842576102c0516103c052613873565b6102a051610440511415613859576138d756613873565b6102e06104405160048110156141635760200201516103c0525b6103a080516103c05181818301106141635780820190509050815250610400516103805180820282158284830414171561416357905090506103c0516004808202821582848304141715614163579050905080801561416357820490509050610400525b81516001018083528114156138285750506104005161038051808202821582848304141715614163579050905060648082028215828483041417156141635790509050610420516004808202821582848304141715614163579050905080801561416357820490509050610400526103a0516103805160648082028215828483041417156141635790509050610420518080156141635782049050905081818301106141635780820190509050610440526103805161046052610480600060ff818352015b610460516103e0526104605161046051808202821582848304141715614163579050905061040051818183011061416357808201905090506002610460518082028215828483041417156141635790509050610440518181830110614163578082019050905061038051808210614163578082039050905080801561416357820490509050610460526103e0516104605111613a615760016103e05161046051808210614163578082039050905011613a8c57505061046051815250613aa356613a8c565b6001610460516103e051808210614163578082039050905011613a8c57505061046051815250613aa3565b815160010180835281141561399c57505060006000fd5b565b60006101005112614163576004610100511215614163576060366101c0376101a0516102205260e051600480820282158284830414171561416357905090506102405261026060006004818352015b61010051610260511415613b0b57613b8956613b25565b6101206102605160048110156141635760200201516101e0525b6101c080516101e05181818301106141635780820190509050815250610220516101a05180820282158284830414171561416357905090506101e0516004808202821582848304141715614163579050905080801561416357820490509050610220525b8151600101808352811415613af4575050610220516101a051808202821582848304141715614163579050905060648082028215828483041417156141635790509050610240516004808202821582848304141715614163579050905080801561416357820490509050610220526101c0516101a05160648082028215828483041417156141635790509050610240518080156141635782049050905081818301106141635780820190509050610260526101a051610280526102a0600060ff818352015b6102805161020052610280516102805180820282158284830414171561416357905090506102205181818301106141635780820190509050600261028051808202821582848304141715614163579050905061026051818183011061416357808201905090506101a05180821061416357808203905090508080156141635782049050905061028052610200516102805111613d135760016102005161028051808210614163578082039050905011613d3e57505061028051815250613d5556613d3e565b60016102805161020051808210614163578082039050905011613d3e57505061028051815250613d55565b8151600101808352811415613c4e57505060006000fd5b565b613d6261032061326b565b6103205161030052600f54610320526010546103405260115461036052601254610380526103205160e05261034051610100526103605161012052610380516101405260065461016052600754610180526008546101a0526009546101c052613dcc6104206133a6565b61042080516103a05280602001516103c05280604001516103e052806060015161040052506103a05160e0526103c051610100526103e0516101205261040051610140526103005161016052613e23610440613450565b6104405161042052601a5461044052610420516102c05161042051808202821582848304141715614163579050905061044051808015614163578204905090508082106141635780820390509050610460526103005160e0526102e051610100526103a051610120526103c051610140526103e051610160526104005161018052610460516101a052613eb76104a0613aa5565b6104a05161048052600a5460048082028215828483041417156141635790509050600c808204905090506104a0526080366104c03761054060006004818352015b6000610560526103a0610540516004811015614163576020020151610580526102e0516105405118613f6c5761058051610460518082028215828483041417156141635790509050610420518080156141635782049050905061048051808210614163578082039050905061056052613fb0565b610580516105805161046051808202821582848304141715614163579050905061042051808015614163578204905090508082106141635780820390509050610560525b610580516104a0516105605180820282158284830414171561416357905090506402540be4008082049050905080821061416357808203905090506104c06105405160048110156141635760200201528151600101808352811415613ef85750506104c06102e05160048110156141635760200201516103005160e0526102e051610100526104c051610120526104e0516101405261050051610160526105205161018052610460516101a052614068610560613aa5565b610560518082106141635780820390509050610540526103a06102e0516004811015614163576020020151610480518082106141635780820390509050670de0b6b3a764000080820282158284830414171561416357905090506103206102e051600481101561416357602002015180801561416357820490509050610560526105405160018082106141635780820390509050670de0b6b3a764000080820282158284830414171561416357905090506103206102e0516004811015614163576020020151808015614163578204905090506105405261054051815261056051610540518082106141635780820390509050816020015250565b600080fd5b61000a6141720361000a60003961000a614172036000f3617a69600a5561439d56600436101561000d576132ed565b60046000601c376000513461438e5763a461b3c8811861039957600435600401602081351161438e57808035602001808260e037505050602435600401600a81351161438e578080356020018082610120375050506044358060a01c61438e57610160526064358060a01c61438e57610180526084358060a01c61438e576101a05260a4358060a01c61438e576101c052600a5461438e576101e060006004818352015b6101606101e051600481101561438e57602002015161020052610200516100d75761011e565b6102005160016101e051600481101561438e57026002015560206101e0510260c4013560016101e051600481101561438e5702600f015581516001018083528114156100b1575b505061014435606480820282158284830414171561438e57905090506101e0526101e051600b556101e051600c5561016435600a55336001556000601d610260527f43757276652e666920466163746f727920506c61696e20506f6f6c3a2000000061028052610260601d806020846102a00101826020850160045afa50508051820191505060e06020806020846102a00101826020850160045afa505080518201915050806102a0526102a09050805160200180610200828460045afa90505050610200806013602082510160c060006003818352015b8260c051602002111561020857610227565b60c05160200285015160c05185015581516001018083528114156101f6575b5050505050506000610120600a806020846102a00101826020850160045afa5050805182019150506002610260527f2d66000000000000000000000000000000000000000000000000000000000000610280526102606002806020846102a00101826020850160045afa505080518201915050806102a0526102a09050806016602082510160c060006002818352015b8260c05160200211156102c9576102e8565b60c05160200285015160c05185015581516001018083528114156102b7575b5050505050507f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61034052610200805160208201209050610360527f572f01d824885a118d5d21c74542f263b131d2897955c62a721594f1d7c3b2e261038052466103a052306103c05260a061032052610320805160208201209050601b553060007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6000610260526020610260a3005b63313ce56781186103af57601260e052602060e0f35b63a9059cbb81186103f1576004358060a01c61438e57610160523360e0526101605161010052602435610120526103e46132f3565b6001610180526020610180f35b6323b872dd81186104c5576004358060a01c61438e57610160526024358060a01c61438e57610180526101605160e0526101805161010052604435610120526104386132f3565b60196101605160a05260805260406080203360a0526080526040608020546101a0527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101a051146104b8576101a05160443580821061438e578082039050905060196101605160a05260805260406080203360a0526080526040608020555b60016101c05260206101c0f35b63095ea7b3811861053d576004358060a01c61438e5760e05260243560193360a052608052604060802060e05160a05260805260406080205560e051337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925602435610100526020610100a36001610100526020610100f35b63d505accf81186108aa576004358060a01c61438e5760e0526024358060a01c61438e57610100526084358060081c61438e5761012052600060e0511461438e57606435421161438e57601c60e05160a0526080526040608020546101405260006002610400527f1901000000000000000000000000000000000000000000000000000000000000610420526104006002806020846106000101826020850160045afa505080518201915050601b546020826106000101526020810190507f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c96105405260e0516105605261010051610580526044356105a052610140516105c0526064356105e05260c0610520526105208051602082012090506020826106000101526020810190508061060052610600905080516020820120905061016052600060e0513b116106be5760e0516101605161018052610120516101a052604060a46101c03760206080608061018060015afa506080511861438e5761081e565b600060a4356102205260c435610240526040610200526102006040806020846102c00101826020850160045afa505080518201915050601f6001602082066102600160208284011161438e576020806102808261012060045afa5050818152905090506001806020846102c00101826020850160045afa505080518201915050806102c0526102c09050805160200180610180828460045afa905050507f1626ba7e00000000000000000000000000000000000000000000000000000000631626ba7e610200526102208060406101605182526020820191508082528083018061018080516020018083828460045afa905050508051806020830101818260206001820306601f8201039050033682375050805160200160206001820306601f820103905090509050810150505050602061020060c461021c60e0515afa61080b573d600060003e3d6000fd5b601f3d111561438e57610200511861438e575b604435601960e05160a05260805260406080206101005160a052608052604060802055610140516001818183011061438e5780820190509050601c60e05160a0526080526040608020556101005160e0517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925604435610180526020610180a36001610180526020610180f35b634903b0d181186108df576108c06101c061337c565b6101c0600435600481101561438e576020020151610240526020610240f35b6314f059798118610921576108f56101c061337c565b6101c080516102405280602001516102605280604001516102805280606001516102a052506080610240f35b63fee3f7f9811861093b5764012a05f20060e052602060e0f35b63f446c1d0811861096957610951610160613442565b61016051606480820490509050610180526020610180f35b6376a2f0f0811861098e5761097f610160613442565b61016051610180526020610180f35b63bb7b8b808118610abd576109a46102a0613442565b6102a051610280526109b761032061337c565b61032080516102a05280602001516102c05280604001516102e05280606001516103005250600f5460e0526010546101005260115461012052601254610140526102a051610160526102c051610180526102e0516101a052610300516101c052610a226103a061357d565b6103a0805161032052806020015161034052806040015161036052806060015161038052506103205160e0526103405161010052610360516101205261038051610140526102805161016052610a796103c0613627565b6103c0516103a0526103a051670de0b6b3a764000080820282158284830414171561438e5790509050601a5480801561438e578204905090506103c05260206103c0f35b63cf701ff78118610cd9576084358060011c61438e576104a052610ae26104e0613442565b6104e0516104c052610af561056061337c565b61056080516104e05280602001516105005280604001516105205280606001516105405250600f54610280526010546102a0526011546102c0526012546102e0526104e051610300526105005161032052610520516103405261054051610360526104c05161038052610b69610580613894565b610580516105605261058060006004818352015b60206105805102600401356105a0526104a051610bc4576104e061058051600481101561438e576020020180516105a05180821061438e5780820390509050815250610bf2565b6104e061058051600481101561438e576020020180516105a051818183011061438e57808201905090508152505b8151600101808352811415610b7d575050600f54610280526010546102a0526011546102c0526012546102e0526104e051610300526105005161032052610520516103405261054051610360526104c05161038052610c526105a0613894565b6105a0516105805260006105a0526104a051610c8757610560516105805180821061438e57808203905090506105a052610ca2565b610580516105605180821061438e57808203905090506105a0525b6105a051601a5480820282158284830414171561438e57905090506105605180801561438e578204905090506105c05260206105c0f35b63029b2f348118610cee57336104a052610d09565b63cb495064811861148a5760a4358060a01c61438e576104a0525b60005461438e576001600055610d206104e0613442565b6104e0516104c052610d3361056061337c565b61056080516104e05280602001516105005280604001516105205280606001516105405250600f5461056052601054610580526011546105a0526012546105c0526105605161028052610580516102a0526105a0516102c0526105c0516102e0526104e051610300526105005161032052610520516103405261054051610360526104c05161038052610dc7610600613894565b610600516105e052601a54610600526104e051610620526105005161064052610520516106605261054051610680526106a060006004818352015b60206106a05102600401356106c05260006106c05111610e2c576000610600511461438e57610ffa565b60016106a051600481101561438e5702600201546106e0526370a082316107205230610740526020610720602461073c6106e0515afa610e71573d600060003e3d6000fd5b601f3d111561438e57610720516107005260006004610760527f23b872dd00000000000000000000000000000000000000000000000000000000610780526107606004806020846107a00101826020850160045afa505080518201915050336020826107a0010152602081019050306020826107a00101526020810190506106c0516020826107a0010152602081019050806107a0526107a0505060206108606107a0516107c060006106e0515af1610f2f573d600060003e3d6000fd5b61084060203d808211610f425781610f44565b805b905090508152805160200180610720828460045afa905050506000610720511115610f8457610740516107205181816020036008021c905090501561438e575b6106206106a051600481101561438e576020020180516370a082316107605230610780526020610760602461077c6106e0515afa610fc7573d600060003e3d6000fd5b601f3d111561438e57610760516107005180821061438e5780820390509050818183011061438e57808201905090508152505b8151600101808352811415610e025750506105605161028052610580516102a0526105a0516102c0526105c0516102e05261062051610300526106405161032052610660516103405261068051610360526104c0516103805261105e6106c0613894565b6106c0516106a0526105e0516106a051111561438e5760a0366106c03760006106005111611093576106a051610740526112fb565b600a54600480820282158284830414171561438e5790509050600c808204905090506107605261078060006004818352015b6106a0516104e061078051600481101561438e57602002015180820282158284830414171561438e57905090506105e05180801561438e578204905090506107a05260006107c05261062061078051600481101561438e5760200201516107e0526107e0516107a05111611152576107e0516107a05180821061438e57808203905090506107c05261116d565b6107a0516107e05180821061438e57808203905090506107c0525b610760516107c05180820282158284830414171561438e57905090506402540be400808204905090506106c061078051600481101561438e576020020152600161078051600481101561438e570260060180546106c061078051600481101561438e57602002015164012a05f20080820282158284830414171561438e57905090506402540be40080820490509050818183011061438e578082019050905081555061062061078051600481101561438e576020020180516106c061078051600481101561438e57602002015180821061438e578082039050905081525081516001018083528114156110c55750506105605161028052610580516102a0526105a0516102c0526105c0516102e05261062051610300526106405161032052610660516103405261068051610360526104c051610380526112af6107a0613894565b6107a0516107805261060051610780516105e05180821061438e578082039050905080820282158284830414171561438e57905090506105e05180801561438e57820490509050610740525b60843561074051101561137f576014610760527f536c697070616765207363726577656420796f750000000000000000000000006107805261076050610760518061078001818260206001820306601f82010390500336823750506308c379a0610720526020610740526107605160206001820306601f820103905060440161073cfd5b610600805161074051818183011061438e578082019050905081525060186104a05160a0526080526040608020805461074051818183011061438e578082019050905081555061060051601a556104a05160007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef61074051610760526020610760a3337f3f1915775e0c9a38a57a7bb7f1f9005f486fb904e1f84aa215364d567319a58d60043561076052602435610780526044356107a0526064356107c0526106c0516107e0526106e05161080052610700516108205261072051610840526106a051610860526106005161088052610140610760a2610740516107605260206107606000600055f35b635e0d443f811861170f576004358060801d81607f1d1861438e576104a0526024358060801d81607f1d1861438e576104c052600f546104e0526010546105005260115461052052601254610540526104e0516106e0526105005161070052610520516107205261054051610740526115046105e061337c565b6105e080516107605280602001516107805280604001516107a05280606001516107c052506106e05160e052610700516101005261072051610120526107405161014052610760516101605261078051610180526107a0516101a0526107c0516101c05261157361066061357d565b61066080516105605280602001516105805280604001516105a05280606001516105c052506105606104a051600481101561438e5760200201516044356104e06104a051600481101561438e57602002015180820282158284830414171561438e5790509050670de0b6b3a764000080820490509050818183011061438e57808201905090506105e0526104a051610280526104c0516102a0526105e0516102c052610560516102e05261058051610300526105a051610320526105c0516103405261164061062061393e565b61062051610600526105606104c051600481101561438e5760200201516106005180821061438e5780820390509050600180821061438e578082039050905061062052600a546106205180820282158284830414171561438e57905090506402540be4008082049050905061064052610620516106405180821061438e5780820390509050670de0b6b3a764000080820282158284830414171561438e57905090506104e06104c051600481101561438e57602002015180801561438e57820490509050610660526020610660f35b633df02124811861172457336104e05261173f565b63ddc1f59d8118611de1576084358060a01c61438e576104e0525b6004358060801d81607f1d1861438e576104a0526024358060801d81607f1d1861438e576104c05260005461438e576001600055600f546105005260105461052052601154610540526012546105605261179a61060061337c565b61060080516105805280602001516105a05280604001516105c05280606001516105e052506105005160e05261052051610100526105405161012052610560516101405261058051610160526105a051610180526105c0516101a0526105e0516101c05261180961068061357d565b6106808051610600528060200151610620528060400151610640528060600151610660525060016104a051600481101561438e570260020154610680526370a082316106c052306106e05260206106c060246106dc610680515afa611873573d600060003e3d6000fd5b601f3d111561438e576106c0516106a05260006004610700527f23b872dd00000000000000000000000000000000000000000000000000000000610720526107006004806020846107400101826020850160045afa5050805182019150503360208261074001015260208101905030602082610740010152602081019050604435602082610740010152602081019050806107405261074050506020610800610740516107606000610680515af1611930573d600060003e3d6000fd5b6107e060203d8082116119435781611945565b805b9050905081528051602001806106c0828460045afa9050505060006106c0511115611985576106e0516106c05181816020036008021c905090501561438e575b6370a082316107005230610720526020610700602461071c610680515afa6119b2573d600060003e3d6000fd5b601f3d111561438e57610700516106a05180821061438e57808203905090506106a0526106006104a051600481101561438e5760200201516106a0516105006104a051600481101561438e57602002015180820282158284830414171561438e5790509050670de0b6b3a764000080820490509050818183011061438e5780820190509050610700526104a051610280526104c0516102a052610700516102c052610600516102e052610620516103005261064051610320526106605161034052611a7e61074061393e565b61074051610720526106006104c051600481101561438e5760200201516107205180821061438e5780820390509050600180821061438e57808203905090506107405261074051600a5480820282158284830414171561438e57905090506402540be4008082049050905061076052610740516107605180821061438e5780820390509050670de0b6b3a764000080820282158284830414171561438e57905090506105006104c051600481101561438e57602002015180801561438e5782049050905061074052606435610740511015611bef57602e610780527f45786368616e676520726573756c74656420696e20666577657220636f696e736107a0527f207468616e2065787065637465640000000000000000000000000000000000006107c0526107805061078051806107a001818260206001820306601f82010390500336823750506308c379a0610740526020610760526107805160206001820306601f820103905060440161075cfd5b60016104c051600481101561438e570260060180546107605164012a05f20080820282158284830414171561438e57905090506402540be40080820490509050670de0b6b3a764000080820282158284830414171561438e57905090506105006104c051600481101561438e57602002015180801561438e57820490509050818183011061438e578082019050905081555060006004610780527fa9059cbb000000000000000000000000000000000000000000000000000000006107a0526107806004806020846107c00101826020850160045afa5050805182019150506104e0516020826107c0010152602081019050610740516020826107c0010152602081019050806107c0526107c0505060206108606107c0516107e0600060016104c051600481101561438e5702600201545af1611d31573d600060003e3d6000fd5b61084060203d808211611d445781611d46565b805b9050905081528051602001806106c0828460045afa9050505060006106c0511115611d86576106e0516106c05181816020036008021c905090501561438e575b337f8b3e96f2b889fa771c53c981b40daf005f63f637f1869f707052d15a3dd971406104a051610780526044356107a0526104c0516107c052610740516107e0526080610780a2610740516107805260206107806000600055f35b637d49d8758118611df657336101c052611e11565b63b2fdb76f81186121815760a4358060a01c61438e576101c0525b60005461438e576001600055601a546101e05260803661020037611e3661030061337c565b61030080516102805280602001516102a05280604001516102c05280606001516102e0525061030060006004818352015b61028061030051600481101561438e57602002015160043580820282158284830414171561438e57905090506101e05180801561438e57820490509050610320526020610300510260240135610320511015611f59576030610340527f5769746864726177616c20726573756c74656420696e20666577657220636f69610360527f6e73207468616e206578706563746564000000000000000000000000000000006103805261034050610340518061036001818260206001820306601f82010390500336823750506308c379a0610300526020610320526103405160206001820306601f820103905060440161031cfd5b6103205161020061030051600481101561438e57602002015260006004610380527fa9059cbb000000000000000000000000000000000000000000000000000000006103a0526103806004806020846103c00101826020850160045afa5050805182019150506101c0516020826103c0010152602081019050610320516020826103c0010152602081019050806103c0526103c0505060206104606103c0516103e06000600161030051600481101561438e5702600201545af1612022573d600060003e3d6000fd5b61044060203d8082116120355781612037565b805b905090508152805160200180610340828460045afa90505050600061034051111561207757610360516103405181816020036008021c905090501561438e575b8151600101808352811415611e675750506101e0805160043580821061438e578082039050905081525060183360a0526080526040608020805460043580821061438e57808203905090508155506101e051601a556000337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600435610300526020610300a3337f9878ca375e106f2a43c3b599fc624568131c4c9a4ba66a14563715763be9d59d6102005161030052610220516103205261024051610340526102605161036052608036610380376101e05161040052610120610300a2610200516103005261022051610320526102405161034052610260516103605260806103006000600055f35b6318a7bd76811861219657336104a0526121b1565b634ab3a82b81186128715760a4358060a01c61438e576104a0525b60005461438e5760016000556121c86104e0613442565b6104e0516104c0526121db61056061337c565b61056080516104e05280602001516105005280604001516105205280606001516105405250600f5461056052601054610580526011546105a0526012546105c0526105605161028052610580516102a0526105a0516102c0526105c0516102e0526104e051610300526105005161032052610520516103405261054051610360526104c0516103805261226f610600613894565b610600516105e0526104e0516106005261050051610620526105205161064052610540516106605261068060006004818352015b60206106805102600401356106a05260006106a051146123ed5761060061068051600481101561438e576020020180516106a05180821061438e578082039050905081525060006004610700527fa9059cbb00000000000000000000000000000000000000000000000000000000610720526107006004806020846107400101826020850160045afa5050805182019150506104a0516020826107400101526020810190506106a0516020826107400101526020810190508061074052610740505060206107e0610740516107606000600161068051600481101561438e5702600201545af1612398573d600060003e3d6000fd5b6107c060203d8082116123ab57816123ad565b805b9050905081528051602001806106c0828460045afa9050505060006106c05111156123ed576106e0516106c05181816020036008021c905090501561438e575b81516001018083528114156122a35750506105605161028052610580516102a0526105a0516102c0526105c0516102e05261060051610300526106205161032052610640516103405261066051610360526104c051610380526124516106a0613894565b6106a051610680526080366106a037600a54600480820282158284830414171561438e5790509050600c808204905090506107205261074060006004818352015b610680516104e061074051600481101561438e57602002015180820282158284830414171561438e57905090506105e05180801561438e578204905090506107605260006107805261060061074051600481101561438e5760200201516107a0526107a051610760511161251f576107a0516107605180821061438e57808203905090506107805261253a565b610760516107a05180821061438e5780820390509050610780525b610720516107805180820282158284830414171561438e57905090506402540be400808204905090506106a061074051600481101561438e576020020152600161074051600481101561438e570260060180546106a061074051600481101561438e57602002015164012a05f20080820282158284830414171561438e57905090506402540be40080820490509050818183011061438e578082019050905081555061060061074051600481101561438e576020020180516106a061074051600481101561438e57602002015180821061438e578082039050905081525081516001018083528114156124925750506105605161028052610580516102a0526105a0516102c0526105c0516102e05261060051610300526106205161032052610640516103405261066051610360526104c0516103805261267c610760613894565b6107605161074052601a54610760526105e0516107405180821061438e57808203905090506107605180820282158284830414171561438e57905090506105e05180801561438e578204905090506001818183011061438e578082019050905061078052600161078051111561438e576084356107805111156127705760146107a0527f536c697070616765207363726577656420796f750000000000000000000000006107c0526107a0506107a051806107c001818260206001820306601f82010390500336823750506308c379a0610760526020610780526107a05160206001820306601f820103905060440161077cfd5b61076080516107805180821061438e578082039050905081525061076051601a5560183360a052608052604060802080546107805180821061438e57808203905090508155506000337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef610780516107a05260206107a0a3337fb964b72f73f5ef5bf0fdc559b2fab9a7b12a39e47817a547f1f0aee47febd6026004356107a0526024356107c0526044356107e052606435610800526106a051610820526106c051610840526106e051610860526107005161088052610680516108a052610760516108c0526101406107a0a2610780516107a05260206107a06000600055f35b63cc2b27d781186128b9576024358060801d81607f1d1861438e57610620526004356102c052610620516102e0526128aa610640613f2e565b61064051610680526020610680f35b631a4d01d281186128ce5733610640526128e9565b63081579a58118612bd9576064358060a01c61438e57610640525b6024358060801d81607f1d1861438e576106205260005461438e5760016000556004356102c052610620516102e0526129236106a0613f2e565b6106a0805161066052806020015161068052506044356106605110156129ba5760186106a0527f4e6f7420656e6f75676820636f696e732072656d6f76656400000000000000006106c0526106a0506106a051806106c001818260206001820306601f82010390500336823750506308c379a0610660526020610680526106a05160206001820306601f820103905060440161067cfd5b600161062051600481101561438e570260060180546106805164012a05f20080820282158284830414171561438e57905090506402540be40080820490509050818183011061438e5780820190509050815550601a5460043580821061438e57808203905090506106a0526106a051601a5560183360a0526080526040608020805460043580821061438e57808203905090508155506000337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6004356106c05260206106c0a360006004610700527fa9059cbb00000000000000000000000000000000000000000000000000000000610720526107006004806020846107400101826020850160045afa50508051820191505061064051602082610740010152602081019050610660516020826107400101526020810190508061074052610740505060206107e0610740516107606000600161062051600481101561438e5702600201545af1612b31573d600060003e3d6000fd5b6107c060203d808211612b445781612b46565b805b9050905081528051602001806106c0828460045afa9050505060006106c0511115612b86576106e0516106c05181816020036008021c905090501561438e575b337f5ad056f2e28a8cec232015406b843668c1e36cda598127ec3b8c59b8c72773a06004356107005261066051610720526106a051610740526060610700a2610660516107005260206107006000600055f35b633c157e648118612d5d5763f851a440610160526020610160600461017c6001545afa612c0b573d600060003e3d6000fd5b601f3d111561438e5761016051331861438e57600d5462015180818183011061438e5780820190509050421061438e574262015180818183011061438e57808201905090506024351061438e57612c63610180613442565b6101805161016052600435606480820282158284830414171561438e579050905061018052600060043511612c99576000612ca2565b620f4240600435105b1561438e57610160516101805110612cdc5761016051600a80820282158284830414171561438e5790509050610180511161438e57612d00565b6101605161018051600a80820282158284830414171561438e57905090501061438e575b61016051600b5561018051600c5542600d55602435600e557fa2b71ec6df949300b59aab36b55e189697b750119dd349fcfa8c0f779e83c254610160516101a052610180516101c052426101e0526024356102005260806101a0a1005b63551a65888118612e015763f851a440610160526020610160600461017c6001545afa612d8f573d600060003e3d6000fd5b601f3d111561438e5761016051331861438e57612dad610180613442565b610180516101605261016051600b5561016051600c5542600d5542600e557f46e22fb3709ad289f62ce63d469248536dbc78d82b84a3d7e74ad606dc2019386101605161018052426101a0526040610180a1005b6330c540858118612f5f5763154aa8f56101005230610120526020610100602461011c6001545afa612e38573d600060003e3d6000fd5b601f3d111561438e57610100518060a01c61438e5760e05261010060006004818352015b600161010051600481101561438e5702600601546101205260006101205114612f4c57600161010051600481101561438e5702600201546101405260006004610160527fa9059cbb00000000000000000000000000000000000000000000000000000000610180526101606004806020846101a00101826020850160045afa50508051820191505060e0516020826101a0010152602081019050610120516020826101a0010152602081019050806101a0526101a05050600060006101a0516101c06000610140515af1612f35573d600060003e3d6000fd5b6000600161010051600481101561438e5702600601555b8151600101808352811415612e5c575050005b6354fd4d508118612ff957610120806020808252600660e0527f76352e302e3000000000000000000000000000000000000000000000000000006101005260e0818401808280516020018083828460045afa905050508051806020830101818260206001820306601f8201039050033682375050805160200160206001820306601f82010390509050905090508101905090509050610120f35b63c66106578118613020576001600435600481101561438e57026002015460e052602060e0f35b63e2e7d2648118613047576001600435600481101561438e57026006015460e052602060e0f35b63ddca3f43811861305e57600a5460e052602060e0f35b635409491a811861307557600b5460e052602060e0f35b63b4b577ad811861308c57600c5460e052602060e0f35b632081066c81186130a357600d5460e052602060e0f35b631405228881186130ba57600e5460e052602060e0f35b6306fdde03811861315d5760e08060208082528083018060138082602082540160c060006003818352015b8260c05160200211156130f757613116565b60c05185015460c05160200285015281516001018083528114156130e5575b5050505050508051806020830101818260206001820306601f8201039050033682375050805160200160206001820306601f820103905090509050810190509050905060e0f35b6395d89b4181186132005760e08060208082528083018060168082602082540160c060006002818352015b8260c051602002111561319a576131b9565b60c05185015460c0516020028501528151600101808352811415613188575b5050505050508051806020830101818260206001820306601f8201039050033682375050805160200160206001820306601f820103905090509050810190509050905060e0f35b6370a082318118613235576004358060a01c61438e5760e052601860e05160a052608052604060802054610100526020610100f35b63dd62ed3e8118613288576004358060a01c61438e5760e0526024358060a01c61438e5761010052601960e05160a05260805260406080206101005160a052608052604060802054610120526020610120f35b6318160ddd811861329f57601a5460e052602060e0f35b633644e51581186132b657601b5460e052602060e0f35b637ecebe0081186132eb576004358060a01c61438e5760e052601c60e05160a052608052604060802054610100526020610100f35b505b60006000fd5b601860e05160a052608052604060802080546101205180821061438e578082039050905081555060186101005160a0526080526040608020805461012051818183011061438e57808201905090508155506101005160e0517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef61012051610140526020610140a3565b60803660e03761016060006004818352015b6370a0823161018052306101a0526020610180602461019c600161016051600481101561438e5702600201545afa6133cb573d600060003e3d6000fd5b601f3d111561438e5761018051600161016051600481101561438e57026006015480821061438e578082039050905060e061016051600481101561438e576020020152815160010180835281141561338e57505060e051815261010051816020015261012051816040015261014051816060015250565b600e5460e052600c546101005260e0514210613468576101005181525061357b5661357b565b600b5461012052600d54610140526101205161010051116135005761012051610120516101005180821061438e5780820390509050426101405180821061438e578082039050905080820282158284830414171561438e579050905060e0516101405180821061438e578082039050905080801561438e5782049050905080821061438e578082039050905081525061357b5661357b565b61012051610100516101205180821061438e5780820390509050426101405180821061438e578082039050905080820282158284830414171561438e579050905060e0516101405180821061438e578082039050905080801561438e57820490509050818183011061438e578082019050905081525061357b565b565b6080366101e03761026060006004818352015b60e061026051600481101561438e57602002015161016061026051600481101561438e57602002015180820282158284830414171561438e5790509050670de0b6b3a7640000808204905090506101e061026051600481101561438e57602002015281516001018083528114156135905750506101e051815261020051816020015261022051816040015261024051816060015250565b604036610180376101e060006004818352015b60206101e0510260e001516101c05261018080516101c051818183011061438e5780820190509050815250815160010180835281141561363a57505061018051613688576000815250613892565b610180516101c05261016051600480820282158284830414171561438e57905090506101e052610200600060ff818352015b6101c0516102205261026060006004818352015b6020610260510260e0015161024052610220516101c05180820282158284830414171561438e579050905061024051600480820282158284830414171561438e579050905080801561438e578204905090506102205281516001018083528114156136ce5750506101c0516101a0526101e0516101805180820282158284830414171561438e579050905060648082049050905061022051600480820282158284830414171561438e5790509050818183011061438e57808201905090506101c05180820282158284830414171561438e57905090506101e051606480821061438e57808203905090506101c05180820282158284830414171561438e579050905060648082049050905060056102205180820282158284830414171561438e5790509050818183011061438e578082019050905080801561438e578204905090506101c0526101a0516101c051116138505760016101a0516101c05180821061438e57808203905090501161387b5750506101c0518152506138925661387b565b60016101c0516101a05180821061438e57808203905090501161387b5750506101c051815250613892565b81516001018083528114156136ba57505060006000fd5b565b6102805160e0526102a051610100526102c051610120526102e0516101405261030051610160526103205161018052610340516101a052610360516101c0526138de61042061357d565b61042080516103a05280602001516103c05280604001516103e052806060015161040052506103a05160e0526103c051610100526103e0516101205261040051610140526103805161016052613935610420613627565b61042051815250565b6102a051610280511461438e5760006102a0511261438e5760046102a051121561438e576000610280511261438e57600461028051121561438e57613984610380613442565b61038051610360526102e05160e05261030051610100526103205161012052610340516101405261036051610160526139be6103a0613627565b6103a051610380526060366103a037610380516104005261036051600480820282158284830414171561438e57905090506104205261044060006004818352015b610280516104405118613a19576102c0516103c052613a4a565b6102a051610440511415613a3057613aae56613a4a565b6102e061044051600481101561438e5760200201516103c0525b6103a080516103c051818183011061438e5780820190509050815250610400516103805180820282158284830414171561438e57905090506103c051600480820282158284830414171561438e579050905080801561438e57820490509050610400525b81516001018083528114156139ff575050610400516103805180820282158284830414171561438e5790509050606480820282158284830414171561438e579050905061042051600480820282158284830414171561438e579050905080801561438e57820490509050610400526103a05161038051606480820282158284830414171561438e57905090506104205180801561438e57820490509050818183011061438e5780820190509050610440526103805161046052610480600060ff818352015b610460516103e052610460516104605180820282158284830414171561438e579050905061040051818183011061438e578082019050905060026104605180820282158284830414171561438e579050905061044051818183011061438e57808201905090506103805180821061438e578082039050905080801561438e57820490509050610460526103e0516104605111613c385760016103e0516104605180821061438e578082039050905011613c6357505061046051815250613c7a56613c63565b6001610460516103e05180821061438e578082039050905011613c6357505061046051815250613c7a565b8151600101808352811415613b7357505060006000fd5b565b6000610100511261438e57600461010051121561438e576060366101c0376101a0516102205260e051600480820282158284830414171561438e57905090506102405261026060006004818352015b61010051610260511415613ce257613d6056613cfc565b61012061026051600481101561438e5760200201516101e0525b6101c080516101e051818183011061438e5780820190509050815250610220516101a05180820282158284830414171561438e57905090506101e051600480820282158284830414171561438e579050905080801561438e57820490509050610220525b8151600101808352811415613ccb575050610220516101a05180820282158284830414171561438e5790509050606480820282158284830414171561438e579050905061024051600480820282158284830414171561438e579050905080801561438e57820490509050610220526101c0516101a051606480820282158284830414171561438e57905090506102405180801561438e57820490509050818183011061438e5780820190509050610260526101a051610280526102a0600060ff818352015b6102805161020052610280516102805180820282158284830414171561438e579050905061022051818183011061438e578082019050905060026102805180820282158284830414171561438e579050905061026051818183011061438e57808201905090506101a05180821061438e578082039050905080801561438e5782049050905061028052610200516102805111613eea576001610200516102805180821061438e578082039050905011613f1557505061028051815250613f2c56613f15565b6001610280516102005180821061438e578082039050905011613f1557505061028051815250613f2c565b8151600101808352811415613e2557505060006000fd5b565b613f39610320613442565b6103205161030052600f54610320526010546103405260115461036052601254610380526103205161052052610340516105405261036051610560526103805161058052613f8861042061337c565b61042080516105a05280602001516105c05280604001516105e052806060015161060052506105205160e0526105405161010052610560516101205261058051610140526105a051610160526105c051610180526105e0516101a052610600516101c052613ff76104a061357d565b6104a080516103a05280602001516103c05280604001516103e052806060015161040052506103a05160e0526103c051610100526103e051610120526104005161014052610300516101605261404e610440613627565b6104405161042052601a5461044052610420516102c0516104205180820282158284830414171561438e57905090506104405180801561438e5782049050905080821061438e5780820390509050610460526103005160e0526102e051610100526103a051610120526103c051610140526103e051610160526104005161018052610460516101a0526140e26104a0613c7c565b6104a05161048052600a54600480820282158284830414171561438e5790509050600c808204905090506104a0526080366104c03761054060006004818352015b6000610560526103a061054051600481101561438e576020020151610580526102e051610540511861419757610580516104605180820282158284830414171561438e57905090506104205180801561438e578204905090506104805180821061438e5780820390509050610560526141db565b61058051610580516104605180820282158284830414171561438e57905090506104205180801561438e5782049050905080821061438e5780820390509050610560525b610580516104a0516105605180820282158284830414171561438e57905090506402540be4008082049050905080821061438e57808203905090506104c061054051600481101561438e57602002015281516001018083528114156141235750506104c06102e051600481101561438e5760200201516103005160e0526102e051610100526104c051610120526104e0516101405261050051610160526105205161018052610460516101a052614293610560613c7c565b6105605180821061438e5780820390509050610540526103a06102e051600481101561438e5760200201516104805180821061438e5780820390509050670de0b6b3a764000080820282158284830414171561438e57905090506103206102e051600481101561438e57602002015180801561438e578204905090506105605261054051600180821061438e5780820390509050670de0b6b3a764000080820282158284830414171561438e57905090506103206102e051600481101561438e57602002015180801561438e5782049050905061054052610540518152610560516105405180821061438e5780820390509050816020015250565b600080fd5b61000a61439d0361000a60003961000a61439d036000f3 diff --git a/engine-tests/src/tests/sanity.rs b/engine-tests/src/tests/sanity.rs index d5e6539fa..a7f2abf9a 100644 --- a/engine-tests/src/tests/sanity.rs +++ b/engine-tests/src/tests/sanity.rs @@ -44,8 +44,10 @@ fn test_total_supply_accounting() { constructor.deployed_at(contract_address) }; - let get_total_supply = |runner: &mut utils::AuroraRunner| -> Wei { - let result = runner.call("ft_total_eth_supply_on_aurora", "aurora", Vec::new()); + let get_total_supply = |runner: &utils::AuroraRunner| -> Wei { + let result = runner + .one_shot() + .call("ft_total_eth_supply_on_aurora", "aurora", Vec::new()); let amount: u128 = String::from_utf8(result.unwrap().return_data.as_value().unwrap()) .unwrap() .replace('"', "") @@ -897,9 +899,10 @@ fn test_block_hash() { #[test] fn test_block_hash_api() { - let mut runner = utils::deploy_runner(); + let runner = utils::deploy_runner(); let block_height: u64 = 10; let outcome = runner + .one_shot() .call( "get_block_hash", "any.near", @@ -941,9 +944,12 @@ fn test_block_hash_contract() { #[test] fn test_ft_metadata() { - let mut runner = utils::deploy_runner(); + let runner = utils::deploy_runner(); let account_id: String = runner.context.signer_account_id.clone().into(); - let outcome = runner.call("ft_metadata", &account_id, Vec::new()).unwrap(); + let outcome = runner + .one_shot() + .call("ft_metadata", &account_id, Vec::new()) + .unwrap(); let metadata = serde_json::from_slice::(&outcome.return_data.as_value().unwrap()) .unwrap(); @@ -1009,6 +1015,7 @@ fn test_set_owner() { // get owner to see if the owner_id property has changed let outcome = runner + .one_shot() .call("get_owner", &aurora_account_id, vec![]) .unwrap(); @@ -1064,7 +1071,9 @@ fn test_set_upgrade_delay_blocks() { assert!(result.is_ok()); // get upgrade_delay_blocks to see if the upgrade_delay_blocks property has changed - let result = runner.call("get_upgrade_delay_blocks", &aurora_account_id, vec![]); + let result = runner + .one_shot() + .call("get_upgrade_delay_blocks", &aurora_account_id, vec![]); // check if the query goes through the standalone runner assert!(result.is_ok()); diff --git a/engine-tests/src/tests/standalone/call_tracer.rs b/engine-tests/src/tests/standalone/call_tracer.rs index 4880063a2..82acb8d10 100644 --- a/engine-tests/src/tests/standalone/call_tracer.rs +++ b/engine-tests/src/tests/standalone/call_tracer.rs @@ -247,6 +247,43 @@ fn test_trace_contract_with_precompile_sub_call() { runner.close(); } +#[test] +fn test_contract_create_too_large() { + let mut runner = standalone::StandaloneRunner::default(); + let signer = Signer::random(); + + runner.init_evm(); + + let tx_data = { + let tx_data_hex = + std::fs::read_to_string("src/tests/res/contract_data_too_large.hex").unwrap(); + hex::decode( + tx_data_hex + .strip_prefix("0x") + .unwrap_or(&tx_data_hex) + .trim(), + ) + .unwrap() + }; + let tx = aurora_engine_transactions::legacy::TransactionLegacy { + nonce: U256::zero(), + gas_price: U256::zero(), + gas_limit: u64::MAX.into(), + to: None, + value: Wei::zero(), + data: tx_data, + }; + + let mut listener = CallTracer::default(); + let standalone_result = sputnik::traced_call(&mut listener, || { + runner.submit_transaction(&signer.secret_key, tx) + }); + assert!( + standalone_result.is_err(), + "Expected contract too large error" + ); +} + #[allow(clippy::too_many_lines)] #[test] fn test_trace_precompiles_with_subcalls() { diff --git a/engine-tests/src/tests/xcc.rs b/engine-tests/src/tests/xcc.rs index 382312179..0b16e5335 100644 --- a/engine-tests/src/tests/xcc.rs +++ b/engine-tests/src/tests/xcc.rs @@ -1,5 +1,5 @@ use crate::utils::solidity::erc20::{ERC20Constructor, ERC20}; -use crate::utils::{self, AuroraRunner, ORIGIN}; +use crate::utils::{self, AuroraRunner, DEFAULT_AURORA_ACCOUNT_ID}; use aurora_engine_precompiles::xcc::{costs, cross_contract_call}; use aurora_engine_transactions::legacy::TransactionLegacy; use aurora_engine_types::account_id::AccountId; @@ -24,7 +24,7 @@ fn test_xcc_eth_gas_cost() { let mut runner = utils::deploy_runner(); runner.standalone_runner = None; let xcc_wasm_bytes = contract_bytes(); - let _res = runner.call("factory_update", ORIGIN, xcc_wasm_bytes); + let _res = runner.call("factory_update", DEFAULT_AURORA_ACCOUNT_ID, xcc_wasm_bytes); let mut signer = utils::Signer::random(); let mut baseline_signer = utils::Signer::random(); runner.context.block_height = aurora_engine::engine::ZERO_ADDRESS_FIX_HEIGHT + 1; @@ -44,7 +44,7 @@ fn test_xcc_eth_gas_cost() { ); let _res = runner.call( "factory_set_wnear_address", - ORIGIN, + DEFAULT_AURORA_ACCOUNT_ID, wnear_erc20.0.address.as_bytes().to_vec(), ); @@ -189,7 +189,7 @@ fn test_xcc_schedule_gas() { let outcome = router .call( "schedule", - ORIGIN, + DEFAULT_AURORA_ACCOUNT_ID, PromiseArgs::Create(promise).try_to_vec().unwrap(), ) .unwrap(); @@ -231,7 +231,11 @@ fn test_xcc_exec_gas() { let args = PromiseArgs::Recursive(x); let outcome = router - .call("execute", ORIGIN, args.try_to_vec().unwrap()) + .call( + "execute", + DEFAULT_AURORA_ACCOUNT_ID, + args.try_to_vec().unwrap(), + ) .unwrap(); let callback_count = args.promise_count() - 1; let router_exec_cost = costs::ROUTER_EXEC_BASE @@ -273,12 +277,18 @@ fn deploy_router() -> AuroraRunner { ..Default::default() }; + // Standalone not relevant here because this is not an Aurora Engine instance + router.standalone_runner = None; router.context.current_account_id = "some_address.aurora".parse().unwrap(); - router.context.predecessor_account_id = ORIGIN.parse().unwrap(); + router.context.predecessor_account_id = DEFAULT_AURORA_ACCOUNT_ID.parse().unwrap(); let init_args = r#"{"wnear_account": "wrap.near", "must_register": true}"#; let outcome = router - .call("initialize", ORIGIN, init_args.as_bytes().to_vec()) + .call( + "initialize", + DEFAULT_AURORA_ACCOUNT_ID, + init_args.as_bytes().to_vec(), + ) .unwrap(); assert!(outcome.used_gas < aurora_engine::xcc::INITIALIZE_GAS.as_u64()); @@ -763,6 +773,9 @@ mod workspace { .await?; assert!(result.is_success()); + let wnear_address = aurora.factory_get_wnear_address().await.unwrap().result; + assert_eq!(wnear_address, wnear_erc20.0.address); + let approve_tx = wnear_erc20.approve( cross_contract_call::ADDRESS, WNEAR_AMOUNT.into(), diff --git a/engine-tests/src/utils/mod.rs b/engine-tests/src/utils/mod.rs index 2a0087f60..b314d01be 100644 --- a/engine-tests/src/utils/mod.rs +++ b/engine-tests/src/utils/mod.rs @@ -31,20 +31,13 @@ use crate::prelude::transactions::{ use crate::prelude::{sdk, Address, Wei, H256, U256}; use crate::utils::solidity::{ContractConstructor, DeployedContract}; -// TODO(Copied from #84): Make sure that there is only one Signer after both PR are merged. -pub const ORIGIN: &str = "aurora"; +pub const DEFAULT_AURORA_ACCOUNT_ID: &str = "aurora"; pub const SUBMIT: &str = "submit"; pub const SUBMIT_WITH_ARGS: &str = "submit_with_args"; -pub const CALL: &str = "call"; -pub const DEPLOY_ERC20: &str = "deploy_erc20_token"; pub const PAUSE_PRECOMPILES: &str = "pause_precompiles"; pub const PAUSED_PRECOMPILES: &str = "paused_precompiles"; pub const RESUME_PRECOMPILES: &str = "resume_precompiles"; -pub const SET_OWNER: &str = "set_owner"; -pub const SET_UPGRADE_DELAY_BLOCKS: &str = "set_upgrade_delay_blocks"; -pub const PAUSE_CONTRACT: &str = "pause_contract"; -pub const RESUME_CONTRACT: &str = "resume_contract"; -pub const SET_KEY_MANAGER: &str = "set_key_manager"; +pub const DEFAULT_CHAIN_ID: u64 = 1_313_161_556; // NEAR localnet const CALLER_ACCOUNT_ID: &str = "some-account.near"; @@ -234,21 +227,8 @@ impl AuroraRunner { self.previous_logs = outcome.logs.clone(); if let Some(standalone_runner) = &mut self.standalone_runner { - if method_name == SUBMIT - || method_name == SUBMIT_WITH_ARGS - || method_name == CALL - || method_name == DEPLOY_ERC20 - || method_name == PAUSE_PRECOMPILES - || method_name == RESUME_PRECOMPILES - || method_name == SET_OWNER - || method_name == SET_UPGRADE_DELAY_BLOCKS - || method_name == PAUSE_CONTRACT - || method_name == RESUME_CONTRACT - || method_name == SET_KEY_MANAGER - { - standalone_runner.submit_raw(method_name, &self.context, &self.promise_results)?; - self.validate_standalone(); - } + standalone_runner.submit_raw(method_name, &self.context, &self.promise_results)?; + self.validate_standalone(); } Ok(outcome) @@ -575,11 +555,12 @@ impl Default for AuroraRunner { let runtime_config_store = RuntimeConfigStore::new(None); let runtime_config = runtime_config_store.get_config(PROTOCOL_VERSION); let wasm_config = runtime_config.wasm_config.clone(); - let origin_account_id: near_primitives::types::AccountId = ORIGIN.parse().unwrap(); + let origin_account_id: near_primitives::types::AccountId = + DEFAULT_AURORA_ACCOUNT_ID.parse().unwrap(); Self { - aurora_account_id: ORIGIN.to_string(), - chain_id: 1_313_161_556, // NEAR localnet, + aurora_account_id: DEFAULT_AURORA_ACCOUNT_ID.to_string(), + chain_id: DEFAULT_CHAIN_ID, code: ContractCode::new(evm_wasm_bytes, None), cache: MockCompiledContractCache::default(), ext: mocked_external::MockedExternalWithTrie::new(MockedExternal::default()), @@ -605,7 +586,7 @@ impl Default for AuroraRunner { fees_config: RuntimeFeesConfig::test(), current_protocol_version: u32::MAX, previous_logs: Vec::new(), - standalone_runner: None, + standalone_runner: Some(standalone::StandaloneRunner::default()), promise_results: Vec::new(), } } @@ -659,12 +640,6 @@ pub fn deploy_runner() -> AuroraRunner { assert!(result.is_ok()); - let mut standalone_runner = standalone::StandaloneRunner::default(); - standalone_runner.init_evm(); - - runner.standalone_runner = Some(standalone_runner); - runner.validate_standalone(); - runner } diff --git a/engine-tests/src/utils/standalone/mocks/mod.rs b/engine-tests/src/utils/standalone/mocks/mod.rs index 0d1f35249..f43864a57 100644 --- a/engine-tests/src/utils/standalone/mocks/mod.rs +++ b/engine-tests/src/utils/standalone/mocks/mod.rs @@ -32,10 +32,7 @@ pub fn insert_block(storage: &mut Storage, block_height: u64) { } pub fn default_env(block_height: u64) -> aurora_engine_sdk::env::Fixed { - let aurora_id: AccountId = utils::AuroraRunner::default() - .aurora_account_id - .parse() - .unwrap(); + let aurora_id: AccountId = utils::DEFAULT_AURORA_ACCOUNT_ID.parse().unwrap(); aurora_engine_sdk::env::Fixed { signer_account_id: aurora_id.clone(), current_account_id: aurora_id.clone(), diff --git a/engine-tests/src/utils/standalone/mod.rs b/engine-tests/src/utils/standalone/mod.rs index 8a41ed5f7..0663d5a30 100644 --- a/engine-tests/src/utils/standalone/mod.rs +++ b/engine-tests/src/utils/standalone/mod.rs @@ -1,13 +1,8 @@ use aurora_engine::engine; -use aurora_engine::parameters::{ - CallArgs, DeployErc20TokenArgs, PausePrecompilesCallArgs, SetOwnerArgs, - SetUpgradeDelayBlocksArgs, SubmitArgs, SubmitResult, TransactionStatus, -}; +use aurora_engine::parameters::{SubmitResult, TransactionStatus}; use aurora_engine_modexp::AuroraModExp; use aurora_engine_sdk::env::{self, Env}; use aurora_engine_transactions::legacy::{LegacyEthSignedTransaction, TransactionLegacy}; -use aurora_engine_types::borsh::BorshDeserialize; -use aurora_engine_types::parameters::engine::RelayerKeyManagerArgs; use aurora_engine_types::types::{Address, NearGas, PromiseResult, Wei}; use aurora_engine_types::{H256, U256}; use engine_standalone_storage::{ @@ -202,195 +197,46 @@ impl StandaloneRunner { env.signer_account_id = ctx.signer_account_id.as_ref().parse().unwrap(); env.prepaid_gas = NearGas::new(ctx.prepaid_gas); + let promise_data: Vec<_> = promise_results + .iter() + .map(|r| match r { + PromiseResult::Successful(bytes) => Some(bytes.clone()), + PromiseResult::Failed | PromiseResult::NotReady => None, + }) + .collect(); + let transaction_kind = engine_standalone_storage::sync::parse_transaction_kind( + method_name, + ctx.input.clone(), + &promise_data, + ) + .expect("All method names must be known by standalone"); + + let transaction_hash = if let TransactionKind::SubmitWithArgs(args) = &transaction_kind { + aurora_engine_sdk::keccak(&args.tx_data) + } else { + aurora_engine_sdk::keccak(&ctx.input) + }; + let storage = &mut self.storage; - if method_name == utils::SUBMIT { - let transaction_bytes = &ctx.input; - Self::internal_submit_transaction( - transaction_bytes, - 0, - storage, - &mut env, - &mut self.cumulative_diff, - promise_results, - ) - } else if method_name == utils::SUBMIT_WITH_ARGS { - let submit_args = SubmitArgs::try_from_slice(&ctx.input).unwrap(); - let transaction_hash = aurora_engine_sdk::keccak(&submit_args.tx_data); - let mut tx_msg = - Self::template_tx_msg(storage, &env, 0, transaction_hash, promise_results); - tx_msg.transaction = TransactionKind::SubmitWithArgs(submit_args); - - let outcome = - sync::execute_transaction_message::(storage, tx_msg).unwrap(); - self.cumulative_diff.append(outcome.diff.clone()); - storage::commit(storage, &outcome); - - unwrap_result(outcome) - } else if method_name == utils::CALL { - let call_args = CallArgs::try_from_slice(&ctx.input).unwrap(); - let transaction_hash = aurora_engine_sdk::keccak(&ctx.input); - let mut tx_msg = - Self::template_tx_msg(storage, &env, 0, transaction_hash, promise_results); - tx_msg.transaction = TransactionKind::Call(call_args); - - let outcome = - sync::execute_transaction_message::(storage, tx_msg).unwrap(); - self.cumulative_diff.append(outcome.diff.clone()); - storage::commit(storage, &outcome); - - unwrap_result(outcome) - } else if method_name == utils::DEPLOY_ERC20 { - let deploy_args = DeployErc20TokenArgs::try_from_slice(&ctx.input).unwrap(); - let transaction_hash = aurora_engine_sdk::keccak(&ctx.input); - let mut tx_msg = - Self::template_tx_msg(storage, &env, 0, transaction_hash, promise_results); - tx_msg.transaction = TransactionKind::DeployErc20(deploy_args); - - let outcome = - sync::execute_transaction_message::(storage, tx_msg).unwrap(); - self.cumulative_diff.append(outcome.diff.clone()); - storage::commit(storage, &outcome); - - let sync::TransactionExecutionResult::DeployErc20(address) = outcome.maybe_result.unwrap().unwrap() else { unreachable!() }; - - Ok(SubmitResult::new( + let mut tx_msg = Self::template_tx_msg(storage, &env, 0, transaction_hash, promise_results); + tx_msg.transaction = transaction_kind; + + let outcome = sync::execute_transaction_message::(storage, tx_msg).unwrap(); + self.cumulative_diff.append(outcome.diff.clone()); + storage::commit(storage, &outcome); + + match outcome.maybe_result.unwrap() { + Some(sync::TransactionExecutionResult::Submit(result)) => result, + Some(sync::TransactionExecutionResult::DeployErc20(address)) => Ok(SubmitResult::new( TransactionStatus::Succeed(address.raw().as_ref().to_vec()), 0, Vec::new(), - )) - } else if method_name == utils::RESUME_PRECOMPILES { - let input = &ctx.input[..]; - let call_args = PausePrecompilesCallArgs::try_from_slice(input) - .expect("Unable to parse input as PausePrecompilesCallArgs"); - - let transaction_hash = aurora_engine_sdk::keccak(&ctx.input); - let mut tx_msg = - Self::template_tx_msg(storage, &env, 0, transaction_hash, promise_results); - tx_msg.transaction = TransactionKind::ResumePrecompiles(call_args); - - let outcome = - sync::execute_transaction_message::(storage, tx_msg).unwrap(); - self.cumulative_diff.append(outcome.diff.clone()); - storage::commit(storage, &outcome); - - Ok(SubmitResult::new( - TransactionStatus::Succeed(Vec::new()), - 0, - Vec::new(), - )) - } else if method_name == utils::PAUSE_PRECOMPILES { - let input = &ctx.input[..]; - let call_args = PausePrecompilesCallArgs::try_from_slice(input) - .expect("Unable to parse input as PausePrecompilesCallArgs"); - - let transaction_hash = aurora_engine_sdk::keccak(&ctx.input); - let mut tx_msg = - Self::template_tx_msg(storage, &env, 0, transaction_hash, promise_results); - tx_msg.transaction = TransactionKind::PausePrecompiles(call_args); - - let outcome = - sync::execute_transaction_message::(storage, tx_msg).unwrap(); - self.cumulative_diff.append(outcome.diff.clone()); - storage::commit(storage, &outcome); - - Ok(SubmitResult::new( + )), + _ => Ok(SubmitResult::new( TransactionStatus::Succeed(Vec::new()), 0, Vec::new(), - )) - } else if method_name == utils::SET_OWNER { - let input = &ctx.input[..]; - let call_args = - SetOwnerArgs::try_from_slice(input).expect("Unable to parse input as SetOwnerArgs"); - - let transaction_hash = aurora_engine_sdk::keccak(&ctx.input); - let mut tx_msg = - Self::template_tx_msg(storage, &env, 0, transaction_hash, promise_results); - tx_msg.transaction = TransactionKind::SetOwner(call_args); - - let outcome = - sync::execute_transaction_message::(storage, tx_msg).unwrap(); - self.cumulative_diff.append(outcome.diff.clone()); - storage::commit(storage, &outcome); - - Ok(SubmitResult::new( - TransactionStatus::Succeed(Vec::new()), - 0, - Vec::new(), - )) - } else if method_name == utils::SET_UPGRADE_DELAY_BLOCKS { - let input = &ctx.input; - let call_args = SetUpgradeDelayBlocksArgs::try_from_slice(input) - .expect("Unable to parse input as SetUpgradeDelayBlocksArgs"); - - let transaction_hash = aurora_engine_sdk::keccak(&ctx.input); - let mut tx_msg = - Self::template_tx_msg(storage, &env, 0, transaction_hash, promise_results); - tx_msg.transaction = TransactionKind::SetUpgradeDelayBlocks(call_args); - - let outcome = - sync::execute_transaction_message::(storage, tx_msg).unwrap(); - self.cumulative_diff.append(outcome.diff.clone()); - storage::commit(storage, &outcome); - - Ok(SubmitResult::new( - TransactionStatus::Succeed(Vec::new()), - 0, - Vec::new(), - )) - } else if method_name == utils::PAUSE_CONTRACT { - let transaction_hash = aurora_engine_sdk::keccak(&ctx.input); - let mut tx_msg = - Self::template_tx_msg(storage, &env, 0, transaction_hash, promise_results); - tx_msg.transaction = TransactionKind::PauseContract; - - let outcome = - sync::execute_transaction_message::(storage, tx_msg).unwrap(); - self.cumulative_diff.append(outcome.diff.clone()); - storage::commit(storage, &outcome); - - Ok(SubmitResult::new( - TransactionStatus::Succeed(Vec::new()), - 0, - Vec::new(), - )) - } else if method_name == utils::RESUME_CONTRACT { - let transaction_hash = aurora_engine_sdk::keccak(&ctx.input); - let mut tx_msg = - Self::template_tx_msg(storage, &env, 0, transaction_hash, promise_results); - tx_msg.transaction = TransactionKind::ResumeContract; - - let outcome = - sync::execute_transaction_message::(storage, tx_msg).unwrap(); - self.cumulative_diff.append(outcome.diff.clone()); - storage::commit(storage, &outcome); - - Ok(SubmitResult::new( - TransactionStatus::Succeed(Vec::new()), - 0, - Vec::new(), - )) - } else if method_name == utils::SET_KEY_MANAGER { - let transaction_hash = aurora_engine_sdk::keccak(&ctx.input); - let call_args: RelayerKeyManagerArgs = serde_json::from_slice(&ctx.input) - .expect("Unable to parse input as RelayerKeyManagerArgs"); - - let mut tx_msg = - Self::template_tx_msg(storage, &env, 0, transaction_hash, promise_results); - tx_msg.transaction = TransactionKind::SetKeyManager(call_args); - - let outcome = - sync::execute_transaction_message::(storage, tx_msg).unwrap(); - self.cumulative_diff.append(outcome.diff.clone()); - storage::commit(storage, &outcome); - - Ok(SubmitResult::new( - TransactionStatus::Succeed(Vec::new()), - 0, - Vec::new(), - )) - } else { - panic!("Unsupported standalone method {method_name}"); + )), } } @@ -500,14 +346,16 @@ fn unwrap_result( impl Default for StandaloneRunner { fn default() -> Self { - let (storage_dir, storage) = storage::create_db(); + let (storage_dir, mut storage) = storage::create_db(); let env = mocks::default_env(0); - let chain_id = utils::AuroraRunner::default().chain_id; + storage + .set_engine_account_id(&env.current_account_id) + .unwrap(); Self { storage_dir, storage, env, - chain_id, + chain_id: utils::DEFAULT_CHAIN_ID, cumulative_diff: Diff::default(), } } diff --git a/engine-workspace/src/contract.rs b/engine-workspace/src/contract.rs index 000ba8531..f7fe70551 100644 --- a/engine-workspace/src/contract.rs +++ b/engine-workspace/src/contract.rs @@ -9,10 +9,11 @@ use crate::operation::{ CallSetKeyManager, CallSetPausedFlags, CallStageUpgrade, CallStateMigration, CallStorageDeposit, CallStorageUnregister, CallStorageWithdraw, CallSubmit, CallWithdraw, ViewAccountsCounter, ViewBalance, ViewBlockHash, ViewBridgeProver, ViewChainId, ViewCode, - ViewErc20FromNep141, ViewFtBalanceOf, ViewFtBalanceOfEth, ViewFtMetadata, - ViewFtTotalEthSupplyOnAurora, ViewFtTotalEthSupplyOnNear, ViewFtTotalSupply, ViewIsUsedProof, - ViewNep141FromErc20, ViewNonce, ViewOwner, ViewPausedFlags, ViewPausedPrecompiles, - ViewStorageAt, ViewStorageBalanceOf, ViewUpgradeIndex, ViewVersion, ViewView, + ViewErc20FromNep141, ViewFactoryWnearAddress, ViewFtBalanceOf, ViewFtBalanceOfEth, + ViewFtMetadata, ViewFtTotalEthSupplyOnAurora, ViewFtTotalEthSupplyOnNear, ViewFtTotalSupply, + ViewIsUsedProof, ViewNep141FromErc20, ViewNonce, ViewOwner, ViewPausedFlags, + ViewPausedPrecompiles, ViewStorageAt, ViewStorageBalanceOf, ViewUpgradeIndex, ViewVersion, + ViewView, }; use crate::transaction::{CallTransaction, ViewTransaction}; use aurora_engine_types::account_id::AccountId; @@ -390,6 +391,10 @@ impl EngineContract { pub fn get_accounts_counter(&self) -> ViewAccountsCounter { ViewAccountsCounter::view(&self.contract) } + + pub fn factory_get_wnear_address(&self) -> ViewFactoryWnearAddress { + ViewFactoryWnearAddress::view(&self.contract) + } } #[derive(Debug, Clone)] diff --git a/engine-workspace/src/operation.rs b/engine-workspace/src/operation.rs index 0a084694f..02507935a 100644 --- a/engine-workspace/src/operation.rs +++ b/engine-workspace/src/operation.rs @@ -78,7 +78,8 @@ impl_view_return![ (ViewErc20FromNep141 => Address, View::Erc20FromNep141, borsh), (ViewNep141FromErc20 => AccountId, View::Nep141FromErc20, borsh), (ViewPausedFlags => u8, View::PausedFlags, borsh), - (ViewAccountsCounter => u64, View::AccountsCounter, borsh) + (ViewAccountsCounter => u64, View::AccountsCounter, borsh), + (ViewFactoryWnearAddress => Address, View::FactoryWnearAddress, borsh) ]; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -181,6 +182,7 @@ pub enum View { Erc20FromNep141, Nep141FromErc20, AccountsCounter, + FactoryWnearAddress, } impl AsRef for View { @@ -210,6 +212,7 @@ impl AsRef for View { View::Erc20FromNep141 => "get_erc20_from_nep141", View::Nep141FromErc20 => "get_nep141_from_erc20", View::AccountsCounter => "get_accounts_counter", + View::FactoryWnearAddress => "factory_get_wnear_address", } } } diff --git a/engine/Cargo.toml b/engine/Cargo.toml index 70485820a..bbd34fbc0 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aurora-engine" -version = "2.10.1" +version = "2.10.2" authors.workspace = true edition.workspace = true homepage.workspace = true diff --git a/engine/src/engine.rs b/engine/src/engine.rs index b4132996c..180ca8c5d 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -128,9 +128,12 @@ impl EngineErrorKind { Self::EvmError(ExitError::CallTooDeep) => errors::ERR_CALL_TOO_DEEP, Self::EvmError(ExitError::CreateCollision) => errors::ERR_CREATE_COLLISION, Self::EvmError(ExitError::CreateContractLimit) => errors::ERR_CREATE_CONTRACT_LIMIT, + Self::EvmError(ExitError::InvalidCode(_)) => errors::ERR_INVALID_OPCODE, Self::EvmError(ExitError::OutOfOffset) => errors::ERR_OUT_OF_OFFSET, Self::EvmError(ExitError::OutOfGas) => errors::ERR_OUT_OF_GAS, Self::EvmError(ExitError::OutOfFund) => errors::ERR_OUT_OF_FUND, + Self::EvmError(ExitError::CreateEmpty) => errors::ERR_CREATE_EMPTY, + Self::EvmError(ExitError::MaxNonce) => errors::ERR_MAX_NONCE, Self::EvmFatal(ExitFatal::NotSupported) => errors::ERR_NOT_SUPPORTED, Self::EvmFatal(ExitFatal::UnhandledInterrupt) => errors::ERR_UNHANDLED_INTERRUPT, Self::EvmError(ExitError::Other(m)) | Self::EvmFatal(ExitFatal::Other(m)) => { diff --git a/engine/src/errors.rs b/engine/src/errors.rs index c2bc58e42..f1e2d1138 100644 --- a/engine/src/errors.rs +++ b/engine/src/errors.rs @@ -41,7 +41,10 @@ pub const ERR_INVALID_RANGE: &[u8; 17] = b"ERR_INVALID_RANGE"; pub const ERR_DESIGNATED_INVALID: &[u8; 22] = b"ERR_DESIGNATED_INVALID"; pub const ERR_CREATE_COLLISION: &[u8; 20] = b"ERR_CREATE_COLLISION"; pub const ERR_CREATE_CONTRACT_LIMIT: &[u8; 25] = b"ERR_CREATE_CONTRACT_LIMIT"; +pub const ERR_INVALID_OPCODE: &[u8; 18] = b"ERR_INVALID_OPCODE"; pub const ERR_OUT_OF_FUND: &[u8; 15] = b"ERR_OUT_OF_FUND"; +pub const ERR_CREATE_EMPTY: &[u8; 16] = b"ERR_CREATE_EMPTY"; +pub const ERR_MAX_NONCE: &[u8; 13] = b"ERR_MAX_NONCE"; pub const ERR_NOT_SUPPORTED: &[u8; 17] = b"ERR_NOT_SUPPORTED"; pub const ERR_UNHANDLED_INTERRUPT: &[u8; 23] = b"ERR_UNHANDLED_INTERRUPT"; pub const ERR_INCORRECT_NONCE: &[u8; 19] = b"ERR_INCORRECT_NONCE"; diff --git a/engine/src/lib.rs b/engine/src/lib.rs index bab5a84d5..5fac26883 100644 --- a/engine/src/lib.rs +++ b/engine/src/lib.rs @@ -499,6 +499,15 @@ mod contract { crate::xcc::set_wnear_address(&mut io, &Address::from_array(address)); } + /// Returns the address for the `wNEAR` ERC-20 contract in borsh format. + #[no_mangle] + pub extern "C" fn factory_get_wnear_address() { + let mut io = Runtime; + let address = aurora_engine_precompiles::xcc::state::get_wnear_address(&io); + let bytes = address.try_to_vec().sdk_expect(errors::ERR_SERIALIZE); + io.return_output(&bytes); + } + /// Create and/or fund an XCC sub-account directly (as opposed to having one be automatically /// created via the XCC precompile in the EVM). The purpose of this method is to enable /// XCC on engine instances where wrapped NEAR (WNEAR) is not bridged. @@ -609,6 +618,7 @@ mod contract { let mut io = Runtime; let mut state = state::get_state(&io).sdk_unwrap(); + require_running(&state); require_owner_only(&state, &io.predecessor_account_id()); let key_manager = @@ -629,6 +639,8 @@ mod contract { pub extern "C" fn add_relayer_key() { let mut io = Runtime; let state = state::get_state(&io).sdk_unwrap(); + + require_running(&state); require_key_manager_only(&state, &io.predecessor_account_id()); let public_key = serde_json::from_slice::(&io.read_input().to_vec()) @@ -665,6 +677,8 @@ mod contract { pub extern "C" fn remove_relayer_key() { let mut io = Runtime; let state = state::get_state(&io).sdk_unwrap(); + + require_running(&state); require_key_manager_only(&state, &io.predecessor_account_id()); let args: RelayerKeyArgs = serde_json::from_slice(&io.read_input().to_vec())