diff --git a/.catalog-info.yaml b/.catalog-info.yaml index d553cf1cb..0a8a121b1 100644 --- a/.catalog-info.yaml +++ b/.catalog-info.yaml @@ -6,6 +6,4 @@ metadata: description: Public Aurora Engine repository spec: targets: - - ./engine/.catalog-info.yaml - - ./etc/eth-contracts/.catalog-info.yaml - - ./engine-precompiles/.catalog-info.yaml + - ./**/.catalog-info.yaml diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 872563eb5..4ad0f797a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,2 +1,9 @@ -* @artob * @joshuajbouw +/engine/ @aleksuss +/engine-precompiles/ @mandreyel +/engine-sdk/ @aleksuss +/engine-standalone-storage/ @RomanHodulak +/engine-standalone-tracing/ @RomanHodulak +/engine-test-doubles/ @hskang9 +/engine-tests/ @hskang9 +/engine-transactions/ @aleksuss diff --git a/.github/workflows/contract-analysis.yml b/.github/workflows/contract-analysis.yml new file mode 100644 index 000000000..19eb0771e --- /dev/null +++ b/.github/workflows/contract-analysis.yml @@ -0,0 +1,17 @@ +--- +on: + push: + branches: + - main + - develop + pull_request: + schedule: + - cron: "30 5 * * *" + workflow_dispatch: + +name: "Contract Security Analysis" +jobs: + contract_analysis: + name: "Shared" + uses: aurora-is-near/.github/.github/workflows/contract_analysis.yml@master + secrets: inherit diff --git a/AUTHORS b/AUTHORS index 6ca08348c..5ae3acde3 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,12 +1,16 @@ -Aleksey Kladov -Andrew Bednoff -Arto Bendiken -Evgeny Kuzyakov -Evgeny Ukhanov -Frank Braun -Illia Polosukhin -Joshua J. Bouw -Kirill Abramov -Marcelo Fornet -Michael Birch -Roman Hodulak +Ahmed Ali +Aleksey Kladov +Andrew Bednoff +Arto Bendiken +Evgeny Kuzyakov +Evgeny Ukhanov +Frank Braun +Hyungsuk Kang +Illia Polosukhin +Joshua J. Bouw +Kirill Abramov +Leandro Casuso Montero +Marcelo Fornet +Michael Birch +Oleksandr Anyshchenko +Roman Hodulak diff --git a/CHANGES.md b/CHANGES.md index f12ec0c81..5dc010dcb 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,68 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [2.9.0] 2023-04-05 + +### Added + +- Enabled XCC for mainnet release by [@birchmd]. ([#694]) +- Added `set_owner` contract method which sets the owner of the contract by [@hskang9]. ([#690]) +- New variant of submit function `submit_with_args` which accepts additional arguments along with the transaction such as the max gas price a user is ready to pay by [@aleksuss]. ([#696]) +- Added the ability to create and fund XCC sub-accounts from external NEAR accounts by [@birchmd]. ([#735]) + +### Changes + +- Replaced `rjson` with `serde_json` by [@aleksuss]. ([#677]) +- Changed owner intended contract methods to now require owner or the contract itself by [@hskang9]. ([#676]) + +### Fixes + +- Fixed nonce incorrectly being incremented on an out of fund failure by [@joshuajbouw]. ([#671]) +- Fixed a check in promise results before executing cross contract calls (XCC) callbacks by [@birchmd]. ([#693]) +- Fixed a reachable panic in `receive_erc20_tokens` by [@0x3bfc]. ([#709]) +- Fixed a lack of minimum size checks when instantiating a new `EthGas` object by [@lempire123]. ([#722]) +- Fixed a lack of division by 0 checks in `EthGas::Div()` by [@lempire123]. ([#718]) +- Fixed the validation of the return of `exports:storage_remove` by [@0x3bfc]. ([#712]) +- Fixed missing account validations of NEAR account IDs by [@0x3bfc]. ([#703]) +- Fixed a reachable panic in the `exitToNear` and `exitToEthereum` precompiles if the input amount is greater than 1^128 when cast from a `U256` to `u128` by [@0x3bfc]. ([#681]) +- Fixed a reachable panic in `modExp` due to arithmetic overflow by [@0x3bfc]. ([#688]) +- Fixed the ability attaching values to Aurora specific precompiles, this no longer is possible, by [@0x3bfc]. ([#714]) +- Fixed a return error if an ecrecover signature length is not exactly 65 by [@0x3bfc]. ([#717]) +- Fixed size checks on input array passed to `exitToNear` and `exitToEthereum` precompiles by [@0x3bfc]. ([#684]) +- Fixed missing gas costs in `exitToNear` and `exitToEthereum` precompiles by [@lempire123]. ([#687]) +- Fixed a reachable panic due to out of memory in the `modExp` precompile by [@0x3bfc]. ([#689]) +- Fixed an assurance that the `sender_id` has a balance greater than the amount in `ft_transfer_call` by [@0x3bfc]. ([#708]) +- Fixed returning `0x` when a length cannot be cast as `usize` instead of returning an error in the `modExp` precompile by [@birchmd]. ([#737]) +- Miscellaneous minor fixes by [@0x3bfc]. ([#738]) + +[#671]: https://github.com/aurora-is-near/aurora-engine/pull/671 +[#677]: https://github.com/aurora-is-near/aurora-engine/pull/677 +[#693]: https://github.com/aurora-is-near/aurora-engine/pull/693 +[#694]: https://github.com/aurora-is-near/aurora-engine/pull/694 +[#690]: https://github.com/aurora-is-near/aurora-engine/pull/690 +[#676]: https://github.com/aurora-is-near/aurora-engine/pull/676 +[#709]: https://github.com/aurora-is-near/aurora-engine/pull/709 +[#722]: https://github.com/aurora-is-near/aurora-engine/pull/722 +[#718]: https://github.com/aurora-is-near/aurora-engine/pull/718 +[#696]: https://github.com/aurora-is-near/aurora-engine/pull/696 +[#712]: https://github.com/aurora-is-near/aurora-engine/pull/712 +[#703]: https://github.com/aurora-is-near/aurora-engine/pull/703 +[#681]: https://github.com/aurora-is-near/aurora-engine/pull/681 +[#688]: https://github.com/aurora-is-near/aurora-engine/pull/688 +[#714]: https://github.com/aurora-is-near/aurora-engine/pull/714 +[#717]: https://github.com/aurora-is-near/aurora-engine/pull/717 +[#684]: https://github.com/aurora-is-near/aurora-engine/pull/684 +[#687]: https://github.com/aurora-is-near/aurora-engine/pull/687 +[#689]: https://github.com/aurora-is-near/aurora-engine/pull/689 +[#708]: https://github.com/aurora-is-near/aurora-engine/pull/708 +[#737]: https://github.com/aurora-is-near/aurora-engine/pull/737 +[#735]: https://github.com/aurora-is-near/aurora-engine/pull/735 +[#738]: https://github.com/aurora-is-near/aurora-engine/pull/738 + +## [2.8.1] 2022-12-07 + +- Updated SputnikVM to v0.37.2 by [@birchmd]. ([#645]) + ## [2.8.1] 2022-12-07 ### Changes @@ -334,18 +396,18 @@ struct SubmitResult { ## [1.0.0] - 2021-05-12 -[Unreleased]: https://github.com/aurora-is-near/aurora-engine/compare/2.8.1...develop -[2.8.1]: https://github.com/aurora-is-near/aurora-engine/compare/2.8.0...2.8.1 +[Unreleased]: https://github.com/aurora-is-near/aurora-engine/compare/2.9.0...develop +[2.9.0]: https://github.com/aurora-is-near/aurora-engine/compare/2.8.0...2.9.0 [2.8.0]: https://github.com/aurora-is-near/aurora-engine/compare/2.7.0...2.8.0 [2.7.0]: https://github.com/aurora-is-near/aurora-engine/compare/2.6.1...2.7.0 -[2.6.1]: https://github.com/aurora-is-near/aurora-engine/compare/2.6.0...2.6.1 +[2.6.1]: https://github.com/aurora-is-near/aurora-engine/compare/2.6.0...2.6.1 [2.6.0]: https://github.com/aurora-is-near/aurora-engine/compare/2.5.3...2.6.0 [2.5.3]: https://github.com/aurora-is-near/aurora-engine/compare/2.5.2...2.5.3 [2.5.2]: https://github.com/aurora-is-near/aurora-engine/compare/2.5.1...2.5.2 [2.5.1]: https://github.com/aurora-is-near/aurora-engine/compare/2.5.0...2.5.1 [2.5.0]: https://github.com/aurora-is-near/aurora-engine/compare/2.4.0...2.5.0 [2.4.0]: https://github.com/aurora-is-near/aurora-engine/compare/2.3.0...2.4.0 -[2.3.0]: https://github.com/aurora-is-near/aurora-engine/compare/2.2.0...2.3.0 +[2.3.0]: https://github.com/aurora-is-near/aurora-engine/compare/2.2.0...2.3.0 [2.2.0]: https://github.com/aurora-is-near/aurora-engine/compare/2.1.0...2.2.0 [2.1.0]: https://github.com/aurora-is-near/aurora-engine/compare/2.0.2...2.1.0 [2.0.2]: https://github.com/aurora-is-near/aurora-engine/compare/2.0.1...2.0.2 @@ -367,8 +429,11 @@ struct SubmitResult { [1.1.0]: https://github.com/aurora-is-near/aurora-engine/compare/1.0.0...1.1.0 [1.0.0]: https://github.com/aurora-is-near/aurora-engine/tree/1.0.0 +[@0x3bfc]: https://github.com/0x3bfc +[@aleksuss]: https://github.com/aleksuss [@andrcmdr]: https://github.com/andrcmdr [@birchmd]: https://github.com/birchmd +[@hskang9]: https://github.com/hskang9 [@joshuajbouw]: https://github.com/joshuajbouw [@mfornet]: https://github.com/mfornet [@mrLSD]: https://github.com/mrLSD diff --git a/Cargo.lock b/Cargo.lock index d321c1287..b81ebf94c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,7 +14,16 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" dependencies = [ - "gimli", + "gimli 0.26.2", +] + +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli 0.27.1", ] [[package]] @@ -36,9 +45,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.19" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] @@ -60,9 +69,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anyhow" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" [[package]] name = "arrayref" @@ -105,9 +114,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.58" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" +checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" dependencies = [ "proc-macro2", "quote", @@ -120,33 +129,30 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] [[package]] name = "aurora-engine" -version = "2.8.1" +version = "2.9.0" dependencies = [ "aurora-engine-precompiles", "aurora-engine-sdk", "aurora-engine-test-doubles", "aurora-engine-transactions", "aurora-engine-types", - "base64", "bitflags", - "borsh", + "borsh 0.10.2", "byte-slice-cast", - "digest 0.10.5", + "digest 0.10.6", "ethabi", "evm", "hex", - "rjson", "rlp", "serde", "serde_json", - "sha3", "test-case", "wee_alloc", ] @@ -158,7 +164,7 @@ dependencies = [ "aurora-engine-sdk", "aurora-engine-test-doubles", "aurora-engine-types", - "borsh", + "borsh 0.10.2", "ethabi", "evm", "hex", @@ -178,7 +184,8 @@ name = "aurora-engine-sdk" version = "1.0.0" dependencies = [ "aurora-engine-types", - "borsh", + "base64 0.21.0", + "borsh 0.10.2", "sha2 0.10.6", "sha3", ] @@ -204,8 +211,7 @@ dependencies = [ "aurora-engine-test-doubles", "aurora-engine-transactions", "aurora-engine-types", - "base64", - "borsh", + "borsh 0.10.2", "bstr", "byte-slice-cast", "criterion", @@ -252,11 +258,13 @@ dependencies = [ name = "aurora-engine-types" version = "1.0.0" dependencies = [ - "borsh", + "borsh 0.10.2", + "borsh 0.9.3", "hex", "primitive-types 0.12.1", "rand 0.8.5", "serde", + "serde_json", ] [[package]] @@ -279,16 +287,16 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" dependencies = [ - "addr2line", + "addr2line 0.19.0", "cc", "cfg-if 1.0.0", "libc", "miniz_oxide", - "object 0.29.0", + "object 0.30.3", "rustc-demangle", ] @@ -298,6 +306,12 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "base64" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" + [[package]] name = "bincode" version = "1.3.3" @@ -309,9 +323,9 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.60.1" +version = "0.64.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "062dddbc1ba4aca46de6338e2bf87771414c335f7b2f2036e8f3e9befebf88e6" +checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4" dependencies = [ "bitflags", "cexpr", @@ -324,6 +338,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", + "syn", ] [[package]] @@ -394,18 +409,41 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" dependencies = [ - "borsh-derive", + "borsh-derive 0.9.3", "hashbrown 0.11.2", ] +[[package]] +name = "borsh" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40f9ca3698b2e4cb7c15571db0abc5551dca417a21ae8140460b50309bb2cc62" +dependencies = [ + "borsh-derive 0.10.2", + "hashbrown 0.12.3", +] + [[package]] name = "borsh-derive" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" dependencies = [ - "borsh-derive-internal", - "borsh-schema-derive-internal", + "borsh-derive-internal 0.9.3", + "borsh-schema-derive-internal 0.9.3", + "proc-macro-crate 0.1.5", + "proc-macro2", + "syn", +] + +[[package]] +name = "borsh-derive" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598b3eacc6db9c3ee57b22707ad8f6a8d2f6d442bfe24ffeb8cbb70ca59e6a35" +dependencies = [ + "borsh-derive-internal 0.10.2", + "borsh-schema-derive-internal 0.10.2", "proc-macro-crate 0.1.5", "proc-macro2", "syn", @@ -422,6 +460,17 @@ dependencies = [ "syn", ] +[[package]] +name = "borsh-derive-internal" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186b734fa1c9f6743e90c95d7233c9faab6360d1a96d4ffa19d9cfd1e9350f8a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "borsh-schema-derive-internal" version = "0.9.3" @@ -433,6 +482,17 @@ dependencies = [ "syn", ] +[[package]] +name = "borsh-schema-derive-internal" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99b7ff1008316626f485991b960ade129253d4034014616b94f309a15366cc49" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "bs58" version = "0.4.0" @@ -441,9 +501,9 @@ checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] name = "bstr" -version = "1.0.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fca0852af221f458706eb0725c03e4ed6c46af9ac98e6a689d5e634215d594dd" +checksum = "b7f0778972c64420fdedc63f09919c8a88bda7b25135357fd25a5d9f3257e832" dependencies = [ "memchr", "once_cell", @@ -453,9 +513,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "byte-slice-cast" @@ -492,9 +552,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.2.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "bytesize" @@ -534,9 +594,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.74" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581f5dba903aac52ea3feb5ec4810848460ee833876f1f9b0fdeab1f19091574" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" dependencies = [ "jobserver", ] @@ -564,16 +624,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.22" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" dependencies = [ "iana-time-zone", "js-sys", "num-integer", "num-traits", "serde", - "time 0.1.44", + "time 0.1.45", "wasm-bindgen", "winapi", ] @@ -648,7 +708,7 @@ version = "3.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" dependencies = [ - "heck 0.4.0", + "heck 0.4.1", "proc-macro-error", "proc-macro2", "quote", @@ -738,11 +798,11 @@ dependencies = [ "cranelift-codegen-meta", "cranelift-codegen-shared", "cranelift-entity", - "gimli", + "gimli 0.26.2", "log", "regalloc2", "smallvec", - "target-lexicon 0.12.4", + "target-lexicon 0.12.5", ] [[package]] @@ -778,7 +838,7 @@ dependencies = [ "cranelift-codegen", "log", "smallvec", - "target-lexicon 0.12.4", + "target-lexicon 0.12.5", ] [[package]] @@ -789,7 +849,7 @@ checksum = "bba027cc41bf1d0eee2ddf16caba2ee1be682d0214520fff0129d2c6557fda89" dependencies = [ "cranelift-codegen", "libc", - "target-lexicon 0.12.4", + "target-lexicon 0.12.5", ] [[package]] @@ -890,22 +950,22 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.11" +version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" dependencies = [ "autocfg", "cfg-if 1.0.0", "crossbeam-utils", - "memoffset", + "memoffset 0.7.1", "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -913,9 +973,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ "cfg-if 1.0.0", ] @@ -961,9 +1021,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.80" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a" +checksum = "bc831ee6a32dd495436e317595e639a587aa9907bef96fe6e6abc290ab6204e9" dependencies = [ "cc", "cxxbridge-flags", @@ -973,9 +1033,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.80" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827" +checksum = "94331d54f1b1a8895cd81049f7eaaaef9d05a7dcb4d1fd08bf3ff0806246789d" dependencies = [ "cc", "codespan-reporting", @@ -988,15 +1048,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.80" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a" +checksum = "48dcd35ba14ca9b40d6e4b4b39961f23d835dbb8eed74565ded361d93e1feb8a" [[package]] name = "cxxbridge-macro" -version = "1.0.80" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7" +checksum = "81bbeb29798b407ccd82a3324ade1a7286e0d29851475990b612670f6f5124d2" dependencies = [ "proc-macro2", "quote", @@ -1005,9 +1065,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa" +checksum = "c0808e1bd8671fb44a113a14e13497557533369847788fa2ae912b6ebfce9fa8" dependencies = [ "darling_core", "darling_macro", @@ -1015,9 +1075,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f" +checksum = "001d80444f28e193f30c2f293455da62dcf9a6b29918a4253152ae2b1de592cb" dependencies = [ "fnv", "ident_case", @@ -1028,9 +1088,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e" +checksum = "b36230598a2d5de7ec1c6f51f72d8a99a9208daff41de2084d06e3fd3ea56685" dependencies = [ "darling_core", "quote", @@ -1070,9 +1130,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer 0.10.3", "crypto-common", @@ -1113,9 +1173,9 @@ checksum = "53aff6fdc1b181225acdcb5b14c47106726fd8e486707315b1b138baed68ee31" [[package]] name = "ed25519" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369" +checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" dependencies = [ "signature", ] @@ -1136,9 +1196,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "elastic-array" @@ -1158,8 +1218,7 @@ dependencies = [ "aurora-engine-sdk", "aurora-engine-transactions", "aurora-engine-types", - "base64", - "borsh", + "borsh 0.10.2", "evm-core", "hex", "postgres", @@ -1183,18 +1242,18 @@ dependencies = [ [[package]] name = "enum-map" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5a56d54c8dd9b3ad34752ed197a4eb2a6601bc010808eb097a04a58ae4c43e1" +checksum = "50c25992259941eb7e57b936157961b217a4fc8597829ddef0596d6c3cd86e1a" dependencies = [ "enum-map-derive", ] [[package]] name = "enum-map-derive" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9045e2676cd5af83c3b167d917b0a5c90a4d8e266e2683d6631b235c457fc27" +checksum = "2a4da76b3b6116d758c7ba93f7ec6a35d2e2cf24feda76c6e38a375f4d5c59f2" dependencies = [ "proc-macro2", "quote", @@ -1224,9 +1283,9 @@ dependencies = [ [[package]] name = "environmental" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b91989ae21441195d7d9b9993a2f9295c7e1a8c96255d8b729accddc124797" +checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" [[package]] name = "errno" @@ -1301,9 +1360,9 @@ dependencies = [ [[package]] name = "ethereum-types" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81224dc661606574f5a0f28c9947d0ee1d93ff11c5f1c4e7272f52e8c0b5483c" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" dependencies = [ "ethbloom", "fixed-hash 0.8.0", @@ -1318,7 +1377,7 @@ dependencies = [ [[package]] name = "evm" version = "0.37.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.37.3-aurora#ad17d1c242356e25692573a5eea4b50ee80f6de3" +source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.37.4-aurora#a7a0fb429d5fd479aecaa51687cad1f818772051" dependencies = [ "auto_impl", "environmental", @@ -1338,7 +1397,7 @@ dependencies = [ [[package]] name = "evm-core" version = "0.37.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.37.3-aurora#ad17d1c242356e25692573a5eea4b50ee80f6de3" +source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.37.4-aurora#a7a0fb429d5fd479aecaa51687cad1f818772051" dependencies = [ "parity-scale-codec", "primitive-types 0.12.1", @@ -1349,7 +1408,7 @@ dependencies = [ [[package]] name = "evm-gasometer" version = "0.37.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.37.3-aurora#ad17d1c242356e25692573a5eea4b50ee80f6de3" +source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.37.4-aurora#a7a0fb429d5fd479aecaa51687cad1f818772051" dependencies = [ "environmental", "evm-core", @@ -1360,7 +1419,7 @@ dependencies = [ [[package]] name = "evm-runtime" version = "0.37.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.37.3-aurora#ad17d1c242356e25692573a5eea4b50ee80f6de3" +source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.37.4-aurora#a7a0fb429d5fd479aecaa51687cad1f818772051" dependencies = [ "auto_impl", "environmental", @@ -1436,12 +1495,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "fs_extra" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" - [[package]] name = "funty" version = "1.1.0" @@ -1456,9 +1509,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" dependencies = [ "futures-channel", "futures-core", @@ -1470,9 +1523,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", "futures-sink", @@ -1480,15 +1533,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-executor" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" dependencies = [ "futures-core", "futures-task", @@ -1497,15 +1550,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" [[package]] name = "futures-macro" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ "proc-macro2", "quote", @@ -1514,21 +1567,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-util" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ "futures-channel", "futures-core", @@ -1603,11 +1656,17 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "gimli" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "221996f774192f0f718773def8201c4ae31f02616a54ccfc2d358bb0e5cefdec" + [[package]] name = "git2" -version = "0.15.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2994bee4a3a6a51eb90c218523be382fd7ea09b16380b9312e9dbe955ff7c7d1" +checksum = "ccf7f68c2995f392c49fffb4f95ae2c873297830eb25c6bc4c114ce8f4562acc" dependencies = [ "bitflags", "libc", @@ -1620,9 +1679,9 @@ dependencies = [ [[package]] name = "glob" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "h2" @@ -1639,7 +1698,7 @@ dependencies = [ "indexmap", "slab", "tokio", - "tokio-util 0.7.4", + "tokio-util 0.7.5", "tracing", ] @@ -1702,9 +1761,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" @@ -1715,6 +1774,15 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + [[package]] name = "hex" version = "0.4.3" @@ -1740,7 +1808,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -1790,9 +1858,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" -version = "0.14.22" +version = "0.14.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abfba89e19b959ca163c7752ba59d737c1ceea53a5d31a149c805446fc958064" +checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" dependencies = [ "bytes", "futures-channel", @@ -1910,9 +1978,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", "hashbrown 0.12.3", @@ -1945,9 +2013,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "jobserver" @@ -1960,24 +2028,27 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] [[package]] name = "keccak" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838" +checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" +dependencies = [ + "cpufeatures", +] [[package]] name = "lazy-static-include" -version = "3.1.2" +version = "3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e559d5071cbb9743796593a892d96a7cc411d90aad711f57cc7dcbbf3893c10c" +checksum = "b1c2e13f42790900c1a0736b66f8bfbf99d02ee9fb9c54571c9f2d1d4891bfb0" dependencies = [ "lazy_static", "manifest-dir-macros", @@ -2007,15 +2078,15 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.137" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libgit2-sys" -version = "0.14.0+1.5.0" +version = "0.14.2+1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47a00859c70c8a4f7218e6d1cc32875c4b55f6799445b842b0d8ed5e4c3d959b" +checksum = "7f3d95f6b51075fe9810a7ae22c7095f12b98005ab364d8544797a825ce946a4" dependencies = [ "cc", "libc", @@ -2027,9 +2098,9 @@ dependencies = [ [[package]] name = "libloading" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ "cfg-if 1.0.0", "winapi", @@ -2037,9 +2108,9 @@ dependencies = [ [[package]] name = "librocksdb-sys" -version = "0.8.0+7.4.4" +version = "0.8.3+7.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "611804e4666a25136fcc5f8cf425ab4d26c7f74ea245ffe92ea23b85b6420b5d" +checksum = "557b255ff04123fcc176162f56ed0c9cd42d8f357cf55b3fabeb60f7413741b3" dependencies = [ "bindgen", "bzip2-sys", @@ -2058,7 +2129,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" dependencies = [ "arrayref", - "base64", + "base64 0.13.1", "digest 0.9.0", "hmac-drbg", "libsecp256k1-core", @@ -2127,9 +2198,9 @@ dependencies = [ [[package]] name = "link-cplusplus" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" dependencies = [ "cc", ] @@ -2233,7 +2304,7 @@ version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" dependencies = [ - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -2254,9 +2325,9 @@ dependencies = [ [[package]] name = "memmap2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498" +checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc" dependencies = [ "libc", ] @@ -2270,6 +2341,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + [[package]] name = "memory_units" version = "0.4.0" @@ -2284,9 +2364,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.5.4" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" dependencies = [ "adler", ] @@ -2300,7 +2380,7 @@ dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -2320,7 +2400,7 @@ name = "near-account-id" version = "0.0.0" source = "git+https://github.com/birchmd/nearcore.git?rev=6033903be2037d67510188450f289b2d6e033f04#6033903be2037d67510188450f289b2d6e033f04" dependencies = [ - "borsh", + "borsh 0.9.3", "serde", ] @@ -2357,7 +2437,7 @@ source = "git+https://github.com/birchmd/nearcore.git?rev=6033903be2037d67510188 dependencies = [ "arrayref", "blake2", - "borsh", + "borsh 0.9.3", "bs58", "c2-chacha", "curve25519-dalek", @@ -2402,7 +2482,7 @@ name = "near-pool" version = "0.0.0" source = "git+https://github.com/birchmd/nearcore.git?rev=6033903be2037d67510188450f289b2d6e033f04#6033903be2037d67510188450f289b2d6e033f04" dependencies = [ - "borsh", + "borsh 0.9.3", "near-crypto", "near-o11y", "near-primitives", @@ -2415,7 +2495,7 @@ name = "near-primitives" version = "0.0.0" source = "git+https://github.com/birchmd/nearcore.git?rev=6033903be2037d67510188450f289b2d6e033f04#6033903be2037d67510188450f289b2d6e033f04" dependencies = [ - "borsh", + "borsh 0.9.3", "byteorder", "bytesize", "cfg-if 1.0.0", @@ -2444,8 +2524,8 @@ name = "near-primitives-core" version = "0.0.0" source = "git+https://github.com/birchmd/nearcore.git?rev=6033903be2037d67510188450f289b2d6e033f04#6033903be2037d67510188450f289b2d6e033f04" dependencies = [ - "base64", - "borsh", + "base64 0.13.1", + "borsh 0.9.3", "bs58", "derive_more", "near-account-id", @@ -2481,8 +2561,8 @@ name = "near-sdk" version = "3.1.0" source = "git+https://github.com/aurora-is-near/near-sdk-rs.git?rev=a4634850023fd115053970f17e10861779d5167d#a4634850023fd115053970f17e10861779d5167d" dependencies = [ - "base64", - "borsh", + "base64 0.13.1", + "borsh 0.9.3", "bs58", "near-primitives-core", "near-sdk-macros", @@ -2543,7 +2623,7 @@ version = "0.0.0" source = "git+https://github.com/birchmd/nearcore.git?rev=6033903be2037d67510188450f289b2d6e033f04#6033903be2037d67510188450f289b2d6e033f04" dependencies = [ "anyhow", - "borsh", + "borsh 0.9.3", "byteorder", "bytesize", "crossbeam", @@ -2574,7 +2654,7 @@ name = "near-vm-errors" version = "0.0.0" source = "git+https://github.com/birchmd/nearcore.git?rev=6033903be2037d67510188450f289b2d6e033f04#6033903be2037d67510188450f289b2d6e033f04" dependencies = [ - "borsh", + "borsh 0.9.3", "near-account-id", "near-rpc-error-macro", "serde", @@ -2586,7 +2666,7 @@ name = "near-vm-logic" version = "0.0.0" source = "git+https://github.com/birchmd/nearcore.git?rev=6033903be2037d67510188450f289b2d6e033f04#6033903be2037d67510188450f289b2d6e033f04" dependencies = [ - "borsh", + "borsh 0.9.3", "bs58", "byteorder", "ed25519-dalek", @@ -2609,9 +2689,9 @@ version = "0.0.0" source = "git+https://github.com/birchmd/nearcore.git?rev=6033903be2037d67510188450f289b2d6e033f04#6033903be2037d67510188450f289b2d6e033f04" dependencies = [ "anyhow", - "borsh", + "borsh 0.9.3", "loupe", - "memoffset", + "memoffset 0.6.5", "near-cache", "near-primitives", "near-stable-hasher", @@ -2653,7 +2733,7 @@ name = "node-runtime" version = "0.0.0" source = "git+https://github.com/birchmd/nearcore.git?rev=6033903be2037d67510188450f289b2d6e033f04#6033903be2037d67510188450f289b2d6e033f04" dependencies = [ - "borsh", + "borsh 0.9.3", "byteorder", "hex", "near-chain-configs", @@ -2679,14 +2759,23 @@ dependencies = [ [[package]] name = "nom" -version = "7.1.1" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", ] +[[package]] +name = "nom8" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" +dependencies = [ + "memchr", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -2735,9 +2824,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" +checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" dependencies = [ "num-traits", ] @@ -2799,20 +2888,11 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_threads" -version = "0.1.6" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ + "hermit-abi 0.2.6", "libc", ] @@ -2830,18 +2910,18 @@ dependencies = [ [[package]] name = "object" -version = "0.29.0" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" [[package]] name = "oorandom" @@ -2863,9 +2943,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.77" +version = "0.9.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03b84c3b2d099b81f0953422b4d4ad58761589d0229b5506356afca05a3670a" +checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" dependencies = [ "autocfg", "cc", @@ -2924,9 +3004,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.3.1" +version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3baf96e39c5359d2eb0dd6ccb42c62b91d9678aa68160d261b9e0ccbf9e9dea9" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" [[package]] name = "overload" @@ -2946,9 +3026,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.2.1" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "366e44391a8af4cfd6002ef6ba072bae071a96aafca98d7d448a34c5dca38b6a" +checksum = "c3840933452adf7b3b9145e27086a5a3376c619dca1a21b1e5a5af0d54979bed" dependencies = [ "arrayvec 0.7.2", "bitvec", @@ -2960,11 +3040,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.1.3" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9299338969a3d2f491d65f140b00ddec470858402f888af98e8642fb5e8965cd" +checksum = "86b26a931f824dd4eca30b3e43bb4f31cd5f0d3a403c5f5ff27106b805bfde7b" dependencies = [ - "proc-macro-crate 1.2.1", + "proc-macro-crate 1.3.0", "proc-macro2", "quote", "syn", @@ -2989,7 +3069,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" dependencies = [ "lock_api 0.3.4", - "parking_lot_core 0.7.2", + "parking_lot_core 0.7.3", ] [[package]] @@ -2999,14 +3079,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api 0.4.9", - "parking_lot_core 0.9.4", + "parking_lot_core 0.9.7", ] [[package]] name = "parking_lot_core" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" +checksum = "b93f386bb233083c799e6e642a9d73db98c24a5deeb95ffc85bf281255dffc98" dependencies = [ "cfg-if 0.1.10", "cloudabi", @@ -3018,22 +3098,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.4" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall 0.2.16", "smallvec", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] name = "paste" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" +checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" [[package]] name = "peeking_take_while" @@ -3049,9 +3129,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "petgraph" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" +checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" dependencies = [ "fixedbitset", "indexmap", @@ -3161,7 +3241,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "878c6cbf956e03af9aa8204b407b9cbf47c072164800aa918c516cd4b056c50c" dependencies = [ - "base64", + "base64 0.13.1", "byteorder", "bytes", "fallible-iterator", @@ -3186,9 +3266,9 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "primitive-types" @@ -3225,13 +3305,12 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" +checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" dependencies = [ "once_cell", - "thiserror", - "toml", + "toml_edit", ] [[package]] @@ -3260,9 +3339,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] @@ -3383,9 +3462,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] @@ -3469,21 +3548,19 @@ dependencies = [ [[package]] name = "rayon" -version = "1.5.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" dependencies = [ - "autocfg", - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.9.3" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -3529,9 +3606,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", @@ -3549,9 +3626,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.27" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "region" @@ -3601,14 +3678,9 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" dependencies = [ - "digest 0.10.5", + "digest 0.10.6", ] -[[package]] -name = "rjson" -version = "0.3.2" -source = "git+https://github.com/aurora-is-near/rjson?rev=cc3da949#cc3da9495e7e520900d66d2b517539f74fff93cf" - [[package]] name = "rkyv" version = "0.7.39" @@ -3708,7 +3780,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.14", + "semver 1.0.16", ] [[package]] @@ -3727,15 +3799,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" +checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" [[package]] name = "ryu" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "same-file" @@ -3748,9 +3820,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d8a765117b237ef233705cc2cc4c6a27fccd46eea6ef0c8c6dae5f3ef407f8" +checksum = "001cf62ece89779fd16105b5f515ad0e5cedcd5440d3dd806bb067978e7c3608" dependencies = [ "bitvec", "cfg-if 1.0.0", @@ -3761,11 +3833,11 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdcd47b380d8c4541044e341dcd9475f55ba37ddc50c908d945fc036a8642496" +checksum = "303959cf613a6f6efd19ed4b4ad5bf79966a13352716299ad532cfb115f4205c" dependencies = [ - "proc-macro-crate 1.2.1", + "proc-macro-crate 1.3.0", "proc-macro2", "quote", "syn", @@ -3779,9 +3851,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scratch" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" [[package]] name = "seahash" @@ -3791,9 +3863,9 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" [[package]] name = "secp256k1" -version = "0.24.1" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff55dc09d460954e9ef2fa8a7ced735a964be9981fd50e870b2b3b0705e14964" +checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" dependencies = [ "rand 0.8.5", "secp256k1-sys", @@ -3819,9 +3891,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" [[package]] name = "semver-parser" @@ -3831,9 +3903,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.147" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" dependencies = [ "serde_derive", ] @@ -3850,18 +3922,18 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.7" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b" +checksum = "416bda436f9aab92e02c8e10d49a15ddd339cea90b6e340fe51ed97abb548294" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.147" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", @@ -3870,9 +3942,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.87" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ "itoa", "ryu", @@ -3881,9 +3953,9 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca" +checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" dependencies = [ "proc-macro2", "quote", @@ -3911,7 +3983,7 @@ checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.5", + "digest 0.10.6", ] [[package]] @@ -3920,7 +3992,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9" dependencies = [ - "digest 0.10.5", + "digest 0.10.6", "keccak", ] @@ -4051,7 +4123,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ - "heck 0.4.0", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", @@ -4066,9 +4138,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.103" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", @@ -4101,9 +4173,9 @@ checksum = "ab0e7238dcc7b40a7be719a25365910f6807bd864f4cce6b2e6b873658e2b19d" [[package]] name = "target-lexicon" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1" +checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d" [[package]] name = "tempfile" @@ -4121,9 +4193,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] @@ -4158,18 +4230,18 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", @@ -4187,20 +4259,19 @@ dependencies = [ [[package]] name = "tikv-jemalloc-sys" -version = "0.5.2+5.3.0-patched" +version = "0.5.3+5.3.0-patched" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec45c14da997d0925c7835883e4d5c181f196fa142f8c19d7643d1e9af2592c3" +checksum = "a678df20055b43e57ef8cddde41cdfda9a3c1a060b67f4c5836dfb1d78543ba8" dependencies = [ "cc", - "fs_extra", "libc", ] [[package]] name = "time" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" dependencies = [ "libc", "wasi 0.10.0+wasi-snapshot-preview1", @@ -4209,13 +4280,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fab5c8b9980850e06d92ddbe3ab839c062c801f3927c0fb8abd6fc8e918fbca" +checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" dependencies = [ "itoa", - "libc", - "num_threads", "serde", "time-core", "time-macros", @@ -4229,9 +4298,9 @@ checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" [[package]] name = "time-macros" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bb801831d812c562ae7d2bfb531f26e66e4e1f6b17307ba4149c5064710e5b" +checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" dependencies = [ "time-core", ] @@ -4266,15 +4335,15 @@ dependencies = [ [[package]] name = "tinyvec_macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.21.2" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" +checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" dependencies = [ "autocfg", "bytes", @@ -4287,7 +4356,7 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "winapi", + "windows-sys 0.42.0", ] [[package]] @@ -4302,9 +4371,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.8.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" dependencies = [ "proc-macro2", "quote", @@ -4332,7 +4401,7 @@ dependencies = [ "postgres-types", "socket2", "tokio", - "tokio-util 0.7.4", + "tokio-util 0.7.5", ] [[package]] @@ -4362,9 +4431,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +checksum = "7e267c18a719545b481171952a79f8c25c80361463ba44bc7fa9eba7c742ef4f" dependencies = [ "bytes", "futures-core", @@ -4376,13 +4445,30 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" + +[[package]] +name = "toml_edit" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" +dependencies = [ + "indexmap", + "nom8", + "toml_datetime", +] + [[package]] name = "tonic" version = "0.6.2" @@ -4391,7 +4477,7 @@ checksum = "ff08f4649d10a70ffa3522ca559031285d8e421d727ac85c60825761818f5d0a" dependencies = [ "async-stream", "async-trait", - "base64", + "base64 0.13.1", "bytes", "futures-core", "futures-util", @@ -4440,7 +4526,7 @@ dependencies = [ "rand 0.8.5", "slab", "tokio", - "tokio-util 0.7.4", + "tokio-util 0.7.5", "tower-layer", "tower-service", "tracing", @@ -4478,7 +4564,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e" dependencies = [ "crossbeam-channel", - "time 0.3.16", + "time 0.3.17", "tracing-subscriber", ] @@ -4568,21 +4654,21 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "typenum" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "uint" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a45526d29728d135c2900b0d30573fe3ee79fceb12ef534c7bb30e810a91b601" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" dependencies = [ "byteorder", "crunchy", @@ -4592,15 +4678,15 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" [[package]] name = "unicode-ident" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unicode-normalization" @@ -4613,9 +4699,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" @@ -4731,9 +4817,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -4741,9 +4827,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", "log", @@ -4756,9 +4842,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4766,9 +4852,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", @@ -4779,9 +4865,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "wasmer-compiler-near" @@ -4792,7 +4878,7 @@ dependencies = [ "enumset", "rkyv", "smallvec", - "target-lexicon 0.12.4", + "target-lexicon 0.12.5", "thiserror", "wasmer-types-near", "wasmer-vm-near", @@ -4809,7 +4895,7 @@ dependencies = [ "dynasm", "dynasmrt", "lazy_static", - "memoffset", + "memoffset 0.6.5", "more-asserts", "rayon", "smallvec", @@ -4830,7 +4916,7 @@ dependencies = [ "memmap2", "more-asserts", "rustc-demangle", - "target-lexicon 0.12.4", + "target-lexicon 0.12.5", "thiserror", "wasmer-compiler-near", "wasmer-types-near", @@ -4864,7 +4950,7 @@ checksum = "5a3fac37da3c625e98708c5dd92d3f642aaf700fd077168d3d0fff277ec6a165" dependencies = [ "bincode", "blake3", - "borsh", + "borsh 0.9.3", "cc", "digest 0.8.1", "errno", @@ -4907,7 +4993,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f6edd0ba6c0bcf9b279186d4dbe81649dda3e5ef38f586865943de4dcd653f8" dependencies = [ "bincode", - "borsh", + "borsh 0.9.3", "byteorder", "dynasm", "dynasmrt", @@ -4942,7 +5028,7 @@ dependencies = [ "cfg-if 1.0.0", "indexmap", "libc", - "memoffset", + "memoffset 0.6.5", "more-asserts", "region 3.0.0", "rkyv", @@ -4998,7 +5084,7 @@ dependencies = [ "psm", "region 2.2.0", "serde", - "target-lexicon 0.12.4", + "target-lexicon 0.12.5", "wasmparser 0.84.0", "wasmtime-cranelift", "wasmtime-environ", @@ -5019,11 +5105,11 @@ dependencies = [ "cranelift-frontend", "cranelift-native", "cranelift-wasm", - "gimli", + "gimli 0.26.2", "log", "more-asserts", "object 0.28.4", - "target-lexicon 0.12.4", + "target-lexicon 0.12.5", "thiserror", "wasmparser 0.84.0", "wasmtime-environ", @@ -5037,13 +5123,13 @@ checksum = "4201389132ec467981980549574b33fc70d493b40f2c045c8ce5c7b54fbad97e" dependencies = [ "anyhow", "cranelift-entity", - "gimli", + "gimli 0.26.2", "indexmap", "log", "more-asserts", "object 0.28.4", "serde", - "target-lexicon 0.12.4", + "target-lexicon 0.12.5", "thiserror", "wasmparser 0.84.0", "wasmtime-types", @@ -5055,19 +5141,19 @@ version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1587ca7752d00862faa540d00fd28e5ccf1ac61ba19756449193f1153cb2b127" dependencies = [ - "addr2line", + "addr2line 0.17.0", "anyhow", "bincode", "cfg-if 1.0.0", "cpp_demangle", - "gimli", + "gimli 0.26.2", "log", "object 0.28.4", "region 2.2.0", "rustc-demangle", "rustix", "serde", - "target-lexicon 0.12.4", + "target-lexicon 0.12.5", "thiserror", "wasmtime-environ", "wasmtime-runtime", @@ -5097,7 +5183,7 @@ dependencies = [ "libc", "log", "mach", - "memoffset", + "memoffset 0.6.5", "more-asserts", "rand 0.8.5", "region 2.2.0", @@ -5122,9 +5208,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" dependencies = [ "js-sys", "wasm-bindgen", @@ -5144,9 +5230,9 @@ dependencies = [ [[package]] name = "which" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" dependencies = [ "either", "libc", @@ -5199,53 +5285,77 @@ dependencies = [ "windows_x86_64_msvc", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" [[package]] name = "windows_aarch64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" [[package]] name = "windows_i686_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" [[package]] name = "windows_i686_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" [[package]] name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" [[package]] name = "windows_x86_64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] name = "wyz" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b31594f29d27036c383b53b59ed3476874d518f0efb151b27a4c275141390e" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" dependencies = [ "tap", ] @@ -5261,9 +5371,9 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.3.2" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" +checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" dependencies = [ "proc-macro2", "quote", @@ -5277,7 +5387,7 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e61de68ede9ffdd69c01664f65a178c5188b73f78faa21f0936016a888ff7c" dependencies = [ - "borsh", + "borsh 0.9.3", "byteorder", "crunchy", "lazy_static", @@ -5287,10 +5397,11 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.1+zstd.1.5.2" +version = "2.0.6+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b" +checksum = "68a3f9792c0c3dc6c165840a75f47ae1f4da402c2d006881129579f6597e801b" dependencies = [ "cc", "libc", + "pkg-config", ] diff --git a/Makefile.toml b/Makefile.toml index 460ba56a5..c175226ee 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -85,6 +85,55 @@ args = [ "--", "-D", "warnings", + "-D", + "clippy::as_conversions", +] + +[tasks.clippy-contract] +category = "Check" +command = "${CARGO}" +args = [ + "clippy", + "--all-targets", + "--features", + "contract", + "--", + "-D", + "warnings", + "-D", + "clippy::as_conversions", +] + +[tasks.clippy-contract-refund] +category = "Check" +command = "${CARGO}" +args = [ + "clippy", + "--all-targets", + "--features", + "contract,error_refund", + "--", + "-D", + "warnings", + "-D", + "clippy::as_conversions", +] + +[tasks.clippy-borsh-compat] +category = "Check" +command = "${CARGO}" +args = [ + "clippy", + "-p", + "aurora-engine-types", + "--all-targets", + "--features", + "borsh-compat", + "--", + "-D", + "warnings", + "-D", + "clippy::as_conversions", ] [tasks.check-fmt] @@ -110,6 +159,9 @@ dependencies = [ "check-contracts", "check-fmt", "clippy", + "clippy-contract", + "clippy-contract-refund", + "clippy-borsh-compat", "udeps", ] diff --git a/README.md b/README.md index 46d05e8ce..44d271120 100644 --- a/README.md +++ b/README.md @@ -142,103 +142,6 @@ required: cargo make clean ``` -## Deployment - -### Downloading the latest EVM release - -```sh -wget https://github.com/aurora-is-near/aurora-engine/releases/download/latest/mainnet-release.wasm -``` - -### Installing the Aurora CLI tool - -```sh -npm install -g aurora-is-near/aurora-cli -``` - -### Deploying the EVM with the CLI - -```sh -export NEAR_ENV=local -near delete aurora.test.near test.near # if needed -near create-account aurora.test.near --master-account=test.near --initial-balance 1000000 -aurora install --chain 1313161556 --owner test.near bin/mainnet-release.wasm -``` - -### Deploying the EVM without the CLI - -```sh -export NEAR_ENV=local -near delete aurora.test.near test.near # if needed -near create-account aurora.test.near --master-account=test.near --initial-balance 1000000 -near deploy --account-id=aurora.test.near --wasm-file=bin/mainnet-release.wasm -aurora initialize --chain 1313161556 --owner test.near -``` - -## Usage - -### Examining deployed EVM metadata - -```sh -aurora get-version -aurora get-owner -aurora get-bridge-prover -aurora get-chain-id -``` - -### Deploying EVM contract bytecode - -```sh -aurora deploy-code @contract.bytecode -``` - -```sh -aurora deploy-code 0x600060005560648060106000396000f360e060020a6000350480638ada066e146028578063d09de08a1460365780632baeceb714604d57005b5060005460005260206000f3005b5060016000540160005560005460005260206000f3005b5060016000540360005560005460005260206000f300 -``` - -### Examining EVM contract state - -```console -$ aurora encode-address test.near -0xCBdA96B3F2B8eb962f97AE50C3852CA976740e2B -``` - -```sh -aurora get-nonce 0xCBdA96B3F2B8eb962f97AE50C3852CA976740e2B -aurora get-balance 0xCBdA96B3F2B8eb962f97AE50C3852CA976740e2B -aurora get-code 0xFc481F4037887e10708552c0D7563Ec6858640d6 -aurora get-storage-at 0xFc481F4037887e10708552c0D7563Ec6858640d6 0 -``` - -### Calling an EVM contract read-only - -```console -$ aurora encode-address test.near -0xCBdA96B3F2B8eb962f97AE50C3852CA976740e2B -``` - -```sh -aurora view --sender 0xCBdA96B3F2B8eb962f97AE50C3852CA976740e2B 0xFc481F4037887e10708552c0D7563Ec6858640d6 0x8ada066e # getCounter() -aurora view --sender 0xCBdA96B3F2B8eb962f97AE50C3852CA976740e2B 0xFc481F4037887e10708552c0D7563Ec6858640d6 0xd09de08a # increment() -aurora view --sender 0xCBdA96B3F2B8eb962f97AE50C3852CA976740e2B 0xFc481F4037887e10708552c0D7563Ec6858640d6 0x2baeceb7 # decrement() -``` - -### Calling an EVM contract mutatively - -```sh -aurora call 0xFc481F4037887e10708552c0D7563Ec6858640d6 0xd09de08a # increment() -aurora call 0xFc481F4037887e10708552c0D7563Ec6858640d6 0x2baeceb7 # decrement() -``` - -## Debugging - -### Inspecting EVM storage state - -```sh -near state aurora.test.near -aurora dump-storage -``` - [`master`]: https://github.com/aurora-is-near/aurora-engine/commits/master [`develop`]: https://github.com/aurora-is-near/aurora-engine/commits/develop diff --git a/VERSION b/VERSION index dbe590065..c8e38b614 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.8.1 +2.9.0 diff --git a/engine-precompiles/Cargo.toml b/engine-precompiles/Cargo.toml index b5b57b9a5..d65442216 100644 --- a/engine-precompiles/Cargo.toml +++ b/engine-precompiles/Cargo.toml @@ -15,9 +15,9 @@ autobenches = false [dependencies] aurora-engine-types = { path = "../engine-types", default-features = false } aurora-engine-sdk = { path = "../engine-sdk", default-features = false } -borsh = { version = "0.9.3", default-features = false } +borsh = { version = "0.10", default-features = false } bn = { version = "0.5.11", package = "zeropool-bn", default-features = false } -evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.3-aurora", default-features = false } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false } libsecp256k1 = { version = "0.7.0", default-features = false, features = ["static-context", "hmac"] } num = { version = "0.4.0", default-features = false, features = ["alloc"] } ripemd = { version = "0.1.1", default-features = false } diff --git a/engine-precompiles/src/account_ids.rs b/engine-precompiles/src/account_ids.rs index 19e6477a2..ec61f79ad 100644 --- a/engine-precompiles/src/account_ids.rs +++ b/engine-precompiles/src/account_ids.rs @@ -1,6 +1,6 @@ use super::{EvmPrecompileResult, Precompile}; use crate::prelude::types::{Address, EthGas}; -use crate::PrecompileOutput; +use crate::{utils, PrecompileOutput}; use aurora_engine_sdk::env::Env; use aurora_engine_types::account_id::AccountId; use evm::{Context, ExitError}; @@ -11,6 +11,7 @@ mod costs { // TODO(#483): Determine the correct amount of gas pub(super) const PREDECESSOR_ACCOUNT_GAS: EthGas = EthGas::new(0); // TODO(#483): Determine the correct amount of gas + #[allow(dead_code)] pub(super) const CURRENT_ACCOUNT_GAS: EthGas = EthGas::new(0); } @@ -21,7 +22,7 @@ pub struct PredecessorAccount<'a, E> { pub mod predecessor_account { use aurora_engine_types::types::Address; - /// predecessor_account_id precompile address + /// `predecessor_account_id` precompile address /// /// Address: `0x723ffbaba940e75e7bf5f6d61dcbf8d9a4de0fd7` /// This address is computed as: `&keccak("predecessorAccountId")[12..]` @@ -30,7 +31,7 @@ pub mod predecessor_account { } impl<'a, E> PredecessorAccount<'a, E> { - pub fn new(env: &'a E) -> Self { + pub const fn new(env: &'a E) -> Self { Self { env } } } @@ -44,9 +45,10 @@ impl<'a, E: Env> Precompile for PredecessorAccount<'a, E> { &self, input: &[u8], target_gas: Option, - _context: &Context, + context: &Context, _is_static: bool, ) -> EvmPrecompileResult { + utils::validate_no_value_attached_to_precompile(context.apparent_value)?; let cost = Self::required_gas(input)?; if let Some(target_gas) = target_gas { if cost > target_gas { @@ -67,14 +69,15 @@ pub struct CurrentAccount { } impl CurrentAccount { - /// current_account_id precompile address + /// `current_account_id` precompile address /// /// Address: `0xfefae79e4180eb0284f261205e3f8cea737aff56` /// This address is computed as: `&keccak("currentAccountId")[12..]` pub const ADDRESS: Address = super::make_address(0xfefae79e, 0x4180eb0284f261205e3f8cea737aff56); - pub fn new(current_account_id: AccountId) -> Self { + #[must_use] + pub const fn new(current_account_id: AccountId) -> Self { Self { current_account_id } } } @@ -88,9 +91,10 @@ impl Precompile for CurrentAccount { &self, input: &[u8], target_gas: Option, - _context: &Context, + context: &Context, _is_static: bool, ) -> EvmPrecompileResult { + utils::validate_no_value_attached_to_precompile(context.apparent_value)?; let cost = Self::required_gas(input)?; if let Some(target_gas) = target_gas { if cost > target_gas { @@ -114,7 +118,7 @@ mod tests { fn test_predecessor_account_precompile_id() { assert_eq!( predecessor_account::ADDRESS, - near_account_to_evm_address("predecessorAccountId".as_bytes()) + near_account_to_evm_address(b"predecessorAccountId") ); } @@ -122,7 +126,7 @@ mod tests { fn test_curent_account_precompile_id() { assert_eq!( CurrentAccount::ADDRESS, - near_account_to_evm_address("currentAccountId".as_bytes()) + near_account_to_evm_address(b"currentAccountId") ); } } diff --git a/engine-precompiles/src/alt_bn256.rs b/engine-precompiles/src/alt_bn256.rs index 1619885a0..58b8a21c0 100644 --- a/engine-precompiles/src/alt_bn256.rs +++ b/engine-precompiles/src/alt_bn256.rs @@ -3,34 +3,35 @@ use crate::prelude::{Borrowed, PhantomData, Vec}; use crate::utils; use crate::{Byzantium, EvmPrecompileResult, HardFork, Istanbul, Precompile, PrecompileOutput}; use bn::Group; +use core::num::{NonZeroU64, NonZeroUsize}; use evm::{Context, ExitError}; /// bn128 costs. mod costs { use crate::prelude::types::EthGas; - /// Cost of the Byzantium alt_bn128_add operation. + /// Cost of the Byzantium `alt_bn128_add` operation. pub(super) const BYZANTIUM_ADD: EthGas = EthGas::new(500); - /// Cost of the Byzantium alt_bn128_mul operation. + /// Cost of the Byzantium `alt_bn128_mul` operation. pub(super) const BYZANTIUM_MUL: EthGas = EthGas::new(40_000); - /// Cost of the alt_bn128_pair per point. + /// Cost of the `alt_bn128_pair` per point. pub(super) const BYZANTIUM_PAIR_PER_POINT: EthGas = EthGas::new(80_000); - /// Cost of the alt_bn128_pair operation. + /// Cost of the `alt_bn128_pair` operation. pub(super) const BYZANTIUM_PAIR_BASE: EthGas = EthGas::new(100_000); - /// Cost of the Istanbul alt_bn128_add operation. + /// Cost of the Istanbul `alt_bn128_add` operation. pub(super) const ISTANBUL_ADD: EthGas = EthGas::new(150); - /// Cost of the Istanbul alt_bn128_mul operation. + /// Cost of the Istanbul `alt_bn128_mul` operation. pub(super) const ISTANBUL_MUL: EthGas = EthGas::new(6_000); - /// Cost of the Istanbul alt_bn128_pair per point. + /// Cost of the Istanbul `alt_bn128_pair` per point. pub(super) const ISTANBUL_PAIR_PER_POINT: EthGas = EthGas::new(34_000); - /// Cost of the Istanbul alt_bn128_pair operation. + /// Cost of the Istanbul `alt_bn128_pair` operation. pub(super) const ISTANBUL_PAIR_BASE: EthGas = EthGas::new(45_000); } @@ -48,18 +49,14 @@ mod consts { /// Pair element length. pub(super) const PAIR_ELEMENT_LEN: usize = 192; - pub(super) const SCALAR_PART_LEN: usize = SCALAR_LEN / 2; - /// Size of BN scalars. pub(super) const SCALAR_LEN: usize = 32; - /// Half the size of a point size. - pub(super) const POINT_PART_LEN: usize = POINT_LEN / 2; - /// Size of BN points. pub(super) const POINT_LEN: usize = 64; /// Size of BN pairs. + #[cfg(feature = "contract")] pub(super) const POINT_PAIR_LEN: usize = 128; /// Output length. @@ -70,6 +67,15 @@ mod consts { pub(super) const ERR_BIG_ENDIAN: ExitError = ExitError::Other(Borrowed("ERR_BIG_ENDIAN")); } +#[cfg(feature = "contract")] +mod type_arith { + pub struct Double; + pub trait Is {} + impl Is<128> for Double<64> {} + impl Is<64> for Double<32> {} + impl Is<32> for Double<16> {} +} + #[cfg(feature = "contract")] trait HostFnEncode { type Encoded; @@ -78,10 +84,13 @@ trait HostFnEncode { } #[cfg(feature = "contract")] -fn concat_low_high(low: [u8; P], high: [u8; P]) -> [u8; S] { +fn concat_low_high(low: [u8; P], high: [u8; P]) -> [u8; S] +where + type_arith::Double

: type_arith::Is, +{ let mut bytes = [0u8; S]; bytes[0..P].copy_from_slice(&low); - bytes[P..P * 2].copy_from_slice(&high); + bytes[P..S].copy_from_slice(&high); bytes } @@ -126,12 +135,13 @@ impl HostFnEncode for bn::G1 { type Encoded = [u8; consts::POINT_LEN]; fn host_fn_encode(self) -> Self::Encoded { - bn::AffineG1::from_jacobian(self) - .map(|p| { + bn::AffineG1::from_jacobian(self).map_or_else( + || [0u8; consts::POINT_LEN], + |p| { let (px, py) = (p.x().host_fn_encode(), p.y().host_fn_encode()); concat_low_high(px, py) - }) - .unwrap_or_else(|| [0u8; consts::POINT_LEN]) + }, + ) } } @@ -140,19 +150,23 @@ impl HostFnEncode for bn::G2 { type Encoded = [u8; consts::POINT_PAIR_LEN]; fn host_fn_encode(self) -> Self::Encoded { - bn::AffineG2::from_jacobian(self) - .map(|g2| { + bn::AffineG2::from_jacobian(self).map_or_else( + || [0u8; consts::POINT_PAIR_LEN], + |g2| { let x = g2.x().host_fn_encode(); let y = g2.y().host_fn_encode(); concat_low_high(x, y) - }) - .unwrap_or_else(|| [0u8; consts::POINT_PAIR_LEN]) + }, + ) } } /// Reads the `x` and `y` points from an input at a given position. fn read_point(input: &[u8], pos: usize) -> Result { use bn::{AffineG1, Fq, G1}; + if input.len() < (pos + consts::SCALAR_LEN * 2) { + return Err(ExitError::Other(Borrowed("INVALID_INPUT_LENGTH"))); + } let px = Fq::from_slice(&input[pos..(pos + consts::SCALAR_LEN)]) .map_err(|_e| ExitError::Other(Borrowed("ERR_FQ_INCORRECT")))?; @@ -174,8 +188,9 @@ pub struct Bn256Add(PhantomData); impl Bn256Add { pub const ADDRESS: Address = super::make_address(0, 6); + #[must_use] pub fn new() -> Self { - Self(Default::default()) + Self(PhantomData::default()) } } @@ -197,15 +212,16 @@ impl Bn256Add { if let Some(sum) = bn::AffineG1::from_jacobian(p1 + p2) { sum.x() .to_big_endian(&mut output[0..consts::SCALAR_LEN]) - .map_err(|_e| consts::ERR_BIG_ENDIAN)?; + .map_err(|_| consts::ERR_BIG_ENDIAN)?; sum.y() .to_big_endian(&mut output[consts::SCALAR_LEN..consts::SCALAR_LEN * 2]) - .map_err(|_e| consts::ERR_BIG_ENDIAN)?; + .map_err(|_| consts::ERR_BIG_ENDIAN)?; } Ok(output) } #[cfg(feature = "contract")] + #[allow(clippy::unnecessary_wraps)] fn execute(p1: bn::G1, p2: bn::G1) -> Result<[u8; consts::OUTPUT_LEN], ExitError> { Ok(aurora_engine_sdk::alt_bn128_g1_sum( p1.host_fn_encode(), @@ -219,11 +235,11 @@ impl Precompile for Bn256Add { Ok(costs::BYZANTIUM_ADD) } - /// Takes in two points on the elliptic curve alt_bn128 and calculates the sum + /// Takes in two points on the elliptic curve `alt_bn128` and calculates the sum /// of them. /// - /// See: https://eips.ethereum.org/EIPS/eip-196 - /// See: https://etherscan.io/address/0000000000000000000000000000000000000006 + /// See: `https://eips.ethereum.org/EIPS/eip-196` + /// See: `https://etherscan.io/address/0000000000000000000000000000000000000006` fn run( &self, input: &[u8], @@ -248,11 +264,11 @@ impl Precompile for Bn256Add { Ok(costs::ISTANBUL_ADD) } - /// Takes in two points on the elliptic curve alt_bn128 and calculates the sum + /// Takes in two points on the elliptic curve `alt_bn128` and calculates the sum /// of them. /// - /// See: https://eips.ethereum.org/EIPS/eip-196 - /// See: https://etherscan.io/address/0000000000000000000000000000000000000006 + /// See: `https://eips.ethereum.org/EIPS/eip-196` + /// See: `https://etherscan.io/address/0000000000000000000000000000000000000006` fn run( &self, input: &[u8], @@ -277,8 +293,9 @@ pub struct Bn256Mul(PhantomData); impl Bn256Mul { pub const ADDRESS: Address = super::make_address(0, 7); + #[must_use] pub fn new() -> Self { - Self(Default::default()) + Self(PhantomData::default()) } } @@ -313,6 +330,7 @@ impl Bn256Mul { } #[cfg(feature = "contract")] + #[allow(clippy::unnecessary_wraps)] fn execute(g1: bn::G1, fr: bn::Fr) -> Result<[u8; consts::OUTPUT_LEN], ExitError> { Ok(aurora_engine_sdk::alt_bn128_g1_scalar_multiple( g1.host_fn_encode(), @@ -326,10 +344,10 @@ impl Precompile for Bn256Mul { Ok(costs::BYZANTIUM_MUL) } - /// Takes in two points on the elliptic curve alt_bn128 and multiples them. + /// Takes in two points on the elliptic curve `alt_bn128` and multiples them. /// - /// See: https://eips.ethereum.org/EIPS/eip-196 - /// See: https://etherscan.io/address/0000000000000000000000000000000000000007 + /// See: `https://eips.ethereum.org/EIPS/eip-196` + /// See: `https://etherscan.io/address/0000000000000000000000000000000000000007` fn run( &self, input: &[u8], @@ -354,10 +372,10 @@ impl Precompile for Bn256Mul { Ok(costs::ISTANBUL_MUL) } - /// Takes in two points on the elliptic curve alt_bn128 and multiples them. + /// Takes in two points on the elliptic curve `alt_bn128` and multiples them. /// - /// See: https://eips.ethereum.org/EIPS/eip-196 - /// See: https://etherscan.io/address/0000000000000000000000000000000000000007 + /// See: `https://eips.ethereum.org/EIPS/eip-196` + /// See: `https://etherscan.io/address/0000000000000000000000000000000000000007` fn run( &self, input: &[u8], @@ -383,8 +401,9 @@ pub struct Bn256Pair(PhantomData); impl Bn256Pair { pub const ADDRESS: Address = super::make_address(0, 8); + #[must_use] pub fn new() -> Self { - Self(Default::default()) + Self(PhantomData::default()) } } @@ -452,7 +471,7 @@ impl Bn256Pair { .into() } }; - vals.push((g1_a, g1_b)) + vals.push((g1_a, g1_b)); } let result = Self::execute(vals); @@ -471,6 +490,7 @@ impl Bn256Pair { } #[cfg(not(feature = "contract"))] + #[allow(clippy::needless_pass_by_value)] fn execute(vals: Vec<(bn::G1, bn::G2)>) -> bool { bn::pairing_batch(&vals) == bn::Gt::one() } @@ -487,8 +507,9 @@ impl Bn256Pair { impl Precompile for Bn256Pair { fn required_gas(input: &[u8]) -> Result { let input_len = u64::try_from(input.len()).map_err(utils::err_usize_conv)?; - let pair_element_len = - u64::try_from(consts::PAIR_ELEMENT_LEN).map_err(utils::err_usize_conv)?; + let pair_element_len = NonZeroUsize::try_from(consts::PAIR_ELEMENT_LEN) + .and_then(NonZeroU64::try_from) + .map_err(utils::err_usize_conv)?; Ok( costs::BYZANTIUM_PAIR_PER_POINT * input_len / pair_element_len + costs::BYZANTIUM_PAIR_BASE, @@ -497,8 +518,8 @@ impl Precompile for Bn256Pair { /// Takes in elements and calculates the pair. /// - /// See: https://eips.ethereum.org/EIPS/eip-197 - /// See: https://etherscan.io/address/0000000000000000000000000000000000000008 + /// See: `https://eips.ethereum.org/EIPS/eip-197` + /// See: `https://etherscan.io/address/0000000000000000000000000000000000000008` fn run( &self, input: &[u8], @@ -521,8 +542,9 @@ impl Precompile for Bn256Pair { impl Precompile for Bn256Pair { fn required_gas(input: &[u8]) -> Result { let input_len = u64::try_from(input.len()).map_err(utils::err_usize_conv)?; - let pair_element_len = - u64::try_from(consts::PAIR_ELEMENT_LEN).map_err(utils::err_usize_conv)?; + let pair_element_len = NonZeroUsize::try_from(consts::PAIR_ELEMENT_LEN) + .and_then(NonZeroU64::try_from) + .map_err(utils::err_usize_conv)?; Ok( costs::ISTANBUL_PAIR_PER_POINT * input_len / pair_element_len + costs::ISTANBUL_PAIR_BASE, @@ -531,8 +553,8 @@ impl Precompile for Bn256Pair { /// Takes in elements and calculates the pair. /// - /// See: https://eips.ethereum.org/EIPS/eip-197 - /// See: https://etherscan.io/address/0000000000000000000000000000000000000008 + /// See: `https://eips.ethereum.org/EIPS/eip-197` + /// See: `https://etherscan.io/address/0000000000000000000000000000000000000008` fn run( &self, input: &[u8], @@ -745,6 +767,7 @@ mod tests { } #[test] + #[allow(clippy::too_many_lines)] fn test_alt_bn128_pair() { let input = hex::decode( "\ diff --git a/engine-precompiles/src/blake2.rs b/engine-precompiles/src/blake2.rs index 8c6b6d7fc..447bdee51 100644 --- a/engine-precompiles/src/blake2.rs +++ b/engine-precompiles/src/blake2.rs @@ -67,6 +67,7 @@ mod consts { /// /// See [RFC 7693](https://datatracker.ietf.org/doc/html/rfc7693#section-3.1) specification for more /// details. +#[allow(clippy::many_single_char_names)] fn g(v: &mut [u64], a: usize, b: usize, c: usize, d: usize, x: u64, y: u64) { v[a] = v[a].wrapping_add(v[b]).wrapping_add(x); v[d] = (v[d] ^ v[a]).rotate_right(consts::R1); @@ -81,11 +82,12 @@ fn g(v: &mut [u64], a: usize, b: usize, c: usize, d: usize, x: u64, y: u64) { /// Takes as an argument the state vector `h`, message block vector `m` (the last block is padded /// with zeros to full block size, if required), 2w-bit offset counter `t`, and final block /// indicator flag `f`. Local vector v[0..15] is used in processing. F returns a new state vector. -/// The number of rounds, `r`, is 12 for BLAKE2b and 10 for BLAKE2s. Rounds are numbered from 0 to +/// The number of rounds, `r`, is 12 for `BLAKE2b` and 10 for BLAKE2s. Rounds are numbered from 0 to /// r - 1. /// /// See [RFC 7693](https://datatracker.ietf.org/doc/html/rfc7693#section-3.2) specification for more /// details. +#[allow(clippy::many_single_char_names)] fn f(mut h: [u64; 8], m: [u64; 16], t: [u64; 2], f: bool, rounds: u32) -> Vec { // Initialize the work vector. let mut v = [0u64; 16]; @@ -97,7 +99,7 @@ fn f(mut h: [u64; 8], m: [u64; 16], t: [u64; 2], f: bool, rounds: u32) -> Vec) -> Self { Self { cost, @@ -386,6 +391,7 @@ pub enum AllPrecompiles<'a, I, E, H> { /// fn for making an address by concatenating the bytes from two given numbers, /// Note that 32 + 128 = 160 = 20 bytes (the length of an address). This function is used /// as a convenience for specifying the addresses of the various precompiles. +#[must_use] pub const fn make_address(x: u32, y: u128) -> prelude::types::Address { let x_bytes = x.to_be_bytes(); let y_bytes = y.to_be_bytes(); @@ -482,11 +488,12 @@ mod tests { for _ in 0..u8::MAX { let address = Address::new(H160(rng.gen())); let (x, y) = split_address(address); - assert_eq!(address, super::make_address(x, y)) + assert_eq!(address, super::make_address(x, y)); } } #[test] + #[allow(clippy::too_many_lines)] fn test_paused_precompiles_throws_error() { use crate::{ AllPrecompiles, Context, EvmPrecompileResult, ExitError, Precompile, PrecompileOutput, @@ -525,7 +532,7 @@ mod tests { } impl MockPrecompileHandle { - pub fn new(code_address: H160) -> Self { + pub const fn new(code_address: H160) -> Self { Self { code_address } } } @@ -610,7 +617,7 @@ mod tests { assert_eq!(expected_failure, actual_failure); } - fn u8_to_address(x: u8) -> Address { + const fn u8_to_address(x: u8) -> Address { let mut bytes = [0u8; 20]; bytes[19] = x; Address::new(H160(bytes)) diff --git a/engine-precompiles/src/modexp.rs b/engine-precompiles/src/modexp.rs index 686a664d7..57af4b0a2 100644 --- a/engine-precompiles/src/modexp.rs +++ b/engine-precompiles/src/modexp.rs @@ -12,8 +12,9 @@ pub struct ModExp(PhantomData); impl ModExp { pub const ADDRESS: Address = super::make_address(0, 5); + #[must_use] pub fn new() -> Self { - Self(Default::default()) + Self(PhantomData::default()) } } @@ -40,11 +41,11 @@ impl ModExp { } } - fn run_inner(input: &[u8]) -> Result, ExitError> { + fn run_inner(input: &[u8]) -> Vec { let (base_len, exp_len, mod_len) = parse_lengths(input); - let base_len = usize::try_from(base_len).map_err(utils::err_usize_conv)?; - let exp_len = usize::try_from(exp_len).map_err(utils::err_usize_conv)?; - let mod_len = usize::try_from(mod_len).map_err(utils::err_usize_conv)?; + let base_len = usize::try_from(base_len).unwrap_or(usize::MAX); + let exp_len = usize::try_from(exp_len).unwrap_or(usize::MAX); + let mod_len = usize::try_from(mod_len).unwrap_or(usize::MAX); let base_start = 96; let base_end = base_len.saturating_add(base_start); @@ -55,33 +56,32 @@ impl ModExp { let mod_start = exp_end; let base = parse_bytes(input, base_start, base_len, BigUint::from_bytes_be); - let exponent = parse_bytes(input, exp_start, exp_len, BigUint::from_bytes_be); let modulus = parse_bytes(input, mod_start, mod_len, BigUint::from_bytes_be); - let output = { - let computed_result = if modulus == BigUint::from(0u32) { - Vec::new() - } else { - base.modpow(&exponent, &modulus).to_bytes_be() - }; - // The result must be the same length as the input modulus. - // To ensure this we pad on the left with zeros. - if mod_len > computed_result.len() { - let diff = mod_len - computed_result.len(); - let mut padded_result = Vec::with_capacity(mod_len); - padded_result.extend(core::iter::repeat(0).take(diff)); - padded_result.extend_from_slice(&computed_result); - padded_result - } else { - computed_result - } + let computed_result = if modulus == BigUint::from(0u32) { + Vec::new() + } else { + // The OOM panic is no longer possible because if the modulus is non-zero + // then the required gas prevents passing a huge exponent. + let exponent = parse_bytes(input, exp_start, exp_len, BigUint::from_bytes_be); + base.modpow(&exponent, &modulus).to_bytes_be() }; - - Ok(output) + // The result must be the same length as the input modulus. + // To ensure this we pad on the left with zeros. + if mod_len > computed_result.len() { + let diff = mod_len - computed_result.len(); + let mut padded_result = Vec::with_capacity(mod_len); + padded_result.extend(core::iter::repeat(0).take(diff)); + padded_result.extend_from_slice(&computed_result); + padded_result + } else { + computed_result + } } } impl ModExp { + const MIN_GAS: EthGas = EthGas::new(0); // ouput of this function is bounded by 2^128 fn mul_complexity(x: u64) -> U256 { if x <= 64 { @@ -100,17 +100,20 @@ impl ModExp { impl Precompile for ModExp { fn required_gas(input: &[u8]) -> Result { let (base_len, exp_len, mod_len) = parse_lengths(input); + if base_len == 0 && mod_len == 0 { + Ok(Self::MIN_GAS) + } else { + let mul = Self::mul_complexity(core::cmp::max(mod_len, base_len)); + let iter_count = Self::calc_iter_count(exp_len, base_len, input)?; + // mul * iter_count bounded by 2^195 < 2^256 (no overflow) + let gas = mul * core::cmp::max(iter_count, U256::one()) / U256::from(20); - let mul = Self::mul_complexity(core::cmp::max(mod_len, base_len)); - let iter_count = Self::calc_iter_count(exp_len, base_len, input)?; - // mul * iter_count bounded by 2^195 < 2^256 (no overflow) - let gas = mul * core::cmp::max(iter_count, U256::one()) / U256::from(20); - - Ok(EthGas::new(saturating_round(gas))) + Ok(EthGas::new(saturating_round(gas))) + } } - /// See: https://eips.ethereum.org/EIPS/eip-198 - /// See: https://etherscan.io/address/0000000000000000000000000000000000000005 + /// See: `https://eips.ethereum.org/EIPS/eip-198` + /// See: `https://etherscan.io/address/0000000000000000000000000000000000000005` fn run( &self, input: &[u8], @@ -125,12 +128,13 @@ impl Precompile for ModExp { } } - let output = Self::run_inner(input)?; + let output = Self::run_inner(input); Ok(PrecompileOutput::without_logs(cost, output)) } } impl ModExp { + const MIN_GAS: EthGas = EthGas::new(200); // output bounded by 2^122 fn mul_complexity(base_len: u64, mod_len: u64) -> U256 { let max_len = core::cmp::max(mod_len, base_len); @@ -142,13 +146,16 @@ impl ModExp { impl Precompile for ModExp { fn required_gas(input: &[u8]) -> Result { let (base_len, exp_len, mod_len) = parse_lengths(input); + if base_len == 0 && mod_len == 0 { + Ok(Self::MIN_GAS) + } else { + let mul = Self::mul_complexity(base_len, mod_len); + let iter_count = Self::calc_iter_count(exp_len, base_len, input)?; + // mul * iter_count bounded by 2^189 (so no overflow) + let gas = mul * iter_count.max(U256::one()) / U256::from(3); - let mul = Self::mul_complexity(base_len, mod_len); - let iter_count = Self::calc_iter_count(exp_len, base_len, input)?; - // mul * iter_count bounded by 2^189 (so no overflow) - let gas = mul * iter_count.max(U256::one()) / U256::from(3); - - Ok(EthGas::new(core::cmp::max(200, saturating_round(gas)))) + Ok(EthGas::new(core::cmp::max(200, saturating_round(gas)))) + } } fn run( @@ -165,7 +172,7 @@ impl Precompile for ModExp { } } - let output = Self::run_inner(input)?; + let output = Self::run_inner(input); Ok(PrecompileOutput::without_logs(cost, output)) } } @@ -201,7 +208,6 @@ fn saturating_round(x: U256) -> u64 { fn parse_lengths(input: &[u8]) -> (u64, u64, u64) { let parse = |start: usize| -> u64 { // I don't understand why I need a closure here, but doesn't compile without one - #[allow(clippy::redundant_closure)] saturating_round(parse_bytes(input, start, 32, |x| U256::from(x))) }; let base_len = parse(0); @@ -221,6 +227,27 @@ mod tests { // Byzantium tests: https://github.com/holiman/go-ethereum/blob/master/core/vm/testdata/precompiles/modexp.json // Berlin tests:https://github.com/holiman/go-ethereum/blob/master/core/vm/testdata/precompiles/modexp_eip2565.json + struct ModExpTestInput { + base_len: U256, + exp_len: U256, + mod_len: U256, + base: U256, + exp: U256, + modulus: U256, + } + + fn generate_modexp_test_input(test_input: &ModExpTestInput) -> Vec { + [ + u256_to_arr(&test_input.base_len), + u256_to_arr(&test_input.exp_len), + u256_to_arr(&test_input.mod_len), + u256_to_arr(&test_input.base), + u256_to_arr(&test_input.exp), + u256_to_arr(&test_input.modulus), + ] + .concat() + } + struct Test { input: &'static str, expected: &'static str, @@ -451,38 +478,28 @@ mod tests { #[test] fn test_berlin_modexp_big_input() { - let base_len = U256::from(4); - let exp_len = U256::from(u64::MAX); - let mod_len = U256::from(4); - let base: u32 = 1; - let exp = U256::MAX; - - let mut input: Vec = Vec::new(); - input.extend_from_slice(&u256_to_arr(&base_len)); - input.extend_from_slice(&u256_to_arr(&exp_len)); - input.extend_from_slice(&u256_to_arr(&mod_len)); - input.extend_from_slice(&base.to_be_bytes()); - input.extend_from_slice(&u256_to_arr(&exp)); - + let input = generate_modexp_test_input(&ModExpTestInput { + base_len: U256::from(4), + exp_len: U256::from(u64::MAX), + mod_len: U256::from(4), + base: U256::from(1), + exp: U256::MAX, + modulus: U256::MAX, + }); // completes without any overflow ModExp::::required_gas(&input).unwrap(); } #[test] fn test_berlin_modexp_bigger_input() { - let base_len = U256::MAX; - let exp_len = U256::MAX; - let mod_len = U256::MAX; - let base: u32 = 1; - let exp = U256::MAX; - - let mut input: Vec = Vec::new(); - input.extend_from_slice(&u256_to_arr(&base_len)); - input.extend_from_slice(&u256_to_arr(&exp_len)); - input.extend_from_slice(&u256_to_arr(&mod_len)); - input.extend_from_slice(&base.to_be_bytes()); - input.extend_from_slice(&u256_to_arr(&exp)); - + let input = generate_modexp_test_input(&ModExpTestInput { + base_len: U256::MAX, + exp_len: U256::MAX, + mod_len: U256::MAX, + base: U256::from(1), + exp: U256::MAX, + modulus: U256::MAX, + }); // completes without any overflow ModExp::::required_gas(&input).unwrap(); } @@ -493,7 +510,7 @@ mod tests { .run(&[], Some(EthGas::new(100_000)), &new_context(), false) .unwrap(); let expected: Vec = Vec::new(); - assert_eq!(res.output, expected) + assert_eq!(res.output, expected); } #[test] @@ -508,4 +525,187 @@ mod tests { ); assert_eq!(Err(ExitError::OutOfGas), res); } + + #[test] + fn test_modexp_not_overflow() { + let input = generate_modexp_test_input(&ModExpTestInput { + base_len: U256::from(0), + exp_len: U256::from(usize::MAX - 95), + mod_len: U256::from(0), + base: U256::MAX, + exp: U256::MAX, + modulus: U256::MAX, + }); + + let res = ModExp::::new() + .run(&input, Some(EthGas::new(100_000)), &new_context(), false) + .unwrap(); + let expected = [0u8; 0]; + assert_eq!(res.output, expected); + + let gas = ModExp::::required_gas(&input).unwrap(); + let min_gas = EthGas::new(0); + assert_eq!(gas, min_gas); + + let res = ModExp::::new() + .run(&input, Some(EthGas::new(100_000)), &new_context(), false) + .unwrap(); + let expected = [0u8; 0]; + assert_eq!(res.output, expected); + + let gas = ModExp::::required_gas(&input).unwrap(); + let min_gas = EthGas::new(200); + assert_eq!(gas, min_gas); + } + + #[test] + fn test_zero_base_len_zero_mod_len() { + let input = generate_modexp_test_input(&ModExpTestInput { + base_len: U256::from(0), + exp_len: U256::from(1), + mod_len: U256::from(0), + base: U256::from(1), + exp: U256::from(1), + modulus: U256::from(1), + }); + let res = ModExp::::new() + .run(&input, Some(EthGas::new(100_000)), &new_context(), false) + .unwrap(); + let expected = [0u8; 0]; + assert_eq!(res.output, expected); + + let gas = ModExp::::required_gas(&input).unwrap(); + let min_gas = EthGas::new(0); + assert_eq!(gas, min_gas); + + let res = ModExp::::new() + .run(&input, Some(EthGas::new(100_000)), &new_context(), false) + .unwrap(); + let expected = [0u8; 0]; + assert_eq!(res.output, expected); + + let gas = ModExp::::required_gas(&input).unwrap(); + let min_gas = EthGas::new(200); + assert_eq!(gas, min_gas); + } + + #[test] + fn test_max_exp_zero_base_zero_mod() { + let input = hex::decode("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff9f0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + let res = ModExp::::new().run( + &input.unwrap(), + Some(EthGas::new(100_000)), + &new_context(), + false, + ); + assert!(res.is_ok()); + } + + #[test] + fn test_max_exp_max_base_zero_mod() { + let input = hex::decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffff9f0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + let res = ModExp::::new().run( + &input.unwrap(), + Some(EthGas::new(100_000)), + &new_context(), + false, + ); + assert_eq!(Err(ExitError::OutOfGas), res); + } + + #[test] + fn test_max_exp_max_base_non_zero_mod() { + let input = hex::decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffff9f0000000000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000001"); + let res = ModExp::::new().run( + &input.unwrap(), + Some(EthGas::new(100_000)), + &new_context(), + false, + ); + assert_eq!(Err(ExitError::OutOfGas), res); + } + + #[test] + fn test_max_exp_max_base_max_mod() { + let input = hex::decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffff9fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + let res = ModExp::::new().run( + &input.unwrap(), + Some(EthGas::new(100_000)), + &new_context(), + false, + ); + assert_eq!(Err(ExitError::OutOfGas), res); + } + + #[test] + fn test_max_exp_non_zero_base_zero_mod() { + let input = hex::decode("0000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff9f0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + let res = ModExp::::new().run( + &input.unwrap(), + Some(EthGas::new(100_000)), + &new_context(), + false, + ); + assert_eq!(Err(ExitError::OutOfGas), res); + } + + #[test] + fn test_max_exp_zero_base_non_zero_mod() { + let input = hex::decode("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff9f00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000001"); + let res = ModExp::::new().run( + &input.unwrap(), + Some(EthGas::new(100_000)), + &new_context(), + false, + ); + assert_eq!(Err(ExitError::OutOfGas), res); + } + + #[test] + fn test_modexp_no_oom_with_isize_max() { + // this test should not panic if exp_len is `isize::MAX` + let input = generate_modexp_test_input(&ModExpTestInput { + base_len: U256::from(0), + exp_len: U256::from(isize::MAX), + mod_len: U256::from(0), + base: U256::MAX, + exp: U256::MAX, + modulus: U256::MAX, + }); + let res = + ModExp::::new().run(&input, Some(EthGas::new(100_000)), &new_context(), false); + assert!(res.is_ok()); + } + + #[test] + fn test_modexp_capacity_overflow() { + // this test should not panic with capacity overflow + let input = generate_modexp_test_input(&ModExpTestInput { + base_len: U256::from(0), + exp_len: U256::from(usize::MAX - 96), + mod_len: U256::from(0), + base: U256::MAX, + exp: U256::MAX, + modulus: U256::MAX, + }); + let res = + ModExp::::new().run(&input, Some(EthGas::new(100_000)), &new_context(), false); + assert!(res.is_ok()); + } + + #[test] + fn test_modexp_add_to_overflow() { + // This test should not panicing with capacity overflow + let input = generate_modexp_test_input(&ModExpTestInput { + base_len: U256::from(0), + exp_len: U256::from(usize::MAX), + mod_len: U256::from(0), + base: U256::MAX, + exp: U256::MAX, + modulus: U256::MAX, + }); + let res = + ModExp::::new().run(&input, Some(EthGas::new(100_000)), &new_context(), false); + assert!(res.is_ok()); + } } diff --git a/engine-precompiles/src/native.rs b/engine-precompiles/src/native.rs index 91064c96b..c92b06c07 100644 --- a/engine-precompiles/src/native.rs +++ b/engine-precompiles/src/native.rs @@ -15,7 +15,7 @@ use crate::prelude::{ use crate::prelude::types::EthGas; use crate::PrecompileOutput; -use aurora_engine_types::account_id::AccountId; +use aurora_engine_types::{account_id::AccountId, types::NEP141Wei}; use evm::backend::Log; use evm::{Context, ExitError}; @@ -31,7 +31,7 @@ mod costs { pub(super) const EXIT_TO_ETHEREUM_GAS: EthGas = EthGas::new(0); /// Value determined experimentally based on tests and mainnet data. Example: - /// https://explorer.mainnet.near.org/transactions/5CD7NrqWpK3H8MAAU4mYEPuuWz9AqR9uJkkZJzw5b8PM#D1b5NVRrAsJKUX2ZGs3poKViu1Rgt4RJZXtTfMgdxH4S + /// `https://explorer.mainnet.near.org/transactions/5CD7NrqWpK3H8MAAU4mYEPuuWz9AqR9uJkkZJzw5b8PM#D1b5NVRrAsJKUX2ZGs3poKViu1Rgt4RJZXtTfMgdxH4S` pub(super) const FT_TRANSFER_GAS: NearGas = NearGas::new(10_000_000_000_000); /// Value determined experimentally based on tests. @@ -46,12 +46,12 @@ mod costs { pub mod events { use crate::prelude::{types::Address, vec, String, ToString, H160, H256, U256}; - /// Derived from event signature (see tests::test_exit_signatures) + /// Derived from event signature (see `tests::test_exit_signatures`) pub const EXIT_TO_NEAR_SIGNATURE: H256 = crate::make_h256( 0x5a91b8bc9c1981673db8fb226dbd8fcd, 0xd0c23f45cd28abb31403a5392f6dd0c7, ); - /// Derived from event signature (see tests::test_exit_signatures) + /// Derived from event signature (see `tests::test_exit_signatures`) pub const EXIT_TO_ETH_SIGNATURE: H256 = crate::make_h256( 0xd046c2bb01a5622bc4b9696332391d87, 0x491373762eeac0831c48400e2d5a5f07, @@ -63,9 +63,9 @@ pub mod events { /// used for this purpose. pub const ETH_ADDRESS: Address = Address::new(H160([0; 20])); - /// ExitToNear( + /// `ExitToNear`( /// Address indexed sender, - /// Address indexed erc20_address, + /// Address indexed `erc20_address`, /// string indexed dest, /// uint amount /// ) @@ -81,6 +81,7 @@ pub mod events { } impl ExitToNear { + #[must_use] pub fn encode(self) -> ethabi::RawLog { let data = ethabi::encode(&[ethabi::Token::Int(self.amount)]); let topics = vec![ @@ -94,9 +95,9 @@ pub mod events { } } - /// ExitToEth( + /// `ExitToEth`( /// Address indexed sender, - /// Address indexed erc20_address, + /// Address indexed `erc20_address`, /// string indexed dest, /// uint amount /// ) @@ -112,6 +113,7 @@ pub mod events { } impl ExitToEth { + #[must_use] pub fn encode(self) -> ethabi::RawLog { let data = ethabi::encode(&[ethabi::Token::Int(self.amount)]); let topics = vec![ @@ -131,6 +133,7 @@ pub mod events { H256(result) } + #[must_use] pub fn exit_to_near_schema() -> ethabi::Event { ethabi::Event { name: "ExitToNear".to_string(), @@ -160,6 +163,7 @@ pub mod events { } } + #[must_use] pub fn exit_to_eth_schema() -> ethabi::Event { ethabi::Event { name: "ExitToEth".to_string(), @@ -208,7 +212,7 @@ pub mod exit_to_near { } impl ExitToNear { - pub fn new(current_account_id: AccountId, io: I) -> Self { + pub const fn new(current_account_id: AccountId, io: I) -> Self { Self { current_account_id, io, @@ -216,6 +220,13 @@ impl ExitToNear { } } +fn validate_input_size(input: &[u8], min: usize, max: usize) -> Result<(), ExitError> { + if input.len() < min || input.len() > max { + return Err(ExitError::Other(Cow::from("ERR_INVALID_INPUT"))); + } + Ok(()) +} + fn get_nep141_from_erc20(erc20_token: &[u8], io: &I) -> Result { AccountId::try_from( io.read_storage(bytes_to_key(KeyPrefix::Erc20Nep141Map, erc20_token).as_slice()) @@ -225,11 +236,19 @@ fn get_nep141_from_erc20(erc20_token: &[u8], io: &I) -> Result Result<(), ExitError> { + if amount > U256::from(u128::MAX) { + return Err(ExitError::Other(Cow::from("ERR_INVALID_AMOUNT"))); + } + Ok(()) +} + impl Precompile for ExitToNear { fn required_gas(_input: &[u8]) -> Result { Ok(costs::EXIT_TO_NEAR_GAS) } + #[allow(clippy::too_many_lines)] fn run( &self, input: &[u8], @@ -237,17 +256,27 @@ impl Precompile for ExitToNear { context: &Context, is_static: bool, ) -> EvmPrecompileResult { + // ETH transfer input format: (85 bytes) + // - flag (1 byte) + // - refund_address (20 bytes) + // - recipient_account_id (max 64 bytes) + // ERC20 transfer input format: (117 bytes) + // - flag (1 byte) + // - refund_address (20 bytes) + // - amount (32 bytes) + // - recipient_account_id (max 64 bytes) #[cfg(feature = "error_refund")] fn parse_input(input: &[u8]) -> Result<(Address, &[u8]), ExitError> { - if input.len() < 21 { - return Err(ExitError::Other(Cow::from("ERR_INVALID_INPUT"))); - } - let refund_address = Address::try_from_slice(&input[1..21]).unwrap(); + validate_input_size(input, 21, 117)?; + let mut buffer = [0; 20]; + buffer.copy_from_slice(&input[1..21]); + let refund_address = Address::from_array(buffer); Ok((refund_address, &input[21..])) } #[cfg(not(feature = "error_refund"))] - fn parse_input(input: &[u8]) -> &[u8] { - &input[1..] + fn parse_input(input: &[u8]) -> Result<&[u8], ExitError> { + validate_input_size(input, 3, 117)?; + Ok(&input[1..]) } if let Some(target_gas) = target_gas { @@ -270,7 +299,7 @@ impl Precompile for ExitToNear { #[cfg(feature = "error_refund")] let (refund_address, mut input) = parse_input(input)?; #[cfg(not(feature = "error_refund"))] - let mut input = parse_input(input); + let mut input = parse_input(input)?; let current_account_id = self.current_account_id.clone(); #[cfg(feature = "error_refund")] let refund_on_error_target = current_account_id.clone(); @@ -308,7 +337,7 @@ impl Precompile for ExitToNear { 0x1 => { // ERC20 transfer // - // This precompile branch is expected to be called from the ERC20 burn function\ + // This precompile branch is expected to be called from the ERC20 burn function. // // Input slice format: // amount (U256 big-endian bytes) - the amount that was burned @@ -326,6 +355,8 @@ impl Precompile for ExitToNear { let amount = U256::from_big_endian(&input[..32]); input = &input[32..]; + validate_amount(amount)?; + if let Ok(receiver_account_id) = AccountId::try_from(input) { ( nep141_address, @@ -402,7 +433,8 @@ impl Precompile for ExitToNear { Ok(PrecompileOutput { logs: vec![promise_log, exit_event_log], - ..Default::default() + cost: Self::required_gas(input)?, + output: Vec::new(), }) } } @@ -424,7 +456,7 @@ pub mod exit_to_ethereum { } impl ExitToEthereum { - pub fn new(current_account_id: AccountId, io: I) -> Self { + pub const fn new(current_account_id: AccountId, io: I) -> Self { Self { current_account_id, io, @@ -444,7 +476,14 @@ impl Precompile for ExitToEthereum { context: &Context, is_static: bool, ) -> EvmPrecompileResult { - use crate::prelude::types::NEP141Wei; + // ETH transfer input format (min size 21 bytes) + // - flag (1 byte) + // - eth_recipient (20 bytes) + // ERC20 transfer input format: max 53 bytes + // - flag (1 byte) + // - amount (32 bytes) + // - eth_recipient (20 bytes) + validate_input_size(input, 21, 53)?; if let Some(target_gas) = target_gas { if Self::required_gas(input)? > target_gas { return Err(ExitError::OutOfGas); @@ -514,6 +553,8 @@ impl Precompile for ExitToEthereum { let amount = U256::from_big_endian(&input[..32]); input = &input[32..]; + validate_amount(amount)?; + if input.len() == 20 { // Parse ethereum address in hex let eth_recipient: String = hex::encode(input); @@ -573,25 +614,27 @@ impl Precompile for ExitToEthereum { Ok(PrecompileOutput { logs: vec![promise_log, exit_event_log], - ..Default::default() + cost: Self::required_gas(input)?, + output: Vec::new(), }) } } #[cfg(test)] mod tests { - use super::{exit_to_ethereum, exit_to_near}; + use super::{exit_to_ethereum, exit_to_near, validate_amount, validate_input_size}; use crate::prelude::sdk::types::near_account_to_evm_address; + use aurora_engine_types::U256; #[test] fn test_precompile_id() { assert_eq!( exit_to_ethereum::ADDRESS, - near_account_to_evm_address("exitToEthereum".as_bytes()) + near_account_to_evm_address(b"exitToEthereum") ); assert_eq!( exit_to_near::ADDRESS, - near_account_to_evm_address("exitToNear".as_bytes()) + near_account_to_evm_address(b"exitToNear") ); } @@ -609,4 +652,41 @@ mod tests { super::events::EXIT_TO_ETH_SIGNATURE ); } + + #[test] + fn test_check_invalid_input_lt_min() { + let input = [0u8; 4]; + assert!(validate_input_size(&input, 10, 20).is_err()); + assert!(validate_input_size(&input, 5, 0).is_err()); + } + + #[test] + fn test_check_invalid_max_value_for_input() { + let input = [0u8; 4]; + assert!(validate_input_size(&input, 5, 0).is_err()); + } + + #[test] + fn test_check_invalid_input_gt_max() { + let input = [1u8; 55]; + assert!(validate_input_size(&input, 10, 54).is_err()); + } + + #[test] + fn test_check_valid_input() { + let input = [1u8; 55]; + validate_input_size(&input, 10, input.len()).unwrap(); + validate_input_size(&input, 0, input.len()).unwrap(); + } + + #[test] + #[should_panic(expected = "ERR_INVALID_AMOUNT")] + fn test_exit_with_invalid_amount() { + validate_amount(U256::MAX).unwrap(); + } + + #[test] + fn test_exit_with_valid_amount() { + validate_amount(U256::from(u128::MAX)).unwrap(); + } } diff --git a/engine-precompiles/src/prepaid_gas.rs b/engine-precompiles/src/prepaid_gas.rs index 9b59b7988..ed8c61050 100644 --- a/engine-precompiles/src/prepaid_gas.rs +++ b/engine-precompiles/src/prepaid_gas.rs @@ -1,11 +1,11 @@ use super::{EvmPrecompileResult, Precompile}; use crate::prelude::types::{Address, EthGas}; -use crate::PrecompileOutput; +use crate::{utils, PrecompileOutput}; use aurora_engine_sdk::env::Env; use aurora_engine_types::{vec, U256}; use evm::{Context, ExitError}; -/// prepaid_gas precompile address +/// `prepaid_gas` precompile address /// /// Address: `0x536822d27de53629ef1f84c60555689e9488609f` /// This address is computed as: `&keccak("prepaidGas")[12..]` @@ -23,7 +23,7 @@ pub struct PrepaidGas<'a, E> { } impl<'a, E> PrepaidGas<'a, E> { - pub fn new(env: &'a E) -> Self { + pub const fn new(env: &'a E) -> Self { Self { env } } } @@ -37,9 +37,10 @@ impl<'a, E: Env> Precompile for PrepaidGas<'a, E> { &self, input: &[u8], target_gas: Option, - _context: &Context, + context: &Context, _is_static: bool, ) -> EvmPrecompileResult { + utils::validate_no_value_attached_to_precompile(context.apparent_value)?; let cost = Self::required_gas(input)?; if let Some(target_gas) = target_gas { if cost > target_gas { @@ -66,7 +67,7 @@ mod tests { fn test_prepaid_gas_precompile_id() { assert_eq!( prepaid_gas::ADDRESS, - near_account_to_evm_address("prepaidGas".as_bytes()) + near_account_to_evm_address(b"prepaidGas") ); } } diff --git a/engine-precompiles/src/promise_result.rs b/engine-precompiles/src/promise_result.rs index 223536c65..d11b6d6ae 100644 --- a/engine-precompiles/src/promise_result.rs +++ b/engine-precompiles/src/promise_result.rs @@ -1,12 +1,12 @@ use super::{EvmPrecompileResult, Precompile}; use crate::prelude::types::{Address, EthGas}; -use crate::PrecompileOutput; +use crate::{utils, PrecompileOutput}; use aurora_engine_sdk::promise::ReadOnlyPromiseHandler; use aurora_engine_types::{Cow, Vec}; use borsh::BorshSerialize; use evm::{Context, ExitError}; -/// get_promise_results precompile address +/// `get_promise_results` precompile address /// /// Address: `0x0a3540f79be10ef14890e87c1a0040a68cc6af71` /// This address is computed as: `&keccak("getPromiseResults")[12..]` @@ -26,7 +26,7 @@ pub struct PromiseResult { } impl PromiseResult { - pub fn new(handler: H) -> Self { + pub const fn new(handler: H) -> Self { Self { handler } } } @@ -42,9 +42,10 @@ impl Precompile for PromiseResult { &self, input: &[u8], target_gas: Option, - _context: &Context, + context: &Context, _is_static: bool, ) -> EvmPrecompileResult { + utils::validate_no_value_attached_to_precompile(context.apparent_value)?; let mut cost = Self::required_gas(input)?; let check_cost = |cost: EthGas| -> Result<(), ExitError> { if let Some(target_gas) = target_gas { @@ -62,7 +63,10 @@ impl Precompile for PromiseResult { for i in 0..num_promises { if let Some(result) = self.handler.ro_promise_result(i) { let n_bytes = u64::try_from(result.size()).map_err(crate::utils::err_usize_conv)?; - cost += n_bytes * costs::PROMISE_RESULT_BYTE_COST; + cost = EthGas::new(n_bytes) + .checked_mul(costs::PROMISE_RESULT_BYTE_COST) + .and_then(|result| result.checked_add(cost)) + .ok_or(ExitError::Other(Cow::Borrowed("ERR_OVERFLOW_NUMBER")))?; check_cost(cost)?; results.push(result); } @@ -84,7 +88,7 @@ mod tests { fn test_get_promise_results_precompile_id() { assert_eq!( promise_result::ADDRESS, - near_account_to_evm_address("getPromiseResults".as_bytes()) + near_account_to_evm_address(b"getPromiseResults") ); } } diff --git a/engine-precompiles/src/random.rs b/engine-precompiles/src/random.rs index 423b26e1f..92bae55bd 100644 --- a/engine-precompiles/src/random.rs +++ b/engine-precompiles/src/random.rs @@ -1,7 +1,7 @@ use super::{EvmPrecompileResult, Precompile}; use crate::prelude::types::{Address, EthGas}; use crate::prelude::H256; -use crate::PrecompileOutput; +use crate::{utils, PrecompileOutput}; use evm::{Context, ExitError}; mod costs { @@ -25,7 +25,8 @@ impl RandomSeed { pub const ADDRESS: Address = super::make_address(0xc104f484, 0x0573bed437190daf5d2898c2bdf928ac); - pub fn new(random_seed: H256) -> Self { + #[must_use] + pub const fn new(random_seed: H256) -> Self { Self { random_seed } } } @@ -39,9 +40,10 @@ impl Precompile for RandomSeed { &self, input: &[u8], target_gas: Option, - _context: &Context, + context: &Context, _is_static: bool, ) -> EvmPrecompileResult { + utils::validate_no_value_attached_to_precompile(context.apparent_value)?; let cost = Self::required_gas(input)?; if let Some(target_gas) = target_gas { if cost > target_gas { @@ -65,7 +67,7 @@ mod tests { fn test_precompile_id() { assert_eq!( RandomSeed::ADDRESS, - near_account_to_evm_address("randomSeed".as_bytes()) + near_account_to_evm_address(b"randomSeed") ); } } diff --git a/engine-precompiles/src/secp256k1.rs b/engine-precompiles/src/secp256k1.rs index 4e862a93d..a9b42cbe9 100644 --- a/engine-precompiles/src/secp256k1.rs +++ b/engine-precompiles/src/secp256k1.rs @@ -1,6 +1,8 @@ use crate::prelude::types::{Address, EthGas}; use crate::prelude::{sdk, vec::Vec, Borrowed, H256}; use crate::{EvmPrecompileResult, Precompile, PrecompileOutput}; +#[cfg(not(feature = "contract"))] +use aurora_engine_types::ToString; use evm::{Context, ExitError}; mod costs { @@ -11,16 +13,18 @@ mod costs { mod consts { pub(super) const INPUT_LEN: usize = 128; + pub(super) const SIGNATURE_LENGTH: usize = 65; } -/// See: https://ethereum.github.io/yellowpaper/paper.pdf -/// See: https://docs.soliditylang.org/en/develop/units-and-global-variables.html#mathematical-and-cryptographic-functions -/// See: https://etherscan.io/address/0000000000000000000000000000000000000001 +/// See: `https://ethereum.github.io/yellowpaper/paper.pdf` +/// See: `https://docs.soliditylang.org/en/develop/units-and-global-variables.html#mathematical-and-cryptographic-functions` +/// See: `https://etherscan.io/address/0000000000000000000000000000000000000001` // Quite a few library methods rely on this and that should be changed. This // should only be for precompiles. -pub fn ecrecover(hash: H256, signature: &[u8]) -> Result { - assert_eq!(signature.len(), 65); - +pub fn ecrecover( + hash: H256, + signature: &[u8; consts::SIGNATURE_LENGTH], +) -> Result { #[cfg(feature = "contract")] return sdk::ecrecover(hash, signature).map_err(|e| ExitError::Other(Borrowed(e.as_str()))); @@ -30,9 +34,11 @@ pub fn ecrecover(hash: H256, signature: &[u8]) -> Result { #[cfg(not(feature = "contract"))] fn internal_impl(hash: H256, signature: &[u8]) -> Result { + use aurora_engine_types::Cow::Owned; use sha3::Digest; - let hash = libsecp256k1::Message::parse_slice(hash.as_bytes()).unwrap(); + let hash = libsecp256k1::Message::parse_slice(hash.as_bytes()) + .map_err(|e| ExitError::Other(Owned(e.to_string())))?; let v = signature[64]; let signature = libsecp256k1::Signature::parse_standard_slice(&signature[0..64]) .map_err(|_| ExitError::Other(Borrowed(sdk::ECRecoverErr.as_str())))?; @@ -87,7 +93,7 @@ impl Precompile for ECRecover { let mut v = [0; 32]; v.copy_from_slice(&input[32..64]); - let mut signature = [0; 65]; // signature is (r, s, v), typed (uint256, uint256, uint8) + let mut signature = [0; consts::SIGNATURE_LENGTH]; // signature is (r, s, v), typed (uint256, uint256, uint8) signature[0..32].copy_from_slice(&input[64..96]); // r signature[32..64].copy_from_slice(&input[96..128]); // s @@ -100,14 +106,13 @@ impl Precompile for ECRecover { signature[64] = v_bit; // v let address_res = ecrecover(H256::from_slice(&hash), &signature); - let output = match address_res { - Ok(a) => { + let output = address_res + .map(|a| { let mut output = [0u8; 32]; output[12..32].copy_from_slice(a.as_bytes()); output.to_vec() - } - Err(_) => Vec::new(), - }; + }) + .unwrap_or_default(); Ok(PrecompileOutput::without_logs(cost, output)) } @@ -119,7 +124,7 @@ mod tests { use crate::utils::new_context; fn ecverify(hash: H256, signature: &[u8], signer: Address) -> bool { - matches!(ecrecover(hash, signature), Ok(s) if s == signer) + matches!(ecrecover(hash, signature[0..super::consts::SIGNATURE_LENGTH].try_into().unwrap()), Ok(s) if s == signer) } #[test] @@ -248,4 +253,17 @@ mod tests { .output; assert_eq!(res, expected); } + + #[test] + fn test_extra_input_length() { + let input = hex::decode("18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549aabbccddeeff").unwrap(); + let expected = + hex::decode("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b") + .unwrap(); + let res = ECRecover + .run(&input, Some(EthGas::new(3_000)), &new_context(), false) + .unwrap() + .output; + assert_eq!(res, expected); + } } diff --git a/engine-precompiles/src/utils.rs b/engine-precompiles/src/utils.rs index b0edcb643..846f6dbd0 100644 --- a/engine-precompiles/src/utils.rs +++ b/engine-precompiles/src/utils.rs @@ -1,18 +1,30 @@ use crate::prelude::Borrowed; +use aurora_engine_types::U256; use core::num::TryFromIntError; + #[cfg(test)] use evm::Context; use evm::ExitError; #[cfg(test)] pub fn new_context() -> Context { + use aurora_engine_types::H160; + Context { - address: Default::default(), - caller: Default::default(), - apparent_value: Default::default(), + address: H160::default(), + caller: H160::default(), + apparent_value: U256::default(), } } -pub fn err_usize_conv(_e: TryFromIntError) -> ExitError { +pub const fn err_usize_conv(_e: TryFromIntError) -> ExitError { ExitError::Other(Borrowed("ERR_USIZE_CONVERSION")) } + +pub fn validate_no_value_attached_to_precompile(value: U256) -> Result<(), ExitError> { + if value > U256::zero() { + // don't attach native token value to that precompile + return Err(ExitError::Other(Borrowed("ATTACHED_VALUE_ERROR"))); + } + Ok(()) +} diff --git a/engine-precompiles/src/xcc.rs b/engine-precompiles/src/xcc.rs index d902a3f7b..0f768b42d 100644 --- a/engine-precompiles/src/xcc.rs +++ b/engine-precompiles/src/xcc.rs @@ -3,7 +3,7 @@ //! Allow Aurora users interacting with NEAR smart contracts using cross contract call primitives. //! TODO: How they work (low level explanation with examples) -use crate::{HandleBasedPrecompile, PrecompileOutput}; +use crate::{utils, HandleBasedPrecompile, PrecompileOutput}; use aurora_engine_sdk::io::IO; use aurora_engine_types::{ account_id::AccountId, @@ -36,7 +36,7 @@ pub mod costs { /// See `CROSS_CONTRACT_CALL_BASE` for estimation methodology. pub const CROSS_CONTRACT_CALL_BYTE: EthGas = EthGas::new(3); /// EVM gas cost per NEAR gas attached to the created promise. - /// This value is derived from the gas report https://hackmd.io/@birchmd/Sy4piXQ29 + /// This value is derived from the gas report `https://hackmd.io/@birchmd/Sy4piXQ29` /// The units on this quantity are `NEAR Gas / EVM Gas`. /// The report gives a value `0.175 T(NEAR_gas) / k(EVM_gas)`. To convert the units to /// `NEAR Gas / EVM Gas`, we simply multiply `0.175 * 10^12 / 10^3 = 175 * 10^6`. @@ -55,7 +55,7 @@ mod consts { pub(super) const ROUTER_EXEC_NAME: &str = "execute"; pub(super) const ROUTER_SCHEDULE_NAME: &str = "schedule"; /// Solidity selector for the ERC-20 transferFrom function - /// https://www.4byte.directory/signatures/?bytes4_signature=0x23b872dd + /// `https://www.4byte.directory/signatures/?bytes4_signature=0x23b872dd` pub(super) const TRANSFER_FROM_SELECTOR: [u8; 4] = [0x23, 0xb8, 0x72, 0xdd]; } @@ -65,7 +65,7 @@ pub struct CrossContractCall { } impl CrossContractCall { - pub fn new(engine_account_id: AccountId, io: I) -> Self { + pub const fn new(engine_account_id: AccountId, io: I) -> Self { Self { io, engine_account_id, @@ -85,11 +85,14 @@ pub mod cross_contract_call { /// Sentinel value used to indicate the following topic field is how much NEAR the /// cross-contract call will require. - pub const AMOUNT_TOPIC: H256 = - crate::make_h256(0x72657175697265645f6e656172, 0x72657175697265645f6e656172); + pub const AMOUNT_TOPIC: H256 = crate::make_h256( + 0x0072657175697265645f6e656172, + 0x0072657175697265645f6e656172, + ); } impl HandleBasedPrecompile for CrossContractCall { + #[allow(clippy::too_many_lines)] fn run_with_handle( &self, handle: &mut impl PrecompileHandle, @@ -97,6 +100,7 @@ impl HandleBasedPrecompile for CrossContractCall { let input = handle.input(); let target_gas = handle.gas_limit().map(EthGas::new); let context = handle.context(); + utils::validate_no_value_attached_to_precompile(context.apparent_value)?; let is_static = handle.is_static(); // This only includes the cost we can easily derive without parsing the input. @@ -261,18 +265,23 @@ pub mod state { pub struct CodeVersion(pub u32); impl CodeVersion { - pub fn increment(self) -> Self { + #[must_use] + pub const fn increment(self) -> Self { Self(self.0 + 1) } } - /// Get the address of the wNEAR ERC-20 contract + /// Get the address of the `wNEAR` ERC-20 contract + /// + /// # Panics + /// + /// Panic is ok here because there is no sense to continue with corrupted storage. pub fn get_wnear_address(io: &I) -> Address { let key = storage::bytes_to_key(KeyPrefix::CrossContractCall, WNEAR_KEY); - match io.read_storage(&key) { - Some(bytes) => Address::try_from_slice(&bytes.to_vec()).expect(ERR_CORRUPTED_STORAGE), - None => panic!("{}", ERR_MISSING_WNEAR_ADDRESS), - } + io.read_storage(&key).map_or_else( + || panic!("{ERR_MISSING_WNEAR_ADDRESS}"), + |bytes| Address::try_from_slice(&bytes.to_vec()).expect(ERR_CORRUPTED_STORAGE), + ) } /// Get the latest router contract version. @@ -309,7 +318,7 @@ fn transfer_from_args(from: H160, to: H160, amount: U256) -> Vec { fn create_target_account_id(sender: H160, engine_account_id: &str) -> AccountId { format!("{}.{}", hex::encode(sender.as_bytes()), engine_account_id) .parse() - .unwrap() + .unwrap_or_default() } fn revert_with_message(message: &str) -> PrecompileFailure { @@ -330,7 +339,7 @@ mod tests { fn test_precompile_id() { assert_eq!( cross_contract_call::ADDRESS, - near_account_to_evm_address("nearCrossContractCall".as_bytes()) + near_account_to_evm_address(b"nearCrossContractCall") ); } @@ -366,7 +375,7 @@ mod tests { }, ], outputs: vec![ethabi::Param { - name: "".into(), + name: String::new(), kind: ethabi::ParamType::Bool, internal_type: None, }], diff --git a/engine-sdk/.catalog-info.yaml b/engine-sdk/.catalog-info.yaml new file mode 100644 index 000000000..7a72f7d77 --- /dev/null +++ b/engine-sdk/.catalog-info.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: aurora-engine-sdk + description: |- + Helper library for interacting with NEAR Blockchain, used by the engine, tests and contracts that need to interact with the engine. + tags: + - contract-library + - near + links: [] + annotations: + aurora.dev/security-tier: "1" +spec: + owner: engine-team + type: contract-library + lifecycle: production + system: aurora-engine + interactsWith: [] diff --git a/engine-sdk/Cargo.toml b/engine-sdk/Cargo.toml index 11aaef8bf..4d8f67854 100644 --- a/engine-sdk/Cargo.toml +++ b/engine-sdk/Cargo.toml @@ -14,12 +14,14 @@ autobenches = false [dependencies] aurora-engine-types = { path = "../engine-types", default-features = false } -borsh = { version = "0.9.3", default-features = false } -sha3 = { version = "0.10.2", default-features = false } -sha2 = { version = "0.10.2", default-features = false } + +base64 = { version = "0.21", default-features = false, features = [ "alloc" ] } +borsh = { version = "0.10", default-features = false } +sha2 = { version = "0.10", default-features = false } +sha3 = { version = "0.10", default-features = false } [features] -std = ["aurora-engine-types/std", "borsh/std", "sha3/std", "sha2/std"] +std = ["aurora-engine-types/std", "borsh/std", "sha3/std", "sha2/std", "base64/std" ] contract = [] log = [] all-promise-actions = [] diff --git a/engine-sdk/src/base64.rs b/engine-sdk/src/base64.rs new file mode 100644 index 000000000..c8e444f02 --- /dev/null +++ b/engine-sdk/src/base64.rs @@ -0,0 +1,13 @@ +use aurora_engine_types::{String, Vec}; +pub use base64::DecodeError; +use base64::Engine; + +/// Encode arbitrary octets as base64 using the standard `base64::Engine`. +pub fn encode>(input: T) -> String { + base64::engine::general_purpose::STANDARD.encode(input) +} + +/// Decode from string reference as octets using the standard `base64::Engine`. +pub fn decode>(input: T) -> Result, DecodeError> { + base64::engine::general_purpose::STANDARD.decode(input) +} diff --git a/engine-sdk/src/caching.rs b/engine-sdk/src/caching.rs index 310d91a3f..d2baa6c6a 100644 --- a/engine-sdk/src/caching.rs +++ b/engine-sdk/src/caching.rs @@ -1,6 +1,6 @@ use aurora_engine_types::BTreeMap; -/// A naive cache storing all key-value pairs it learns about.. +/// A naive cache storing all key-value pairs it learns about. #[derive(Default)] pub struct FullCache { inner: BTreeMap, diff --git a/engine-sdk/src/env.rs b/engine-sdk/src/env.rs index 6140f823a..03e000d12 100644 --- a/engine-sdk/src/env.rs +++ b/engine-sdk/src/env.rs @@ -9,19 +9,23 @@ pub const DEFAULT_PREPAID_GAS: NearGas = NearGas::new(300_000_000_000_000); pub struct Timestamp(u64); impl Timestamp { - pub fn new(ns: u64) -> Self { + #[must_use] + pub const fn new(ns: u64) -> Self { Self(ns) } - pub fn nanos(&self) -> u64 { + #[must_use] + pub const fn nanos(&self) -> u64 { self.0 } - pub fn millis(&self) -> u64 { + #[must_use] + pub const fn millis(&self) -> u64 { self.0 / 1_000_000 } - pub fn secs(&self) -> u64 { + #[must_use] + pub const fn secs(&self) -> u64 { self.0 / 1_000_000_000 } } diff --git a/engine-sdk/src/lib.rs b/engine-sdk/src/lib.rs index 2c93b7088..d4b5965e5 100644 --- a/engine-sdk/src/lib.rs +++ b/engine-sdk/src/lib.rs @@ -1,11 +1,18 @@ #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(not(feature = "std"), feature(alloc_error_handler))] +#![deny(clippy::pedantic, clippy::nursery)] +#![allow( + clippy::module_name_repetitions, + clippy::missing_panics_doc, + clippy::missing_errors_doc, + clippy::as_conversions +)] #[cfg(feature = "contract")] use crate::prelude::{Address, Vec, U256}; use crate::prelude::{H256, STORAGE_PRICE_PER_BYTE}; pub use types::keccak; +pub mod base64; pub mod caching; pub mod env; pub mod error; @@ -43,17 +50,19 @@ pub fn log_utf8(bytes: &[u8]) { /// Calls environment sha256 on given input. #[cfg(feature = "contract")] +#[must_use] pub fn sha256(input: &[u8]) -> H256 { unsafe { const REGISTER_ID: u64 = 1; exports::sha256(input.len() as u64, input.as_ptr() as u64, 1); let bytes = H256::zero(); - exports::read_register(REGISTER_ID, bytes.0.as_ptr() as *const u64 as u64); + exports::read_register(REGISTER_ID, bytes.0.as_ptr() as u64); bytes } } #[cfg(not(feature = "contract"))] +#[must_use] pub fn sha256(input: &[u8]) -> H256 { use sha2::Digest; @@ -63,6 +72,7 @@ pub fn sha256(input: &[u8]) -> H256 { /// Calls environment ripemd160 on given input. #[cfg(feature = "contract")] +#[must_use] pub fn ripemd160(input: &[u8]) -> [u8; 20] { unsafe { const REGISTER_ID: u64 = 1; @@ -74,6 +84,7 @@ pub fn ripemd160(input: &[u8]) -> [u8; 20] { } #[cfg(feature = "contract")] +#[must_use] pub fn alt_bn128_g1_sum(left: [u8; 64], right: [u8; 64]) -> [u8; 64] { let mut bytes = Vec::with_capacity(64 * 2 + 2); // 64 bytes per G1 + 2 positive integer bytes. @@ -99,6 +110,7 @@ pub fn alt_bn128_g1_sum(left: [u8; 64], right: [u8; 64]) -> [u8; 64] { } #[cfg(feature = "contract")] +#[must_use] pub fn alt_bn128_g1_scalar_multiple(g1: [u8; 64], fr: [u8; 32]) -> [u8; 64] { let mut bytes = [0u8; 96]; bytes[0..64].copy_from_slice(&g1); @@ -146,20 +158,21 @@ where #[cfg(feature = "contract")] pub fn ecrecover(hash: H256, signature: &[u8]) -> Result { unsafe { - let hash_ptr = hash.as_ptr() as u64; - let sig_ptr = signature.as_ptr() as u64; const RECOVER_REGISTER_ID: u64 = 1; const KECCACK_REGISTER_ID: u64 = 2; + + let hash_ptr = hash.as_ptr() as u64; + let sig_ptr = signature.as_ptr() as u64; let result = exports::ecrecover( ECRECOVER_MESSAGE_SIZE, hash_ptr, ECRECOVER_SIGNATURE_LENGTH, sig_ptr, - signature[64] as u64, + u64::from(signature[64]), ECRECOVER_MALLEABILITY_FLAG, RECOVER_REGISTER_ID, ); - if result == (true as u64) { + if result == u64::from(true) { // The result from the ecrecover call is in a register; we can use this // register directly for the input to keccak256. This is why the length is // set to `u64::MAX`. @@ -175,10 +188,11 @@ pub fn ecrecover(hash: H256, signature: &[u8]) -> Result #[cfg(feature = "contract")] pub fn log(data: &str) { - log_utf8(data.as_bytes()) + log_utf8(data.as_bytes()); } #[cfg(not(feature = "contract"))] +#[allow(clippy::missing_const_for_fn)] pub fn log(_data: &str) { // TODO: standalone logging } @@ -191,14 +205,16 @@ macro_rules! log { }; } -pub fn storage_byte_cost() -> u128 { +#[must_use] +pub const fn storage_byte_cost() -> u128 { STORAGE_PRICE_PER_BYTE } pub struct ECRecoverErr; impl ECRecoverErr { - pub fn as_str(&self) -> &'static str { + #[must_use] + pub const fn as_str(&self) -> &'static str { "ERR_ECRECOVER" } } diff --git a/engine-sdk/src/near_runtime.rs b/engine-sdk/src/near_runtime.rs index c9dc79d4a..6ec665e6a 100644 --- a/engine-sdk/src/near_runtime.rs +++ b/engine-sdk/src/near_runtime.rs @@ -15,7 +15,7 @@ const CUSTODIAN_ADDRESS: &[u8] = &[ ]; #[cfg(feature = "testnet")] -/// The testnet eth_custodian address 0x84a82Bb39c83989D5Dc07e1310281923D2544dC2 +/// The testnet `eth_custodian` address 0x84a82Bb39c83989D5Dc07e1310281923D2544dC2 const CUSTODIAN_ADDRESS: &[u8] = &[ 132, 168, 43, 179, 156, 131, 152, 157, 93, 192, 126, 19, 16, 40, 25, 35, 210, 84, 77, 194, ]; @@ -49,7 +49,7 @@ impl Runtime { const GAS_FOR_STATE_MIGRATION: NearGas = NearGas::new(100_000_000_000_000); /// Deploy code from given key in place of the current contract. - /// Not implemented in terms of higher level traits (eg IO) for efficiency reasons. + /// Not implemented in terms of higher level traits (e.g. IO) for efficiency reasons. pub fn self_deploy(code_key: &[u8]) { unsafe { // Load current account id into register 0. @@ -57,27 +57,28 @@ impl Runtime { // Use register 0 as the destination for the promise. let promise_id = exports::promise_batch_create(u64::MAX as _, 0); // Remove code from storage and store it in register 1. - exports::storage_remove(code_key.len() as _, code_key.as_ptr() as _, 1); - exports::promise_batch_action_deploy_contract(promise_id, u64::MAX, 1); - Self::promise_batch_action_function_call( - promise_id, - b"state_migration", - &[], - 0, - Self::GAS_FOR_STATE_MIGRATION.as_u64(), - ) + // if the code_key exists call `promise_batch_action_deploy_contract`, otherwise panic with error. + match exports::storage_remove(code_key.len() as _, code_key.as_ptr() as _, 1) { + 1 => { + exports::promise_batch_action_deploy_contract(promise_id, u64::MAX, 1); + Self::promise_batch_action_function_call( + promise_id, + b"state_migration", + &[], + 0, + Self::GAS_FOR_STATE_MIGRATION.as_u64(), + ); + } + _ => panic!("ERR_NO_CODE_STAGED"), + }; } } - /// Assumes a valid account ID has been written to ENV_REGISTER_ID + /// Assumes a valid account ID has been written to `ENV_REGISTER_ID` /// by a previous call. fn read_account_id() -> AccountId { let bytes = Self::ENV_REGISTER_ID.to_vec(); - match AccountId::try_from(bytes) { - Ok(account_id) => account_id, - // the environment must give us a valid Account ID. - Err(_) => unreachable!(), - } + AccountId::try_from(bytes).map_or_else(|_| unreachable!(), |account_id| account_id) } /// Convenience wrapper around `exports::promise_batch_action_function_call` @@ -95,9 +96,9 @@ impl Runtime { method_name.as_ptr() as _, arguments.len() as _, arguments.as_ptr() as _, - &amount as *const u128 as _, + core::ptr::addr_of!(amount) as _, gas, - ) + ); } } } @@ -107,9 +108,9 @@ impl StorageIntermediate for RegisterIndex { unsafe { let result = exports::register_len(self.0); // By convention, an unused register will return a length of U64::MAX - // (see https://nomicon.io/RuntimeSpec/Components/BindingsSpec/RegistersAPI.html). + // (see https://nomicon.io/RuntimeSpec/Components/BindingsSpec/RegistersAPI). if result < u64::MAX { - result as usize + usize::try_from(result).unwrap_or_default() } else { 0 } @@ -130,17 +131,18 @@ impl crate::io::IO for Runtime { fn read_input(&self) -> Self::StorageValue { unsafe { - exports::input(Runtime::INPUT_REGISTER_ID.0); + exports::input(Self::INPUT_REGISTER_ID.0); } - Runtime::INPUT_REGISTER_ID + Self::INPUT_REGISTER_ID } fn return_output(&mut self, value: &[u8]) { unsafe { #[cfg(any(feature = "mainnet", feature = "testnet"))] - if value.len() >= 56 && &value[36..56] == CUSTODIAN_ADDRESS { - panic!("ERR_ILLEGAL_RETURN"); - } + assert!( + !(value.len() >= 56 && &value[36..56] == CUSTODIAN_ADDRESS), + "ERR_ILLEGAL_RETURN" + ); exports::value_return(value.len() as u64, value.as_ptr() as u64); } } @@ -150,10 +152,10 @@ impl crate::io::IO for Runtime { if exports::storage_read( key.len() as u64, key.as_ptr() as u64, - Runtime::READ_STORAGE_REGISTER_ID.0, + Self::READ_STORAGE_REGISTER_ID.0, ) == 1 { - Some(Runtime::READ_STORAGE_REGISTER_ID) + Some(Self::READ_STORAGE_REGISTER_ID) } else { None } @@ -171,10 +173,10 @@ impl crate::io::IO for Runtime { key.as_ptr() as u64, value.len() as u64, value.as_ptr() as u64, - Runtime::WRITE_REGISTER_ID.0, + Self::WRITE_REGISTER_ID.0, ) == 1 { - Some(Runtime::WRITE_REGISTER_ID) + Some(Self::WRITE_REGISTER_ID) } else { None } @@ -192,10 +194,10 @@ impl crate::io::IO for Runtime { key.as_ptr() as _, u64::MAX, value.0, - Runtime::WRITE_REGISTER_ID.0, + Self::WRITE_REGISTER_ID.0, ) == 1 { - Some(Runtime::WRITE_REGISTER_ID) + Some(Self::WRITE_REGISTER_ID) } else { None } @@ -204,13 +206,10 @@ impl crate::io::IO for Runtime { fn remove_storage(&mut self, key: &[u8]) -> Option { unsafe { - if exports::storage_remove( - key.len() as _, - key.as_ptr() as _, - Runtime::EVICT_REGISTER_ID.0, - ) == 1 + if exports::storage_remove(key.len() as _, key.as_ptr() as _, Self::EVICT_REGISTER_ID.0) + == 1 { - Some(Runtime::EVICT_REGISTER_ID) + Some(Self::EVICT_REGISTER_ID) } else { None } @@ -261,7 +260,7 @@ impl crate::env::Env for Runtime { unsafe { exports::random_seed(0); let bytes = H256::zero(); - exports::read_register(0, bytes.0.as_ptr() as *const u64 as u64); + exports::read_register(0, bytes.0.as_ptr() as u64); bytes } } @@ -307,7 +306,7 @@ impl crate::promise::PromiseHandler for Runtime { method_name.as_ptr() as _, arguments.len() as _, arguments.as_ptr() as _, - &amount as *const u128 as _, + core::ptr::addr_of!(amount) as _, gas, ) }; @@ -334,7 +333,7 @@ impl crate::promise::PromiseHandler for Runtime { method_name.as_ptr() as _, arguments.len() as _, arguments.as_ptr() as _, - &amount as *const u128 as _, + core::ptr::addr_of!(amount) as _, gas, ) }; @@ -342,19 +341,21 @@ impl crate::promise::PromiseHandler for Runtime { PromiseId::new(id) } + #[allow(clippy::too_many_lines)] unsafe fn promise_create_batch(&mut self, args: &PromiseBatchAction) -> PromiseId { let account_id = args.target_account_id.as_bytes(); let id = { exports::promise_batch_create(account_id.len() as _, account_id.as_ptr() as _) }; - for action in args.actions.iter() { + for action in &args.actions { match action { PromiseAction::CreateAccount => { exports::promise_batch_action_create_account(id); } PromiseAction::Transfer { amount } => { let amount = amount.as_u128(); - exports::promise_batch_action_transfer(id, &amount as *const u128 as _); + let amount_addr = core::ptr::addr_of!(amount); + exports::promise_batch_action_transfer(id, amount_addr as _); } PromiseAction::DeployContract { code } => { let code = code.as_slice(); @@ -373,27 +374,29 @@ impl crate::promise::PromiseHandler for Runtime { let method_name = name.as_bytes(); let arguments = args.as_slice(); let amount = attached_yocto.as_u128(); + let amount_addr = core::ptr::addr_of!(amount); exports::promise_batch_action_function_call( id, method_name.len() as _, method_name.as_ptr() as _, arguments.len() as _, arguments.as_ptr() as _, - &amount as *const u128 as _, + amount_addr as _, gas.as_u64(), - ) + ); } PromiseAction::Stake { amount, public_key } => { feature_gated!("all-promise-actions", { let amount = amount.as_u128(); + let amount_addr = core::ptr::addr_of!(amount); let pk: RawPublicKey = public_key.into(); let pk_bytes = pk.as_bytes(); exports::promise_batch_action_stake( id, - &amount as *const u128 as _, + amount_addr as _, pk_bytes.len() as _, pk_bytes.as_ptr() as _, - ) + ); }); } PromiseAction::AddFullAccessKey { public_key, nonce } => { @@ -405,7 +408,7 @@ impl crate::promise::PromiseHandler for Runtime { pk_bytes.len() as _, pk_bytes.as_ptr() as _, *nonce, - ) + ); }); } PromiseAction::AddFunctionCallKey { @@ -419,6 +422,7 @@ impl crate::promise::PromiseHandler for Runtime { let pk: RawPublicKey = public_key.into(); let pk_bytes = pk.as_bytes(); let allowance = allowance.as_u128(); + let allowance_addr = core::ptr::addr_of!(allowance); let receiver_id = receiver_id.as_bytes(); let function_names = function_names.as_bytes(); exports::promise_batch_action_add_key_with_function_call( @@ -426,12 +430,12 @@ impl crate::promise::PromiseHandler for Runtime { pk_bytes.len() as _, pk_bytes.as_ptr() as _, *nonce, - &allowance as *const u128 as _, + allowance_addr as _, receiver_id.len() as _, receiver_id.as_ptr() as _, function_names.len() as _, function_names.as_ptr() as _, - ) + ); }); } PromiseAction::DeleteKey { public_key } => { @@ -442,7 +446,7 @@ impl crate::promise::PromiseHandler for Runtime { id, pk_bytes.len() as _, pk_bytes.as_ptr() as _, - ) + ); }); } PromiseAction::DeleteAccount { beneficiary_id } => { @@ -452,7 +456,7 @@ impl crate::promise::PromiseHandler for Runtime { id, beneficiary_id.len() as _, beneficiary_id.as_ptr() as _, - ) + ); }); } } @@ -470,9 +474,25 @@ impl crate::promise::PromiseHandler for Runtime { fn read_only(&self) -> Self::ReadOnly { Self } + + // An optimized version of the default implementation where we do not copy over the + // result bytes of all the successful promise results. + fn promise_result_check(&self) -> Option { + let num_promises = self.promise_results_count(); + if num_promises == 0 { + return None; + } + for index in 0..num_promises { + let status = unsafe { exports::promise_result(index, Self::PROMISE_REGISTER_ID.0) }; + if status != 1 { + return Some(false); + } + } + Some(true) + } } -/// Similar to NearPublicKey, except the first byte includes +/// Similar to `NearPublicKey`, except the first byte includes /// the curve identifier. enum RawPublicKey { Ed25519([u8; 33]), @@ -480,7 +500,7 @@ enum RawPublicKey { } impl RawPublicKey { - fn as_bytes(&self) -> &[u8] { + const fn as_bytes(&self) -> &[u8] { match self { Self::Ed25519(bytes) => bytes, Self::Secp256k1(bytes) => bytes, @@ -543,7 +563,7 @@ impl crate::env::Env for ViewEnv { unsafe { exports::random_seed(0); let bytes = H256::zero(); - exports::read_register(0, bytes.0.as_ptr() as *const u64 as u64); + exports::read_register(0, bytes.0.as_ptr() as u64); bytes } } diff --git a/engine-sdk/src/promise.rs b/engine-sdk/src/promise.rs index 17f5a03cb..d75612ce1 100644 --- a/engine-sdk/src/promise.rs +++ b/engine-sdk/src/promise.rs @@ -7,11 +7,13 @@ use aurora_engine_types::types::PromiseResult; pub struct PromiseId(u64); impl PromiseId { - pub fn new(id: u64) -> Self { + #[must_use] + pub const fn new(id: u64) -> Self { Self(id) } - pub fn raw(self) -> u64 { + #[must_use] + pub const fn raw(self) -> u64 { self.0 } } @@ -54,6 +56,25 @@ pub trait PromiseHandler { } fn read_only(&self) -> Self::ReadOnly; + + /// Returns `None` if there were no prior promises + /// (i.e. the method was not called as a callback). Returns `Some(true)` if + /// there was at least one promise result and all results were successful. + /// Returns `Some(false)` if there was at least one failed promise result. + fn promise_result_check(&self) -> Option { + let num_promises = self.promise_results_count(); + if num_promises == 0 { + return None; + } + for index in 0..num_promises { + if let Some(PromiseResult::Failed | PromiseResult::NotReady) = + self.promise_result(index) + { + return Some(false); + } + } + Some(true) + } } pub trait ReadOnlyPromiseHandler { diff --git a/engine-sdk/src/types.rs b/engine-sdk/src/types.rs index 571019922..f52cdabcb 100644 --- a/engine-sdk/src/types.rs +++ b/engine-sdk/src/types.rs @@ -7,23 +7,26 @@ use sha3::{Digest, Keccak256}; #[cfg(feature = "contract")] #[inline] +#[must_use] pub fn keccak(input: &[u8]) -> H256 { unsafe { super::exports::keccak256(input.len() as u64, input.as_ptr() as u64, 1); let bytes = H256::zero(); - super::exports::read_register(1, bytes.0.as_ptr() as *const u64 as u64); + super::exports::read_register(1, bytes.0.as_ptr() as u64); bytes } } #[cfg(not(feature = "contract"))] #[inline] +#[must_use] pub fn keccak(data: &[u8]) -> H256 { H256::from_slice(Keccak256::digest(data).as_slice()) } -pub fn near_account_to_evm_address(addr: &[u8]) -> Address { - Address::try_from_slice(&keccak(addr)[12..]).unwrap() +#[must_use] +pub fn near_account_to_evm_address(account_id: &[u8]) -> Address { + Address::try_from_slice(&keccak(account_id)[12..]).unwrap() } #[cfg(feature = "contract")] @@ -34,20 +37,14 @@ pub trait ExpectUtf8 { #[cfg(feature = "contract")] impl ExpectUtf8 for Option { fn expect_utf8(self, message: &[u8]) -> T { - match self { - Some(t) => t, - None => crate::panic_utf8(message), - } + self.unwrap_or_else(|| crate::panic_utf8(message)) } } #[cfg(feature = "contract")] -impl ExpectUtf8 for core::result::Result { +impl ExpectUtf8 for Result { fn expect_utf8(self, message: &[u8]) -> T { - match self { - Ok(t) => t, - Err(_) => crate::panic_utf8(message), - } + self.unwrap_or_else(|_| crate::panic_utf8(message)) } } @@ -59,20 +56,14 @@ pub trait SdkExpect { #[cfg(feature = "contract")] impl SdkExpect for Option { fn sdk_expect(self, msg: &str) -> T { - match self { - Some(t) => t, - None => crate::panic_utf8(msg.as_ref()), - } + self.unwrap_or_else(|| crate::panic_utf8(msg.as_bytes())) } } #[cfg(feature = "contract")] -impl SdkExpect for core::result::Result { +impl SdkExpect for Result { fn sdk_expect(self, msg: &str) -> T { - match self { - Ok(t) => t, - Err(_) => crate::panic_utf8(msg.as_ref()), - } + self.unwrap_or_else(|_| crate::panic_utf8(msg.as_bytes())) } } @@ -84,15 +75,12 @@ pub trait SdkUnwrap { #[cfg(feature = "contract")] impl SdkUnwrap for Option { fn sdk_unwrap(self) -> T { - match self { - Some(t) => t, - None => crate::panic_utf8("ERR_UNWRAP".as_bytes()), - } + self.unwrap_or_else(|| crate::panic_utf8(b"ERR_UNWRAP")) } } #[cfg(feature = "contract")] -impl> SdkUnwrap for core::result::Result { +impl> SdkUnwrap for Result { fn sdk_unwrap(self) -> T { match self { Ok(t) => t, diff --git a/engine-standalone-storage/.catalog-info.yaml b/engine-standalone-storage/.catalog-info.yaml new file mode 100644 index 000000000..590588d6f --- /dev/null +++ b/engine-standalone-storage/.catalog-info.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: aurora-engine-standalone-storage + description: |- + Aurora engine standalone storage library. Provides the storage backend used by the standalone engine. + tags: + - near + links: [] + annotations: + aurora.dev/security-tier: "2" +spec: + owner: engine-team + type: contract-tests + lifecycle: production + system: aurora-engine + interactsWith: [] diff --git a/engine-standalone-storage/Cargo.toml b/engine-standalone-storage/Cargo.toml index 889e14d9f..93075b8c1 100644 --- a/engine-standalone-storage/Cargo.toml +++ b/engine-standalone-storage/Cargo.toml @@ -19,14 +19,13 @@ aurora-engine-types = { path = "../engine-types", default-features = false, feat aurora-engine-sdk = { path = "../engine-sdk", default-features = false, features = ["std"] } aurora-engine-transactions = { path = "../engine-transactions", default-features = false, features = ["std"] } aurora-engine-precompiles = { path = "../engine-precompiles", default-features = false, features = ["std"] } -borsh = { version = "0.9.3" } -evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.3-aurora", default-features = false } +borsh = "0.10" +evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false } hex = "0.4.3" rocksdb = { version = "0.19.0", default-features = false } postgres = "0.19.2" serde = "1.0.130" serde_json = "1.0.72" -base64 = "0.13.0" [features] default = ["snappy", "lz4", "zstd", "zlib"] diff --git a/engine-standalone-storage/src/diff.rs b/engine-standalone-storage/src/diff.rs index 623756548..fc9002d3a 100644 --- a/engine-standalone-storage/src/diff.rs +++ b/engine-standalone-storage/src/diff.rs @@ -12,6 +12,7 @@ pub enum DiffValue { } impl DiffValue { + #[must_use] pub fn value(&self) -> Option<&[u8]> { match self { Self::Deleted => None, @@ -19,6 +20,8 @@ impl DiffValue { } } + #[must_use] + #[allow(clippy::missing_const_for_fn)] pub fn take_value(self) -> Option> { match self { Self::Deleted => None, @@ -51,9 +54,10 @@ impl Diff { } pub fn clear(&mut self) { - self.0.clear() + self.0.clear(); } + #[must_use] pub fn get(&self, key: &[u8]) -> Option<&DiffValue> { self.0.get(key) } @@ -66,6 +70,7 @@ impl Diff { self.0.iter() } + #[must_use] pub fn is_empty(&self) -> bool { self.0.is_empty() } diff --git a/engine-standalone-storage/src/engine_state.rs b/engine-standalone-storage/src/engine_state.rs index 2d5125253..05acde8d5 100644 --- a/engine-standalone-storage/src/engine_state.rs +++ b/engine-standalone-storage/src/engine_state.rs @@ -30,7 +30,7 @@ impl<'a> StorageIntermediate for EngineStorageValue<'a> { } fn copy_to_slice(&self, buffer: &mut [u8]) { - buffer.copy_from_slice(self.as_ref()) + buffer.copy_from_slice(self.as_ref()); } } @@ -45,7 +45,7 @@ pub struct EngineStateAccess<'db, 'input, 'output> { } impl<'db, 'input, 'output> EngineStateAccess<'db, 'input, 'output> { - pub fn new( + pub const fn new( input: &'input [u8], bound_block_height: u64, bound_tx_position: u16, @@ -63,6 +63,7 @@ impl<'db, 'input, 'output> EngineStateAccess<'db, 'input, 'output> { } } + #[must_use] pub fn get_transaction_diff(&self) -> Diff { self.transaction_diff.borrow().clone() } @@ -86,7 +87,7 @@ impl<'db, 'input: 'db, 'output: 'db> IO for EngineStateAccess<'db, 'input, 'outp } fn return_output(&mut self, value: &[u8]) { - self.output.set(value.to_vec()) + self.output.set(value.to_vec()); } fn read_storage(&self, key: &[u8]) -> Option { diff --git a/engine-standalone-storage/src/json_snapshot/mod.rs b/engine-standalone-storage/src/json_snapshot/mod.rs index 24ce4367f..67e9464a0 100644 --- a/engine-standalone-storage/src/json_snapshot/mod.rs +++ b/engine-standalone-storage/src/json_snapshot/mod.rs @@ -14,8 +14,8 @@ pub fn initialize_engine_state( let mut batch = rocksdb::WriteBatch::default(); for entry in snapshot.result.values { - let key = base64::decode(entry.key)?; - let value = base64::decode(entry.value)?; + let key = aurora_engine_sdk::base64::decode(entry.key)?; + let value = aurora_engine_sdk::base64::decode(entry.value)?; let storage_key = crate::construct_engine_key(&key, block_height, transaction_position); let storage_value = crate::diff::DiffValue::Modified(value); batch.put(storage_key, storage_value.try_to_bytes()?); @@ -26,15 +26,17 @@ pub fn initialize_engine_state( } pub mod error { + use aurora_engine_sdk::base64::DecodeError; + #[derive(Debug)] pub enum Error { - Base64(base64::DecodeError), + Base64(DecodeError), Rocksdb(rocksdb::Error), Borsh(std::io::Error), } - impl From for Error { - fn from(e: base64::DecodeError) -> Self { + impl From for Error { + fn from(e: DecodeError) -> Self { Self::Base64(e) } } @@ -54,7 +56,7 @@ pub mod error { #[cfg(test)] mod test { - /// Requires a JSON snapshot to work. This can be obtained from https://github.com/aurora-is-near/contract-state + /// Requires a JSON snapshot to work. This can be obtained from `https://github.com/aurora-is-near/contract-state` #[test] #[ignore] fn test_consume_snapshot() { diff --git a/engine-standalone-storage/src/lib.rs b/engine-standalone-storage/src/lib.rs index 0f536c09b..5bb24183a 100644 --- a/engine-standalone-storage/src/lib.rs +++ b/engine-standalone-storage/src/lib.rs @@ -1,3 +1,10 @@ +#![deny(clippy::pedantic, clippy::nursery)] +#![allow( + clippy::similar_names, + clippy::module_name_repetitions, + clippy::missing_panics_doc, + clippy::missing_errors_doc +)] use aurora_engine_sdk::env::Timestamp; use aurora_engine_types::{account_id::AccountId, H256}; use rocksdb::DB; @@ -37,6 +44,21 @@ pub enum StoragePrefix { EngineAccountId = 0x07, } +impl From for u8 { + fn from(value: StoragePrefix) -> Self { + match value { + StoragePrefix::BlockHash => 0x00, + StoragePrefix::BlockHeight => 0x01, + StoragePrefix::TransactionData => 0x02, + StoragePrefix::TransactionHash => 0x03, + StoragePrefix::Diff => 0x04, + StoragePrefix::Engine => 0x05, + StoragePrefix::BlockMetadata => 0x06, + StoragePrefix::EngineAccountId => 0x07, + } + } +} + const ACCOUNT_ID_KEY: &[u8] = b"engine_account_id"; pub struct Storage { @@ -129,7 +151,7 @@ impl Storage { &mut self, block_hash: H256, block_height: u64, - block_metadata: BlockMetadata, + block_metadata: &BlockMetadata, ) -> Result<(), rocksdb::Error> { let block_height_bytes = block_height.to_be_bytes(); @@ -191,7 +213,7 @@ impl Storage { ) -> Result<(), error::Error> { let batch = rocksdb::WriteBatch::default(); self.process_transaction(tx_hash, tx_included, diff, batch, |batch, key, value| { - batch.put(key, value) + batch.put(key, value); }) } @@ -203,7 +225,7 @@ impl Storage { ) -> Result<(), error::Error> { let batch = rocksdb::WriteBatch::default(); self.process_transaction(tx_hash, tx_included, diff, batch, |batch, key, _value| { - batch.delete(key) + batch.delete(key); }) } @@ -277,7 +299,7 @@ impl Storage { let tx_hash = self .get_transaction_by_position(tx_included) .unwrap_or_default(); - result.push((block_height, tx_hash, value)) + result.push((block_height, tx_hash, value)); } Ok(result) } @@ -315,11 +337,11 @@ impl Storage { let value = if iter.valid() { let bytes = iter.value().unwrap(); - diff::DiffValue::try_from_bytes(bytes).unwrap_or_else(|e| { + DiffValue::try_from_bytes(bytes).unwrap_or_else(|e| { panic!( "Could not deserialize key={} value={} error={:?}", - base64::encode(&db_key), - base64::encode(bytes), + aurora_engine_sdk::base64::encode(&db_key), + aurora_engine_sdk::base64::encode(bytes), e, ) }) @@ -334,14 +356,11 @@ impl Storage { // move to the next key by skipping all other DB keys corresponding to the same engine key while iter.valid() - && iter - .key() - .map(|db_key| { - db_key[0..engine_prefix_len] == engine_prefix - && &db_key[engine_prefix_len..(db_key.len() - ENGINE_KEY_SUFFIX_LEN)] - == engine_key - }) - .unwrap_or(false) + && iter.key().map_or(false, |db_key| { + db_key[0..engine_prefix_len] == engine_prefix + && &db_key[engine_prefix_len..(db_key.len() - ENGINE_KEY_SUFFIX_LEN)] + == engine_key + }) { iter.next(); } @@ -405,6 +424,7 @@ pub struct TransactionIncluded { } impl TransactionIncluded { + #[must_use] pub fn to_bytes(self) -> [u8; 34] { let mut bytes = [0u8; 34]; @@ -414,6 +434,7 @@ impl TransactionIncluded { bytes } + #[must_use] pub fn from_bytes(bytes: [u8; 34]) -> Self { let block_hash = H256::from_slice(&bytes[0..32]); let mut position = [0u8; 2]; @@ -436,6 +457,7 @@ pub struct BlockMetadata { } impl BlockMetadata { + #[must_use] pub fn to_bytes(&self) -> [u8; 40] { let mut buf = [0u8; 40]; buf[0..8].copy_from_slice(&self.timestamp.nanos().to_be_bytes()); @@ -443,6 +465,7 @@ impl BlockMetadata { buf } + #[must_use] pub fn from_bytes(bytes: [u8; 40]) -> Self { let nanos = { let mut buf = [0u8; 8]; @@ -463,7 +486,7 @@ impl BlockMetadata { } fn construct_storage_key(prefix: StoragePrefix, key: &[u8]) -> Vec { - [&[VERSION], &[prefix as u8], key].concat() + [&[VERSION], &[u8::from(prefix)], key].concat() } fn construct_engine_key(key: &[u8], block_height: u64, transaction_position: u16) -> Vec { diff --git a/engine-standalone-storage/src/promise.rs b/engine-standalone-storage/src/promise.rs index a508305b1..d19b5b9e2 100644 --- a/engine-standalone-storage/src/promise.rs +++ b/engine-standalone-storage/src/promise.rs @@ -22,10 +22,14 @@ impl<'a> PromiseHandler for NoScheduler<'a> { fn promise_result(&self, index: u64) -> Option { let i = usize::try_from(index).ok()?; - let result = match self.promise_data.get(i)? { - Some(bytes) => PromiseResult::Successful(bytes.clone()), - None => PromiseResult::Failed, - }; + let result = self + .promise_data + .get(i)? + .as_ref() + .map_or(PromiseResult::Failed, |bytes| { + PromiseResult::Successful(bytes.clone()) + }); + Some(result) } diff --git a/engine-standalone-storage/src/relayer_db/mod.rs b/engine-standalone-storage/src/relayer_db/mod.rs index 80fefca95..b4fe7e86f 100644 --- a/engine-standalone-storage/src/relayer_db/mod.rs +++ b/engine-standalone-storage/src/relayer_db/mod.rs @@ -1,4 +1,5 @@ -use aurora_engine::engine; +use aurora_engine::parameters::SubmitArgs; +use aurora_engine::{engine, state}; use aurora_engine_sdk::env::{self, Env, DEFAULT_PREPAID_GAS}; use aurora_engine_transactions::EthTransactionKind; use aurora_engine_types::account_id::AccountId; @@ -54,7 +55,7 @@ where }; storage - .set_block_data(row.hash, row.id, metadata) + .set_block_data(row.hash, row.id, &metadata) .map_err(crate::Error::Rocksdb)?; } Ok(()) @@ -63,7 +64,7 @@ where pub fn initialize_transactions( storage: &mut Storage, mut rows: I, - engine_state: engine::EngineState, + engine_state: &state::EngineState, ) -> Result<(), error::Error> where I: FallibleIterator, @@ -101,11 +102,15 @@ where env.block_timestamp = block_metadata.timestamp; env.random_seed = block_metadata.random_seed; + let args = SubmitArgs { + tx_data: transaction_bytes, + ..Default::default() + }; let result = storage.with_engine_access(block_height, transaction_position, &[], |io| { engine::submit( io, &env, - &transaction_bytes, + &args, engine_state.clone(), env.current_account_id(), relayer_address, @@ -118,9 +123,7 @@ where Err(e) => { if tx_succeeded { println!( - "WARN: Transaction with NEAR hash {:?} expected to succeed, but failed with error message {:?}", - near_tx_hash, - e + "WARN: Transaction with NEAR hash {near_tx_hash:?} expected to succeed, but failed with error message {e:?}", ); } continue; @@ -128,8 +131,7 @@ where Ok(result) => { if result.status.is_fail() && tx_succeeded { println!( - "WARN: Transaction with NEAR hash {:?} expected to succeed, but failed with error message {:?}", - near_tx_hash, + "WARN: Transaction with NEAR hash {near_tx_hash:?} expected to succeed, but failed with error message {:?}", result.status ); continue; @@ -159,13 +161,13 @@ where } pub mod error { - use aurora_engine::engine; + use aurora_engine::{engine, state}; #[derive(Debug)] pub enum Error { Storage(crate::Error), Postgres(postgres::Error), - EngineState(engine::EngineStateError), + EngineState(state::EngineStateError), Engine(engine::EngineError), } @@ -181,8 +183,8 @@ pub mod error { } } - impl From for Error { - fn from(e: engine::EngineStateError) -> Self { + impl From for Error { + fn from(e: state::EngineStateError) -> Self { Self::EngineState(e) } } @@ -197,21 +199,24 @@ pub mod error { #[cfg(test)] mod test { use super::FallibleIterator; + use crate::relayer_db::types::ConnectionParams; use crate::sync::types::{TransactionKind, TransactionMessage}; - use aurora_engine::{connector, engine, parameters}; + use aurora_engine::fungible_token::FungibleTokenMetadata; + use aurora_engine::{connector, parameters, state}; use aurora_engine_types::H256; + #[allow(clippy::doc_markdown)] /// Requires a running postgres server to work. A snapshot of the DB can be - /// downloaded using the script from https://github.com/aurora-is-near/partner-relayer-deploy + /// downloaded using the script from `https://github.com/aurora-is-near/partner-relayer-deploy` /// The postgres DB can be started in Docker using the following command: /// docker run --name mainnet_database -p '127.0.0.1:15432:5432' -v $PATH_TO_DB:/var/lib/postgresql/data auroraisnear/relayer-database:latest #[test] #[ignore] fn test_fill_db() { let mut storage = crate::Storage::open("rocks_tmp/").unwrap(); - let mut connection = super::connect_without_tls(&Default::default()).unwrap(); - let engine_state = engine::EngineState { - chain_id: aurora_engine_types::types::u256_to_arr(&1313161555.into()), + let mut connection = super::connect_without_tls(&ConnectionParams::default()).unwrap(); + let engine_state = state::EngineState { + chain_id: aurora_engine_types::types::u256_to_arr(&1_313_161_555.into()), owner_id: "aurora".parse().unwrap(), bridge_prover_id: "prover.bridge.near".parse().unwrap(), upgrade_delay_blocks: 0, @@ -227,19 +232,19 @@ mod test { random_seed: H256::zero(), }; storage - .set_block_data(block_hash, block_height, block_metadata) + .set_block_data(block_hash, block_height, &block_metadata) .unwrap(); let result = storage.with_engine_access(block_height, 0, &[], |io| { let mut local_io = io; - engine::set_state(&mut local_io, engine_state.clone()); + state::set_state(&mut local_io, &engine_state).unwrap(); connector::EthConnectorContract::create_contract( io, - engine_state.owner_id.clone(), + &engine_state.owner_id, parameters::InitCallArgs { prover_account: engine_state.bridge_prover_id.clone(), eth_custodian_address: "6bfad42cfc4efc96f529d786d643ff4a8b89fa52" .to_string(), - metadata: Default::default(), + metadata: FungibleTokenMetadata::default(), }, ) }); @@ -265,12 +270,16 @@ mod test { .unwrap(); } let block_rows = super::read_block_data(&mut connection).unwrap(); - super::initialize_blocks(&mut storage, block_rows.map(|row| Ok(row.into()))).unwrap(); + super::initialize_blocks( + &mut storage, + block_rows.map(|row| Ok(row.try_into().unwrap())), + ) + .unwrap(); let tx_rows = super::read_transaction_data(&mut connection).unwrap(); super::initialize_transactions( &mut storage, - tx_rows.map(|row| Ok(row.into())), - engine_state, + tx_rows.map(|row| Ok(row.try_into().unwrap())), + &engine_state, ) .unwrap(); diff --git a/engine-standalone-storage/src/relayer_db/types.rs b/engine-standalone-storage/src/relayer_db/types.rs index e7abc12ca..0abadf5a1 100644 --- a/engine-standalone-storage/src/relayer_db/types.rs +++ b/engine-standalone-storage/src/relayer_db/types.rs @@ -19,6 +19,7 @@ pub struct ConnectionParams { } impl ConnectionParams { + #[must_use] pub fn as_connection_string(&self) -> String { format!( "host={} port={} dbname={} user={} password={}", @@ -68,8 +69,10 @@ pub struct BlockRow { pub receipts_root: H256, } -impl From for BlockRow { - fn from(row: postgres::Row) -> Self { +impl TryFrom for BlockRow { + type Error = std::num::TryFromIntError; + + fn try_from(row: postgres::Row) -> Result { let chain: i32 = row.get("chain"); let id: i64 = row.get("id"); let hash = get_hash(&row, "hash"); @@ -83,20 +86,20 @@ impl From for BlockRow { let state_root = get_hash(&row, "state_root"); let receipts_root = get_hash(&row, "receipts_root"); - Self { - chain: chain as u64, - id: id as u64, + Ok(Self { + chain: chain.try_into()?, + id: id.try_into()?, hash, near_hash: near_hash.map(H256::from_slice), timestamp, - size: size as u32, + size: size.try_into()?, gas_limit, gas_used, parent_hash, transactions_root, state_root, receipts_root, - } + }) } } @@ -146,8 +149,10 @@ pub struct TransactionRow { pub output: Vec, } -impl From for TransactionRow { - fn from(row: postgres::Row) -> Self { +impl TryFrom for TransactionRow { + type Error = std::num::TryFromIntError; + + fn try_from(row: postgres::Row) -> Result { let block: i64 = row.get("block"); let block_hash = get_hash(&row, "block_hash"); let index: i32 = row.get("index"); @@ -169,11 +174,11 @@ impl From for TransactionRow { let status: bool = row.get("status"); let output: Option> = row.get("output"); - Self { - block: block as u64, + Ok(Self { + block: block.try_into()?, block_hash, - index: index as u16, - id: id as u64, + index: index.try_into()?, + id: id.try_into()?, hash, near_hash, near_receipt_hash, @@ -190,7 +195,7 @@ impl From for TransactionRow { s, status, output: output.unwrap_or_default(), - } + }) } } @@ -233,7 +238,7 @@ fn get_timestamp(row: &postgres::Row, field: &str) -> Option { let timestamp: Option = row.get(field); timestamp .and_then(|t| t.duration_since(SystemTime::UNIX_EPOCH).ok()) - .map(|d| d.as_nanos() as u64) + .and_then(|d| u64::try_from(d.as_nanos()).ok()) } struct PostgresNumeric { @@ -259,24 +264,36 @@ enum PostgresNumericSign { NaN = 0xc000, } +#[allow(clippy::fallible_impl_from)] +impl From for PostgresNumericSign { + fn from(value: u16) -> Self { + match value { + 0x0000 => Self::Positive, + 0x4000 => Self::Negative, + 0xc000 => Self::NaN, + _ => panic!("Unexpected PostgresNumericSign value"), + } + } +} + impl TryFrom for U256 { type Error = NumericToU256Error; fn try_from(value: PostgresNumeric) -> Result { - if let PostgresNumericSign::Negative = value.sign { + if matches!(value.sign, PostgresNumericSign::Negative) { return Err(NumericToU256Error::Negative); - } else if let PostgresNumericSign::NaN = value.sign { + } else if matches!(value.sign, PostgresNumericSign::NaN) { return Err(NumericToU256Error::NaN); } else if value.scale != 0 || value.weight < 0 { return Err(NumericToU256Error::NotAWholeNumber); } - let mut total = U256::zero(); + let mut total = Self::zero(); let mut weight = PostgresNumeric::BASE_WEIGHT .checked_pow(value.weight.into()) .ok_or(NumericToU256Error::Overflow)?; for group in value.groups { - let contribution = U256::from(group) + let contribution = Self::from(group) .checked_mul(weight) .ok_or(NumericToU256Error::Overflow)?; total = total @@ -316,25 +333,16 @@ impl<'a> postgres::types::FromSql<'a> for PostgresNumeric { let num_groups = read_u16(&mut cursor)?; let weight = read_i16(&mut cursor)?; - let sign_raw = read_u16(&mut cursor)?; - let sign = if sign_raw == PostgresNumericSign::Positive as u16 { - PostgresNumericSign::Positive - } else if sign_raw == PostgresNumericSign::Negative as u16 { - PostgresNumericSign::Negative - } else if sign_raw == PostgresNumericSign::NaN as u16 { - PostgresNumericSign::NaN - } else { - panic!("Unexpected Numeric Sign value"); - }; + let sign = sign_raw.into(); let scale = read_u16(&mut cursor)?; - let mut groups = Vec::with_capacity(num_groups as usize); + let mut groups = Vec::with_capacity(usize::from(num_groups)); for _ in 0..num_groups { groups.push(read_u16(&mut cursor)?); } - Ok(PostgresNumeric { + Ok(Self { weight, sign, scale, diff --git a/engine-standalone-storage/src/sync/mod.rs b/engine-standalone-storage/src/sync/mod.rs index 9142e6b86..63d5241d4 100644 --- a/engine-standalone-storage/src/sync/mod.rs +++ b/engine-standalone-storage/src/sync/mod.rs @@ -1,7 +1,8 @@ +use aurora_engine::parameters::SubmitArgs; use aurora_engine::pausables::{ EnginePrecompilesPauser, PausedPrecompilesManager, PrecompileFlags, }; -use aurora_engine::{connector, engine, parameters::SubmitResult, xcc}; +use aurora_engine::{connector, engine, parameters::SubmitResult, state, xcc}; use aurora_engine_sdk::env::{self, Env, DEFAULT_PREPAID_GAS}; use aurora_engine_types::{ account_id::AccountId, @@ -26,7 +27,7 @@ pub fn consume_message( let block_height = block_message.height; let block_metadata = block_message.metadata; storage - .set_block_data(block_hash, block_height, block_metadata) + .set_block_data(block_hash, block_height, &block_metadata) .map_err(crate::Error::Rocksdb)?; Ok(ConsumeMessageOutcome::BlockAdded) } @@ -134,15 +135,18 @@ fn execute_transaction<'db>( let mut handler = crate::promise::NoScheduler { promise_data: &transaction_message.promise_data, }; - let transaction_bytes: Vec = tx.into(); - let tx_hash = aurora_engine_sdk::keccak(&transaction_bytes); - - let result = engine::get_state(&io) + let tx_data: Vec = tx.into(); + let tx_hash = aurora_engine_sdk::keccak(&tx_data); + let args = SubmitArgs { + tx_data, + ..Default::default() + }; + let result = state::get_state(&io) .map(|engine_state| { let submit_result = engine::submit( io, &env, - &transaction_bytes, + &args, engine_state, env.current_account_id(), relayer_address, @@ -154,7 +158,28 @@ fn execute_transaction<'db>( (tx_hash, result) } + TransactionKind::SubmitWithArgs(args) => { + let mut handler = crate::promise::NoScheduler { + promise_data: &transaction_message.promise_data, + }; + let tx_hash = aurora_engine_sdk::keccak(&args.tx_data); + let result = state::get_state(&io) + .map(|engine_state| { + let submit_result = engine::submit( + io, + &env, + args, + engine_state, + env.current_account_id(), + relayer_address, + &mut handler, + ); + Some(TransactionExecutionResult::Submit(submit_result)) + }) + .map_err(Into::into); + (tx_hash, result) + } other => { let result = non_submit_execute( other, @@ -173,8 +198,9 @@ fn execute_transaction<'db>( } /// Handles all transaction kinds other than `submit`. -/// The `submit` transaction kind is special because it is the only one where the transaction hash is -/// different than the NEAR receipt hash. +/// The `submit` transaction kind is special because it is the only one where the transaction hash +/// differs from the NEAR receipt hash. +#[allow(clippy::too_many_lines)] fn non_submit_execute<'db>( transaction: &TransactionKind, mut io: EngineStateAccess<'db, 'db, 'db>, @@ -248,14 +274,14 @@ fn non_submit_execute<'db>( TransactionKind::ResolveTransfer(args, promise_result) => { let mut connector = connector::EthConnectorContract::init_instance(io)?; - connector.ft_resolve_transfer(args.clone(), promise_result.clone()); + connector.ft_resolve_transfer(args, promise_result.clone()); None } TransactionKind::FtTransfer(args) => { let mut connector = connector::EthConnectorContract::init_instance(io)?; - connector.ft_transfer(&env.predecessor_account_id, args.clone())?; + connector.ft_transfer(&env.predecessor_account_id, args)?; None } @@ -265,7 +291,7 @@ fn non_submit_execute<'db>( connector.withdraw_eth_from_near( &env.current_account_id, &env.predecessor_account_id, - args.clone(), + args, )?; None @@ -296,7 +322,7 @@ fn non_submit_execute<'db>( TransactionKind::StorageDeposit(args) => { let mut connector = connector::EthConnectorContract::init_instance(io)?; - let _ = connector.storage_deposit( + let _promise = connector.storage_deposit( env.predecessor_account_id, Yocto::new(env.attached_deposit), args.clone(), @@ -307,21 +333,21 @@ fn non_submit_execute<'db>( TransactionKind::StorageUnregister(force) => { let mut connector = connector::EthConnectorContract::init_instance(io)?; - let _ = connector.storage_unregister(env.predecessor_account_id, *force)?; + let _promise = connector.storage_unregister(env.predecessor_account_id, *force)?; None } TransactionKind::StorageWithdraw(args) => { let mut connector = connector::EthConnectorContract::init_instance(io)?; - connector.storage_withdraw(&env.predecessor_account_id, args.clone())?; + connector.storage_withdraw(&env.predecessor_account_id, args)?; None } TransactionKind::SetPausedFlags(args) => { let mut connector = connector::EthConnectorContract::init_instance(io)?; - connector.set_paused_flags(args.clone()); + connector.set_paused_flags(args); None } @@ -335,14 +361,14 @@ fn non_submit_execute<'db>( } TransactionKind::RefundOnError(maybe_args) => { - let result: Result, engine::EngineStateError> = + let result: Result, state::EngineStateError> = maybe_args .clone() .map(|args| { let mut handler = crate::promise::NoScheduler { promise_data }; - let engine_state = engine::get_state(&io)?; + let engine_state = state::get_state(&io)?; let result = - engine::refund_on_error(io, &env, engine_state, args, &mut handler); + engine::refund_on_error(io, &env, engine_state, &args, &mut handler); Ok(TransactionExecutionResult::Submit(result)) }) .transpose(); @@ -360,14 +386,14 @@ fn non_submit_execute<'db>( TransactionKind::NewConnector(args) => { connector::EthConnectorContract::create_contract( io, - env.current_account_id, + &env.current_account_id, args.clone(), )?; None } TransactionKind::NewEngine(args) => { - engine::set_state(&mut io, args.clone().into()); + state::set_state(&mut io, &args.clone().into())?; None } @@ -387,9 +413,15 @@ fn non_submit_execute<'db>( None } + TransactionKind::FundXccSubAccound(args) => { + let mut handler = crate::promise::NoScheduler { promise_data }; + xcc::fund_xcc_sub_account(&io, &mut handler, &env, args.clone())?; + + None + } TransactionKind::Unknown => None, // Not handled in this function; is handled by the general `execute_transaction` function - TransactionKind::Submit(_) => unreachable!(), + TransactionKind::Submit(_) | TransactionKind::SubmitWithArgs(_) => unreachable!(), TransactionKind::PausePrecompiles(args) => { let precompiles_to_pause = PrecompileFlags::from_bits_truncate(args.paused_mask); @@ -404,6 +436,14 @@ fn non_submit_execute<'db>( let mut pauser = EnginePrecompilesPauser::from_io(io); pauser.resume_precompiles(precompiles_to_resume); + None + } + TransactionKind::SetOwner(args) => { + let mut prev = state::get_state(&io)?; + + prev.owner_id = args.clone().new_owner; + state::set_state(&mut io, &prev)?; + None } }; @@ -434,11 +474,11 @@ pub enum TransactionExecutionResult { } pub mod error { - use aurora_engine::{connector, engine, fungible_token}; + use aurora_engine::{connector, engine, fungible_token, state, xcc}; #[derive(Debug)] pub enum Error { - EngineState(engine::EngineStateError), + EngineState(state::EngineStateError), Engine(engine::EngineError), DeployErc20(engine::DeployErc20Error), FtOnTransfer(connector::error::FtTransferCallError), @@ -450,10 +490,11 @@ pub mod error { InvalidAddress(aurora_engine_types::types::address::error::AddressError), ConnectorInit(connector::error::InitContractError), ConnectorStorage(connector::error::StorageReadError), + FundXccError(xcc::FundXccError), } - impl From for Error { - fn from(e: engine::EngineStateError) -> Self { + impl From for Error { + fn from(e: state::EngineStateError) -> Self { Self::EngineState(e) } } @@ -523,4 +564,10 @@ pub mod error { Self::ConnectorStorage(e) } } + + impl From for Error { + fn from(e: xcc::FundXccError) -> Self { + Self::FundXccError(e) + } + } } diff --git a/engine-standalone-storage/src/sync/types.rs b/engine-standalone-storage/src/sync/types.rs index c3eb652ca..b4087dbf4 100644 --- a/engine-standalone-storage/src/sync/types.rs +++ b/engine-standalone-storage/src/sync/types.rs @@ -1,7 +1,6 @@ use crate::Storage; use aurora_engine::parameters; -use aurora_engine::parameters::PausePrecompilesCallArgs; -use aurora_engine::xcc::AddressVersionUpdateArgs; +use aurora_engine::xcc::{AddressVersionUpdateArgs, FundXccArgs}; use aurora_engine_transactions::{EthTransactionKind, NormalizedEthTransaction}; use aurora_engine_types::account_id::AccountId; use aurora_engine_types::types::Address; @@ -52,6 +51,7 @@ pub struct TransactionMessage { } impl TransactionMessage { + #[must_use] pub fn to_bytes(&self) -> Vec { let borshable: BorshableTransactionMessage = self.into(); borshable.try_to_vec().unwrap() @@ -76,12 +76,14 @@ impl TransactionMessage { pub enum TransactionKind { /// Raw Ethereum transaction submitted to the engine Submit(EthTransactionKind), + /// Raw Ethereum transaction with additional arguments submitted to the engine + SubmitWithArgs(parameters::SubmitArgs), /// Ethereum transaction triggered by a NEAR account Call(parameters::CallArgs), /// Administrative method that makes a subset of precompiles paused - PausePrecompiles(PausePrecompilesCallArgs), + PausePrecompiles(parameters::PausePrecompilesCallArgs), /// Administrative method that resumes previously paused subset of precompiles - ResumePrecompiles(PausePrecompilesCallArgs), + ResumePrecompiles(parameters::PausePrecompilesCallArgs), /// Input here represents the EVM code used to create the new contract Deploy(Vec), /// New bridged token @@ -107,10 +109,12 @@ pub enum TransactionKind { StorageUnregister(Option), /// FT storage standard method StorageWithdraw(parameters::StorageWithdrawCallArgs), + /// Admin only method; used to transfer administration + SetOwner(parameters::SetOwnerArgs), /// Admin only method SetPausedFlags(parameters::PauseEthConnectorCallArgs), /// Ad entry mapping from address to relayer NEAR account - RegisterRelayer(types::Address), + RegisterRelayer(Address), /// Called if exist precompiles fail RefundOnError(Option), /// Update eth-connector config @@ -123,13 +127,16 @@ pub enum TransactionKind { FactoryUpdate(Vec), /// Update the version of a deployed xcc-router contract FactoryUpdateAddressVersion(AddressVersionUpdateArgs), - FactorySetWNearAddress(types::Address), + FactorySetWNearAddress(Address), + FundXccSubAccound(FundXccArgs), /// Sentinel kind for cases where a NEAR receipt caused a /// change in Aurora state, but we failed to parse the Action. Unknown, } impl TransactionKind { + #[must_use] + #[allow(clippy::too_many_lines)] pub fn eth_repr( self, engine_account: &AccountId, @@ -143,6 +150,9 @@ impl TransactionKind { Self::Submit(eth_tx_kind) => eth_tx_kind .try_into() .unwrap_or_else(|_| Self::no_evm_execution("submit")), + Self::SubmitWithArgs(args) => EthTransactionKind::try_from(args.tx_data.as_slice()) + .and_then(TryInto::try_into) + .unwrap_or_else(|_| Self::no_evm_execution("submit_with_args")), Self::Call(call_args) => { let from = Self::get_implicit_address(caller); let nonce = @@ -259,86 +269,88 @@ impl TransactionKind { } } Self::RefundOnError(maybe_args) => { - match maybe_args { - Some(args) => match args.erc20_address { - Some(erc20_address) => { - // ERC-20 refund - let from = Self::get_implicit_address(engine_account); - let nonce = Self::get_implicit_nonce( - &from, - block_height, - transaction_position, - storage, - ); - let to = erc20_address; - let data = aurora_engine::engine::setup_refund_on_error_input( - U256::from_big_endian(&args.amount), - args.recipient_address, - ); - NormalizedEthTransaction { - address: from, - chain_id: None, - nonce, - gas_limit: U256::from(u64::MAX), - max_priority_fee_per_gas: U256::zero(), - max_fee_per_gas: U256::zero(), - to: Some(to), - value: Wei::zero(), - data, - access_list: Vec::new(), - } - } - None => { - // ETH refund - let value = Wei::new(U256::from_big_endian(&args.amount)); - let from = aurora_engine_precompiles::native::exit_to_near::ADDRESS; - let nonce = Self::get_implicit_nonce( - &from, - block_height, - transaction_position, - storage, - ); - NormalizedEthTransaction { - address: from, - chain_id: None, - nonce, - gas_limit: U256::from(u64::MAX), - max_priority_fee_per_gas: U256::zero(), - max_fee_per_gas: U256::zero(), - to: Some(args.recipient_address), - value, - data: Vec::new(), - access_list: Vec::new(), - } - } + maybe_args.map_or_else( + || Self::no_evm_execution("refund_on_error"), + |args| { + args.erc20_address.map_or_else( + || { + // ETH refund + let value = Wei::new(U256::from_big_endian(&args.amount)); + let from = aurora_engine_precompiles::native::exit_to_near::ADDRESS; + let nonce = Self::get_implicit_nonce( + &from, + block_height, + transaction_position, + storage, + ); + NormalizedEthTransaction { + address: from, + chain_id: None, + nonce, + gas_limit: U256::from(u64::MAX), + max_priority_fee_per_gas: U256::zero(), + max_fee_per_gas: U256::zero(), + to: Some(args.recipient_address), + value, + data: Vec::new(), + access_list: Vec::new(), + } + }, + |erc20_address| { + // ERC-20 refund + let from = Self::get_implicit_address(engine_account); + let nonce = Self::get_implicit_nonce( + &from, + block_height, + transaction_position, + storage, + ); + let to = erc20_address; + let data = aurora_engine::engine::setup_refund_on_error_input( + U256::from_big_endian(&args.amount), + args.recipient_address, + ); + NormalizedEthTransaction { + address: from, + chain_id: None, + nonce, + gas_limit: U256::from(u64::MAX), + max_priority_fee_per_gas: U256::zero(), + max_fee_per_gas: U256::zero(), + to: Some(to), + value: Wei::zero(), + data, + access_list: Vec::new(), + } + }, + ) }, - None => Self::no_evm_execution("refund_on_error"), - } + ) } Self::Deposit(_) => Self::no_evm_execution("deposit"), Self::FtTransferCall(_) => Self::no_evm_execution("ft_transfer_call"), Self::FinishDeposit(_) => Self::no_evm_execution("finish_deposit"), Self::ResolveTransfer(_, _) => Self::no_evm_execution("resolve_transfer"), Self::FtTransfer(_) => Self::no_evm_execution("ft_transfer"), - TransactionKind::Withdraw(_) => Self::no_evm_execution("withdraw"), - TransactionKind::StorageDeposit(_) => Self::no_evm_execution("storage_deposit"), - TransactionKind::StorageUnregister(_) => Self::no_evm_execution("storage_unregister"), - TransactionKind::StorageWithdraw(_) => Self::no_evm_execution("storage_withdraw"), - TransactionKind::SetPausedFlags(_) => Self::no_evm_execution("set_paused_flags"), - TransactionKind::RegisterRelayer(_) => Self::no_evm_execution("register_relayer"), - TransactionKind::SetConnectorData(_) => Self::no_evm_execution("set_connector_data"), - TransactionKind::NewConnector(_) => Self::no_evm_execution("new_connector"), - TransactionKind::NewEngine(_) => Self::no_evm_execution("new_engine"), - TransactionKind::FactoryUpdate(_) => Self::no_evm_execution("factory_update"), - TransactionKind::FactoryUpdateAddressVersion(_) => { + Self::Withdraw(_) => Self::no_evm_execution("withdraw"), + Self::StorageDeposit(_) => Self::no_evm_execution("storage_deposit"), + Self::StorageUnregister(_) => Self::no_evm_execution("storage_unregister"), + Self::StorageWithdraw(_) => Self::no_evm_execution("storage_withdraw"), + Self::SetPausedFlags(_) => Self::no_evm_execution("set_paused_flags"), + Self::RegisterRelayer(_) => Self::no_evm_execution("register_relayer"), + Self::SetConnectorData(_) => Self::no_evm_execution("set_connector_data"), + Self::NewConnector(_) => Self::no_evm_execution("new_connector"), + Self::NewEngine(_) => Self::no_evm_execution("new_engine"), + Self::FactoryUpdate(_) => Self::no_evm_execution("factory_update"), + Self::FactoryUpdateAddressVersion(_) => { Self::no_evm_execution("factory_update_address_version") } - TransactionKind::FactorySetWNearAddress(_) => { - Self::no_evm_execution("factory_set_wnear_address") - } - TransactionKind::Unknown => Self::no_evm_execution("unknown"), + Self::FactorySetWNearAddress(_) => Self::no_evm_execution("factory_set_wnear_address"), + Self::Unknown => Self::no_evm_execution("unknown"), Self::PausePrecompiles(_) => Self::no_evm_execution("pause_precompiles"), Self::ResumePrecompiles(_) => Self::no_evm_execution("resume_precompiles"), + Self::SetOwner(_) => Self::no_evm_execution("set_owner"), + Self::FundXccSubAccound(_) => Self::no_evm_execution("fund_xcc_sub_account"), } } @@ -493,17 +505,20 @@ enum BorshableTransactionKind<'a> { StorageUnregister(Option), StorageWithdraw(Cow<'a, parameters::StorageWithdrawCallArgs>), SetPausedFlags(Cow<'a, parameters::PauseEthConnectorCallArgs>), - RegisterRelayer(Cow<'a, types::Address>), + RegisterRelayer(Cow<'a, Address>), RefundOnError(Cow<'a, Option>), SetConnectorData(Cow<'a, parameters::SetContractDataCallArgs>), NewConnector(Cow<'a, parameters::InitCallArgs>), NewEngine(Cow<'a, parameters::NewCallArgs>), FactoryUpdate(Cow<'a, Vec>), FactoryUpdateAddressVersion(Cow<'a, AddressVersionUpdateArgs>), - FactorySetWNearAddress(types::Address), + FactorySetWNearAddress(Address), PausePrecompiles(Cow<'a, parameters::PausePrecompilesCallArgs>), ResumePrecompiles(Cow<'a, parameters::PausePrecompilesCallArgs>), Unknown, + SetOwner(Cow<'a, parameters::SetOwnerArgs>), + SubmitWithArgs(Cow<'a, parameters::SubmitArgs>), + FundXccSubAccound(Cow<'a, FundXccArgs>), } impl<'a> From<&'a TransactionKind> for BorshableTransactionKind<'a> { @@ -513,6 +528,7 @@ impl<'a> From<&'a TransactionKind> for BorshableTransactionKind<'a> { let tx_bytes = eth_tx.into(); Self::Submit(Cow::Owned(tx_bytes)) } + TransactionKind::SubmitWithArgs(x) => Self::SubmitWithArgs(Cow::Borrowed(x)), TransactionKind::Call(x) => Self::Call(Cow::Borrowed(x)), TransactionKind::Deploy(x) => Self::Deploy(Cow::Borrowed(x)), TransactionKind::DeployErc20(x) => Self::DeployErc20(Cow::Borrowed(x)), @@ -544,6 +560,8 @@ impl<'a> From<&'a TransactionKind> for BorshableTransactionKind<'a> { TransactionKind::Unknown => Self::Unknown, TransactionKind::PausePrecompiles(x) => Self::PausePrecompiles(Cow::Borrowed(x)), TransactionKind::ResumePrecompiles(x) => Self::ResumePrecompiles(Cow::Borrowed(x)), + TransactionKind::SetOwner(x) => Self::SetOwner(Cow::Borrowed(x)), + TransactionKind::FundXccSubAccound(x) => Self::FundXccSubAccound(Cow::Borrowed(x)), } } } @@ -560,6 +578,7 @@ impl<'a> TryFrom> for TransactionKind { let eth_tx = tx_bytes.as_slice().try_into()?; Ok(Self::Submit(eth_tx)) } + BorshableTransactionKind::SubmitWithArgs(x) => Ok(Self::SubmitWithArgs(x.into_owned())), BorshableTransactionKind::Call(x) => Ok(Self::Call(x.into_owned())), BorshableTransactionKind::Deploy(x) => Ok(Self::Deploy(x.into_owned())), BorshableTransactionKind::DeployErc20(x) => Ok(Self::DeployErc20(x.into_owned())), @@ -601,6 +620,10 @@ impl<'a> TryFrom> for TransactionKind { BorshableTransactionKind::ResumePrecompiles(x) => { Ok(Self::ResumePrecompiles(x.into_owned())) } + BorshableTransactionKind::SetOwner(x) => Ok(Self::SetOwner(x.into_owned())), + BorshableTransactionKind::FundXccSubAccound(x) => { + Ok(Self::FundXccSubAccound(x.into_owned())) + } } } } diff --git a/engine-standalone-tracing/.catalog-info.yaml b/engine-standalone-tracing/.catalog-info.yaml new file mode 100644 index 000000000..9b939cc27 --- /dev/null +++ b/engine-standalone-tracing/.catalog-info.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: aurora-engine-standalone-tracing + description: |- + Aurora engine standalone tracing library. Provides functions and types for extracing geth-like traces from standalone engine execution. + tags: + - near + links: [] + annotations: + aurora.dev/security-tier: "2" +spec: + owner: engine-team + type: contract-tests + lifecycle: production + system: aurora-engine + interactsWith: [] diff --git a/engine-standalone-tracing/Cargo.toml b/engine-standalone-tracing/Cargo.toml index 615da9d6e..9f1ccabe9 100644 --- a/engine-standalone-tracing/Cargo.toml +++ b/engine-standalone-tracing/Cargo.toml @@ -15,10 +15,10 @@ crate-type = ["lib"] [dependencies] aurora-engine-types = { path = "../engine-types", default-features = false, features = ["std"] } -evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.3-aurora", default-features = false, features = ["std"] } -evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.3-aurora", default-features = false, features = ["std", "tracing"] } -evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.3-aurora", default-features = false, features = ["std", "tracing"] } -evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.3-aurora", default-features = false, features = ["std", "tracing"] } +evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false, features = ["std"] } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false, features = ["std", "tracing"] } +evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false, features = ["std", "tracing"] } +evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false, features = ["std", "tracing"] } hex = { version = "0.4", default-features = false, features = ["std"] } serde = { version = "1", features = ["derive"], optional = true } diff --git a/engine-standalone-tracing/src/lib.rs b/engine-standalone-tracing/src/lib.rs index da3f130ae..73ef48659 100644 --- a/engine-standalone-tracing/src/lib.rs +++ b/engine-standalone-tracing/src/lib.rs @@ -1,3 +1,5 @@ +#![deny(clippy::pedantic, clippy::nursery)] +#![allow(clippy::module_name_repetitions, clippy::missing_panics_doc)] pub mod sputnik; pub mod types; diff --git a/engine-standalone-tracing/src/sputnik.rs b/engine-standalone-tracing/src/sputnik.rs index 9d82cb3e4..0a3f02fec 100644 --- a/engine-standalone-tracing/src/sputnik.rs +++ b/engine-standalone-tracing/src/sputnik.rs @@ -8,7 +8,7 @@ use crate::types::{ LogStorageKey, LogStorageValue, Logs, ProgramCounter, TraceLog, TransactionTrace, }; -/// Capture all events from SputnikVM emitted from within the given closure using the given listener. +/// Capture all events from `SputnikVM` emitted from within the given closure using the given listener. pub fn traced_call(listener: &mut T, f: F) -> R where T: evm_gasometer::tracing::EventListener @@ -39,6 +39,7 @@ pub struct TransactionTraceBuilder { } impl TransactionTraceBuilder { + #[must_use] pub fn finish(self) -> TransactionTrace { TransactionTrace::new(self.gas_used, self.failed, self.output, Logs(self.logs)) } @@ -51,8 +52,11 @@ impl evm_gasometer::tracing::EventListener for TransactionTraceBuilder { Event::RecordCost { cost, snapshot } => { self.current.gas_cost = EthGas::new(cost); if let Some(snapshot) = snapshot { - self.current.gas = - EthGas::new(snapshot.gas_limit - snapshot.used_gas - snapshot.memory_gas); + self.current.gas = EthGas::new( + snapshot + .gas_limit + .saturating_sub(snapshot.used_gas + snapshot.memory_gas), + ); } } Event::RecordDynamicCost { @@ -73,8 +77,11 @@ impl evm_gasometer::tracing::EventListener for TransactionTraceBuilder { self.current_memory_gas = memory_gas; self.current.gas_cost = EthGas::new(gas_cost + memory_cost_diff); if let Some(snapshot) = snapshot { - self.current.gas = - EthGas::new(snapshot.gas_limit - snapshot.used_gas - snapshot.memory_gas); + self.current.gas = EthGas::new( + snapshot + .gas_limit + .saturating_sub(snapshot.used_gas + snapshot.memory_gas), + ); } } Event::RecordRefund { @@ -87,8 +94,7 @@ impl evm_gasometer::tracing::EventListener for TransactionTraceBuilder { self.gas_used = EthGas::new(snapshot.used_gas); } } - Event::RecordTransaction { .. } => (), // not useful - Event::RecordStipend { .. } => (), // not useful + Event::RecordTransaction { .. } | Event::RecordStipend { .. } => (), // not useful } } } @@ -106,7 +112,8 @@ impl evm_runtime::tracing::EventListener for TransactionTraceBuilder { } => { self.current.opcode = opcode; if let Ok(pc) = position { - self.current.program_counter = ProgramCounter(*pc as u32); + self.current.program_counter = + ProgramCounter(u32::try_from(*pc).unwrap_or_default()); } self.current.stack = stack .data() @@ -164,14 +171,8 @@ impl evm_runtime::tracing::EventListener for TransactionTraceBuilder { address: _, index, value, - } => { - self.current - .storage - .insert(LogStorageKey(index.0), LogStorageValue(value.0)); - self.logs.push(self.current.clone()); } - - Event::SStore { + | Event::SStore { address: _, index, value, @@ -189,13 +190,9 @@ impl evm::tracing::EventListener for TransactionTraceBuilder { fn event(&mut self, event: evm::tracing::Event) { use evm::tracing::Event; match event { - Event::Call { .. } => { - self.current.depth.increment(); - } - Event::Create { .. } => { + Event::Call { .. } | Event::Create { .. } => { self.current.depth.increment(); } - Event::Suicide { .. } => (), // TODO: ??? Event::Exit { reason: _, return_value, @@ -207,20 +204,22 @@ impl evm::tracing::EventListener for TransactionTraceBuilder { self.output = return_value.to_vec(); } } - Event::PrecompileSubcall { .. } => (), - Event::TransactCall { .. } => (), // no useful information - Event::TransactCreate { .. } => (), // no useful information - Event::TransactCreate2 { .. } => (), // no useful information + Event::Suicide { .. } + | Event::PrecompileSubcall { .. } + | Event::TransactCall { .. } + | Event::TransactCreate { .. } + | Event::TransactCreate2 { .. } + | Event::CreateOutput { .. } => (), // no useful information } } } /// This structure is intentionally private to this module as it is memory unsafe (contains a raw pointer). /// Its purpose here is to allow a single event handling object to be used as the listener for -/// all SputnikVM events. It is needed because the listener must be passed as an object with a `'static` +/// all `SputnikVM` events. It is needed because the listener must be passed as an object with a `'static` /// lifetime, hence a normal reference cannot be used and we resort to raw pointers. The usage of this /// struct in this module is safe because the `SharedMutableReference` objects created do not outlive -/// the reference they are based on (see `pub fn traced_call`). Moreover, because the SputnikVM code +/// the reference they are based on (see `pub fn traced_call`). Moreover, because the `SputnikVM` code /// is single-threaded, we do not need to worry about race conditions. struct SharedMutableReference { pointer: Rc>>, @@ -228,7 +227,7 @@ struct SharedMutableReference { impl SharedMutableReference { fn new(reference: &mut T) -> Self { - let ptr = NonNull::new(reference as _).unwrap(); + let ptr = NonNull::new(reference).unwrap(); Self { pointer: Rc::new(RefCell::new(ptr)), } diff --git a/engine-standalone-tracing/src/types/call_tracer.rs b/engine-standalone-tracing/src/types/call_tracer.rs index e54ca22a1..97237ccc8 100644 --- a/engine-standalone-tracing/src/types/call_tracer.rs +++ b/engine-standalone-tracing/src/types/call_tracer.rs @@ -1,5 +1,5 @@ //! This module defines data structure to produce traces compatible with geths "callTracer": -//! https://github.com/ethereum/go-ethereum/blob/ad15050c7fbedd0f05a49e81400de18c2cc2c284/eth/tracers/native/call.go +//! `https://github.com/ethereum/go-ethereum/blob/ad15050c7fbedd0f05a49e81400de18c2cc2c284/eth/tracers/native/call.go` use aurora_engine_types::{types::Address, U256}; @@ -26,9 +26,15 @@ impl CallTracer { fn end(&mut self, output: Vec, error: Option<&evm::ExitReason>) { let frame = self.call_stack.first_mut().unwrap(); match error { - None => frame.output = output, + None => { + match frame.call_type { + // In CREATE case, output is set by the `CreateOutput` rather than the `Exit` event. + CallType::Create | CallType::Create2 => (), + _ => frame.output = output, + } + } Some(error) => { - let error_message = format!("{:?}", error); + let error_message = format!("{error:?}"); if error_message.to_lowercase().contains("revert") { frame.output = output; } @@ -68,14 +74,17 @@ impl CallTracer { let mut frame = self.call_stack.pop().unwrap(); match error { - None => frame.output = output, - Some(error) => { - frame.error = Some(format!("{:?}", error)); + None => { match frame.call_type { - CallType::Create | CallType::Create2 => frame.to = None, - _ => (), + // In CREATE case, output is set by the `CreateOutput` rather than the `Exit` event. + CallType::Create | CallType::Create2 => (), + _ => frame.output = output, } } + Some(error) => { + frame.error = Some(format!("{error:?}")); + frame.output = output; + } } self.call_stack.last_mut().unwrap().calls.push(frame); @@ -91,6 +100,7 @@ impl CallTracer { } #[cfg(feature = "serde")] + #[must_use] pub fn serializable(mut self) -> Option { if self.call_stack.len() != 1 { // If there is more than one element in `call_stack` then it must mean the trace did not complete @@ -138,10 +148,10 @@ impl evm_gasometer::tracing::EventListener for CallTracer { } => self.update_gas_from_snapshot(snapshot), // Not useful - evm_gasometer::tracing::Event::RecordCost { .. } => (), - evm_gasometer::tracing::Event::RecordDynamicCost { .. } => (), - evm_gasometer::tracing::Event::RecordStipend { .. } => (), - evm_gasometer::tracing::Event::RecordTransaction { .. } => (), + evm_gasometer::tracing::Event::RecordCost { .. } + | evm_gasometer::tracing::Event::RecordDynamicCost { .. } + | evm_gasometer::tracing::Event::RecordStipend { .. } + | evm_gasometer::tracing::Event::RecordTransaction { .. } => (), } } } @@ -189,9 +199,10 @@ impl evm::tracing::EventListener for CallTracer { target_gas, } => { let call_type = match scheme { - evm::CreateScheme::Legacy { .. } => CallType::Create, evm::CreateScheme::Create2 { .. } => CallType::Create2, - evm::CreateScheme::Fixed(_) => CallType::Create, // is this even possible in production? + evm::CreateScheme::Legacy { .. } | evm::CreateScheme::Fixed(_) => { + CallType::Create + } // Is Fixed even possible in production? With high probability not. }; self.enter( @@ -203,6 +214,19 @@ impl evm::tracing::EventListener for CallTracer { value, ); } + evm::tracing::Event::CreateOutput { address, code } => { + // `to` field should have been set to the address of the contract being created + debug_assert_eq!( + Some(address), + self.call_stack + .last() + .and_then(|call_frame| call_frame.to.as_ref().map(Address::raw)) + ); + let current_frame = self.call_stack.last_mut(); + if let Some(frame) = current_frame { + frame.output = code.to_vec(); + } + } evm::tracing::Event::Suicide { address, target, @@ -232,10 +256,10 @@ impl evm::tracing::EventListener for CallTracer { } // not useful - evm::tracing::Event::PrecompileSubcall { .. } => (), - evm::tracing::Event::TransactCall { .. } => (), - evm::tracing::Event::TransactCreate { .. } => (), - evm::tracing::Event::TransactCreate2 { .. } => (), + evm::tracing::Event::PrecompileSubcall { .. } + | evm::tracing::Event::TransactCall { .. } + | evm::tracing::Event::TransactCreate { .. } + | evm::tracing::Event::TransactCreate2 { .. } => (), } } } diff --git a/engine-standalone-tracing/src/types/mod.rs b/engine-standalone-tracing/src/types/mod.rs index 93495b43a..096389d8c 100644 --- a/engine-standalone-tracing/src/types/mod.rs +++ b/engine-standalone-tracing/src/types/mod.rs @@ -14,7 +14,8 @@ pub struct Depth(u32); impl Depth { /// Performs the conversion into a u32. - pub fn into_u32(self) -> u32 { + #[must_use] + pub const fn into_u32(self) -> u32 { self.0 } @@ -23,10 +24,11 @@ impl Depth { } pub fn decrement(&mut self) { - self.0 -= 1; + self.0 = self.0.saturating_sub(1); } - pub fn is_zero(&self) -> bool { + #[must_use] + pub const fn is_zero(&self) -> bool { self.0 == 0 } } @@ -38,17 +40,21 @@ pub struct LogMemory(Vec<[u8; 32]>); impl LogMemory { /// Returns the number of elements in the memory buffer. + #[must_use] pub fn len(&self) -> usize { self.0.len() } /// Returns true if there are no elements in the memory buffer. #[allow(dead_code)] + #[must_use] pub fn is_empty(&self) -> bool { self.0.is_empty() } /// Performs the conversion into a raw buffer. + #[must_use] + #[allow(clippy::missing_const_for_fn)] pub fn into_raw(self) -> Vec<[u8; 32]> { self.0 } @@ -62,7 +68,7 @@ impl From<&[u8]> for LogMemory { let j = i % 32; buf[j] = *b; if j == 31 { - result.push(buf) + result.push(buf); } } Self(result) @@ -76,17 +82,21 @@ pub struct LogStack(Vec<[u8; 32]>); impl LogStack { /// Returns the number of elements in the stack buffer. + #[must_use] pub fn len(&self) -> usize { self.0.len() } /// Returns true if there are no elements in the stack buffer. #[allow(dead_code)] + #[must_use] pub fn is_empty(&self) -> bool { self.0.is_empty() } /// Performs the conversion into a vector. + #[must_use] + #[allow(clippy::missing_const_for_fn)] pub fn into_raw(self) -> Vec<[u8; 32]> { self.0 } @@ -105,8 +115,9 @@ impl std::iter::FromIterator<[u8; 32]> for LogStack { pub struct ProgramCounter(pub u32); impl ProgramCounter { - /// Performs the conversion into a u32. - pub fn into_u32(self) -> u32 { + /// Performs the conversion into u32. + #[must_use] + pub const fn into_u32(self) -> u32 { self.0 } } @@ -118,7 +129,8 @@ pub struct LogStorageKey(pub [u8; 32]); impl LogStorageKey { /// Performs the conversion into a 32 byte word. - pub fn into_raw(self) -> [u8; 32] { + #[must_use] + pub const fn into_raw(self) -> [u8; 32] { self.0 } } @@ -130,7 +142,8 @@ pub struct LogStorageValue(pub [u8; 32]); impl LogStorageValue { /// Performs the conversion into a 32 byte word. - pub fn into_raw(self) -> [u8; 32] { + #[must_use] + pub const fn into_raw(self) -> [u8; 32] { self.0 } } @@ -183,15 +196,15 @@ pub struct TraceLog { impl Default for TraceLog { fn default() -> Self { Self { - depth: Default::default(), - error: Default::default(), - gas: Default::default(), - gas_cost: Default::default(), - memory: Default::default(), + depth: Depth::default(), + error: Option::default(), + gas: EthGas::default(), + gas_cost: EthGas::default(), + memory: LogMemory::default(), opcode: Opcode::STOP, - program_counter: Default::default(), - stack: Default::default(), - storage: Default::default(), + program_counter: ProgramCounter::default(), + stack: LogStack::default(), + storage: LogStorage::default(), } } } @@ -203,12 +216,14 @@ pub struct Logs(pub Vec); impl Logs { /// Returns the number of logs. #[allow(dead_code)] + #[must_use] pub fn len(&self) -> usize { self.0.len() } /// Returns true if there are no logs. #[allow(dead_code)] + #[must_use] pub fn is_empty(&self) -> bool { self.0.is_empty() } @@ -246,13 +261,9 @@ pub struct TransactionTrace { } impl TransactionTrace { - /// Constructs a new TransactionTrace with a given gas, return, and logs. - pub fn new( - gas: EthGas, - failed: bool, - return_value: Vec, - struct_logs: Logs, - ) -> TransactionTrace { + /// Constructs a new `TransactionTrace` with a given gas, return, and logs. + #[must_use] + pub fn new(gas: EthGas, failed: bool, return_value: Vec, struct_logs: Logs) -> Self { Self { gas, failed, @@ -261,18 +272,21 @@ impl TransactionTrace { } } - /// Returns the EthGas associated with this transaction as a reference. - pub fn gas(&self) -> EthGas { + /// Returns the `EthGas` associated with this transaction as a reference. + #[must_use] + pub const fn gas(&self) -> EthGas { self.gas } /// Returns the output bytes of the transaction as a slice. + #[must_use] pub fn result(&self) -> &[u8] { self.return_value.as_slice() } /// Returns a reference to the logs. - pub fn logs(&self) -> &Logs { + #[must_use] + pub const fn logs(&self) -> &Logs { &self.struct_logs } } @@ -290,7 +304,8 @@ pub struct StepTransactionTrace { impl StepTransactionTrace { /// Constructs a new `TraceStepper` with a given `TransactionTrace`. #[allow(dead_code)] - pub fn new(transaction_trace: TransactionTrace) -> Self { + #[must_use] + pub const fn new(transaction_trace: TransactionTrace) -> Self { Self { inner: transaction_trace, step: 0, @@ -317,6 +332,7 @@ impl StepTransactionTrace { // See here for custom serde serialization: https://serde.rs/custom-serialization.html #[cfg(feature = "serde")] mod opcode_serde { + #[allow(clippy::trivially_copy_pass_by_ref)] pub fn serialize(opcode: &evm_core::Opcode, serializer: S) -> Result where S: serde::Serializer, diff --git a/engine-test-doubles/.catalog-info.yaml b/engine-test-doubles/.catalog-info.yaml new file mode 100644 index 000000000..f73c997a4 --- /dev/null +++ b/engine-test-doubles/.catalog-info.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: aurora-engine-test-doubles + description: |- + Contains implementations of engine traits suitable for using in tests + tags: + - near + links: [] + annotations: + aurora.dev/security-tier: "-1" +spec: + owner: engine-team + type: contract-tests + lifecycle: production + system: aurora-engine + interactsWith: [] diff --git a/engine-test-doubles/Cargo.toml b/engine-test-doubles/Cargo.toml index 10e29048a..85aa5e10d 100644 --- a/engine-test-doubles/Cargo.toml +++ b/engine-test-doubles/Cargo.toml @@ -15,8 +15,8 @@ autobenches = false [dependencies] aurora-engine-types = { path = "../engine-types", default-features = false, features = ["std"] } aurora-engine-sdk = { path = "../engine-sdk" } -evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.3-aurora", default-features = false, features = ["std", "tracing"] } -evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.3-aurora", default-features = false, features = ["std", "tracing"] } -evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.3-aurora", default-features = false, features = ["std", "tracing"] } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false, features = ["std", "tracing"] } +evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false, features = ["std", "tracing"] } +evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false, features = ["std", "tracing"] } [dev-dependencies] diff --git a/engine-test-doubles/src/io.rs b/engine-test-doubles/src/io.rs index adb066c41..284398fb2 100644 --- a/engine-test-doubles/src/io.rs +++ b/engine-test-doubles/src/io.rs @@ -1,6 +1,6 @@ use aurora_engine_sdk::io::{StorageIntermediate, IO}; +use std::cell::RefCell; use std::collections::HashMap; -use std::sync::RwLock; pub struct Value(Vec); @@ -14,7 +14,7 @@ impl StorageIntermediate for Value { } fn copy_to_slice(&self, buffer: &mut [u8]) { - buffer.copy_from_slice(&self.0) + buffer.copy_from_slice(&self.0); } } @@ -27,37 +27,32 @@ pub struct Storage { /// In-memory implementation of [IO]. #[derive(Debug, Clone, Copy)] -pub struct StoragePointer<'a>(pub &'a RwLock); +pub struct StoragePointer<'a>(pub &'a RefCell); impl<'a> IO for StoragePointer<'a> { type StorageValue = Value; fn read_input(&self) -> Self::StorageValue { - Value(self.0.read().unwrap().input.clone()) + Value(self.0.borrow().input.clone()) } fn return_output(&mut self, value: &[u8]) { - let mut storage = self.0.write().unwrap(); + let mut storage = self.0.borrow_mut(); storage.output = value.to_vec(); } fn read_storage(&self, key: &[u8]) -> Option { - self.0 - .read() - .unwrap() - .kv_store - .get(key) - .map(|v| Value(v.clone())) + self.0.borrow().kv_store.get(key).map(|v| Value(v.clone())) } fn storage_has_key(&self, key: &[u8]) -> bool { - self.0.read().unwrap().kv_store.contains_key(key) + self.0.borrow().kv_store.contains_key(key) } fn write_storage(&mut self, key: &[u8], value: &[u8]) -> Option { let key = key.to_vec(); let value = value.to_vec(); - let mut storage = self.0.write().unwrap(); + let mut storage = self.0.borrow_mut(); storage.kv_store.insert(key, value).map(Value) } @@ -67,12 +62,12 @@ impl<'a> IO for StoragePointer<'a> { value: Self::StorageValue, ) -> Option { let key = key.to_vec(); - let mut storage = self.0.write().unwrap(); + let mut storage = self.0.borrow_mut(); storage.kv_store.insert(key, value.0).map(Value) } fn remove_storage(&mut self, key: &[u8]) -> Option { - let mut storage = self.0.write().unwrap(); + let mut storage = self.0.borrow_mut(); storage.kv_store.remove(key).map(Value) } } diff --git a/engine-test-doubles/src/lib.rs b/engine-test-doubles/src/lib.rs index 5c41c3f48..842f5d972 100644 --- a/engine-test-doubles/src/lib.rs +++ b/engine-test-doubles/src/lib.rs @@ -1,3 +1,5 @@ +#![deny(clippy::pedantic, clippy::nursery)] +#![allow(clippy::module_name_repetitions)] pub mod io; pub mod promise; pub mod tracing; diff --git a/engine-test-doubles/src/promise.rs b/engine-test-doubles/src/promise.rs index 38462b382..20c0b17d4 100644 --- a/engine-test-doubles/src/promise.rs +++ b/engine-test-doubles/src/promise.rs @@ -36,11 +36,13 @@ impl PromiseHandler for PromiseTracker { type ReadOnly = Self; fn promise_results_count(&self) -> u64 { - self.promise_results.len() as u64 + u64::try_from(self.promise_results.len()).unwrap_or_default() } fn promise_result(&self, index: u64) -> Option { - self.promise_results.get(index as usize).cloned() + self.promise_results + .get(usize::try_from(index).ok()?) + .cloned() } unsafe fn promise_create_call(&mut self, args: &PromiseCreateArgs) -> PromiseId { @@ -81,8 +83,8 @@ impl PromiseHandler for PromiseTracker { Self { internal_index: 0, promise_results: self.promise_results.clone(), - scheduled_promises: Default::default(), - returned_promise: Default::default(), + scheduled_promises: HashMap::default(), + returned_promise: Option::default(), } } } diff --git a/engine-test-doubles/src/tracing.rs b/engine-test-doubles/src/tracing.rs index 8dc0225c7..dfaed20fe 100644 --- a/engine-test-doubles/src/tracing.rs +++ b/engine-test-doubles/src/tracing.rs @@ -5,18 +5,18 @@ pub struct Listener { impl evm_gasometer::tracing::EventListener for Listener { fn event(&mut self, event: evm_gasometer::tracing::Event) { - self.events.push(format!("{:?}", event)); + self.events.push(format!("{event:?}")); } } impl evm_runtime::tracing::EventListener for Listener { fn event(&mut self, event: evm_runtime::tracing::Event) { - self.events.push(format!("{:?}", event)); + self.events.push(format!("{event:?}")); } } impl evm::tracing::EventListener for Listener { fn event(&mut self, event: evm::tracing::Event) { - self.events.push(format!("{:?}", event)); + self.events.push(format!("{event:?}")); } } diff --git a/engine-tests/.catalog-info.yaml b/engine-tests/.catalog-info.yaml new file mode 100644 index 000000000..f68edd2ca --- /dev/null +++ b/engine-tests/.catalog-info.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: aurora-engine-tests + description: |- + Aurora Engine Tests + tags: + - near + links: [] + annotations: + aurora.dev/security-tier: "-1" +spec: + owner: engine-team + type: contract-tests + lifecycle: production + system: aurora-engine + interactsWith: [] diff --git a/engine-tests/Cargo.toml b/engine-tests/Cargo.toml index 43da94dd9..5b083b1f7 100644 --- a/engine-tests/Cargo.toml +++ b/engine-tests/Cargo.toml @@ -15,21 +15,20 @@ autobenches = false [dependencies] [dev-dependencies] -aurora-engine = { path = "../engine", default-features = false, features = ["std", "tracing"] } +aurora-engine = { path = "../engine", default-features = false, features = ["std", "tracing", "impl-serde"] } aurora-engine-test-doubles = { path = "../engine-test-doubles", default-features = false } -aurora-engine-types = { path = "../engine-types", default-features = false, features = ["std"] } +aurora-engine-types = { path = "../engine-types", default-features = false, features = ["std", "impl-serde"] } aurora-engine-sdk = { path = "../engine-sdk", default-features = false, features = ["std"] } aurora-engine-precompiles = { path = "../engine-precompiles", default-features = false, features = ["std"] } -aurora-engine-transactions = { path = "../engine-transactions", default-features = false, features = ["std"] } +aurora-engine-transactions = { path = "../engine-transactions", default-features = false, features = ["std", "impl-serde"] } engine-standalone-storage = { path = "../engine-standalone-storage" } engine-standalone-tracing = { path = "../engine-standalone-tracing", default-features = false, features = ["impl-serde"] } -borsh = { version = "0.9.3", default-features = false } +borsh = { version = "0.10", default-features = false } sha3 = { version = "0.10.2", default-features = false } -evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.3-aurora", default-features = false, features = ["std", "tracing"] } -evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.3-aurora", default-features = false, features = ["std", "tracing"] } -evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.3-aurora", default-features = false, features = ["std", "tracing"] } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false, features = ["std", "tracing"] } +evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false, features = ["std", "tracing"] } +evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false, features = ["std", "tracing"] } rlp = { version = "0.5.0", default-features = false } -base64 = "0.13.0" bstr = "1.0.1" byte-slice-cast = { version = "1.0", default-features = false } ethabi = "18.0" @@ -47,7 +46,7 @@ near-primitives = { git = "https://github.com/birchmd/nearcore.git", rev = "6033 libsecp256k1 = { version = "0.7.0", default-features = false } rand = "0.8.5" criterion = "0.4.0" -git2 = "0.15" +git2 = "0.16" tempfile = "3.2.0" walrus = "0.19" diff --git a/engine-tests/src/benches/eth_deploy_code.rs b/engine-tests/src/benches/eth_deploy_code.rs index 20bfab1e1..1e7a01e64 100644 --- a/engine-tests/src/benches/eth_deploy_code.rs +++ b/engine-tests/src/benches/eth_deploy_code.rs @@ -9,7 +9,7 @@ use crate::test_utils::{ const INITIAL_BALANCE: Wei = Wei::new_u64(1000); const INITIAL_NONCE: u64 = 0; -pub(crate) fn eth_deploy_code_benchmark(c: &mut Criterion) { +pub fn eth_deploy_code_benchmark(c: &mut Criterion) { let mut runner = deploy_evm(); let mut rng = rand::thread_rng(); let source_account = SecretKey::random(&mut rng); @@ -33,7 +33,7 @@ pub(crate) fn eth_deploy_code_benchmark(c: &mut Criterion) { let calling_account_id = "some-account.near"; // measure gas usage - for input in inputs.iter() { + for input in &inputs { let input_size = input.len(); let (output, maybe_err) = runner .one_shot() @@ -43,14 +43,14 @@ pub(crate) fn eth_deploy_code_benchmark(c: &mut Criterion) { let gas = output.burnt_gas; let eth_gas = crate::test_utils::parse_eth_gas(&output); // TODO(#45): capture this in a file - println!("ETH_DEPLOY_CODE_{:?} NEAR GAS: {:?}", input_size, gas); - println!("ETH_DEPLOY_CODE_{:?} ETH GAS: {:?}", input_size, eth_gas); + println!("ETH_DEPLOY_CODE_{input_size:?} NEAR GAS: {gas:?}"); + println!("ETH_DEPLOY_CODE_{input_size:?} ETH GAS: {eth_gas:?}"); } // measure wall-clock time let mut group = c.benchmark_group("deploy_code"); for input in inputs { - let input_size = input.len() as u64; + let input_size = u64::try_from(input.len()).unwrap(); let id = BenchmarkId::from_parameter(input_size); group.throughput(Throughput::Bytes(input_size)); group.bench_function(id, |b| { @@ -58,7 +58,7 @@ pub(crate) fn eth_deploy_code_benchmark(c: &mut Criterion) { || (runner.one_shot(), calling_account_id, input.clone()), |(r, c, i)| r.call(SUBMIT, c, i), BatchSize::SmallInput, - ) + ); }); } group.finish(); diff --git a/engine-tests/src/benches/eth_erc20.rs b/engine-tests/src/benches/eth_erc20.rs index c48f764e0..cc6d0f947 100644 --- a/engine-tests/src/benches/eth_erc20.rs +++ b/engine-tests/src/benches/eth_erc20.rs @@ -9,7 +9,7 @@ const INITIAL_BALANCE: u64 = 1000; const INITIAL_NONCE: u64 = 0; const TRANSFER_AMOUNT: u64 = 67; -pub(crate) fn eth_erc20_benchmark(c: &mut Criterion) { +pub fn eth_erc20_benchmark(c: &mut Criterion) { let mut runner = deploy_evm(); let mut rng = rand::thread_rng(); let source_account = SecretKey::random(&mut rng); @@ -57,7 +57,7 @@ pub(crate) fn eth_erc20_benchmark(c: &mut Criterion) { || (runner.one_shot(), calling_account_id, mint_tx_bytes.clone()), |(r, c, i)| r.call(SUBMIT, c, i), BatchSize::SmallInput, - ) + ); }); // Measure mint gas usage; don't use `one_shot` because we want to keep this state change for @@ -68,8 +68,8 @@ pub(crate) fn eth_erc20_benchmark(c: &mut Criterion) { let gas = output.burnt_gas; let eth_gas = crate::test_utils::parse_eth_gas(&output); // TODO(#45): capture this in a file - println!("ETH_ERC20_MINT NEAR GAS: {:?}", gas); - println!("ETH_ERC20_MINT ETH GAS: {:?}", eth_gas); + println!("ETH_ERC20_MINT NEAR GAS: {gas:?}"); + println!("ETH_ERC20_MINT ETH GAS: {eth_gas:?}"); // Measure transfer gas usage let (output, maybe_err) = @@ -81,8 +81,8 @@ pub(crate) fn eth_erc20_benchmark(c: &mut Criterion) { let gas = output.burnt_gas; let eth_gas = crate::test_utils::parse_eth_gas(&output); // TODO(#45): capture this in a file - println!("ETH_ERC20_TRANSFER NEAR GAS: {:?}", gas); - println!("ETH_ERC20_TRANSFER ETH GAS: {:?}", eth_gas); + println!("ETH_ERC20_TRANSFER NEAR GAS: {gas:?}"); + println!("ETH_ERC20_TRANSFER ETH GAS: {eth_gas:?}"); // measure transfer wall-clock time group.bench_function(transfer_id, |b| { @@ -96,7 +96,7 @@ pub(crate) fn eth_erc20_benchmark(c: &mut Criterion) { }, |(r, c, i)| r.call(SUBMIT, c, i), BatchSize::SmallInput, - ) + ); }); group.finish(); diff --git a/engine-tests/src/benches/eth_standard_precompiles.rs b/engine-tests/src/benches/eth_standard_precompiles.rs index 12f043e4d..dbd5130ed 100644 --- a/engine-tests/src/benches/eth_standard_precompiles.rs +++ b/engine-tests/src/benches/eth_standard_precompiles.rs @@ -9,7 +9,7 @@ use crate::test_utils::{address_from_secret_key, deploy_evm, sign_transaction, S const INITIAL_BALANCE: Wei = Wei::new_u64(1000); const INITIAL_NONCE: u64 = 0; -pub(crate) fn eth_standard_precompiles_benchmark(c: &mut Criterion) { +pub fn eth_standard_precompiles_benchmark(c: &mut Criterion) { let mut runner = deploy_evm(); let mut rng = rand::thread_rng(); let source_account = SecretKey::random(&mut rng); @@ -52,8 +52,8 @@ pub(crate) fn eth_standard_precompiles_benchmark(c: &mut Criterion) { let gas = output.burnt_gas; let eth_gas = crate::test_utils::parse_eth_gas(&output); // TODO(#45): capture this in a file - println!("ETH_STANDARD_PRECOMPILES_{} NEAR GAS: {:?}", name, gas); - println!("ETH_STANDARD_PRECOMPILES_{} ETH GAS: {:?}", name, eth_gas); + println!("ETH_STANDARD_PRECOMPILES_{name} NEAR GAS: {gas:?}"); + println!("ETH_STANDARD_PRECOMPILES_{name} ETH GAS: {eth_gas:?}"); } let mut group = c.benchmark_group("standard_precompiles"); @@ -65,7 +65,7 @@ pub(crate) fn eth_standard_precompiles_benchmark(c: &mut Criterion) { || (runner.one_shot(), calling_account_id, tx_bytes.clone()), |(r, c, i)| r.call(SUBMIT, c, i), BatchSize::SmallInput, - ) + ); }); } diff --git a/engine-tests/src/benches/eth_transfer.rs b/engine-tests/src/benches/eth_transfer.rs index 4b704eac2..1cfcbfd21 100644 --- a/engine-tests/src/benches/eth_transfer.rs +++ b/engine-tests/src/benches/eth_transfer.rs @@ -8,7 +8,7 @@ const INITIAL_BALANCE: Wei = Wei::new_u64(1000); const INITIAL_NONCE: u64 = 0; const TRANSFER_AMOUNT: Wei = Wei::new_u64(123); -pub(crate) fn eth_transfer_benchmark(c: &mut Criterion) { +pub fn eth_transfer_benchmark(c: &mut Criterion) { let mut runner = deploy_evm(); let mut rng = rand::thread_rng(); let source_account = SecretKey::random(&mut rng); @@ -35,8 +35,8 @@ pub(crate) fn eth_transfer_benchmark(c: &mut Criterion) { assert!(maybe_err.is_none()); let gas = output.unwrap().burnt_gas; // TODO(#45): capture this in a file - println!("ETH_TRANSFER NEAR GAS: {:?}", gas); - println!("ETH_TRANSFER ETH GAS: {:?}", 21_000); + println!("ETH_TRANSFER NEAR GAS: {gas:?}"); + println!("ETH_TRANSFER ETH GAS: 21_000"); // measure wall-clock time c.bench_function("eth_transfer", |b| { @@ -44,6 +44,6 @@ pub(crate) fn eth_transfer_benchmark(c: &mut Criterion) { || (runner.one_shot(), calling_account_id, input.clone()), |(r, c, i)| r.call(SUBMIT, c, i), BatchSize::SmallInput, - ) + ); }); } diff --git a/engine-tests/src/benches/mod.rs b/engine-tests/src/benches/mod.rs index f242756da..7ae9e79dc 100644 --- a/engine-tests/src/benches/mod.rs +++ b/engine-tests/src/benches/mod.rs @@ -32,7 +32,7 @@ fn measure_nft_pagination_gas_usage() { for size in data_sizes { for n_tokens in tokens_per_page { let gas_used = nft_pagination::measure_gas_usage(TOTAL_TOKENS, size, n_tokens); - println!("{},{},{}", size, n_tokens, gas_used); + println!("{size},{n_tokens},{gas_used}"); } } } diff --git a/engine-tests/src/benches/nft_pagination.rs b/engine-tests/src/benches/nft_pagination.rs index e769dda18..ff24b8b7b 100644 --- a/engine-tests/src/benches/nft_pagination.rs +++ b/engine-tests/src/benches/nft_pagination.rs @@ -12,11 +12,7 @@ const INITIAL_NONCE: u64 = 0; static DOWNLOAD_ONCE: Once = Once::new(); static COMPILE_ONCE: Once = Once::new(); -pub(crate) fn measure_gas_usage( - total_tokens: usize, - data_size: usize, - tokens_per_page: usize, -) -> u64 { +pub fn measure_gas_usage(total_tokens: usize, data_size: usize, tokens_per_page: usize) -> u64 { let (mut runner, mut source_account, dest_address) = initialize_evm(); let marketplace_constructor = MarketPlaceConstructor::load(); @@ -46,7 +42,7 @@ pub(crate) fn measure_gas_usage( // show them let nonce = source_account.nonce; let tx = marketplace.get_page(tokens_per_page, 0, nonce.into()); - let (result, profile) = runner.profiled_view_call(test_utils::as_view_call(tx, dest_address)); + let (result, profile) = runner.profiled_view_call(&test_utils::as_view_call(tx, dest_address)); let status = result.unwrap(); assert!(status.is_ok()); @@ -109,17 +105,17 @@ impl MarketPlaceConstructor { fn download_solidity_sources() -> PathBuf { let sources_dir = Path::new("target").join("NFT-culturas-latinas"); let contracts_dir = sources_dir.join("blockchain"); - if contracts_dir.exists() { - contracts_dir - } else { + + if !contracts_dir.exists() { // Contracts not already present, so download them (but only once, even // if multiple tests running in parallel saw `contracts_dir` does not exist). DOWNLOAD_ONCE.call_once(|| { let url = "https://github.com/birchmd/NFT-culturas-latinas.git"; git2::Repository::clone(url, sources_dir).unwrap(); }); - contracts_dir } + + contracts_dir } } diff --git a/engine-tests/src/benches/uniswap.rs b/engine-tests/src/benches/uniswap.rs index b0876fa07..0a94a97d9 100644 --- a/engine-tests/src/benches/uniswap.rs +++ b/engine-tests/src/benches/uniswap.rs @@ -8,7 +8,7 @@ const MINT_AMOUNT: u64 = 1_000_000_000; const LIQUIDITY_AMOUNT: u64 = MINT_AMOUNT / 2; const OUTPUT_AMOUNT: u64 = LIQUIDITY_AMOUNT / 100; -pub(crate) fn uniswap_benchmark(c: &mut Criterion, context: &mut UniswapTestContext) { +pub fn uniswap_benchmark(c: &mut Criterion, context: &mut UniswapTestContext) { let calling_account_id = "some-account.near"; let chain_id = Some(context.runner.chain_id); let (token_a, token_b) = context.create_token_pair(MINT_AMOUNT.into()); @@ -23,16 +23,17 @@ pub(crate) fn uniswap_benchmark(c: &mut Criterion, context: &mut UniswapTestCont // create transaction for adding liquidity let nonce = context.signer.use_nonce(); let liquidity_params = context.mint_params(LIQUIDITY_AMOUNT.into(), &token_a, &token_b); - let tx = context.manager.mint(liquidity_params, nonce.into()); + let tx = context.manager.mint(&liquidity_params, nonce.into()); let signed_tx = test_utils::sign_transaction(tx, chain_id, &context.signer.secret_key); let liquidity_tx_bytes = rlp::encode(&signed_tx).to_vec(); // create transaction for swapping let nonce = context.signer.use_nonce(); - let swap_params = context.exact_output_single_params(OUTPUT_AMOUNT.into(), &token_a, &token_b); + let swap_params = + UniswapTestContext::exact_output_single_params(OUTPUT_AMOUNT.into(), &token_a, &token_b); let tx = context .swap_router - .exact_output_single(swap_params, nonce.into()); + .exact_output_single(&swap_params, nonce.into()); let signed_tx = test_utils::sign_transaction(tx, chain_id, &context.signer.secret_key); let swap_tx_bytes = rlp::encode(&signed_tx).to_vec(); @@ -52,7 +53,7 @@ pub(crate) fn uniswap_benchmark(c: &mut Criterion, context: &mut UniswapTestCont }, |(r, c, i)| r.call(SUBMIT, c, i), BatchSize::SmallInput, - ) + ); }); // Measure add_liquidity gas usage; don't use `one_shot` because we want to keep @@ -66,8 +67,8 @@ pub(crate) fn uniswap_benchmark(c: &mut Criterion, context: &mut UniswapTestCont let gas = output.burnt_gas; let eth_gas = crate::test_utils::parse_eth_gas(&output); // TODO(#45): capture this in a file - println!("UNISWAP_ADD_LIQUIDITY NEAR GAS: {:?}", gas); - println!("UNISWAP_ADD_LIQUIDITY ETH GAS: {:?}", eth_gas); + println!("UNISWAP_ADD_LIQUIDITY NEAR GAS: {gas:?}"); + println!("UNISWAP_ADD_LIQUIDITY ETH GAS: {eth_gas:?}"); // Measure swap gas usage let (output, maybe_error) = @@ -80,8 +81,8 @@ pub(crate) fn uniswap_benchmark(c: &mut Criterion, context: &mut UniswapTestCont let gas = output.burnt_gas; let eth_gas = crate::test_utils::parse_eth_gas(&output); // TODO(#45): capture this in a file - println!("UNISWAP_SWAP NEAR GAS: {:?}", gas); - println!("UNISWAP_SWAP ETH GAS: {:?}", eth_gas); + println!("UNISWAP_SWAP NEAR GAS: {gas:?}"); + println!("UNISWAP_SWAP ETH GAS: {eth_gas:?}"); // measure add_liquidity wall-clock time group.bench_function(swap_id, |b| { @@ -95,7 +96,7 @@ pub(crate) fn uniswap_benchmark(c: &mut Criterion, context: &mut UniswapTestCont }, |(r, c, i)| r.call(SUBMIT, c, i), BatchSize::SmallInput, - ) + ); }); group.finish(); diff --git a/engine-tests/src/lib.rs b/engine-tests/src/lib.rs index 19f99d38f..41970d34f 100644 --- a/engine-tests/src/lib.rs +++ b/engine-tests/src/lib.rs @@ -1,3 +1,5 @@ +#![deny(clippy::pedantic, clippy::nursery)] +#![allow(clippy::unreadable_literal, clippy::module_name_repetitions)] #[cfg(test)] mod benches; #[cfg(test)] diff --git a/engine-tests/src/test_utils/erc20.rs b/engine-tests/src/test_utils/erc20.rs index be0b8c893..2c3432337 100644 --- a/engine-tests/src/test_utils/erc20.rs +++ b/engine-tests/src/test_utils/erc20.rs @@ -1,12 +1,13 @@ use crate::prelude::{transactions::legacy::TransactionLegacy, Address, U256}; use crate::test_utils::solidity; use aurora_engine_transactions::NormalizedEthTransaction; +use aurora_engine_types::types::Wei; use std::path::{Path, PathBuf}; use std::sync::Once; -pub(crate) struct ERC20Constructor(pub solidity::ContractConstructor); +pub struct ERC20Constructor(pub solidity::ContractConstructor); -pub(crate) struct ERC20(pub solidity::DeployedContract); +pub struct ERC20(pub solidity::DeployedContract); impl From for solidity::ContractConstructor { fn from(c: ERC20Constructor) -> Self { @@ -42,10 +43,10 @@ impl ERC20Constructor { .unwrap(); TransactionLegacy { nonce, - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: None, - value: Default::default(), + value: Wei::default(), data, } } @@ -53,17 +54,17 @@ impl ERC20Constructor { fn download_solidity_sources() -> PathBuf { let sources_dir = Path::new("target").join("openzeppelin-contracts"); let contracts_dir = sources_dir.join("contracts"); - if contracts_dir.exists() { - contracts_dir - } else { + + if !contracts_dir.exists() { // Contracts not already present, so download them (but only once, even // if multiple tests running in parallel saw `contracts_dir` does not exist). DOWNLOAD_ONCE.call_once(|| { let url = "https://github.com/OpenZeppelin/openzeppelin-contracts"; git2::Repository::clone(url, sources_dir).unwrap(); }); - contracts_dir } + + contracts_dir } fn solidity_artifacts_path() -> PathBuf { @@ -86,10 +87,10 @@ impl ERC20 { TransactionLegacy { nonce, - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: Some(self.0.address), - value: Default::default(), + value: Wei::default(), data, } } @@ -107,10 +108,10 @@ impl ERC20 { .unwrap(); TransactionLegacy { nonce, - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: Some(self.0.address), - value: Default::default(), + value: Wei::default(), data, } } @@ -135,10 +136,10 @@ impl ERC20 { .unwrap(); TransactionLegacy { nonce, - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: Some(self.0.address), - value: Default::default(), + value: Wei::default(), data, } } @@ -156,10 +157,10 @@ impl ERC20 { .unwrap(); TransactionLegacy { nonce, - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: Some(self.0.address), - value: Default::default(), + value: Wei::default(), data, } } @@ -174,18 +175,18 @@ impl ERC20 { .unwrap(); TransactionLegacy { nonce, - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: Some(self.0.address), - value: Default::default(), + value: Wei::default(), data, } } } -pub(crate) fn legacy_into_normalized_tx(tx: TransactionLegacy) -> NormalizedEthTransaction { +pub fn legacy_into_normalized_tx(tx: TransactionLegacy) -> NormalizedEthTransaction { NormalizedEthTransaction { - address: Default::default(), + address: Address::default(), chain_id: None, nonce: tx.nonce, gas_limit: tx.gas_limit, diff --git a/engine-tests/src/test_utils/exit_precompile.rs b/engine-tests/src/test_utils/exit_precompile.rs index 6f440d289..a14bfb4f9 100644 --- a/engine-tests/src/test_utils/exit_precompile.rs +++ b/engine-tests/src/test_utils/exit_precompile.rs @@ -4,7 +4,7 @@ use crate::prelude::{ use crate::test_utils::{self, solidity, AuroraRunner, Signer}; use near_vm_errors::VMError; -pub(crate) struct TesterConstructor(pub solidity::ContractConstructor); +pub struct TesterConstructor(pub solidity::ContractConstructor); const DEPLOY_CONTRACT_GAS: u64 = 1_000_000_000; pub const DEST_ACCOUNT: &str = "target.aurora"; @@ -36,16 +36,16 @@ impl TesterConstructor { TransactionLegacy { nonce: nonce.into(), - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: U256::from(DEPLOY_CONTRACT_GAS), to: None, - value: Default::default(), + value: Wei::default(), data, } } } -pub(crate) struct Tester { +pub struct Tester { pub contract: solidity::DeployedContract, } @@ -80,7 +80,7 @@ impl Tester { let tx = TransactionLegacy { nonce: signer.use_nonce().into(), - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: U256::from(DEPLOY_CONTRACT_GAS), to: Some(self.contract.address), value, @@ -94,7 +94,7 @@ impl Tester { match result.status { aurora_engine::parameters::TransactionStatus::Succeed(_) => Ok(result), aurora_engine::parameters::TransactionStatus::Revert(bytes) => Err(Revert(bytes)), - other => panic!("Unexpected status {:?}", other), + other => panic!("Unexpected status {other:?}"), } } @@ -222,4 +222,4 @@ impl Tester { } #[derive(Debug)] -pub(crate) struct Revert(Vec); +pub struct Revert(Vec); diff --git a/engine-tests/src/test_utils/mocked_external.rs b/engine-tests/src/test_utils/mocked_external.rs index 87919c205..becd8d875 100644 --- a/engine-tests/src/test_utils/mocked_external.rs +++ b/engine-tests/src/test_utils/mocked_external.rs @@ -1,17 +1,17 @@ use near_vm_logic::mocks::mock_external::MockedExternal; -/// Derived from mainnet data reported here: https://hackmd.io/@birchmd/r1HRjr0P9 +/// Derived from mainnet data reported here: `https://hackmd.io/@birchmd/r1HRjr0P9` /// Uses the formulas: -/// n_T = (G_T / G_R) * (g_R / g_T) -/// n_c = (G_c / G_R) * (g_R / g_c) -/// Where n_T is the average number of new touched trie nodes per read, -/// n_c is the average number of cached trie nodes read per read, -/// G_T is the average gas cost of touching trie node per Aurora transaction, -/// G_c is the average gas cost of reading cached trie node per Aurora transaction, -/// G_R is the average gas cost of `STORAGE_READ_BASE` per Aurora transaction, -/// g_R is the `STORAGE_READ_BASE` cost (from the config), -/// g_T is the `TOUCHING_TRIE_NODE` cost (from the config), and -/// g_c is the `READ_CACHED_TRIE_NODE` cost (from the config). +/// `n_T = (G_T / G_R) * (g_R / g_T)` +/// `n_c = (G_c / G_R) * (g_R / g_c)` +/// Where `n_T` is the average number of new touched trie nodes per read, +/// `n_c` is the average number of cached trie nodes read per read, +/// `G_T` is the average gas cost of touching trie node per Aurora transaction, +/// `G_c` is the average gas cost of reading cached trie node per Aurora transaction, +/// `G_R` is the average gas cost of `STORAGE_READ_BASE` per Aurora transaction, +/// `g_R` is the `STORAGE_READ_BASE` cost (from the config), +/// `g_T` is the `TOUCHING_TRIE_NODE` cost (from the config), and +/// `g_c` is the `READ_CACHED_TRIE_NODE` cost (from the config). pub const MAINNET_AVERAGE_TOUCHED_TRIE_PER_READ: u64 = 2; pub const MAINNET_AVERAGE_READ_CACHED_TRIE_PER_READ: u64 = 11; /// This is still needed because writes will touch every node in the depth, unlike reads which take advantage of caching. @@ -25,7 +25,7 @@ pub struct MockedExternalWithTrie { } impl MockedExternalWithTrie { - pub fn new(ext: MockedExternal) -> Self { + pub const fn new(ext: MockedExternal) -> Self { Self { underlying: ext, new_trie_node_count: std::cell::Cell::new(0), diff --git a/engine-tests/src/test_utils/mod.rs b/engine-tests/src/test_utils/mod.rs index 881124cf3..223c61ae6 100644 --- a/engine-tests/src/test_utils/mod.rs +++ b/engine-tests/src/test_utils/mod.rs @@ -1,4 +1,4 @@ -use aurora_engine::parameters::ViewCallArgs; +use aurora_engine::parameters::{SubmitArgs, ViewCallArgs}; use aurora_engine_types::account_id::AccountId; use aurora_engine_types::types::{NEP141Wei, PromiseResult}; use borsh::{BorshDeserialize, BorshSerialize}; @@ -9,6 +9,7 @@ use near_primitives_core::config::VMConfig; use near_primitives_core::contract::ContractCode; use near_primitives_core::profile::ProfileData; use near_primitives_core::runtime::fees::RuntimeFeesConfig; +use near_vm_logic::mocks::mock_external::MockedExternal; use near_vm_logic::types::ReturnData; use near_vm_logic::{VMContext, VMOutcome, ViewConfig}; use near_vm_runner::{MockCompiledContractCache, VMError}; @@ -25,30 +26,30 @@ use crate::prelude::{sdk, Address, Wei, H256, U256}; use crate::test_utils::solidity::{ContractConstructor, DeployedContract}; // TODO(Copied from #84): Make sure that there is only one Signer after both PR are merged. - -pub fn origin() -> String { - "aurora".to_string() -} - -pub(crate) const SUBMIT: &str = "submit"; -pub(crate) const CALL: &str = "call"; -pub(crate) const DEPLOY_ERC20: &str = "deploy_erc20_token"; -pub(crate) const PAUSE_PRECOMPILES: &str = "pause_precompiles"; -pub(crate) const PAUSED_PRECOMPILES: &str = "paused_precompiles"; -pub(crate) const RESUME_PRECOMPILES: &str = "resume_precompiles"; - -pub(crate) mod erc20; -pub(crate) mod exit_precompile; -pub(crate) mod mocked_external; -pub(crate) mod one_inch; -pub(crate) mod random; -pub(crate) mod rust; -pub(crate) mod self_destruct; -pub(crate) mod solidity; -pub(crate) mod standalone; -pub(crate) mod standard_precompiles; -pub(crate) mod uniswap; -pub(crate) mod weth; +pub const ORIGIN: &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"; + +const CALLER_ACCOUNT_ID: &str = "some-account.near"; + +pub mod erc20; +pub mod exit_precompile; +pub mod mocked_external; +pub mod one_inch; +pub mod random; +pub mod rust; +pub mod self_destruct; +pub mod solidity; +pub mod standalone; +pub mod standard_precompiles; +pub mod uniswap; +pub mod weth; pub struct Signer { pub nonce: u64, @@ -56,7 +57,7 @@ pub struct Signer { } impl Signer { - pub fn new(secret_key: SecretKey) -> Self { + pub const fn new(secret_key: SecretKey) -> Self { Self { nonce: 0, secret_key, @@ -76,7 +77,7 @@ impl Signer { } } -pub(crate) struct AuroraRunner { +pub struct AuroraRunner { pub aurora_account_id: String, pub chain_id: u64, pub code: ContractCode, @@ -98,7 +99,7 @@ pub(crate) struct AuroraRunner { /// Same as `AuroraRunner`, but consumes `self` on execution (thus preventing building on /// the `ext` post-state with future calls to the contract. #[derive(Clone)] -pub(crate) struct OneShotAuroraRunner<'a> { +pub struct OneShotAuroraRunner<'a> { pub base: &'a AuroraRunner, pub ext: mocked_external::MockedExternalWithTrie, pub context: VMContext, @@ -227,10 +228,12 @@ impl AuroraRunner { if let Some(standalone_runner) = &mut self.standalone_runner { if maybe_error.is_none() && (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 == RESUME_PRECOMPILES + || method_name == SET_OWNER) { standalone_runner .submit_raw(method_name, &self.context, &self.promise_results) @@ -248,8 +251,8 @@ impl AuroraRunner { ) { let trie = &mut self.ext.underlying.fake_trie; for entry in snapshot.result.values { - let key = base64::decode(entry.key).unwrap(); - let value = base64::decode(entry.value).unwrap(); + let key = aurora_engine_sdk::base64::decode(entry.key).unwrap(); + let value = aurora_engine_sdk::base64::decode(entry.value).unwrap(); trie.insert(key, value); } } @@ -260,7 +263,7 @@ impl AuroraRunner { init_balance: crate::prelude::Wei, init_nonce: U256, ) { - self.internal_create_address(address, init_balance, init_nonce, None) + self.internal_create_address(address, init_balance, init_nonce, None); } pub fn create_address_with_code( @@ -270,7 +273,7 @@ impl AuroraRunner { init_nonce: U256, code: Vec, ) { - self.internal_create_address(address, init_balance, init_nonce, Some(code)) + self.internal_create_address(address, init_balance, init_nonce, Some(code)); } fn internal_create_address( @@ -304,7 +307,7 @@ impl AuroraRunner { let ft_key = crate::prelude::storage::bytes_to_key( crate::prelude::storage::KeyPrefix::EthConnector, - &[crate::prelude::storage::EthConnectorStorageId::FungibleToken as u8], + &[crate::prelude::storage::EthConnectorStorageId::FungibleToken.into()], ); let ft_value = { let mut current_ft: FungibleToken = trie @@ -334,7 +337,7 @@ impl AuroraRunner { let proof_key = crate::prelude::storage::bytes_to_key( crate::prelude::storage::KeyPrefix::EthConnector, - &[crate::prelude::storage::EthConnectorStorageId::UsedEvent as u8], + &[crate::prelude::storage::EthConnectorStorageId::UsedEvent.into()], ); trie.insert(balance_key.to_vec(), balance_value.to_vec()); @@ -390,21 +393,65 @@ impl AuroraRunner { account: &SecretKey, transaction: TransactionLegacy, ) -> Result<(SubmitResult, ExecutionProfile), VMError> { - let calling_account_id = "some-account.near"; let signed_tx = sign_transaction(transaction, Some(self.chain_id), account); - let (output, maybe_err) = - self.call(SUBMIT, calling_account_id, rlp::encode(&signed_tx).to_vec()); + self.call(SUBMIT, CALLER_ACCOUNT_ID, rlp::encode(&signed_tx).to_vec()); - if let Some(err) = maybe_err { - Err(err) - } else { - let output = output.unwrap(); - let profile = ExecutionProfile::new(&output); - let submit_result = - SubmitResult::try_from_slice(&output.return_data.as_value().unwrap()).unwrap(); - Ok((submit_result, profile)) - } + Self::profile_outcome(output, maybe_err) + } + + pub fn submit_transaction_with_args( + &mut self, + account: &SecretKey, + transaction: TransactionLegacy, + max_gas_price: u128, + gas_token_address: Option

, + ) -> Result { + self.submit_transaction_with_args_profiled( + account, + transaction, + max_gas_price, + gas_token_address, + ) + .map(|(result, _)| result) + } + + pub fn submit_transaction_with_args_profiled( + &mut self, + account: &SecretKey, + transaction: TransactionLegacy, + max_gas_price: u128, + gas_token_address: Option
, + ) -> Result<(SubmitResult, ExecutionProfile), VMError> { + let signed_tx = sign_transaction(transaction, Some(self.chain_id), account); + let args = SubmitArgs { + tx_data: rlp::encode(&signed_tx).to_vec(), + max_gas_price: Some(max_gas_price), + gas_token_address, + }; + let (output, maybe_err) = self.call( + SUBMIT_WITH_ARGS, + CALLER_ACCOUNT_ID, + args.try_to_vec().unwrap(), + ); + + Self::profile_outcome(output, maybe_err) + } + + fn profile_outcome( + output: Option, + error: Option, + ) -> Result<(SubmitResult, ExecutionProfile), VMError> { + error.map_or_else( + || { + let output = output.unwrap(); + let profile = ExecutionProfile::new(&output); + let submit_result = + SubmitResult::try_from_slice(&output.return_data.as_value().unwrap()).unwrap(); + Ok((submit_result, profile)) + }, + Err, + ) } pub fn deploy_contract TransactionLegacy, T: Into>( @@ -413,11 +460,10 @@ impl AuroraRunner { constructor_tx: F, contract_constructor: T, ) -> DeployedContract { - let calling_account_id = "some-account.near"; let tx = constructor_tx(&contract_constructor); let signed_tx = sign_transaction(tx, Some(self.chain_id), account); let (output, maybe_err) = - self.call(SUBMIT, calling_account_id, rlp::encode(&signed_tx).to_vec()); + self.call(SUBMIT, CALLER_ACCOUNT_ID, rlp::encode(&signed_tx).to_vec()); assert!(maybe_err.is_none()); let submit_result = SubmitResult::try_from_slice(&output.unwrap().return_data.as_value().unwrap()).unwrap(); @@ -429,7 +475,7 @@ impl AuroraRunner { } } - pub fn view_call(&self, args: ViewCallArgs) -> Result { + pub fn view_call(&self, args: &ViewCallArgs) -> Result { let input = args.try_to_vec().unwrap(); let mut runner = self.one_shot(); runner.context.view_config = Some(ViewConfig { @@ -444,7 +490,7 @@ impl AuroraRunner { pub fn profiled_view_call( &self, - args: ViewCallArgs, + args: &ViewCallArgs, ) -> (Result, ExecutionProfile) { let input = args.try_to_vec().unwrap(); let mut runner = self.one_shot(); @@ -504,12 +550,13 @@ impl AuroraRunner { maybe_outcome: Option, maybe_error: Option, ) -> Result, VMError> { - if let Some(error) = maybe_error { - Err(error) - } else { - let bytes = maybe_outcome.unwrap().return_data.as_value().unwrap(); - Ok(bytes) - } + maybe_error.map_or_else( + || { + let bytes = maybe_outcome.unwrap().return_data.as_value().unwrap(); + Ok(bytes) + }, + Err, + ) } pub fn with_random_seed(mut self, random_seed: H256) -> Self { @@ -524,14 +571,12 @@ impl AuroraRunner { // (they are replaced with a Deleted identifier instead; this is important for replaying transactions). assert!(self.ext.underlying.fake_trie.len() <= standalone_state.iter().count()); for (key, value) in standalone_state.iter() { - let trie_value = self.ext.underlying.fake_trie.get(key).map(|v| v.as_slice()); + let trie_value = self.ext.underlying.fake_trie.get(key).map(Vec::as_slice); let standalone_value = value.value(); - if trie_value != standalone_value { - panic!( - "Standalone mismatch at {:?}.\nStandlaone: {:?}\nWasm : {:?}", - key, standalone_value, trie_value - ); - } + assert_eq!( + trie_value, standalone_value, + "Standalone mismatch at {key:?}.\nStandlaone: {standalone_value:?}\nWasm: {trie_value:?}", + ); } } } @@ -539,7 +584,6 @@ impl AuroraRunner { impl Default for AuroraRunner { fn default() -> Self { - let aurora_account_id = "aurora".to_string(); let evm_wasm_bytes = if cfg!(feature = "mainnet-test") { std::fs::read("../bin/aurora-mainnet-test.wasm").unwrap() } else if cfg!(feature = "testnet-test") { @@ -554,16 +598,16 @@ impl Default for AuroraRunner { let wasm_config = runtime_config.wasm_config.clone(); Self { - aurora_account_id: aurora_account_id.clone(), - chain_id: 1313161556, // NEAR localnet, + aurora_account_id: ORIGIN.to_string(), + chain_id: 1_313_161_556, // NEAR localnet, code: ContractCode::new(evm_wasm_bytes, None), - cache: Default::default(), - ext: mocked_external::MockedExternalWithTrie::new(Default::default()), + cache: MockCompiledContractCache::default(), + ext: mocked_external::MockedExternalWithTrie::new(MockedExternal::default()), context: VMContext { - current_account_id: as_account_id(&aurora_account_id), - signer_account_id: as_account_id(&aurora_account_id), + current_account_id: as_account_id(ORIGIN), + signer_account_id: as_account_id(ORIGIN), signer_account_pk: vec![], - predecessor_account_id: as_account_id(&aurora_account_id), + predecessor_account_id: as_account_id(ORIGIN), input: vec![], block_index: 0, block_timestamp: 0, @@ -580,7 +624,7 @@ impl Default for AuroraRunner { wasm_config, fees_config: RuntimeFeesConfig::test(), current_protocol_version: u32::MAX, - previous_logs: Default::default(), + previous_logs: Vec::new(), standalone_runner: None, promise_results: Vec::new(), } @@ -588,9 +632,9 @@ impl Default for AuroraRunner { } /// Wrapper around `ProfileData` to still include the wasm gas usage -/// (which was removed in https://github.com/near/nearcore/pull/4438). +/// (which was removed in `https://github.com/near/nearcore/pull/4438`). #[derive(Debug, Default, Clone)] -pub(crate) struct ExecutionProfile { +pub struct ExecutionProfile { pub host_breakdown: ProfileData, wasm_gas: u64, } @@ -605,7 +649,7 @@ impl ExecutionProfile { } } - pub fn wasm_gas(&self) -> u64 { + pub const fn wasm_gas(&self) -> u64 { self.wasm_gas } @@ -614,7 +658,7 @@ impl ExecutionProfile { } } -pub(crate) fn deploy_evm() -> AuroraRunner { +pub fn deploy_evm() -> AuroraRunner { let mut runner = AuroraRunner::default(); let args = NewCallArgs { chain_id: crate::prelude::u256_to_arr(&U256::from(runner.chain_id)), @@ -647,10 +691,10 @@ pub(crate) fn deploy_evm() -> AuroraRunner { runner } -pub(crate) fn transfer(to: Address, amount: Wei, nonce: U256) -> TransactionLegacy { +pub fn transfer(to: Address, amount: Wei, nonce: U256) -> TransactionLegacy { TransactionLegacy { nonce, - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: Some(to), value: amount, @@ -658,12 +702,9 @@ pub(crate) fn transfer(to: Address, amount: Wei, nonce: U256) -> TransactionLega } } -pub(crate) fn create_deploy_transaction(contract_bytes: Vec, nonce: U256) -> TransactionLegacy { - let len = contract_bytes.len(); - if len > u16::MAX as usize { - panic!("Cannot deploy a contract with that many bytes!"); - } - let len = len as u16; +pub fn create_deploy_transaction(contract_bytes: Vec, nonce: U256) -> TransactionLegacy { + let len = u16::try_from(contract_bytes.len()) + .unwrap_or_else(|_| panic!("Cannot deploy a contract with that many bytes!")); // This bit of EVM byte code essentially says: // "If msg.value > 0 revert; otherwise return `len` amount of bytes that come after me // in the code." By prepending this to `contract_bytes` we create a valid EVM program which @@ -680,7 +721,7 @@ pub(crate) fn create_deploy_transaction(contract_bytes: Vec, nonce: U256) -> TransactionLegacy { nonce, - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: None, value: Wei::zero(), @@ -688,17 +729,17 @@ pub(crate) fn create_deploy_transaction(contract_bytes: Vec, nonce: U256) -> } } -pub(crate) fn create_eth_transaction( +pub fn create_eth_transaction( to: Option
, - value: crate::prelude::Wei, + value: Wei, data: Vec, chain_id: Option, secret_key: &SecretKey, ) -> LegacyEthSignedTransaction { // nonce, gas_price and gas are not used by EVM contract currently let tx = TransactionLegacy { - nonce: Default::default(), - gas_price: Default::default(), + nonce: U256::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to, value, @@ -707,7 +748,7 @@ pub(crate) fn create_eth_transaction( sign_transaction(tx, chain_id, secret_key) } -pub(crate) fn as_view_call(tx: TransactionLegacy, sender: Address) -> ViewCallArgs { +pub fn as_view_call(tx: TransactionLegacy, sender: Address) -> ViewCallArgs { ViewCallArgs { sender, address: tx.to.unwrap(), @@ -716,7 +757,7 @@ pub(crate) fn as_view_call(tx: TransactionLegacy, sender: Address) -> ViewCallAr } } -pub(crate) fn sign_transaction( +pub fn sign_transaction( tx: TransactionLegacy, chain_id: Option, secret_key: &SecretKey, @@ -727,10 +768,10 @@ pub(crate) fn sign_transaction( let message = Message::parse_slice(message_hash.as_bytes()).unwrap(); let (signature, recovery_id) = libsecp256k1::sign(&message, secret_key); - let v: u64 = match chain_id { - Some(chain_id) => (recovery_id.serialize() as u64) + 2 * chain_id + 35, - None => (recovery_id.serialize() as u64) + 27, - }; + let v: u64 = chain_id.map_or_else( + || u64::from(recovery_id.serialize()) + 27, + |chain_id| u64::from(recovery_id.serialize()) + 2 * chain_id + 35, + ); let r = U256::from_big_endian(&signature.r.b32()); let s = U256::from_big_endian(&signature.s.b32()); LegacyEthSignedTransaction { @@ -741,7 +782,7 @@ pub(crate) fn sign_transaction( } } -pub(crate) fn sign_access_list_transaction( +pub fn sign_access_list_transaction( tx: Transaction2930, secret_key: &SecretKey, ) -> SignedTransaction2930 { @@ -763,7 +804,7 @@ pub(crate) fn sign_access_list_transaction( } } -pub(crate) fn sign_eip_1559_transaction( +pub fn sign_eip_1559_transaction( tx: Transaction1559, secret_key: &SecretKey, ) -> SignedTransaction1559 { @@ -785,13 +826,13 @@ pub(crate) fn sign_eip_1559_transaction( } } -pub(crate) fn address_from_secret_key(sk: &SecretKey) -> Address { +pub fn address_from_secret_key(sk: &SecretKey) -> Address { let pk = PublicKey::from_secret_key(sk); let hash = sdk::keccak(&pk.serialize()[1..]); Address::try_from_slice(&hash[12..]).unwrap() } -pub(crate) fn parse_eth_gas(output: &VMOutcome) -> u64 { +pub fn parse_eth_gas(output: &VMOutcome) -> u64 { let submit_result_bytes = match &output.return_data { ReturnData::Value(bytes) => bytes.as_slice(), ReturnData::None | ReturnData::ReceiptIndex(_) => panic!("Unexpected ReturnData"), @@ -800,31 +841,30 @@ pub(crate) fn parse_eth_gas(output: &VMOutcome) -> u64 { submit_result.gas_used } -pub(crate) fn validate_address_balance_and_nonce( +pub fn validate_address_balance_and_nonce( runner: &AuroraRunner, address: Address, - expected_balance: crate::prelude::Wei, + expected_balance: Wei, expected_nonce: U256, ) { assert_eq!(runner.get_balance(address), expected_balance, "balance"); assert_eq!(runner.get_nonce(address), expected_nonce, "nonce"); } -pub(crate) fn address_from_hex(address: &str) -> Address { - let bytes = if let Some(address) = address.strip_prefix("0x") { - hex::decode(address).unwrap() - } else { - hex::decode(address).unwrap() - }; +pub fn address_from_hex(address: &str) -> Address { + let bytes = address.strip_prefix("0x").map_or_else( + || hex::decode(address).unwrap(), + |address| hex::decode(address).unwrap(), + ); Address::try_from_slice(&bytes).unwrap() } -pub(crate) fn as_account_id(account_id: &str) -> near_primitives_core::types::AccountId { +pub fn as_account_id(account_id: &str) -> near_primitives_core::types::AccountId { account_id.parse().unwrap() } -pub(crate) fn str_to_account_id(account_id: &str) -> AccountId { +pub fn str_to_account_id(account_id: &str) -> AccountId { use aurora_engine_types::str::FromStr; AccountId::from_str(account_id).unwrap() } @@ -832,21 +872,21 @@ pub(crate) fn str_to_account_id(account_id: &str) -> AccountId { pub fn unwrap_success(result: SubmitResult) -> Vec { match result.status { TransactionStatus::Succeed(ret) => ret, - other => panic!("Unexpected status: {:?}", other), + other => panic!("Unexpected status: {other:?}"), } } pub fn unwrap_success_slice(result: &SubmitResult) -> &[u8] { match &result.status { TransactionStatus::Succeed(ret) => ret, - other => panic!("Unexpected status: {:?}", other), + other => panic!("Unexpected status: {other:?}"), } } pub fn unwrap_revert(result: SubmitResult) -> Vec { match result.status { TransactionStatus::Revert(ret) => ret, - other => panic!("Unexpected status: {:?}", other), + other => panic!("Unexpected status: {other:?}"), } } @@ -861,17 +901,15 @@ pub fn panic_on_fail(status: TransactionStatus) { pub fn assert_gas_bound(total_gas: u64, tgas_bound: u64) { // Add 1 to round up let tgas_used = (total_gas / 1_000_000_000_000) + 1; - assert!( - tgas_used == tgas_bound, - "{} Tgas is not equal to {} Tgas", - tgas_used, - tgas_bound, + assert_eq!( + tgas_used, tgas_bound, + "{tgas_used} Tgas is not equal to {tgas_bound} Tgas", ); } /// Returns true if `abs(a - b) / max(a, b) <= x / 100`. The implementation is written differently than /// this simpler formula to avoid floating point arithmetic. -pub fn within_x_percent(x: u64, a: u64, b: u64) -> bool { +pub const fn within_x_percent(x: u64, a: u64, b: u64) -> bool { let (larger, smaller) = if a < b { (b, a) } else { (a, b) }; (100 / x) * (larger - smaller) <= larger diff --git a/engine-tests/src/test_utils/one_inch/liquidity_protocol.rs b/engine-tests/src/test_utils/one_inch/liquidity_protocol.rs index 913d3ae43..da96bb3e2 100644 --- a/engine-tests/src/test_utils/one_inch/liquidity_protocol.rs +++ b/engine-tests/src/test_utils/one_inch/liquidity_protocol.rs @@ -1,13 +1,14 @@ use crate::prelude::parameters::SubmitResult; use crate::prelude::{Address, U256}; use crate::test_utils::{self, solidity, ExecutionProfile}; +use aurora_engine_types::types::Wei; use std::path::PathBuf; use std::sync::Once; static DOWNLOAD_ONCE: Once = Once::new(); static COMPILE_ONCE: Once = Once::new(); -pub(crate) struct Helper<'a> { +pub struct Helper<'a> { pub runner: &'a mut test_utils::AuroraRunner, pub signer: &'a mut test_utils::Signer, } @@ -29,10 +30,10 @@ impl<'a> Helper<'a> { .submit_with_signer_profiled(self.signer, |nonce| { crate::prelude::transactions::legacy::TransactionLegacy { nonce, - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: None, - value: Default::default(), + value: Wei::default(), data, } }) @@ -153,7 +154,7 @@ impl<'a> Helper<'a> { pub(crate) fn pool_deposit( &mut self, pool: &Pool, - args: DepositArgs, + args: &DepositArgs, ) -> (SubmitResult, ExecutionProfile) { self.pool_call( pool, @@ -174,7 +175,7 @@ impl<'a> Helper<'a> { pub(crate) fn pool_swap( &mut self, pool: &Pool, - args: SwapArgs, + args: &SwapArgs, ) -> (SubmitResult, ExecutionProfile) { self.pool_call( pool, @@ -192,7 +193,7 @@ impl<'a> Helper<'a> { pub(crate) fn pool_withdraw( &mut self, pool: &Pool, - args: WithdrawArgs, + args: &WithdrawArgs, ) -> (SubmitResult, ExecutionProfile) { self.pool_call( pool, @@ -224,20 +225,20 @@ impl<'a> Helper<'a> { } } -pub(crate) struct PoolDeployer(solidity::DeployedContract); +pub struct PoolDeployer(solidity::DeployedContract); -pub(crate) struct PoolFactory(solidity::DeployedContract); +pub struct PoolFactory(solidity::DeployedContract); -pub(crate) struct Pool(solidity::DeployedContract); +pub struct Pool(solidity::DeployedContract); -pub(crate) struct DepositArgs { +pub struct DepositArgs { pub min_token_a: U256, pub min_token_b: U256, pub max_token_a: U256, pub max_token_b: U256, } -pub(crate) struct SwapArgs { +pub struct SwapArgs { pub src_token: Address, pub dst_token: Address, pub amount: U256, @@ -245,14 +246,14 @@ pub(crate) struct SwapArgs { pub referral: Address, } -pub(crate) struct WithdrawArgs { +pub struct WithdrawArgs { pub amount: U256, pub min_token_a: U256, pub min_token_b: U256, } impl Pool { - pub fn address(&self) -> Address { + pub const fn address(&self) -> Address { self.0.address } } diff --git a/engine-tests/src/test_utils/one_inch/mod.rs b/engine-tests/src/test_utils/one_inch/mod.rs index 9e5923dbb..06036dce4 100644 --- a/engine-tests/src/test_utils/one_inch/mod.rs +++ b/engine-tests/src/test_utils/one_inch/mod.rs @@ -2,9 +2,9 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::sync::Once; -pub(crate) mod liquidity_protocol; +pub mod liquidity_protocol; -pub(crate) fn download_and_compile_solidity_sources( +pub fn download_and_compile_solidity_sources( repo_name: &str, download_once: &'static Once, compile_once: &'static Once, @@ -14,7 +14,7 @@ pub(crate) fn download_and_compile_solidity_sources( // Contracts not already present, so download them (but only once, even // if multiple tests running in parallel saw `contracts_dir` does not exist). download_once.call_once(|| { - let url = format!("https://github.com/1inch/{}", repo_name); + let url = format!("https://github.com/1inch/{repo_name}"); let repo = git2::Repository::clone(&url, &sources_dir).unwrap(); if repo_name == "limit-order-protocol" { // We need to checkout a specific commit because the code in the current `master` diff --git a/engine-tests/src/test_utils/random.rs b/engine-tests/src/test_utils/random.rs index 531606af2..33711d939 100644 --- a/engine-tests/src/test_utils/random.rs +++ b/engine-tests/src/test_utils/random.rs @@ -1,12 +1,13 @@ use crate::prelude::U256; use crate::test_utils::{self, solidity, AuroraRunner, Signer}; use aurora_engine_transactions::legacy::TransactionLegacy; +use aurora_engine_types::types::Wei; use aurora_engine_types::H256; use ethabi::Constructor; const DEFAULT_GAS: u64 = 1_000_000_000; -pub(crate) struct RandomConstructor(pub solidity::ContractConstructor); +pub struct RandomConstructor(pub solidity::ContractConstructor); impl RandomConstructor { pub fn load() -> Self { @@ -26,10 +27,10 @@ impl RandomConstructor { TransactionLegacy { nonce: nonce.into(), - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: U256::from(DEFAULT_GAS), to: None, - value: Default::default(), + value: Wei::default(), data, } } @@ -41,7 +42,7 @@ impl From for solidity::ContractConstructor { } } -pub(crate) struct Random { +pub struct Random { contract: solidity::DeployedContract, } @@ -57,10 +58,10 @@ impl Random { let tx = TransactionLegacy { nonce: signer.use_nonce().into(), - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: U256::from(DEFAULT_GAS), to: Some(self.contract.address), - value: Default::default(), + value: Wei::default(), data, }; diff --git a/engine-tests/src/test_utils/self_destruct.rs b/engine-tests/src/test_utils/self_destruct.rs index 7268dcc68..6bac496f0 100644 --- a/engine-tests/src/test_utils/self_destruct.rs +++ b/engine-tests/src/test_utils/self_destruct.rs @@ -3,9 +3,10 @@ use crate::prelude::{ Address, WeiU256, U256, }; use crate::test_utils::{self, solidity, AuroraRunner, Signer}; +use aurora_engine_types::types::Wei; use borsh::BorshSerialize; -pub(crate) struct SelfDestructFactoryConstructor(pub solidity::ContractConstructor); +pub struct SelfDestructFactoryConstructor(pub solidity::ContractConstructor); const DEFAULT_GAS: u64 = 1_000_000_000; @@ -27,16 +28,16 @@ impl SelfDestructFactoryConstructor { TransactionLegacy { nonce: nonce.into(), - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: U256::from(DEFAULT_GAS), to: None, - value: Default::default(), + value: Wei::default(), data, } } } -pub(crate) struct SelfDestructFactory { +pub struct SelfDestructFactory { contract: solidity::DeployedContract, } @@ -64,10 +65,10 @@ impl SelfDestructFactory { let tx = TransactionLegacy { nonce: signer.use_nonce().into(), - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: U256::from(DEFAULT_GAS), to: Some(self.contract.address), - value: Default::default(), + value: Wei::default(), data, }; @@ -78,7 +79,7 @@ impl SelfDestructFactory { } } -pub(crate) struct SelfDestructConstructor(pub solidity::ContractConstructor); +pub struct SelfDestructConstructor(pub solidity::ContractConstructor); impl SelfDestructConstructor { pub fn load() -> Self { @@ -88,7 +89,7 @@ impl SelfDestructConstructor { } } -pub(crate) struct SelfDestruct { +pub struct SelfDestruct { contract: solidity::DeployedContract, } @@ -104,10 +105,10 @@ impl SelfDestruct { let tx = TransactionLegacy { nonce: signer.use_nonce().into(), - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: U256::from(DEFAULT_GAS), to: Some(self.contract.address), - value: Default::default(), + value: Wei::default(), data, }; @@ -132,10 +133,10 @@ impl SelfDestruct { let tx = TransactionLegacy { nonce: signer.use_nonce().into(), - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: U256::from(DEFAULT_GAS), to: Some(self.contract.address), - value: Default::default(), + value: Wei::default(), data, }; @@ -153,10 +154,10 @@ impl SelfDestruct { let tx = TransactionLegacy { nonce: signer.use_nonce().into(), - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: U256::from(DEFAULT_GAS), to: Some(self.contract.address), - value: Default::default(), + value: Wei::default(), data, }; @@ -175,7 +176,7 @@ impl SelfDestruct { let input = CallArgs::V2(FunctionCallArgsV2 { contract: self.contract.address, value: WeiU256::default(), - input: data.to_vec(), + input: data, }) .try_to_vec() .unwrap(); diff --git a/engine-tests/src/test_utils/solidity.rs b/engine-tests/src/test_utils/solidity.rs index 4123273dc..f0e9b23ca 100644 --- a/engine-tests/src/test_utils/solidity.rs +++ b/engine-tests/src/test_utils/solidity.rs @@ -1,16 +1,17 @@ use crate::prelude::{transactions::legacy::TransactionLegacy, Address, U256}; +use aurora_engine_types::types::Wei; use near_sdk::serde_json; use serde::Deserialize; use std::fs; use std::path::Path; use std::process::Command; -pub(crate) struct ContractConstructor { +pub struct ContractConstructor { pub abi: ethabi::Contract, pub code: Vec, } -pub(crate) struct DeployedContract { +pub struct DeployedContract { pub abi: ethabi::Contract, pub address: Address, } @@ -55,21 +56,21 @@ impl ContractConstructor { P2: AsRef, P3: AsRef, { - let bin_file = format!("{}.bin", contract_name); - let abi_file = format!("{}.abi", contract_name); - let hex_path = artifacts_base_path.as_ref().join(&bin_file); - let hex_rep = match std::fs::read_to_string(&hex_path) { - Ok(hex) => hex, - Err(_) => { + let bin_file = format!("{contract_name}.bin"); + let abi_file = format!("{contract_name}.abi"); + let hex_path = artifacts_base_path.as_ref().join(bin_file); + let hex_rep = fs::read_to_string(&hex_path).map_or_else( + |_| { // An error occurred opening the file, maybe the contract hasn't been compiled? compile(sources_root, contract_file, &artifacts_base_path); // If another error occurs, then we can't handle it so we just unwrap. - std::fs::read_to_string(hex_path).unwrap() - } - }; - let code = hex::decode(&hex_rep).unwrap(); - let abi_path = artifacts_base_path.as_ref().join(&abi_file); - let reader = std::fs::File::open(abi_path).unwrap(); + fs::read_to_string(hex_path).unwrap() + }, + |hex| hex, + ); + let code = hex::decode(hex_rep).unwrap(); + let abi_path = artifacts_base_path.as_ref().join(abi_file); + let reader = fs::File::open(abi_path).unwrap(); let abi = ethabi::Contract::load(reader).unwrap(); Self { abi, code } @@ -98,10 +99,10 @@ impl ContractConstructor { pub fn deploy_without_constructor(&self, nonce: U256) -> TransactionLegacy { TransactionLegacy { nonce, - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: None, - value: Default::default(), + value: Wei::default(), data: self.code.clone(), } } @@ -119,10 +120,10 @@ impl ContractConstructor { .unwrap(); TransactionLegacy { nonce, - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: None, - value: Default::default(), + value: Wei::default(), data, } } @@ -147,10 +148,10 @@ impl DeployedContract { .unwrap(); TransactionLegacy { nonce, - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: Some(self.address), - value: Default::default(), + value: Wei::default(), data, } } @@ -192,10 +193,9 @@ where ]) .output() .unwrap(); - if !output.status.success() { - panic!( - "Could not compile solidity contracts in docker: {}", - String::from_utf8(output.stderr).unwrap() - ); - } + assert!( + output.status.success(), + "Could not compile solidity contracts in docker: {}", + String::from_utf8(output.stderr).unwrap() + ); } diff --git a/engine-tests/src/test_utils/standalone/mocks/mod.rs b/engine-tests/src/test_utils/standalone/mocks/mod.rs index 990ae733f..9a0a6b96a 100644 --- a/engine-tests/src/test_utils/standalone/mocks/mod.rs +++ b/engine-tests/src/test_utils/standalone/mocks/mod.rs @@ -1,9 +1,9 @@ use crate::test_utils; -use aurora_engine::engine; use aurora_engine::fungible_token::FungibleTokenMetadata; use aurora_engine::parameters::{ FinishDepositCallArgs, InitCallArgs, NEP141FtOnTransferArgs, NewCallArgs, }; +use aurora_engine::{engine, state}; use aurora_engine_sdk::env::{Env, DEFAULT_PREPAID_GAS}; use aurora_engine_sdk::io::IO; use aurora_engine_types::types::{Address, Balance, NEP141Wei, NearGas, Wei}; @@ -27,7 +27,7 @@ pub fn insert_block(storage: &mut Storage, block_height: u64) { random_seed: H256::zero(), }; storage - .set_block_data(block_hash, block_height, block_metadata) + .set_block_data(block_hash, block_height, &block_metadata) .unwrap(); } @@ -56,7 +56,7 @@ pub fn init_evm(mut io: I, env: &E, chain_id: u64) { upgrade_delay_blocks: 1, }; - engine::set_state(&mut io, new_args.into()); + state::set_state(&mut io, &new_args.into()).unwrap(); let connector_args = InitCallArgs { prover_account: test_utils::str_to_account_id("prover.near"), @@ -66,7 +66,7 @@ pub fn init_evm(mut io: I, env: &E, chain_id: u64) { aurora_engine::connector::EthConnectorContract::create_contract( io, - env.current_account_id(), + &env.current_account_id(), connector_args, ) .map_err(unsafe_to_string) @@ -108,7 +108,7 @@ pub fn mint_evm_account( // Delete the fake proof so that we can use it again. let proof_key = crate::prelude::storage::bytes_to_key( crate::prelude::storage::KeyPrefix::EthConnector, - &[crate::prelude::storage::EthConnectorStorageId::UsedEvent as u8], + &[crate::prelude::storage::EthConnectorStorageId::UsedEvent.into()], ); io.remove_storage(&proof_key); diff --git a/engine-tests/src/test_utils/standalone/mod.rs b/engine-tests/src/test_utils/standalone/mod.rs index 927e2d624..0543fe4d8 100644 --- a/engine-tests/src/test_utils/standalone/mod.rs +++ b/engine-tests/src/test_utils/standalone/mod.rs @@ -1,6 +1,7 @@ use aurora_engine::engine; use aurora_engine::parameters::{ - CallArgs, DeployErc20TokenArgs, PausePrecompilesCallArgs, SubmitResult, TransactionStatus, + CallArgs, DeployErc20TokenArgs, PausePrecompilesCallArgs, SetOwnerArgs, SubmitArgs, + SubmitResult, TransactionStatus, }; use aurora_engine_sdk::env::{self, Env}; use aurora_engine_transactions::legacy::{LegacyEthSignedTransaction, TransactionLegacy}; @@ -33,7 +34,7 @@ pub struct StandaloneRunner { impl StandaloneRunner { pub fn init_evm(&mut self) { - self.init_evm_with_chain_id(self.chain_id) + self.init_evm_with_chain_id(self.chain_id); } pub fn init_evm_with_chain_id(&mut self, chain_id: u64) { @@ -82,7 +83,7 @@ impl StandaloneRunner { let tx_msg = Self::template_tx_msg(storage, env, 0, transaction_hash, &[]); let result = storage.with_engine_access(env.block_height, 0, &[], |io| { - mocks::mint_evm_account(address, balance, nonce, code, io, env) + mocks::mint_evm_account(address, balance, nonce, code, io, env); }); let outcome = sync::TransactionIncludedOutcome { hash: transaction_hash, @@ -183,6 +184,7 @@ impl StandaloneRunner { Ok(outcome) } + #[allow(clippy::too_many_lines)] pub fn submit_raw( &mut self, method_name: &str, @@ -209,6 +211,18 @@ impl StandaloneRunner { &mut self.cumulative_diff, promise_results, ) + } else if method_name == test_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 == test_utils::CALL { let call_args = CallArgs::try_from_slice(&ctx.input).unwrap(); let transaction_hash = aurora_engine_sdk::keccak(&ctx.input); @@ -218,7 +232,7 @@ impl StandaloneRunner { let outcome = sync::execute_transaction_message(storage, tx_msg).unwrap(); self.cumulative_diff.append(outcome.diff.clone()); - test_utils::standalone::storage::commit(storage, &outcome); + storage::commit(storage, &outcome); unwrap_result(outcome) } else if method_name == test_utils::DEPLOY_ERC20 { @@ -230,12 +244,10 @@ impl StandaloneRunner { let outcome = sync::execute_transaction_message(storage, tx_msg).unwrap(); self.cumulative_diff.append(outcome.diff.clone()); - test_utils::standalone::storage::commit(storage, &outcome); + storage::commit(storage, &outcome); + + let sync::TransactionExecutionResult::DeployErc20(address) = outcome.maybe_result.unwrap().unwrap() else { unreachable!() }; - let address = match outcome.maybe_result.unwrap().unwrap() { - sync::TransactionExecutionResult::DeployErc20(address) => address, - _ => unreachable!(), - }; Ok(SubmitResult::new( TransactionStatus::Succeed(address.raw().as_ref().to_vec()), 0, @@ -274,17 +286,36 @@ impl StandaloneRunner { 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 == test_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 { - panic!("Unsupported standalone method {}", method_name); + panic!("Unsupported standalone method {method_name}"); } } - pub fn get_current_state(&self) -> &Diff { + pub const fn get_current_state(&self) -> &Diff { &self.cumulative_diff } @@ -330,7 +361,7 @@ impl StandaloneRunner { random_seed: env.random_seed, }; storage - .set_block_data(block_hash, env.block_height, block_metadata) + .set_block_data(block_hash, env.block_height, &block_metadata) .unwrap(); let promise_data = promise_results .iter() @@ -352,10 +383,10 @@ impl StandaloneRunner { } } - fn internal_submit_transaction<'db>( + fn internal_submit_transaction( transaction_bytes: &[u8], transaction_position: u16, - storage: &'db mut Storage, + storage: &mut Storage, env: &mut env::Fixed, cumulative_diff: &mut Diff, promise_results: &[PromiseResult], diff --git a/engine-tests/src/test_utils/standard_precompiles.rs b/engine-tests/src/test_utils/standard_precompiles.rs index bf85dcdb8..8d57495cb 100644 --- a/engine-tests/src/test_utils/standard_precompiles.rs +++ b/engine-tests/src/test_utils/standard_precompiles.rs @@ -2,9 +2,9 @@ use crate::prelude::{transactions::legacy::TransactionLegacy, U256}; use crate::test_utils::solidity; use std::path::{Path, PathBuf}; -pub(crate) struct PrecompilesConstructor(pub solidity::ContractConstructor); +pub struct PrecompilesConstructor(pub solidity::ContractConstructor); -pub(crate) struct PrecompilesContract(pub solidity::DeployedContract); +pub struct PrecompilesContract(pub solidity::DeployedContract); impl From for solidity::ContractConstructor { fn from(c: PrecompilesConstructor) -> Self { @@ -40,7 +40,7 @@ impl PrecompilesContract { self.0.call_method_without_args(method_name, nonce) } - pub fn all_method_names() -> &'static [&'static str] { + pub const fn all_method_names() -> &'static [&'static str] { &[ "test_ecrecover", "test_sha256", diff --git a/engine-tests/src/test_utils/uniswap.rs b/engine-tests/src/test_utils/uniswap.rs index 275df297e..f7b7aadba 100644 --- a/engine-tests/src/test_utils/uniswap.rs +++ b/engine-tests/src/test_utils/uniswap.rs @@ -1,26 +1,27 @@ use crate::prelude::{Address, U256}; use crate::test_utils::solidity; use aurora_engine_transactions::legacy::TransactionLegacy; +use aurora_engine_types::types::Wei; use std::ops::Not; use std::path::{Path, PathBuf}; use std::process::Command; use std::sync::Once; -pub(crate) struct FactoryConstructor(pub solidity::ContractConstructor); +pub struct FactoryConstructor(pub solidity::ContractConstructor); -pub(crate) struct Factory(pub solidity::DeployedContract); +pub struct Factory(pub solidity::DeployedContract); -pub(crate) struct Pool(pub solidity::DeployedContract); +pub struct Pool(pub solidity::DeployedContract); -pub(crate) struct PositionManagerConstructor(pub solidity::ContractConstructor); +pub struct PositionManagerConstructor(pub solidity::ContractConstructor); -pub(crate) struct PositionManager(pub solidity::DeployedContract); +pub struct PositionManager(pub solidity::DeployedContract); -pub(crate) struct SwapRouterConstructor(pub solidity::ContractConstructor); +pub struct SwapRouterConstructor(pub solidity::ContractConstructor); -pub(crate) struct SwapRouter(pub solidity::DeployedContract); +pub struct SwapRouter(pub solidity::DeployedContract); -pub(crate) struct MintParams { +pub struct MintParams { pub token0: Address, pub token1: Address, pub fee: u64, @@ -120,10 +121,10 @@ impl PositionManagerConstructor { .unwrap(); TransactionLegacy { nonce, - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: None, - value: Default::default(), + value: Wei::default(), data, } } @@ -151,10 +152,10 @@ impl Factory { TransactionLegacy { nonce, - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: Some(self.0.address), - value: Default::default(), + value: Wei::default(), data, } } @@ -194,17 +195,17 @@ impl Pool { TransactionLegacy { nonce, - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: Some(self.0.address), - value: Default::default(), + value: Wei::default(), data, } } } impl PositionManager { - pub fn mint(&self, params: MintParams, nonce: U256) -> TransactionLegacy { + pub fn mint(&self, params: &MintParams, nonce: U256) -> TransactionLegacy { let tick_lower = Self::i64_to_u256(params.tick_lower); let tick_upper = Self::i64_to_u256(params.tick_upper); let data = self @@ -229,10 +230,10 @@ impl PositionManager { TransactionLegacy { nonce, - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: Some(self.0.address), - value: Default::default(), + value: Wei::default(), data, } } @@ -283,10 +284,10 @@ impl SwapRouterConstructor { .unwrap(); TransactionLegacy { nonce, - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: None, - value: Default::default(), + value: Wei::default(), data, } } @@ -316,7 +317,7 @@ pub struct ExactInputParams { impl SwapRouter { pub fn exact_output_single( &self, - params: ExactOutputSingleParams, + params: &ExactOutputSingleParams, nonce: U256, ) -> TransactionLegacy { let data = self @@ -338,20 +339,20 @@ impl SwapRouter { TransactionLegacy { nonce, - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: Some(self.0.address), - value: Default::default(), + value: Wei::default(), data, } } - pub fn exact_input(&self, params: ExactInputParams, nonce: U256) -> TransactionLegacy { + pub fn exact_input(&self, params: &ExactInputParams, nonce: U256) -> TransactionLegacy { let path: Vec = { // The encoding here is 32-byte address, then 3-byte (24-bit) fee, alternating let mut result = Vec::with_capacity(32 + 35 * params.path.len()); result.extend_from_slice(params.token_in.as_bytes()); - for (fee, token) in params.path.iter() { + for (fee, token) in ¶ms.path { let fee_bytes = fee.to_be_bytes(); result.extend_from_slice(&fee_bytes[5..8]); result.extend_from_slice(token.as_bytes()); @@ -374,10 +375,10 @@ impl SwapRouter { TransactionLegacy { nonce, - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: Some(self.0.address), - value: Default::default(), + value: Wei::default(), data, } } @@ -403,11 +404,10 @@ fn download_uniswap_artifacts() { .output() .unwrap(); - if !output.status.success() { - panic!( - "Downloading uniswap npm package failed.\n{}", - String::from_utf8(output.stderr).unwrap() - ); - } + assert!( + output.status.success(), + "Downloading uniswap npm package failed.\n{}", + String::from_utf8(output.stderr).unwrap() + ); }); } diff --git a/engine-tests/src/tests/access_lists.rs b/engine-tests/src/tests/access_lists.rs index bdb0b76e4..88de5c76d 100644 --- a/engine-tests/src/tests/access_lists.rs +++ b/engine-tests/src/tests/access_lists.rs @@ -49,7 +49,7 @@ fn test_access_list_tx_encoding_decoding() { let decoded_tx = match EthTransactionKind::try_from(expected_bytes.as_slice()) { Ok(EthTransactionKind::Eip2930(tx)) => tx, Ok(_) => panic!("Unexpected transaction type"), - Err(_) => panic!("Transaction parsing failed"), + Err(e) => panic!("Transaction parsing failed: {e:?}"), }; assert_eq!(signed_tx, decoded_tx); @@ -57,10 +57,10 @@ fn test_access_list_tx_encoding_decoding() { assert_eq!( signed_tx.sender().unwrap(), test_utils::address_from_secret_key(&secret_key) - ) + ); } -fn one() -> H256 { +const fn one() -> H256 { let mut x = [0u8; 32]; x[31] = 1; H256(x) diff --git a/engine-tests/src/tests/account_id_precompiles.rs b/engine-tests/src/tests/account_id_precompiles.rs index cc456ed3d..54679d6b3 100644 --- a/engine-tests/src/tests/account_id_precompiles.rs +++ b/engine-tests/src/tests/account_id_precompiles.rs @@ -45,7 +45,7 @@ fn test_account_id_precompiles() { let tx = contract.call_method_without_args("predecessorAccountId", 0.into()); let sender = test_utils::address_from_secret_key(&signer.secret_key); let result = runner - .view_call(test_utils::as_view_call(tx, sender)) + .view_call(&test_utils::as_view_call(tx, sender)) .unwrap(); assert!(result.is_ok()); diff --git a/engine-tests/src/tests/contract_call.rs b/engine-tests/src/tests/contract_call.rs index b9c6143ae..5ecb025d0 100644 --- a/engine-tests/src/tests/contract_call.rs +++ b/engine-tests/src/tests/contract_call.rs @@ -1,5 +1,5 @@ use crate::prelude::{parameters::SubmitResult, vec, Address, Wei, H256, U256}; -use crate::test_utils::{origin, AuroraRunner, Signer}; +use crate::test_utils::{AuroraRunner, Signer, ORIGIN}; use crate::test_utils; use crate::test_utils::exit_precompile::{Tester, TesterConstructor, DEST_ACCOUNT, DEST_ADDRESS}; @@ -25,17 +25,25 @@ fn setup_test() -> (AuroraRunner, Signer, Address, Tester) { ) .into(); - runner.mint(token, tester.contract.address, 1_000_000_000, origin()); + runner.mint(token, tester.contract.address, 1_000_000_000, ORIGIN); (runner, signer, token, tester) } +#[test] +#[should_panic] +fn test_deploy_erc20_token_with_invalid_account_id() { + let mut runner = AuroraRunner::new(); + let invalid_nep141 = "_"; + runner.deploy_erc20_token(invalid_nep141); +} + #[test] fn hello_world_solidity() { let (mut runner, mut signer, _token, tester) = setup_test(); let name = "AuroraG".to_string(); - let expected = format!("Hello {}!", name); + let expected = format!("Hello {name}!"); let result = tester.hello_world(&mut runner, &mut signer, name); assert_eq!(expected, result); @@ -156,7 +164,7 @@ fn try_withdraw_and_avoid_fail_and_succeed() { ]; for (flag, expected) in test_data { - println!("{}", flag); + println!("{flag}"); assert!(tester .try_withdraw_and_avoid_fail_and_succeed(&mut runner, &mut signer, flag) .is_ok()); diff --git a/engine-tests/src/tests/ecrecover.rs b/engine-tests/src/tests/ecrecover.rs index 9378e165f..ec15865c6 100644 --- a/engine-tests/src/tests/ecrecover.rs +++ b/engine-tests/src/tests/ecrecover.rs @@ -1,6 +1,6 @@ use super::sanity::initialize_transfer; -use crate::prelude::Wei; use crate::prelude::{Address, U256}; +use crate::prelude::{Wei, H160}; use crate::test_utils::{self, AuroraRunner, Signer}; use aurora_engine_precompiles::Precompile; @@ -17,6 +17,7 @@ fn test_ecrecover_geth() { "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c100000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549", "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000001000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549", "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000001000000000000000000000011c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549", + "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549aabbccddeeff" ]; let outputs = [ Vec::new(), @@ -24,6 +25,7 @@ fn test_ecrecover_geth() { Vec::new(), Vec::new(), Vec::new(), + hex::decode("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b").unwrap(), ]; for (input, output) in inputs.iter().zip(outputs.iter()) { @@ -48,8 +50,8 @@ fn test_ecrecover_standalone() { let input = construct_input(&hash, &sig); let ctx = evm::Context { - address: Default::default(), - caller: Default::default(), + address: H160::default(), + caller: H160::default(), apparent_value: U256::zero(), }; let standalone_result = aurora_engine_precompiles::secp256k1::ECRecover diff --git a/engine-tests/src/tests/eip1559.rs b/engine-tests/src/tests/eip1559.rs index fa13ecde9..b1c1840ef 100644 --- a/engine-tests/src/tests/eip1559.rs +++ b/engine-tests/src/tests/eip1559.rs @@ -24,7 +24,7 @@ const EXAMPLE_TX_HEX: &str = "02f8c101010a8207d0833d090094cccccccccccccccccccccc // TODO(#170): generally support Ethereum tests #[test] fn test_eip_1559_tx_encoding_decoding() { - let secret_key = exmaple_signer().secret_key; + let secret_key = example_signer().secret_key; let transaction = example_transaction(); let signed_tx = test_utils::sign_eip_1559_transaction(transaction, &secret_key); @@ -36,7 +36,7 @@ fn test_eip_1559_tx_encoding_decoding() { let decoded_tx = match EthTransactionKind::try_from(expected_bytes.as_slice()) { Ok(EthTransactionKind::Eip1559(tx)) => tx, Ok(_) => panic!("Unexpected transaction type"), - Err(_) => panic!("Transaction parsing failed"), + Err(e) => panic!("Transaction parsing failed: {e:?}"), }; assert_eq!(signed_tx, decoded_tx); @@ -44,7 +44,7 @@ fn test_eip_1559_tx_encoding_decoding() { assert_eq!( signed_tx.sender().unwrap(), test_utils::address_from_secret_key(&secret_key) - ) + ); } // Test inspired by https://github.com/ethereum/tests/blob/develop/GeneralStateTests/stExample/eip1559.json @@ -52,7 +52,7 @@ fn test_eip_1559_tx_encoding_decoding() { #[test] fn test_eip_1559_example() { let mut runner = test_utils::deploy_evm(); - let mut signer = exmaple_signer(); + let mut signer = example_signer(); let signer_address = test_utils::address_from_secret_key(&signer.secret_key); let contract_address = test_utils::address_from_hex(CONTRACT_ADDRESS); let contract_code = hex::decode(CONTRACT_CODE).unwrap(); @@ -112,7 +112,7 @@ fn encode_tx(signed_tx: &SignedTransaction1559) -> Vec { .collect() } -fn exmaple_signer() -> test_utils::Signer { +fn example_signer() -> test_utils::Signer { let secret_key = libsecp256k1::SecretKey::parse_slice(&hex::decode(SECRET_KEY).unwrap()).unwrap(); @@ -146,7 +146,7 @@ fn h256_from_hex(hex: &str) -> H256 { H256(result) } -fn one() -> H256 { +const fn one() -> H256 { let mut x = [0u8; 32]; x[31] = 1; H256(x) diff --git a/engine-tests/src/tests/erc20.rs b/engine-tests/src/tests/erc20.rs index a1a11af3e..e7fe344a7 100644 --- a/engine-tests/src/tests/erc20.rs +++ b/engine-tests/src/tests/erc20.rs @@ -40,6 +40,9 @@ fn erc20_mint() { #[test] fn erc20_mint_out_of_gas() { + const GAS_LIMIT: u64 = 67_000; + const GAS_PRICE: u64 = 10; + let (mut runner, mut source_account, dest_address, contract) = initialize_erc20(); // Validate pre-state @@ -60,12 +63,10 @@ fn erc20_mint_out_of_gas() { mint_tx.gas_limit = (intrinsic_gas - 1).into(); let outcome = runner.submit_transaction(&source_account.secret_key, mint_tx.clone()); let error = outcome.unwrap_err(); - let error_message = format!("{:?}", error); + let error_message = format!("{error:?}"); assert!(error_message.contains("ERR_INTRINSIC_GAS")); // not enough gas to complete transaction - const GAS_LIMIT: u64 = 67_000; - const GAS_PRICE: u64 = 10; mint_tx.gas_limit = U256::from(GAS_LIMIT); mint_tx.gas_price = U256::from(GAS_PRICE); // also set non-zero gas price to check gas still charged. let outcome = runner.submit_transaction(&source_account.secret_key, mint_tx); @@ -102,7 +103,7 @@ fn profile_erc20_get_balance() { let balance_tx = contract.balance_of(source_address, U256::zero()); let (result, profile) = - runner.profiled_view_call(test_utils::as_view_call(balance_tx, source_address)); + runner.profiled_view_call(&test_utils::as_view_call(balance_tx, source_address)); assert!(result.is_ok()); // call costs less than 2 Tgas @@ -111,8 +112,7 @@ fn profile_erc20_get_balance() { let wasm_fraction = (100 * profile.wasm_gas()) / profile.all_gas(); assert!( (20..=30).contains(&wasm_fraction), - "{}% is not between 20% and 30%", - wasm_fraction + "{wasm_fraction}% is not between 20% and 30%", ); } @@ -217,7 +217,7 @@ fn deploy_erc_20_out_of_gas() { deploy_transaction.gas_limit = (intrinsic_gas - 1).into(); let outcome = runner.submit_transaction(&source_account, deploy_transaction.clone()); let error = outcome.unwrap_err(); - let error_message = format!("{:?}", error); + let error_message = format!("{error:?}"); assert!(error_message.contains("ERR_INTRINSIC_GAS")); // not enough gas to complete transaction @@ -243,14 +243,14 @@ fn get_address_erc20_balance( ) -> U256 { let balance_tx = contract.balance_of(address, signer.nonce.into()); let result = runner - .view_call(test_utils::as_view_call( + .view_call(&test_utils::as_view_call( balance_tx, test_utils::address_from_secret_key(&signer.secret_key), )) .unwrap(); let bytes = match result { - aurora_engine::parameters::TransactionStatus::Succeed(bytes) => bytes, - err => panic!("Unexpected view call status {:?}", err), + TransactionStatus::Succeed(bytes) => bytes, + err => panic!("Unexpected view call status {err:?}"), }; U256::from_big_endian(&bytes) } diff --git a/engine-tests/src/tests/erc20_connector.rs b/engine-tests/src/tests/erc20_connector.rs index 3cccf9f31..74cbcac11 100644 --- a/engine-tests/src/tests/erc20_connector.rs +++ b/engine-tests/src/tests/erc20_connector.rs @@ -1,6 +1,5 @@ use crate::prelude::{Address, Balance, Wei, WeiU256, U256}; -use crate::test_utils; -use crate::test_utils::{create_eth_transaction, origin, AuroraRunner}; +use crate::test_utils::{self, create_eth_transaction, AuroraRunner, ORIGIN}; use aurora_engine::parameters::{CallArgs, FunctionCallArgsV2, SubmitResult}; use aurora_engine_transactions::legacy::LegacyEthSignedTransaction; use borsh::{BorshDeserialize, BorshSerialize}; @@ -50,7 +49,7 @@ fn get_selector(str_selector: &str) -> Vec { fn build_input(str_selector: &str, inputs: &[Token]) -> Vec { let sel = get_selector(str_selector); let inputs = ethabi::encode(inputs); - [sel.as_slice(), inputs.as_slice()].concat().to_vec() + [sel.as_slice(), inputs.as_slice()].concat() } fn create_ethereum_address() -> Address { @@ -64,7 +63,7 @@ pub struct EthereumAddress { pub address: Address, } -impl test_utils::AuroraRunner { +impl AuroraRunner { pub fn new() -> Self { test_utils::deploy_evm() } @@ -72,26 +71,26 @@ impl test_utils::AuroraRunner { pub fn make_call( &mut self, method_name: &str, - caller_account_id: String, + caller_account_id: &str, input: Vec, ) -> CallResult { - let (outcome, error) = self.call(method_name, &caller_account_id, input); + let (outcome, error) = self.call(method_name, caller_account_id, input); CallResult { outcome, error } } pub fn make_call_with_signer( &mut self, method_name: &str, - caller_account_id: String, - signer_account_id: String, + caller_account_id: &str, + signer_account_id: &str, input: Vec, ) -> CallResult { let (outcome, error) = - self.call_with_signer(method_name, &caller_account_id, &signer_account_id, input); + self.call_with_signer(method_name, caller_account_id, signer_account_id, input); CallResult { outcome, error } } - pub fn evm_call(&mut self, contract: Address, input: Vec, origin: String) -> CallResult { + pub fn evm_call(&mut self, contract: Address, input: Vec, origin: &str) -> CallResult { self.make_call( "call", origin, @@ -105,12 +104,12 @@ impl test_utils::AuroraRunner { ) } - pub fn evm_submit(&mut self, input: LegacyEthSignedTransaction, origin: String) -> CallResult { - self.make_call("submit", origin, rlp::encode(&input).to_vec()) + pub fn evm_submit(&mut self, input: &LegacyEthSignedTransaction, origin: &str) -> CallResult { + self.make_call("submit", origin, rlp::encode(input).to_vec()) } pub fn deploy_erc20_token(&mut self, nep141: &str) -> Address { - let result = self.make_call("deploy_erc20_token", origin(), nep141.try_to_vec().unwrap()); + let result = self.make_call("deploy_erc20_token", ORIGIN, nep141.try_to_vec().unwrap()); result.check_ok(); @@ -132,7 +131,7 @@ impl test_utils::AuroraRunner { } } - pub fn balance_of(&mut self, token: Address, target: Address, origin: String) -> U256 { + pub fn balance_of(&mut self, token: Address, target: Address, origin: &str) -> U256 { let input = build_input("balanceOf(address)", &[Token::Address(target.raw())]); let result = self.evm_call(token, input, origin); result.check_ok(); @@ -145,7 +144,7 @@ impl test_utils::AuroraRunner { token: Address, target: Address, amount: u64, - origin: String, + origin: &str, ) -> CallResult { let input = build_input( "mint(address,uint256)", @@ -160,7 +159,7 @@ impl test_utils::AuroraRunner { } #[allow(dead_code)] - pub fn admin(&mut self, token: Address, origin: String) -> CallResult { + pub fn admin(&mut self, token: Address, origin: &str) -> CallResult { let input = build_input("admin()", &[]); let result = self.evm_call(token, input, origin); result.check_ok(); @@ -173,7 +172,7 @@ impl test_utils::AuroraRunner { sender: SecretKey, receiver: Address, amount: u64, - origin: String, + origin: &str, ) -> CallResult { // transfer(address recipient, uint256 amount) let input = build_input( @@ -186,18 +185,18 @@ impl test_utils::AuroraRunner { let input = create_eth_transaction(Some(token), Wei::zero(), input, None, &sender); - let result = self.evm_submit(input, origin); // create_eth_transaction() + let result = self.evm_submit(&input, origin); // create_eth_transaction() result.check_ok(); result } pub fn ft_on_transfer( &mut self, - nep141: String, - sender_id: String, - relayer_id: String, + nep141: &str, + sender_id: &str, + relayer_id: &str, amount: Balance, - msg: String, + msg: &str, ) -> String { let res = self.make_call_with_signer( "ft_on_transfer", @@ -217,7 +216,7 @@ impl test_utils::AuroraRunner { pub fn register_relayer( &mut self, - relayer_account_id: String, + relayer_account_id: &str, relayer_address: Address, ) -> CallResult { self.make_call( @@ -239,11 +238,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, ORIGIN); 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, ORIGIN); + let balance = runner.balance_of(token, address, ORIGIN); assert_eq!(balance, U256::from(amount)); } @@ -252,11 +251,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, ORIGIN); assert_eq!(balance, U256::from(0)); let amount = 10; - runner.mint(token, address, amount, "not_admin".to_string()); - let balance = runner.balance_of(token, address, origin()); + runner.mint(token, address, amount, "not_admin"); + let balance = runner.balance_of(token, address, ORIGIN); assert_eq!(balance, U256::from(0)); } @@ -265,36 +264,34 @@ fn test_ft_on_transfer() { let mut runner = AuroraRunner::new(); // Standalone runner presently does not support ft_on_transfer runner.standalone_runner = None; - let nep141 = "tt.testnet".to_string(); - let alice = "alice".to_string(); - let token = runner.deploy_erc20_token(&nep141); + let nep141 = "tt.testnet"; + let alice = "alice"; + let token = runner.deploy_erc20_token(nep141); 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, ORIGIN); assert_eq!(balance, U256::from(0)); - let res = runner.ft_on_transfer(nep141, alice.clone(), alice, amount, recipient.encode()); + 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, ORIGIN); assert_eq!(balance, U256::from(amount.as_u128())); } #[test] fn test_ft_on_transfer_fail() { let mut runner = AuroraRunner::new(); - let nep141 = "tt.testnet".to_string(); - let alice = "alice".to_string(); + let nep141 = "tt.testnet"; + let alice = "alice"; let amount = Balance::new(10); - let recipient = runner.create_account().address; - - let res = runner.ft_on_transfer(nep141, alice.clone(), alice, amount, recipient.encode()); + let res = runner.ft_on_transfer(nep141, alice, alice, amount, &recipient.encode()); // Transaction should fail so it must return everything - assert_eq!(res, format!("\"{}\"", amount)); + assert_eq!(res, format!("\"{amount}\"")); } #[ignore] @@ -305,20 +302,20 @@ fn test_relayer_charge_fee() { runner.standalone_runner = None; let amount = Balance::new(10); let fee = 51; - let nep141 = "tt.testnet".to_string(); - let alice = "alice".to_string(); - let token = runner.deploy_erc20_token(&nep141); + let nep141 = "tt.testnet"; + let alice = "alice"; + let token = runner.deploy_erc20_token(nep141); let recipient = runner.create_account().address; let recipient_balance = runner.get_balance(recipient); assert_eq!(recipient_balance, INITIAL_BALANCE); let relayer = create_ethereum_address(); - runner.register_relayer(alice.clone(), relayer); + runner.register_relayer(alice, relayer); 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, ORIGIN); assert_eq!(balance, U256::from(0)); let fee_encoded = &mut [0; 32]; @@ -326,10 +323,10 @@ fn test_relayer_charge_fee() { runner.ft_on_transfer( nep141, - alice.clone(), + alice, alice, amount, - recipient.encode() + &hex::encode(fee_encoded), + &format!("{}{}", recipient.encode(), hex::encode(fee_encoded)), ); let recipient_balance_end = runner.get_balance(recipient); @@ -340,7 +337,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, ORIGIN); assert_eq!(balance, U256::from(amount.as_u128())); } @@ -355,35 +352,29 @@ fn test_transfer_erc20_token() { let to_transfer = 43; assert_eq!( - runner.balance_of(token, peer0.address, origin()), + runner.balance_of(token, peer0.address, ORIGIN), U256::zero() ); assert_eq!( - runner.balance_of(token, peer1.address, origin()), + runner.balance_of(token, peer1.address, ORIGIN), U256::zero() ); - runner.mint(token, peer0.address, to_mint, origin()); + runner.mint(token, peer0.address, to_mint, ORIGIN); assert_eq!( - runner.balance_of(token, peer0.address, origin()), + runner.balance_of(token, peer0.address, ORIGIN), U256::from(to_mint) ); - runner.transfer_erc20( - token, - peer0.secret_key, - peer1.address, - to_transfer, - origin(), - ); + runner.transfer_erc20(token, peer0.secret_key, peer1.address, to_transfer, ORIGIN); assert_eq!( - runner.balance_of(token, peer0.address, origin()), + runner.balance_of(token, peer0.address, ORIGIN), U256::from(to_mint - to_transfer) ); assert_eq!( - runner.balance_of(token, peer1.address, origin()), + runner.balance_of(token, peer1.address, ORIGIN), U256::from(to_transfer) ); } @@ -438,7 +429,7 @@ pub mod sim_tests { let submit_result = SubmitResult::try_from_slice(bytes).unwrap(); Address::try_from_slice(test_utils::unwrap_success_slice(&submit_result)).unwrap() } - _ => panic!("Unknown result: {:?}", deploy_result), + _ => panic!("Unknown result: {deploy_result:?}"), }; let contract = constructor.deployed_at(contract_address); @@ -464,7 +455,7 @@ pub mod sim_tests { &aurora.contract, &aurora, ), - INITIAL_ETH_BALANCE as u128 + u128::from(INITIAL_ETH_BALANCE) ); assert_eq!( nep_141_balance_of(hacker_account, &aurora.contract, &aurora), @@ -563,7 +554,7 @@ pub mod sim_tests { tester_address, aurora, } = test_exit_to_near_eth_common(); - let exit_account_id = "any.near".to_owned(); + let exit_account_id = "any.near"; // call exit to near let input = super::build_input( @@ -586,11 +577,11 @@ pub mod sim_tests { &aurora.contract, &aurora, ), - (INITIAL_ETH_BALANCE - ETH_EXIT_AMOUNT) as u128 + u128::from(INITIAL_ETH_BALANCE - ETH_EXIT_AMOUNT) ); assert_eq!( - nep_141_balance_of(exit_account_id.as_str(), &aurora.contract, &aurora), - ETH_EXIT_AMOUNT as u128 + nep_141_balance_of(exit_account_id, &aurora.contract, &aurora), + u128::from(ETH_EXIT_AMOUNT) ); assert_eq!( eth_balance_of(signer_address, &aurora), @@ -615,7 +606,7 @@ pub mod sim_tests { // Make the ft_transfer call fail by draining the Aurora account let transfer_args = json!({ "receiver_id": "tmp.near", - "amount": format!("{:?}", INITIAL_ETH_BALANCE), + "amount": format!("{INITIAL_ETH_BALANCE}"), "memo": "null", }); aurora @@ -681,7 +672,7 @@ pub mod sim_tests { &aurora.contract, &aurora, ), - INITIAL_ETH_BALANCE as u128 + u128::from(INITIAL_ETH_BALANCE) ); assert_eq!( eth_balance_of(signer_address, &aurora), @@ -691,7 +682,12 @@ pub mod sim_tests { // deploy contract with simple exit to near method let constructor = TesterConstructor::load(); let deploy_data = constructor.deploy(0, Address::zero()).data; - let submit_result: SubmitResult = aurora.call("deploy_code", &deploy_data).unwrap_borsh(); + let submit_result = match aurora.call("deploy_code", &deploy_data).status() { + near_primitives::transaction::ExecutionStatus::SuccessValue(bytes) => { + SubmitResult::try_from_slice(&bytes).unwrap() + } + other => panic!("Unexpected status {other:?}"), + }; let tester_address = Address::try_from_slice(&test_utils::unwrap_success(submit_result)).unwrap(); @@ -771,7 +767,7 @@ pub mod sim_tests { } fn exit_to_near( - source: &near_sdk_sim::UserAccount, + source: &UserAccount, dest: &str, amount: u128, erc20: &ERC20, @@ -800,17 +796,17 @@ pub mod sim_tests { .assert_success(); } - pub(crate) fn transfer_nep_141_to_erc_20( - nep_141: &near_sdk_sim::UserAccount, + pub fn transfer_nep_141_to_erc_20( + nep_141: &UserAccount, erc20: &ERC20, - source: &near_sdk_sim::UserAccount, + source: &UserAccount, dest: Address, amount: u128, aurora: &AuroraAccount, ) { let transfer_args = json!({ "receiver_id": aurora.contract.account_id.as_str(), - "amount": format!("{:?}", amount), + "amount": format!("{amount}"), "memo": "null", }); source @@ -861,14 +857,16 @@ pub mod sim_tests { input: balance_tx.data, }); let result = aurora.call("call", &call_args.try_to_vec().unwrap()); - let submit_result: SubmitResult = result.unwrap_borsh(); + let submit_result = match result.status() { + near_primitives::transaction::ExecutionStatus::SuccessValue(bytes) => { + SubmitResult::try_from_slice(&bytes).unwrap() + } + other => panic!("Unexpected status {other:?}"), + }; U256::from_big_endian(&test_utils::unwrap_success(submit_result)) } - pub(crate) fn deploy_erc20_from_nep_141( - nep_141: &near_sdk_sim::UserAccount, - aurora: &AuroraAccount, - ) -> ERC20 { + pub fn deploy_erc20_from_nep_141(nep_141: &UserAccount, aurora: &AuroraAccount) -> ERC20 { let args = DeployErc20TokenArgs { nep141: nep_141.account_id().as_str().parse().unwrap(), }; @@ -876,12 +874,12 @@ pub mod sim_tests { let addr_bytes: Vec = result.unwrap_borsh(); let address = Address::try_from_slice(&addr_bytes).unwrap(); let abi = ERC20Constructor::load().0.abi; - ERC20(crate::test_utils::solidity::DeployedContract { abi, address }) + ERC20(test_utils::solidity::DeployedContract { abi, address }) } pub fn nep_141_balance_of( account_id: &str, - nep_141: &near_sdk_sim::UserAccount, + nep_141: &UserAccount, aurora: &AuroraAccount, ) -> u128 { aurora @@ -901,7 +899,7 @@ pub mod sim_tests { } /// Deploys the standard FT implementation: - /// https://github.com/near/near-sdk-rs/blob/master/examples/fungible-token/ft/src/lib.rs + /// `https://github.com/near/near-sdk-rs/blob/master/examples/fungible-token/ft/src/lib.rs` pub fn deploy_nep_141( nep_141_account_id: &str, token_owner: &str, @@ -918,7 +916,7 @@ pub mod sim_tests { let init_args = json!({ "owner_id": token_owner, - "total_supply": format!("{:?}", amount), + "total_supply": format!("{amount}"), }) .to_string(); @@ -953,9 +951,9 @@ pub mod sim_tests { } struct TestExitToNearContext { - ft_owner: near_sdk_sim::UserAccount, + ft_owner: UserAccount, ft_owner_address: Address, - nep_141: near_sdk_sim::UserAccount, + nep_141: UserAccount, erc20: ERC20, aurora: AuroraAccount, } diff --git a/engine-tests/src/tests/eth_connector.rs b/engine-tests/src/tests/eth_connector.rs index 03f7d51bc..f6283423a 100644 --- a/engine-tests/src/tests/eth_connector.rs +++ b/engine-tests/src/tests/eth_connector.rs @@ -156,7 +156,7 @@ fn assert_proof_was_not_used(account: &UserAccount, contract: &str, proof: &str) #[allow(dead_code)] fn print_logs(logs: &[String]) { for l in logs { - println!("[log] {}", l); + println!("[log] {l}"); } } @@ -173,11 +173,6 @@ fn call_deposit_eth_to_aurora(master_account: &UserAccount, contract: &str) { } fn get_eth_on_near_balance(master_account: &UserAccount, acc: &str, contract: &str) -> u128 { - #[derive(BorshSerialize)] - pub struct BalanceOfCallArgs { - pub account_id: String, - } - let balance = master_account.view( contract.parse().unwrap(), "ft_balance_of", @@ -189,15 +184,12 @@ fn get_eth_on_near_balance(master_account: &UserAccount, acc: &str, contract: &s } fn get_eth_balance(master_account: &UserAccount, address: Address, contract: &str) -> u128 { - #[derive(BorshSerialize, BorshDeserialize)] - pub struct BalanceOfEthCallArgs { - pub address: Address, - } - let balance = master_account.view( contract.parse().unwrap(), "ft_balance_of_eth", - &BalanceOfEthCallArgs { address }.try_to_vec().unwrap(), + &aurora_engine::parameters::BalanceOfEthCallArgs { address } + .try_to_vec() + .unwrap(), ); let val_str = String::from_utf8(balance.unwrap()).unwrap(); let val = &val_str[1..val_str.len() - 1]; @@ -363,13 +355,10 @@ fn test_ft_transfer() { res.assert_success(); let balance = get_eth_on_near_balance(&master_account, DEPOSITED_RECIPIENT, CONTRACT_ACC); - assert_eq!( - balance, - DEPOSITED_AMOUNT - DEPOSITED_FEE + transfer_amount as u128 - ); + assert_eq!(balance, DEPOSITED_AMOUNT - DEPOSITED_FEE + transfer_amount); let balance = get_eth_on_near_balance(&master_account, CONTRACT_ACC, CONTRACT_ACC); - assert_eq!(balance, DEPOSITED_FEE - transfer_amount as u128); + assert_eq!(balance, DEPOSITED_FEE - transfer_amount); let balance = total_supply(&master_account, CONTRACT_ACC); assert_eq!(balance, DEPOSITED_AMOUNT); @@ -461,6 +450,7 @@ fn test_ft_transfer_call_eth() { } #[test] +#[allow(clippy::too_many_lines)] fn test_ft_transfer_call_without_message() { let (master_account, contract) = init(CUSTODIAN_ADDRESS); let recipient_account = create_user_account(&master_account); @@ -511,6 +501,46 @@ fn test_ft_transfer_call_without_message() { let balance = get_eth_on_near_balance(&master_account, CONTRACT_ACC, CONTRACT_ACC); assert_eq!(balance, DEPOSITED_FEE); + // should revert with `not enough balance` error when sending arbitrary amount while sender_id == receiver_id + let transfer_amount = 1000000000; + let res = recipient_account.call( + CONTRACT_ACC.parse().unwrap(), + "ft_transfer_call", + json!({ + "receiver_id": recipient_account.signer.account_id.to_string(), + "amount": transfer_amount.to_string(), + "msg": "", + }) + .to_string() + .as_bytes(), + DEFAULT_GAS, + 1, + ); + + assert_execution_status_failure( + res.outcome().clone().status, + "ExecutionError(\"Smart contract panicked: ERR_NOT_ENOUGH_BALANCE\")", + "Expected failure in `ft_transfer_call` call, but call succeeded", + ); + + // should not revert with `not enough balance` error when sending arbitrary amount while sender_id == receiver_id with amount < balance + let transfer_amount = 1; + let res = recipient_account.call( + CONTRACT_ACC.parse().unwrap(), + "ft_transfer_call", + json!({ + "receiver_id": recipient_account.signer.account_id.to_string(), + "amount": transfer_amount.to_string(), + "msg": "", + }) + .to_string() + .as_bytes(), + DEFAULT_GAS, + 1, + ); + + res.assert_success(); + // Sending to random account should not change balances let transfer_amount = 22; let res = recipient_account.call( @@ -540,7 +570,7 @@ fn test_ft_transfer_call_without_message() { let dummy_ft_receiver = master_account.deploy( &dummy_ft_receiver_bytes(), "ft-rec.root".parse().unwrap(), - near_sdk_sim::STORAGE_AMOUNT, + STORAGE_AMOUNT, ); let res = recipient_account.call( CONTRACT_ACC.parse().unwrap(), @@ -729,10 +759,10 @@ fn test_deposit_eth_to_near_account() { 0, ); let promises = res.promise_results(); - for p in promises.iter() { + for p in &promises { assert!(p.is_some()); let p = p.as_ref().unwrap(); - p.assert_success() + p.assert_success(); } res.assert_success(); @@ -778,8 +808,7 @@ fn test_deposit_eth_with_empty_custom_connector_account() { assert_execution_status_failure( promise.as_ref().unwrap().outcome().clone().status, format!( - r#"CompilationError(CodeDoesNotExist {{ account_id: AccountId("{}") }}"#, - user_account_id + r#"CompilationError(CodeDoesNotExist {{ account_id: AccountId("{user_account_id}") }}"#, ) .as_str(), "Expected failure in `ft_on_transfer` call, but deposit succeeded", @@ -825,17 +854,17 @@ fn test_deposit_eth_with_custom_connector_account() { 0, ); let promises = res.promise_results(); - for p in promises.iter() { + for p in &promises { assert!(p.is_some()); let p = p.as_ref().unwrap(); if p.executor_id().as_str() == user_account_id { // The `ft_on_transfer` implementation in the user's account generates this log. assert_eq!( - p.logs().first().map(|s| s.as_str()), + p.logs().first().map(String::as_str), Some("in 17 tokens from @eth_connector.root ft_on_transfer, msg = some_user.root:00000000000000000000000000000000000000000000000000000000000000000a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a"), ); } - p.assert_success() + p.assert_success(); } res.assert_success(); @@ -855,10 +884,10 @@ fn test_deposit_with_same_proof() { assert_proof_was_not_used(&contract, CONTRACT_ACC, PROOF_DATA_NEAR); let promises = call_deposit_eth_to_near(&contract, CONTRACT_ACC); - for p in promises.iter() { + for p in &promises { assert!(p.is_some()); let p = p.as_ref().unwrap(); - p.assert_success() + p.assert_success(); } assert_proof_was_used(&contract, CONTRACT_ACC, PROOF_DATA_NEAR); @@ -1053,6 +1082,16 @@ fn create_user_account(master_account: &UserAccount) -> UserAccount { ) } +fn validate_promises(promises: Vec>) { + assert!(promises.len() > 1); + + for p in promises { + assert!(p.is_some()); + let p = p.as_ref().unwrap(); + p.assert_success(); + } +} + #[test] fn test_admin_controlled_only_admin_can_pause() { let (master_account, contract) = init(CUSTODIAN_ADDRESS); @@ -1078,11 +1117,7 @@ fn test_admin_controlled_admin_can_peform_actions_when_paused() { // 1st deposit call when unpaused - should succeed let promises = call_deposit_with_proof(&contract, CONTRACT_ACC, PROOF_DATA_NEAR); - for p in promises.iter() { - assert!(p.is_some()); - let p = p.as_ref().unwrap(); - p.assert_success() - } + validate_promises(promises); let withdraw_amount = NEP141Wei::new(100); let recipient_addr = validate_eth_address(RECIPIENT_ETH_ADDRESS); @@ -1102,11 +1137,7 @@ fn test_admin_controlled_admin_can_peform_actions_when_paused() { ); res.assert_success(); let promises = res.promise_results(); - for p in promises.iter() { - assert!(p.is_some()); - let p = p.as_ref().unwrap(); - p.assert_success() - } + validate_promises(promises); // Pause deposit let res = call_set_paused_flags(&contract, CONTRACT_ACC, PAUSE_DEPOSIT); @@ -1116,11 +1147,7 @@ fn test_admin_controlled_admin_can_peform_actions_when_paused() { // NB: We can use `PROOF_DATA_ETH` this will be just a different proof but the same deposit // method which should be paused let promises = call_deposit_with_proof(&contract, CONTRACT_ACC, PROOF_DATA_ETH); - for p in promises.iter() { - assert!(p.is_some()); - let p = p.as_ref().unwrap(); - p.assert_success() - } + validate_promises(promises); // Pause withdraw let res = call_set_paused_flags(&contract, CONTRACT_ACC, PAUSE_WITHDRAW); @@ -1141,11 +1168,7 @@ fn test_admin_controlled_admin_can_peform_actions_when_paused() { ); res.assert_success(); let promises = res.promise_results(); - for p in promises.iter() { - assert!(p.is_some()); - let p = p.as_ref().unwrap(); - p.assert_success() - } + validate_promises(promises); } #[test] @@ -1155,11 +1178,7 @@ fn test_deposit_pausability() { // 1st deposit call - should succeed let promises = call_deposit_with_proof(&user_account, CONTRACT_ACC, PROOF_DATA_NEAR); - for p in promises.iter() { - assert!(p.is_some()); - let p = p.as_ref().unwrap(); - p.assert_success() - } + validate_promises(promises); // Pause deposit let res = call_set_paused_flags(&contract, CONTRACT_ACC, PAUSE_DEPOSIT); @@ -1183,11 +1202,7 @@ fn test_deposit_pausability() { // 3rd deposit call - should succeed let promises = call_deposit_with_proof(&user_account, CONTRACT_ACC, PROOF_DATA_ETH); - for p in promises.iter() { - assert!(p.is_some()); - let p = p.as_ref().unwrap(); - p.assert_success() - } + validate_promises(promises); } #[test] @@ -1214,12 +1229,7 @@ fn test_withdraw_from_near_pausability() { ); res.assert_success(); let promises = res.promise_results(); - assert!(promises.len() > 1); - for p in promises.iter() { - assert!(p.is_some()); - let p = p.as_ref().unwrap(); - p.assert_success() - } + validate_promises(promises); // Pause withdraw let res = call_set_paused_flags(&contract, CONTRACT_ACC, PAUSE_WITHDRAW); @@ -1264,12 +1274,7 @@ fn test_withdraw_from_near_pausability() { ); res.assert_success(); let promises = res.promise_results(); - assert!(promises.len() > 1); - for p in promises.iter() { - assert!(p.is_some()); - let p = p.as_ref().unwrap(); - p.assert_success() - } + validate_promises(promises); } #[test] @@ -1310,13 +1315,10 @@ fn test_get_accounts_counter_and_transfer() { res.assert_success(); let balance = get_eth_on_near_balance(&master_account, DEPOSITED_RECIPIENT, CONTRACT_ACC); - assert_eq!( - balance, - DEPOSITED_AMOUNT - DEPOSITED_FEE + transfer_amount as u128 - ); + assert_eq!(balance, DEPOSITED_AMOUNT - DEPOSITED_FEE + transfer_amount); let balance = get_eth_on_near_balance(&master_account, CONTRACT_ACC, CONTRACT_ACC); - assert_eq!(balance, DEPOSITED_FEE - transfer_amount as u128); + assert_eq!(balance, DEPOSITED_FEE - transfer_amount); let balance = total_supply(&master_account, CONTRACT_ACC); assert_eq!(balance, DEPOSITED_AMOUNT); @@ -1571,14 +1573,14 @@ fn assert_execution_status_failure( // "right: 'MISMATCHED_DATA': ERR_MSG [src/some_file.rs:LINE_NUMBER:COLUMN_NUMBER]" // So the ": ERR_MSG [" pattern should catch all invariants of error, even if one of the errors // message is a subset of another one (e.g. `ERR_MSG_FAILED` is a subset of `ERR_MSG_FAILED_FOO`) - let expected_err_msg_pattern = format!(": {}", err_msg); + let expected_err_msg_pattern = format!(": {err_msg}"); match execution_status { ExecutionStatus::Failure(err) => { - println!("Error: {}", err); + println!("Error: {err}"); assert!(err.to_string().contains(&expected_err_msg_pattern)); } - _ => panic!("{}", panic_msg), + _ => panic!("{panic_msg}"), } } @@ -1634,7 +1636,7 @@ fn test_ft_transfer_empty_value() { eprintln!("{:#?}", promise.as_ref().unwrap().outcome().clone().status); assert_execution_status_failure( promise.as_ref().unwrap().outcome().clone().status, - "ERR_FAILED_PARSE_U128", + "cannot parse integer from empty string", "Expected failure as empty string can't be parsed to u128", ); } @@ -1662,7 +1664,7 @@ fn test_ft_transfer_wrong_u128_json_type() { eprintln!("{:#?}", promise.as_ref().unwrap().outcome().clone().status); assert_execution_status_failure( promise.as_ref().unwrap().outcome().clone().status, - "ERR_EXPECTED_STRING_GOT_NUMBER", + "Wait for a string but got: 200", "Expected failure as number type can't be parsed to u128", ); } diff --git a/engine-tests/src/tests/ghsa_3p69_m8gg_fwmf.rs b/engine-tests/src/tests/ghsa_3p69_m8gg_fwmf.rs index 065af19c6..604057253 100644 --- a/engine-tests/src/tests/ghsa_3p69_m8gg_fwmf.rs +++ b/engine-tests/src/tests/ghsa_3p69_m8gg_fwmf.rs @@ -43,6 +43,9 @@ fn test_exploit_fix() { let input = view_call_args.try_to_vec().unwrap(); let (_outcome, maybe_error) = runner.one_shot().call("view", "viewer", input); - let error_message = format!("{:?}", maybe_error); - assert!(error_message.contains("ERR_ILLEGAL_RETURN")); + let error_message = format!("{maybe_error:?}"); + assert!( + error_message.contains("ERR_ILLEGAL_RETURN"), + "{error_message}", + ); } diff --git a/engine-tests/src/tests/mod.rs b/engine-tests/src/tests/mod.rs index 741e56ae8..a7fbc4a66 100644 --- a/engine-tests/src/tests/mod.rs +++ b/engine-tests/src/tests/mod.rs @@ -9,6 +9,7 @@ pub mod eth_connector; mod ghsa_3p69_m8gg_fwmf; #[cfg(feature = "meta-call")] mod meta_parsing; +pub mod modexp; mod multisender; mod one_inch; mod pausable_precompiles; @@ -16,10 +17,11 @@ mod prepaid_gas_precompile; mod promise_results_precompile; mod random; mod repro; -pub(crate) mod sanity; +pub mod sanity; mod self_destruct_state; +mod serde; mod standalone; mod standard_precompiles; mod state_migration; -pub(crate) mod uniswap; -pub(crate) mod xcc; +pub mod uniswap; +pub mod xcc; diff --git a/engine-tests/src/tests/modexp.rs b/engine-tests/src/tests/modexp.rs new file mode 100644 index 000000000..77b2accaf --- /dev/null +++ b/engine-tests/src/tests/modexp.rs @@ -0,0 +1,55 @@ +use super::sanity::initialize_transfer; +use crate::prelude::Wei; +use crate::prelude::{Address, U256}; +use crate::test_utils::{self, AuroraRunner, Signer}; + +const MODEXP_ADDRESS: Address = aurora_engine_precompiles::make_address(0, 5); + +#[test] +fn test_modexp_oom() { + let (mut runner, mut signer, _) = initialize_transfer(); + + let inputs = [ + // exp_len: i32::MAX + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + // exp_len: u32::MAX + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + // exp_len: u64::MAX + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000c000000000000000000000000000000000000000000000000000000000000000071000000000000ff600000000000000000000000000000000000000000000000", + ]; + + let outputs = [Vec::new(), Vec::new(), Vec::new()]; + + for (input, output) in inputs.iter().zip(outputs.iter()) { + check_wasm_modexp( + &mut runner, + &mut signer, + hex::decode(input).unwrap(), + output, + ); + } +} + +fn check_wasm_modexp( + runner: &mut AuroraRunner, + signer: &mut Signer, + input: Vec, + expected_output: &[u8], +) { + let wasm_result = runner + .submit_with_signer(signer, |nonce| { + aurora_engine_transactions::legacy::TransactionLegacy { + nonce, + gas_price: U256::zero(), + gas_limit: u64::MAX.into(), + to: Some(MODEXP_ADDRESS), + value: Wei::zero(), + data: input, + } + }) + .unwrap(); + assert_eq!( + expected_output, + test_utils::unwrap_success_slice(&wasm_result), + ); +} diff --git a/engine-tests/src/tests/multisender.rs b/engine-tests/src/tests/multisender.rs index 3bd9a2dc4..1c8f8ed5c 100644 --- a/engine-tests/src/tests/multisender.rs +++ b/engine-tests/src/tests/multisender.rs @@ -9,13 +9,6 @@ const INITIAL_NONCE: u64 = 0; #[test] fn test_multisender_eth() { let (mut runner, mut signer, contract_address) = initialize(); - - let call_contract = |nonce: U256, data: Vec| -> TransactionLegacy { - let mut tx = test_utils::transfer(contract_address, Wei::zero(), nonce); - tx.data = data; - tx - }; - let mut multi_send_eth = |num_addr: usize| -> (u64, u64) { let destinations: Vec<(Address, U256)> = (0..num_addr) .map(|_| { @@ -28,7 +21,7 @@ fn test_multisender_eth() { let (result, profile) = runner .submit_with_signer_profiled(&mut signer, |nonce| { - call_contract(nonce, send_eth_data(&destinations)) + call_contract(contract_address, nonce, send_eth_data(&destinations)) }) .unwrap(); test_utils::unwrap_success_slice(&result); @@ -70,12 +63,6 @@ fn test_multisender_erc20() { .unwrap(); test_utils::unwrap_success_slice(&result); - let call_contract = |nonce: U256, data: Vec| -> TransactionLegacy { - let mut tx = test_utils::transfer(contract_address, Wei::zero(), nonce); - tx.data = data; - tx - }; - let mut multi_send_erc20 = |num_addr: usize| -> (u64, u64) { let destinations: Vec<(Address, U256)> = (0..num_addr) .map(|_| { @@ -88,7 +75,11 @@ fn test_multisender_erc20() { let (result, profile) = runner .submit_with_signer_profiled(&mut signer, |nonce| { - call_contract(nonce, send_erc20_data(erc20.0.address, &destinations)) + call_contract( + contract_address, + nonce, + send_erc20_data(erc20.0.address, &destinations), + ) }) .unwrap(); test_utils::unwrap_success_slice(&result); @@ -104,15 +95,7 @@ fn test_multisender_erc20() { fn send_erc20_data(token_address: Address, amounts: &[(Address, U256)]) -> Vec { const SELECTOR: [u8; 4] = [142, 3, 28, 182]; - let amounts: Vec = amounts - .iter() - .map(|(addr, amount)| { - ethabi::Token::Tuple(vec![ - ethabi::Token::Address(addr.raw()), - ethabi::Token::Uint(*amount), - ]) - }) - .collect(); + let amounts = convert_amounts(amounts); let tokens = vec![ ethabi::Token::Address(token_address.raw()), ethabi::Token::Array(amounts), @@ -128,15 +111,7 @@ fn send_erc20_data(token_address: Address, amounts: &[(Address, U256)]) -> Vec Vec { const SELECTOR: [u8; 4] = [86, 232, 150, 19]; - let amounts: Vec = amounts - .iter() - .map(|(addr, amount)| { - ethabi::Token::Tuple(vec![ - ethabi::Token::Address(addr.raw()), - ethabi::Token::Uint(*amount), - ]) - }) - .collect(); + let amounts = convert_amounts(amounts); let tokens = vec![ethabi::Token::Array(amounts)]; let mut result = Vec::new(); @@ -198,3 +173,21 @@ fn initialize_data(owner_address: Address) -> Vec { result } + +fn call_contract(contract_address: Address, nonce: U256, data: Vec) -> TransactionLegacy { + let mut tx = test_utils::transfer(contract_address, Wei::zero(), nonce); + tx.data = data; + tx +} + +fn convert_amounts(amounts: &[(Address, U256)]) -> Vec { + amounts + .iter() + .map(|(addr, amount)| { + ethabi::Token::Tuple(vec![ + ethabi::Token::Address(addr.raw()), + ethabi::Token::Uint(*amount), + ]) + }) + .collect() +} diff --git a/engine-tests/src/tests/one_inch.rs b/engine-tests/src/tests/one_inch.rs index b1f4d388f..123cc33e2 100644 --- a/engine-tests/src/tests/one_inch.rs +++ b/engine-tests/src/tests/one_inch.rs @@ -50,7 +50,7 @@ fn test_1inch_liquidity_protocol() { helper.runner.context.block_timestamp += 10_000_000 * 1_000_000_000; let (result, profile) = helper.pool_deposit( &pool, - liquidity_protocol::DepositArgs { + &liquidity_protocol::DepositArgs { min_token_a: U256::zero(), min_token_b: U256::zero(), max_token_a: 10_000.into(), @@ -64,7 +64,7 @@ fn test_1inch_liquidity_protocol() { helper.runner.context.block_timestamp += 10_000_000 * 1_000_000_000; let (result, profile) = helper.pool_swap( &pool, - liquidity_protocol::SwapArgs { + &liquidity_protocol::SwapArgs { src_token: token_a.0.address, dst_token: token_b.0.address, amount: 1000.into(), @@ -77,7 +77,7 @@ fn test_1inch_liquidity_protocol() { let (result, profile) = helper.pool_withdraw( &pool, - liquidity_protocol::WithdrawArgs { + &liquidity_protocol::WithdrawArgs { amount: 100.into(), min_token_a: U256::one(), min_token_b: U256::one(), @@ -106,8 +106,7 @@ fn test_1_inch_limit_order_deploy() { let wasm_fraction = 100 * profile.wasm_gas() / profile.all_gas(); assert!( (50..=60).contains(&wasm_fraction), - "{}% is not between 50% and 60%", - wasm_fraction + "{wasm_fraction}% is not between 50% and 60%", ); } @@ -127,10 +126,10 @@ fn deploy_1_inch_limit_order_contract( let nonce = signer.use_nonce(); let deploy_tx = crate::prelude::transactions::legacy::TransactionLegacy { nonce: nonce.into(), - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: None, - value: Default::default(), + value: Wei::default(), data: constructor.code, }; let tx = test_utils::sign_transaction(deploy_tx, Some(runner.chain_id), &signer.secret_key); diff --git a/engine-tests/src/tests/pausable_precompiles.rs b/engine-tests/src/tests/pausable_precompiles.rs index 745a83f9c..7e6351120 100644 --- a/engine-tests/src/tests/pausable_precompiles.rs +++ b/engine-tests/src/tests/pausable_precompiles.rs @@ -1,7 +1,7 @@ use crate::prelude::{Address, U256}; use crate::test_utils::exit_precompile::{Tester, TesterConstructor}; use crate::test_utils::{ - self, origin, AuroraRunner, Signer, PAUSED_PRECOMPILES, PAUSE_PRECOMPILES, RESUME_PRECOMPILES, + self, AuroraRunner, Signer, ORIGIN, PAUSED_PRECOMPILES, PAUSE_PRECOMPILES, RESUME_PRECOMPILES, }; use aurora_engine::parameters::{PausePrecompilesCallArgs, TransactionStatus}; use aurora_engine_types::types::Wei; @@ -23,10 +23,10 @@ fn test_paused_precompile_is_shown_when_viewing() { let mut input: Vec = Vec::new(); call_args.serialize(&mut input).unwrap(); - let _ = runner.call(PAUSE_PRECOMPILES, CALLED_ACCOUNT_ID, input.clone()); + let _res = runner.call(PAUSE_PRECOMPILES, CALLED_ACCOUNT_ID, input.clone()); let (outcome, error) = runner.call(PAUSED_PRECOMPILES, CALLED_ACCOUNT_ID, Vec::new()); - assert!(error.is_none(), "{:?}", error); + assert!(error.is_none(), "{error:?}"); let output: Vec = outcome .as_ref() @@ -53,22 +53,22 @@ fn test_executing_paused_precompile_throws_error() { let mut input: Vec = Vec::new(); call_args.serialize(&mut input).unwrap(); - let _ = runner.call(PAUSE_PRECOMPILES, CALLED_ACCOUNT_ID, input.clone()); + let _res = runner.call(PAUSE_PRECOMPILES, CALLED_ACCOUNT_ID, input.clone()); let is_to_near = false; let result = tester.withdraw(&mut runner, &mut signer, is_to_near); - assert!(result.is_err(), "{:?}", result); + assert!(result.is_err(), "{result:?}"); let error = result.unwrap_err(); match &error { VMError::FunctionCallError(fn_error) => match fn_error { FunctionCallError::HostError(err) => match err { HostError::GuestPanic { panic_msg } => assert_eq!(panic_msg, "ERR_PAUSED"), - other => panic!("Unexpected host error {:?}", other), + other => panic!("Unexpected host error {other:?}"), }, - other => panic!("Unexpected function call error {:?}", other), + other => panic!("Unexpected function call error {other:?}"), }, - other => panic!("Unexpected VM error {:?}", other), + other => panic!("Unexpected VM error {other:?}"), }; } @@ -83,8 +83,8 @@ fn test_executing_paused_and_then_resumed_precompile_succeeds() { let mut input: Vec = Vec::new(); call_args.serialize(&mut input).unwrap(); - let _ = runner.call(PAUSE_PRECOMPILES, CALLED_ACCOUNT_ID, input.clone()); - let _ = runner.call(RESUME_PRECOMPILES, CALLED_ACCOUNT_ID, input); + let _res = runner.call(PAUSE_PRECOMPILES, CALLED_ACCOUNT_ID, input.clone()); + let _res = runner.call(RESUME_PRECOMPILES, CALLED_ACCOUNT_ID, input); let is_to_near = false; let result = tester .withdraw(&mut runner, &mut signer, is_to_near) @@ -92,7 +92,7 @@ fn test_executing_paused_and_then_resumed_precompile_succeeds() { let number = match result.status { TransactionStatus::Succeed(number) => U256::from(number.as_slice()), - _ => panic!("Unexpected status {:?}", result), + _ => panic!("Unexpected status {result:?}"), }; assert_eq!(number, U256::zero()); @@ -109,7 +109,7 @@ fn test_resuming_precompile_does_not_throw_error() { let (_, error) = runner.call(RESUME_PRECOMPILES, CALLED_ACCOUNT_ID, input); - assert!(error.is_none(), "{:?}", error); + assert!(error.is_none(), "{error:?}"); } #[test] @@ -123,7 +123,7 @@ fn test_pausing_precompile_does_not_throw_error() { let (_, error) = runner.call(PAUSE_PRECOMPILES, CALLED_ACCOUNT_ID, input); - assert!(error.is_none(), "{:?}", error); + assert!(error.is_none(), "{error:?}"); } fn setup_test() -> (AuroraRunner, Signer, Address, Tester) { @@ -149,7 +149,7 @@ fn setup_test() -> (AuroraRunner, Signer, Address, Tester) { ) .into(); - runner.mint(token, tester.contract.address, 1_000_000_000, origin()); + runner.mint(token, tester.contract.address, 1_000_000_000, ORIGIN); (runner, signer, token, tester) } diff --git a/engine-tests/src/tests/prepaid_gas_precompile.rs b/engine-tests/src/tests/prepaid_gas_precompile.rs index f008dcf08..e360afa08 100644 --- a/engine-tests/src/tests/prepaid_gas_precompile.rs +++ b/engine-tests/src/tests/prepaid_gas_precompile.rs @@ -5,6 +5,7 @@ use aurora_engine_types::{types::Wei, U256}; #[test] fn test_prepaid_gas_precompile() { + const EXPECTED_VALUE: u64 = 157_277_246_352_223; let mut signer = test_utils::Signer::random(); let mut runner = test_utils::deploy_evm(); let mut standalone = standalone::StandaloneRunner::default(); @@ -21,7 +22,6 @@ fn test_prepaid_gas_precompile() { data: Vec::new(), }; - const EXPECTED_VALUE: u64 = 157_277_246_352_223; runner.context.prepaid_gas = EXPECTED_VALUE; let result = runner .submit_transaction(&signer.secret_key, transaction.clone()) @@ -35,7 +35,7 @@ fn test_prepaid_gas_precompile() { // confirm the precompile works in view calls too let sender = test_utils::address_from_secret_key(&signer.secret_key); let result = runner - .view_call(test_utils::as_view_call(transaction, sender)) + .view_call(&test_utils::as_view_call(transaction, sender)) .unwrap(); assert!(result.is_ok()); } diff --git a/engine-tests/src/tests/promise_results_precompile.rs b/engine-tests/src/tests/promise_results_precompile.rs index b5788867b..967aed2fa 100644 --- a/engine-tests/src/tests/promise_results_precompile.rs +++ b/engine-tests/src/tests/promise_results_precompile.rs @@ -70,7 +70,7 @@ fn test_promise_result_gas_cost() { .unwrap(); let mut profile_for_promises = |promise_data: Vec| -> (u64, u64, u64) { - let input_length: usize = promise_data.iter().map(|p| p.size()).sum(); + let input_length: usize = promise_data.iter().map(PromiseResult::size).sum(); runner.promise_results = promise_data; let (submit_result, profile) = runner .submit_with_signer_profiled(&mut signer, |nonce| TransactionLegacy { diff --git a/engine-tests/src/tests/repro.rs b/engine-tests/src/tests/repro.rs index 1370a7cf9..42c327181 100644 --- a/engine-tests/src/tests/repro.rs +++ b/engine-tests/src/tests/repro.rs @@ -1,13 +1,13 @@ //! A module containing tests which reproduce transactions sent to live networks. -use crate::test_utils::standalone; +use crate::test_utils::{standalone, ORIGIN}; use crate::test_utils::{AuroraRunner, ExecutionProfile}; use aurora_engine::parameters::SubmitResult; use borsh::{BorshDeserialize, BorshSerialize}; use engine_standalone_storage::json_snapshot; /// This test reproduces a transaction from testnet: -/// https://explorer.testnet.near.org/transactions/GdASJ3KESs8VegpFECTveCwLQp8fxw8yvsauNEmGb6pZ +/// `https://explorer.testnet.near.org/transactions/GdASJ3KESs8VegpFECTveCwLQp8fxw8yvsauNEmGb6pZ` /// It hit the NEAR gas limit even after the 2.4 engine release and limit increase to 300 Tgas. /// The purpose of having it here is to be able to track it's performance as we continue to /// optimize the Engine. @@ -21,72 +21,72 @@ fn repro_GdASJ3KESs() { // Note: this snapshot is pruned from the full Engine state on testnet at that block height. // The full snapshot is very large, and all that is necessary for this test are the keys used // in the transaction. This pruned snapshot contains precisely those keys, and no others. - repro_common(ReproContext { + repro_common(&ReproContext { snapshot_path: "src/tests/res/aurora_state_GdASJ3KESs.json", - block_index: 83596945, - block_timestamp: 1645717564644206730, + block_index: 83_596_945, + block_timestamp: 1_645_717_564_644_206_730, input_path: "src/tests/res/input_GdASJ3KESs.hex", - evm_gas_used: 706713, + evm_gas_used: 706_713, near_gas_used: 122, }); } /// This test reproduces a transaction from mainnet: -/// https://explorer.mainnet.near.org/transactions/8ru7VEAEbyfZdbC1W2PYQv2cY3W92rbTToDEN4yTp8aZ +/// `https://explorer.mainnet.near.org/transactions/8ru7VEAEbyfZdbC1W2PYQv2cY3W92rbTToDEN4yTp8aZ` /// It hit the NEAR gas limit even after the 2.5.2 engine release and limit increase to 300 Tgas. /// The purpose of having it here is to be able to track its performance as we continue to /// optimize the Engine. /// The test is somewhat inscrutable because the data was directly pulled from the Engine contract /// on mainnet, but according to the partner that submitted the transaction, the transaction should /// be doing something similar to this one on Ethereum itself: -/// https://etherscan.io/tx/0x6c1ccadf6553f4f8bdb475667a91f050b1dfb63ded09053354f1e6fd78ff63a6 +/// `https://etherscan.io/tx/0x6c1ccadf6553f4f8bdb475667a91f050b1dfb63ded09053354f1e6fd78ff63a6` #[allow(non_snake_case)] #[test] fn repro_8ru7VEA() { // Note: this snapshot is pruned from the full Engine state on mainnet at that block height. // The full snapshot is very large, and all that is necessary for this test are the keys used // in the transaction. This pruned snapshot contains precisely those keys, and no others. - repro_common(ReproContext { + repro_common(&ReproContext { snapshot_path: "src/tests/res/aurora_state_8ru7VEA.json", - block_index: 62625815, - block_timestamp: 1648829935343349589, + block_index: 62_625_815, + block_timestamp: 1_648_829_935_343_349_589, input_path: "src/tests/res/input_8ru7VEA.hex", - evm_gas_used: 1732181, + evm_gas_used: 1_732_181, near_gas_used: 223, }); } /// This test reproduces a transaction from mainnet: -/// https://explorer.mainnet.near.org/transactions/FRcorNvFojoxBrdiVMTy9gRD3H8EYXXKau4feevMZmFV +/// `https://explorer.mainnet.near.org/transactions/FRcorNvFojoxBrdiVMTy9gRD3H8EYXXKau4feevMZmFV` /// It hit the gas limit at the time of its execution (engine v2.5.2 after 300 Tgas limit increase). /// The transaction performs some complex defi interaction (description from the user): -/// 1. It sell 30% BSTN to NEAR, and mint cNEAR +/// 1. It sells 30% BSTN to NEAR, and mint `cNEAR` /// 2. It sells 35% BSTN to NEAR, and make NEAR-BSTN LP token /// 3. Deposit LP token created from step2 to Trisolaris farm #[allow(non_snake_case)] #[test] fn repro_FRcorNv() { - repro_common(ReproContext { + repro_common(&ReproContext { snapshot_path: "src/tests/res/aurora_state_FRcorNv.json", - block_index: 64328524, - block_timestamp: 1650960438774745116, + block_index: 64_328_524, + block_timestamp: 1_650_960_438_774_745_116, input_path: "src/tests/res/input_FRcorNv.hex", - evm_gas_used: 1239721, + evm_gas_used: 1_239_721, near_gas_used: 181, }); } /// This test reproduces a transaction from mainnet: -/// https://explorer.mainnet.near.org/transactions/5bEgfRQ5TSJfN9XCqYkMr9cgBLToM7JmS1bNzKpDXJhT +/// `https://explorer.mainnet.near.org/transactions/5bEgfRQ5TSJfN9XCqYkMr9cgBLToM7JmS1bNzKpDXJhT` /// It hit the gas limit at the time of its execution (engine v2.5.2 after 300 Tgas limit increase). -/// The transaction is a "claim xp rewards action" from the game CryptoBlades. +/// The transaction is a "claim xp rewards action" from the game `CryptoBlades`. #[allow(non_snake_case)] #[test] fn repro_5bEgfRQ() { - repro_common(ReproContext { + repro_common(&ReproContext { snapshot_path: "src/tests/res/aurora_state_5bEgfRQ.json", - block_index: 64417403, - block_timestamp: 1651073772931594646, + block_index: 64_417_403, + block_timestamp: 1_651_073_772_931_594_646, input_path: "src/tests/res/input_5bEgfRQ.hex", evm_gas_used: 6_414_105, near_gas_used: 657, @@ -94,17 +94,17 @@ fn repro_5bEgfRQ() { } /// This test reproduces a transaction from mainnet: -/// https://explorer.mainnet.near.org/transactions/D98vwmi44hAYs8KtX5aLne1zEkj3MUss42e5SkG2a4SC +/// `https://explorer.mainnet.near.org/transactions/D98vwmi44hAYs8KtX5aLne1zEkj3MUss42e5SkG2a4SC` /// It hit the gas limit at the time of its execution (engine v2.5.2 after 300 Tgas limit increase). /// The transaction is a harvest action for some sort of defi contract. See the report here: -/// https://github.com/aurora-is-near/aurora-relayer/issues/60#issuecomment-1118549256 +/// `https://github.com/aurora-is-near/aurora-relayer/issues/60#issuecomment-1118549256` #[allow(non_snake_case)] #[test] fn repro_D98vwmi() { - repro_common(ReproContext { + repro_common(&ReproContext { snapshot_path: "src/tests/res/aurora_state_D98vwmi.json", - block_index: 64945381, - block_timestamp: 1651753443421003245, + block_index: 64_945_381, + block_timestamp: 1_651_753_443_421_003_245, input_path: "src/tests/res/input_D98vwmi.hex", evm_gas_used: 1_035_348, near_gas_used: 182, @@ -112,25 +112,25 @@ fn repro_D98vwmi() { } /// This test reproduces a transaction from testnet: -/// https://explorer.testnet.near.org/transactions/Emufid2pv2UpxrZae4NyowF2N2ZHvYEPq16LsQc7Uoc6 +/// `https://explorer.testnet.near.org/transactions/Emufid2pv2UpxrZae4NyowF2N2ZHvYEPq16LsQc7Uoc6` /// It hit the gas limit at the time of its execution (engine v2.7.0). /// The transaction is some kind of multi-step token swap. The user says it should be similar /// to this transaction on Polygon: -/// https://mumbai.polygonscan.com/tx/0xd9ab182692c74a873f0c444854ed1045edbb32a252b561677042276143a024b7 +/// `https://mumbai.polygonscan.com/tx/0xd9ab182692c74a873f0c444854ed1045edbb32a252b561677042276143a024b7` #[allow(non_snake_case)] #[test] fn repro_Emufid2() { - repro_common(ReproContext { + repro_common(&ReproContext { snapshot_path: "src/tests/res/aurora_state_Emufid2.json", - block_index: 99197180, - block_timestamp: 1662118048636713538, + block_index: 99_197_180, + 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: 306, }); } -fn repro_common(context: ReproContext) { +fn repro_common(context: &ReproContext) { let ReproContext { snapshot_path, block_index, @@ -146,8 +146,8 @@ fn repro_common(context: ReproContext) { 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()); - runner.context.block_index = block_index; - runner.context.block_timestamp = block_timestamp; + runner.context.block_index = *block_index; + runner.context.block_timestamp = *block_timestamp; let tx_hex = std::fs::read_to_string(input_path).unwrap(); let tx_bytes = hex::decode(tx_hex.trim()).unwrap(); @@ -156,19 +156,19 @@ fn repro_common(context: ReproContext) { let outcome = outcome.unwrap(); let profile = ExecutionProfile::new(&outcome); if let Some(error) = error { - panic!("{:?}", error); + panic!("{error:?}"); } let submit_result = SubmitResult::try_from_slice(&outcome.return_data.as_value().unwrap()).unwrap(); - assert_eq!(submit_result.gas_used, evm_gas_used); - assert_eq!(near_gas_used, profile.all_gas() / 1_000_000_000_000); + assert_eq!(submit_result.gas_used, *evm_gas_used); + assert_eq!(*near_gas_used, profile.all_gas() / 1_000_000_000_000); // Also validate the SubmitResult in the standalone engine let mut standalone = standalone::StandaloneRunner::default(); standalone .storage - .set_engine_account_id(&"aurora".parse().unwrap()) + .set_engine_account_id(&ORIGIN.parse().unwrap()) .unwrap(); json_snapshot::initialize_engine_state(&mut standalone.storage, snapshot).unwrap(); let standalone_result = standalone @@ -178,7 +178,7 @@ fn repro_common(context: ReproContext) { submit_result.try_to_vec().unwrap(), standalone_result.try_to_vec().unwrap() ); - standalone.close() + standalone.close(); } struct ReproContext<'a> { diff --git a/engine-tests/src/tests/sanity.rs b/engine-tests/src/tests/sanity.rs index fb51786bd..6f8328c82 100644 --- a/engine-tests/src/tests/sanity.rs +++ b/engine-tests/src/tests/sanity.rs @@ -1,9 +1,9 @@ use crate::prelude::{Address, U256}; use crate::prelude::{Wei, ERC20_MINT_SELECTOR}; -use crate::test_utils; +use crate::test_utils::{self, str_to_account_id}; use crate::tests::state_migration; use aurora_engine::fungible_token::FungibleTokenMetadata; -use aurora_engine::parameters::{SubmitResult, TransactionStatus}; +use aurora_engine::parameters::{SetOwnerArgs, SubmitResult, TransactionStatus}; use aurora_engine_sdk as sdk; use borsh::BorshSerialize; use libsecp256k1::SecretKey; @@ -109,21 +109,21 @@ fn test_transaction_to_zero_address() { context.input = tx_bytes; // Prior to the fix the zero address is interpreted as None, causing a contract deployment. // It also incorrectly derives the sender address, so does not increment the right nonce. - context.block_index = aurora_engine::engine::ZERO_ADDRESS_FIX_HEIGHT - 1; + context.block_index = ZERO_ADDRESS_FIX_HEIGHT - 1; let result = runner .submit_raw(test_utils::SUBMIT, &context, &[]) .unwrap(); assert_eq!(result.gas_used, 53_000); - runner.env.block_height = aurora_engine::engine::ZERO_ADDRESS_FIX_HEIGHT; + runner.env.block_height = ZERO_ADDRESS_FIX_HEIGHT; assert_eq!(runner.get_nonce(&address), U256::zero()); // After the fix this transaction is simply a transfer of 0 ETH to the zero address - context.block_index = aurora_engine::engine::ZERO_ADDRESS_FIX_HEIGHT; + context.block_index = ZERO_ADDRESS_FIX_HEIGHT; let result = runner .submit_raw(test_utils::SUBMIT, &context, &[]) .unwrap(); assert_eq!(result.gas_used, 21_000); - runner.env.block_height = aurora_engine::engine::ZERO_ADDRESS_FIX_HEIGHT + 1; + runner.env.block_height = ZERO_ADDRESS_FIX_HEIGHT + 1; assert_eq!(runner.get_nonce(&address), U256::one()); } @@ -139,7 +139,7 @@ fn test_state_format() { bridge_prover_id: "prover_mcprovy_face".parse().unwrap(), upgrade_delay_blocks: 3, }; - let state: aurora_engine::engine::EngineState = args.into(); + let state: aurora_engine::state::EngineState = args.into(); let expected_hex: String = [ "000000000000000000000000000000000000000000000000000000000000029a", "04000000626f7373", @@ -150,19 +150,19 @@ fn test_state_format() { assert_eq!(hex::encode(state.try_to_vec().unwrap()), expected_hex); } +fn generate_code(len: usize) -> Vec { + let mut rng = rand::thread_rng(); + let mut buf = vec![0u8; len]; + rng.fill_bytes(&mut buf); + buf +} + #[test] fn test_deploy_contract() { let (mut runner, mut signer, _) = initialize_transfer(); // Randomly generate some "contract code" - const LEN: usize = 567; - let code: Vec = { - let mut rng = rand::thread_rng(); - let mut buf = vec![0u8; LEN]; - rng.fill_bytes(&mut buf); - buf - }; - + let code = generate_code(567); // Deploy that code let result = runner .submit_with_signer(&mut signer, |nonce| { @@ -183,12 +183,7 @@ fn test_deploy_largest_contract() { let (mut runner, mut signer, _) = initialize_transfer(); let len = evm::Config::berlin().create_contract_limit.unwrap(); - let code: Vec = { - let mut rng = rand::thread_rng(); - let mut buf = vec![0u8; len]; - rng.fill_bytes(&mut buf); - buf - }; + let code = generate_code(len); // Deploy that code let (result, profile) = runner @@ -352,9 +347,7 @@ fn test_solidity_pure_bench() { ); // Pure rust version of the same contract - let base_path = std::path::Path::new("../etc") - .join("tests") - .join("benchmark-contract"); + let base_path = Path::new("../etc").join("tests").join("benchmark-contract"); let output_path = base_path.join("target/wasm32-unknown-unknown/release/benchmark_contract.wasm"); test_utils::rust::compile(base_path); @@ -377,12 +370,12 @@ fn test_solidity_pure_bench() { near_vm_runner::VMResult::Ok(outcome) => (Some(outcome), None), }; if let Some(e) = error { - panic!("{:?}", e); + panic!("{e:?}"); } let outcome = outcome.unwrap(); let profile = test_utils::ExecutionProfile::new(&outcome); // Check the contract actually did the work. - assert_eq!(&outcome.logs, &[format!("Done {} iterations!", loop_limit)]); + assert_eq!(&outcome.logs, &[format!("Done {loop_limit} iterations!")]); assert!(profile.all_gas() < 1_000_000_000_000); // Less than 1 Tgas used! } @@ -404,7 +397,7 @@ fn test_revert_during_contract_deploy() { .submit_transaction(&signer.secret_key, deploy_tx) .unwrap(); - let revert_bytes = crate::test_utils::unwrap_revert(submit_result); + let revert_bytes = test_utils::unwrap_revert(submit_result); // First 4 bytes is a function selector with signature `Error(string)` assert_eq!(&revert_bytes[0..4], &[8, 195, 121, 160]); // Remaining data is an ABI-encoded string @@ -449,7 +442,7 @@ fn test_call_too_deep_error() { // visible to users. match result.status { TransactionStatus::Revert(_) => (), - other => panic!("Unexpected status {:?}", other), + other => panic!("Unexpected status {other:?}"), } } @@ -504,9 +497,9 @@ fn test_timestamp() { let t = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap(); - let t_ns = t.as_nanos(); - let t_s = U256::from(t.as_secs()); - runner.context.block_timestamp = t_ns as u64; + let nanos = t.as_nanos(); + let secs = U256::from(t.as_secs()); + runner.context.block_timestamp = u64::try_from(nanos).unwrap(); // call contract let result = runner @@ -519,7 +512,7 @@ fn test_timestamp() { // Check time is correct. // The `+1` is needed here because the runner increments the context // timestamp by 1 second automatically before each transaction. - assert_eq!(t_s + 1, timestamp); + assert_eq!(secs + 1, timestamp); } #[test] @@ -542,10 +535,10 @@ fn test_override_state() { .submit_with_signer(&mut account1, |nonce| { crate::prelude::transactions::legacy::TransactionLegacy { nonce, - gas_price: Default::default(), + gas_price: U256::default(), gas_limit: u64::MAX.into(), to: None, - value: Default::default(), + value: Wei::default(), data: contract.code.clone(), } }) @@ -556,15 +549,13 @@ fn test_override_state() { // define functions to interact with the contract let get_address = |runner: &test_utils::AuroraRunner| { let result = runner - .view_call(test_utils::as_view_call( + .view_call(&test_utils::as_view_call( contract.call_method_without_args("get", U256::zero()), viewer_address, )) .unwrap(); match result { - crate::prelude::parameters::TransactionStatus::Succeed(bytes) => { - Address::try_from_slice(&bytes[12..32]).unwrap() - } + TransactionStatus::Succeed(bytes) => Address::try_from_slice(&bytes[12..32]).unwrap(), _ => panic!("tx failed"), } }; @@ -603,8 +594,7 @@ fn test_num_wasm_functions() { let num_functions = module.funcs.iter().count(); assert!( num_functions <= 1440, - "{} is not less than 1440", - num_functions + "{num_functions} is not less than 1440", ); } @@ -704,7 +694,7 @@ fn test_eth_transfer_incorrect_nonce() { test_utils::transfer(dest_address, TRANSFER_AMOUNT, nonce + 1) }) .unwrap_err(); - let error_message = format!("{:?}", err); + let error_message = format!("{err:?}"); assert!(error_message.contains("ERR_INCORRECT_NONCE")); // validate post-state (which is the same as pre-state in this case) @@ -740,7 +730,7 @@ fn test_eth_transfer_not_enough_gas() { let err = runner .submit_with_signer(&mut source_account, transaction) .unwrap_err(); - let error_message = format!("{:?}", err); + let error_message = format!("{err:?}"); assert!(error_message.contains("ERR_INTRINSIC_GAS")); // validate post-state (which is the same as pre-state in this case) @@ -808,6 +798,8 @@ fn test_transfer_charging_gas_success() { #[test] fn test_eth_transfer_charging_gas_not_enough_balance() { + use near_vm_errors::{FunctionCallError, HostError, VMError}; + let (mut runner, mut source_account, dest_address) = initialize_transfer(); let source_address = test_utils::address_from_secret_key(&source_account.secret_key); let transaction = |nonce| { @@ -829,10 +821,13 @@ fn test_eth_transfer_charging_gas_not_enough_balance() { test_utils::validate_address_balance_and_nonce(&runner, dest_address, Wei::zero(), 0.into()); // attempt transfer - let result = runner + let error = runner .submit_with_signer(&mut source_account, transaction) - .unwrap(); - assert_eq!(result.status, TransactionStatus::OutOfFund); + .unwrap_err(); + assert!(matches!(error, VMError::FunctionCallError( + FunctionCallError::HostError( + HostError::GuestPanic { panic_msg })) if panic_msg == "ERR_OUT_OF_FUND" + )); // validate post-state let relayer = sdk::types::near_account_to_evm_address( @@ -843,14 +838,14 @@ fn test_eth_transfer_charging_gas_not_enough_balance() { &runner, source_address, INITIAL_BALANCE, - // nonce is still incremented since the transaction was otherwise valid - (INITIAL_NONCE + 1).into(), + // nonce is still not incremented since the transaction was invalid + INITIAL_NONCE.into(), ); test_utils::validate_address_balance_and_nonce(&runner, dest_address, Wei::zero(), 0.into()); test_utils::validate_address_balance_and_nonce(&runner, relayer, Wei::zero(), 0.into()); } -pub(crate) fn initialize_transfer() -> (test_utils::AuroraRunner, test_utils::Signer, Address) { +pub fn initialize_transfer() -> (test_utils::AuroraRunner, test_utils::Signer, Address) { // set up Aurora runner and accounts let mut runner = test_utils::deploy_evm(); let mut rng = rand::thread_rng(); @@ -864,6 +859,7 @@ pub(crate) fn initialize_transfer() -> (test_utils::AuroraRunner, test_utils::Si (runner, signer, dest_address) } +use aurora_engine::engine::ZERO_ADDRESS_FIX_HEIGHT; use aurora_engine_types::H160; use sha3::Digest; @@ -884,8 +880,8 @@ fn test_block_hash() { let number = crate::prelude::U256::from(runner.chain_id); crate::prelude::u256_to_arr(&number) }; - let account_id = runner.aurora_account_id; - let block_hash = aurora_engine::engine::compute_block_hash(chain_id, 10, account_id.as_bytes()); + let account_id = runner.aurora_account_id.as_bytes(); + let block_hash = aurora_engine::engine::compute_block_hash(chain_id, 10, account_id); assert_eq!( hex::encode(block_hash.0).as_str(), @@ -904,13 +900,13 @@ fn test_block_hash_api() { block_height.try_to_vec().unwrap(), ); if let Some(error) = maybe_error { - panic!("Call failed: {:?}", error); + panic!("Call failed: {error:?}"); } let outcome = maybe_outcome.unwrap(); let block_hash = outcome.return_data.as_value().unwrap(); assert_eq!( - hex::encode(&block_hash).as_str(), + hex::encode(block_hash).as_str(), "c4a46f076b64877cbd8c5dbfd7bfbbea21a5653b79e3b6d06b6dfb5c88f1c384", ); } @@ -948,13 +944,11 @@ fn test_ft_metadata() { let (maybe_outcome, maybe_error) = runner.call("ft_metadata", &account_id, Vec::new()); assert!(maybe_error.is_none()); let outcome = maybe_outcome.unwrap(); - let json_value = - aurora_engine::json::parse_json(&outcome.return_data.as_value().unwrap()).unwrap(); + let metadata = + serde_json::from_slice::(&outcome.return_data.as_value().unwrap()) + .unwrap(); - assert_eq!( - json_value, - aurora_engine::json::JsonValue::from(FungibleTokenMetadata::default()) - ); + assert_eq!(metadata, FungibleTokenMetadata::default()); } // Same as `test_eth_transfer_insufficient_balance` above, except runs through @@ -979,7 +973,13 @@ fn test_eth_transfer_insufficient_balance_sim() { &signer.secret_key, ); let call_result = aurora.call("submit", rlp::encode(&signed_tx).as_ref()); - let result: SubmitResult = call_result.unwrap_borsh(); + let result = match call_result.status() { + near_primitives::transaction::ExecutionStatus::SuccessValue(bytes) => { + use borsh::BorshDeserialize; + SubmitResult::try_from_slice(&bytes).unwrap() + } + other => panic!("Unexpected status {other:?}"), + }; assert_eq!(result.status, TransactionStatus::OutOfFund); // validate post-state @@ -996,6 +996,8 @@ fn test_eth_transfer_insufficient_balance_sim() { // Same as `test_eth_transfer_charging_gas_not_enough_balance` but run through `near-sdk-sim`. #[test] fn test_eth_transfer_charging_gas_not_enough_balance_sim() { + use near_primitives::{errors::TxExecutionError, transaction::ExecutionStatus}; + let (aurora, mut signer, address) = initialize_evm_sim(); // Run transaction which will fail (not enough balance to cover gas) @@ -1009,13 +1011,17 @@ fn test_eth_transfer_charging_gas_not_enough_balance_sim() { &signer.secret_key, ); let call_result = aurora.call("submit", rlp::encode(&signed_tx).as_ref()); - let result: SubmitResult = call_result.unwrap_borsh(); - assert_eq!(result.status, TransactionStatus::OutOfFund); + let outcome = call_result.outcome(); + assert!(matches!( + &outcome.status, + ExecutionStatus::Failure( + TxExecutionError::ActionError(e)) if e.to_string().contains("ERR_OUT_OF_FUND") + )); // validate post-state assert_eq!( query_address_sim(&address, "get_nonce", &aurora), - U256::from(INITIAL_NONCE + 1), + INITIAL_NONCE.into(), // nonce hasn't been changed because an error occurs ); assert_eq!( query_address_sim(&address, "get_balance", &aurora), @@ -1023,6 +1029,106 @@ fn test_eth_transfer_charging_gas_not_enough_balance_sim() { ); } +/// Tests transfer Eth from one account to another with custom argument `max_gas_price`. +#[test] +fn test_eth_transfer_with_max_gas_price() { + // set up Aurora runner and accounts + let (mut runner, source_account, dest_address) = initialize_transfer(); + let source_address = test_utils::address_from_secret_key(&source_account.secret_key); + + // validate pre-state + test_utils::validate_address_balance_and_nonce( + &runner, + source_address, + INITIAL_BALANCE, + INITIAL_NONCE.into(), + ); + test_utils::validate_address_balance_and_nonce(&runner, dest_address, Wei::zero(), 0.into()); + + // perform transfer + let max_gas_price = 5; + let mut transaction = test_utils::transfer(dest_address, TRANSFER_AMOUNT, INITIAL_NONCE.into()); + transaction.gas_price = 10.into(); + transaction.gas_limit = 30_000.into(); + + let result = runner + .submit_transaction_with_args(&source_account.secret_key, transaction, max_gas_price, None) + .unwrap(); + + let fee = u128::from(result.gas_used) * max_gas_price; + // validate post-state + test_utils::validate_address_balance_and_nonce( + &runner, + source_address, + INITIAL_BALANCE - TRANSFER_AMOUNT - Wei::new_u128(fee), + (INITIAL_NONCE + 1).into(), + ); + test_utils::validate_address_balance_and_nonce( + &runner, + dest_address, + TRANSFER_AMOUNT, + 0.into(), + ); +} + +#[test] +fn test_set_owner() { + let mut runner = test_utils::deploy_evm(); + let aurora_account_id = runner.aurora_account_id.clone(); + + // set owner args + let set_owner_args = SetOwnerArgs { + new_owner: str_to_account_id("new_owner.near"), + }; + + let (outcome, error) = runner.call( + "set_owner", + &aurora_account_id, + set_owner_args.try_to_vec().unwrap(), + ); + + // setting owner from the owner with same owner id should succeed + assert!(outcome.is_some() && error.is_none()); + + // get owner to see if the owner_id property has changed + let (outcome, error) = runner.call("get_owner", &aurora_account_id, vec![]); + + // check if the query goes through the standalone runner + assert!(outcome.is_some() && error.is_none()); + + // check if the owner_id property has changed to new_owner.near + assert_eq!( + b"new_owner.near", + outcome.unwrap().return_data.as_value().unwrap().as_slice() + ); +} + +#[test] +fn test_set_owner_fail_on_same_owner() { + let mut runner = test_utils::deploy_evm(); + let aurora_account_id = runner.aurora_account_id.clone(); + + // set owner args + let set_owner_args = SetOwnerArgs { + new_owner: str_to_account_id(&aurora_account_id), + }; + + let (outcome, error) = runner.call( + "set_owner", + &aurora_account_id, + set_owner_args.try_to_vec().unwrap(), + ); + + // setting owner from the owner with same owner id should fail + assert!(outcome.is_some() && error.is_some()); + + // check error equality + assert_eq!( + error.unwrap().to_string(), + "Smart contract panicked: ERR_SAME_OWNER" + ); +} + fn initialize_evm_sim() -> (state_migration::AuroraAccount, test_utils::Signer, Address) { let aurora = state_migration::deploy_evm(); let signer = test_utils::Signer::random(); @@ -1054,6 +1160,6 @@ fn query_address_sim( let x = aurora.call(method, address.as_bytes()); match &x.outcome().status { near_sdk_sim::transaction::ExecutionStatus::SuccessValue(b) => U256::from_big_endian(b), - other => panic!("Unexpected outcome: {:?}", other), + other => panic!("Unexpected outcome: {other:?}"), } } diff --git a/engine-tests/src/tests/serde.rs b/engine-tests/src/tests/serde.rs new file mode 100644 index 000000000..fab1b8cd2 --- /dev/null +++ b/engine-tests/src/tests/serde.rs @@ -0,0 +1,43 @@ +//! Tests to ensure we can use serde to serialize various types. + +use aurora_engine::{ + engine::{EngineError, EngineErrorKind}, + parameters::{ResultLog, SubmitResult, TransactionStatus}, +}; +use aurora_engine_transactions::eip_2930::AccessTuple; +use aurora_engine_types::{types::Address, H160}; + +#[test] +fn test_serde_submit_result() { + let result = SubmitResult::new( + TransactionStatus::OutOfFund, + 0, + vec![ResultLog { + address: Address::default(), + topics: Vec::new(), + data: Vec::new(), + }], + ); + let serialized = serde_json::to_value(result).unwrap(); + assert!(serialized.is_object()); +} + +#[test] +fn test_serde_engine_error() { + let engine_error = EngineError { + kind: EngineErrorKind::GasOverflow, + gas_used: 0, + }; + let serialized = serde_json::to_value(engine_error).unwrap(); + assert!(serialized.is_object()); +} + +#[test] +fn test_serde_access_tuple() { + let tuple = AccessTuple { + address: H160::default(), + storage_keys: Vec::new(), + }; + let serialized = serde_json::to_value(tuple).unwrap(); + assert!(serialized.is_object()); +} diff --git a/engine-tests/src/tests/standalone/call_tracer.rs b/engine-tests/src/tests/standalone/call_tracer.rs index 64669f08f..3439cc876 100644 --- a/engine-tests/src/tests/standalone/call_tracer.rs +++ b/engine-tests/src/tests/standalone/call_tracer.rs @@ -1,3 +1,4 @@ +use crate::prelude::H256; use crate::test_utils::{self, standalone}; use aurora_engine_types::{ parameters::{CrossContractCallArgs, PromiseArgs, PromiseCreateArgs}, @@ -12,6 +13,34 @@ use engine_standalone_tracing::{ types::call_tracer::{self, CallTracer}, }; +#[test] +fn test_trace_contract_deploy() { + let mut runner = standalone::StandaloneRunner::default(); + let mut signer = test_utils::Signer::random(); + + runner.init_evm(); + + let constructor = test_utils::erc20::ERC20Constructor::load(); + let deploy_tx = constructor.deploy("Test", "TST", signer.use_nonce().into()); + let mut listener = CallTracer::default(); + let deploy_result = sputnik::traced_call(&mut listener, || { + runner + .submit_transaction(&signer.secret_key, deploy_tx) + .unwrap() + }); + let contract_address = { + let bytes = test_utils::unwrap_success_slice(&deploy_result); + Address::try_from_slice(bytes).unwrap() + }; + let code = runner.get_code(&contract_address); + + assert_eq!(listener.call_stack.len(), 1); + let trace = listener.call_stack.pop().unwrap(); + + assert_eq!(trace.to, Some(contract_address)); + assert_eq!(trace.output, code); +} + #[test] fn test_trace_precompile_direct_call() { let mut runner = standalone::StandaloneRunner::default(); @@ -120,14 +149,15 @@ fn test_trace_contract_with_sub_call() { context.approve_erc20(&token_a, context.swap_router.0.address, U256::MAX); context.approve_erc20(&token_b, context.swap_router.0.address, U256::MAX); - let params = context.exact_output_single_params(OUTPUT_AMOUNT.into(), &token_a, &token_b); + let params = + UniswapTestContext::exact_output_single_params(OUTPUT_AMOUNT.into(), &token_a, &token_b); let mut listener = CallTracer::default(); let (_amount_in, _profile) = sputnik::traced_call(&mut listener, || { context .runner .submit_with_signer_profiled(&mut context.signer, |nonce| { - context.swap_router.exact_output_single(params, nonce) + context.swap_router.exact_output_single(¶ms, nonce) }) .unwrap() }); @@ -253,7 +283,7 @@ fn test_trace_precompiles_with_subcalls() { let env = &runner.env; let mut tx = - standalone::StandaloneRunner::template_tx_msg(storage, env, 0, Default::default(), &[]); + standalone::StandaloneRunner::template_tx_msg(storage, env, 0, H256::default(), &[]); tx.transaction = sync::types::TransactionKind::DeployErc20( aurora_engine::parameters::DeployErc20TokenArgs { nep141: "wrap.near".parse().unwrap(), @@ -278,7 +308,7 @@ fn test_trace_precompiles_with_subcalls() { let env = &runner.env; let mut tx = - standalone::StandaloneRunner::template_tx_msg(storage, env, 0, Default::default(), &[]); + standalone::StandaloneRunner::template_tx_msg(storage, env, 0, H256::default(), &[]); tx.transaction = sync::types::TransactionKind::FactoryUpdate(xcc_router_bytes); tx }; @@ -290,7 +320,7 @@ fn test_trace_precompiles_with_subcalls() { let env = &runner.env; let mut tx = - standalone::StandaloneRunner::template_tx_msg(storage, env, 0, Default::default(), &[]); + standalone::StandaloneRunner::template_tx_msg(storage, env, 0, H256::default(), &[]); tx.transaction = sync::types::TransactionKind::FactorySetWNearAddress(wnear_address); tx }; @@ -338,9 +368,9 @@ fn test_trace_precompiles_with_subcalls() { /// The `path` gives the index to pull out of each `calls` array. /// For example `path == []` simply returns the given `root`, while /// `path == [2, 0]` will return `root.calls[2].calls[0]`. -fn subcall_lense<'a, 'b>( +fn subcall_lense<'a>( root: &'a call_tracer::CallFrame, - path: &'b [usize], + path: &[usize], ) -> &'a call_tracer::CallFrame { let mut result = root; for index in path { diff --git a/engine-tests/src/tests/standalone/json_snapshot.rs b/engine-tests/src/tests/standalone/json_snapshot.rs index 764ddef0b..2eadaef01 100644 --- a/engine-tests/src/tests/standalone/json_snapshot.rs +++ b/engine-tests/src/tests/standalone/json_snapshot.rs @@ -19,19 +19,19 @@ fn test_consume_snapshot() { // check accounts to see they were written properly runner.env.block_height = snapshot.result.block_height + 1; for entry in snapshot.result.values { - let key = base64::decode(entry.key).unwrap(); - let value = base64::decode(entry.value).unwrap(); + let key = aurora_engine_sdk::base64::decode(entry.key).unwrap(); + let value = aurora_engine_sdk::base64::decode(entry.value).unwrap(); if key.as_slice().starts_with(&NONCE_PREFIX) { let address = address_from_key(&key); let nonce = U256::from_big_endian(&value); - assert_eq!(nonce, runner.get_nonce(&address)) + assert_eq!(nonce, runner.get_nonce(&address)); } else if key.as_slice().starts_with(&BALANCE_PREFIX) { let address = address_from_key(&key); let balance = U256::from_big_endian(&value); - assert_eq!(balance, runner.get_balance(&address).raw()) + assert_eq!(balance, runner.get_balance(&address).raw()); } else if key.as_slice().starts_with(&CODE_PREFIX) { let address = address_from_key(&key); - assert_eq!(value, runner.get_code(&address)) + assert_eq!(value, runner.get_code(&address)); } } @@ -45,7 +45,7 @@ fn test_produce_snapshot() { ) .unwrap(); let mut runner = standalone::StandaloneRunner { - chain_id: 1313161554, + chain_id: 1_313_161_554, ..Default::default() }; runner @@ -79,9 +79,9 @@ fn test_produce_snapshot() { .unwrap(); // Computed snapshot should exactly the same keys from initial snapshot - for entry in snapshot.result.values.iter() { - let key = base64::decode(&entry.key).unwrap(); - let value = base64::decode(&entry.value).unwrap(); + for entry in &snapshot.result.values { + let key = aurora_engine_sdk::base64::decode(&entry.key).unwrap(); + let value = aurora_engine_sdk::base64::decode(&entry.value).unwrap(); assert_eq!(computed_snapshot.remove(&key).unwrap(), value); } assert!(computed_snapshot.is_empty()); @@ -94,12 +94,12 @@ fn test_produce_snapshot() { // New snapshot should still contain all keys from initial snapshot for entry in snapshot.result.values { - let key = base64::decode(entry.key).unwrap(); + let key = aurora_engine_sdk::base64::decode(entry.key).unwrap(); // skip the eth-connector keys; they were changed by minting the new account if key[0..3] == [7, 6, 1] { continue; } - let value = base64::decode(entry.value).unwrap(); + let value = aurora_engine_sdk::base64::decode(entry.value).unwrap(); assert_eq!(computed_snapshot.get(&key).unwrap(), &value); } diff --git a/engine-tests/src/tests/standalone/sanity.rs b/engine-tests/src/tests/standalone/sanity.rs index 26197c6a3..88fdb2a12 100644 --- a/engine-tests/src/tests/standalone/sanity.rs +++ b/engine-tests/src/tests/standalone/sanity.rs @@ -1,28 +1,28 @@ -use aurora_engine::engine; +use aurora_engine::{engine, state}; use aurora_engine_sdk::env::DEFAULT_PREPAID_GAS; use aurora_engine_test_doubles::io::{Storage, StoragePointer}; use aurora_engine_test_doubles::promise::PromiseTracker; use aurora_engine_types::types::{Address, Wei}; use aurora_engine_types::{account_id::AccountId, H160, H256, U256}; -use std::sync::RwLock; +use std::cell::RefCell; #[test] fn test_deploy_code() { let chain_id: [u8; 32] = { - let value = U256::from(1313161554); + let value = U256::from(1_313_161_554); let mut buf = [0u8; 32]; value.to_big_endian(&mut buf); buf }; let owner_id: AccountId = "aurora".parse().unwrap(); - let state = engine::EngineState { + let state = state::EngineState { chain_id, owner_id: owner_id.clone(), bridge_prover_id: "mr_the_prover".parse().unwrap(), upgrade_delay_blocks: 0, }; let origin = Address::new(H160([0u8; 20])); - let storage = RwLock::new(Storage::default()); + let storage = RefCell::new(Storage::default()); let io = StoragePointer(&storage); let env = aurora_engine_sdk::env::Fixed { signer_account_id: owner_id.clone(), @@ -54,7 +54,7 @@ fn test_deploy_code() { aurora_engine::parameters::TransactionStatus::Succeed(bytes) => { Address::try_from_slice(&bytes).unwrap() } - other => panic!("Unexpected status: {:?}", other), + other => panic!("Unexpected status: {other:?}"), }; // state is updated @@ -67,11 +67,8 @@ fn test_deploy_code() { } fn evm_deploy(code: &[u8]) -> Vec { - let len = code.len(); - if len > u16::MAX as usize { - panic!("Cannot deploy a contract with that many bytes!"); - } - let len = len as u16; + let len = u16::try_from(code.len()) + .unwrap_or_else(|_| panic!("Cannot deploy a contract with that many bytes!")); // This bit of EVM byte code essentially says: // "If msg.value > 0 revert; otherwise return `len` amount of bytes that come after me // in the code." By prepending this to `code` we create a valid EVM program which diff --git a/engine-tests/src/tests/standalone/storage.rs b/engine-tests/src/tests/standalone/storage.rs index be5de9d1d..993a9e9b5 100644 --- a/engine-tests/src/tests/standalone/storage.rs +++ b/engine-tests/src/tests/standalone/storage.rs @@ -10,6 +10,7 @@ use crate::test_utils::standalone::{mocks, storage::create_db}; use crate::test_utils::{self, Signer}; #[test] +#[allow(clippy::too_many_lines)] fn test_replay_transaction() { let mut signer = Signer::random(); let address = test_utils::address_from_secret_key(&signer.secret_key); @@ -85,7 +86,11 @@ fn test_replay_transaction() { .enumerate() .map(|(position, tx)| { let diff = runner - .execute_transaction_at_position(tx, block_height, position as u16) + .execute_transaction_at_position( + tx, + block_height, + u16::try_from(position).unwrap(), + ) .unwrap(); test_utils::standalone::storage::commit(&mut runner.storage, &diff); @@ -117,7 +122,7 @@ fn test_replay_transaction() { rand::seq::SliceRandom::shuffle(txs.as_mut_slice(), &mut rng); for ((position, tx), diff) in txs { let replay_diff = runner - .execute_transaction_at_position(tx, block_height, position as u16) + .execute_transaction_at_position(tx, block_height, u16::try_from(position).unwrap()) .unwrap() .diff; assert_eq!(replay_diff, diff); @@ -170,7 +175,7 @@ fn test_block_index() { // write block hash / height association storage - .set_block_data(block_hash, block_height, block_metadata.clone()) + .set_block_data(block_hash, block_height, &block_metadata.clone()) .unwrap(); // read it back assert_eq!( @@ -199,22 +204,22 @@ fn test_block_index() { let missing_block_hash = H256([32u8; 32]); match storage.get_block_hash_by_height(missing_block_height) { Err(engine_standalone_storage::Error::NoBlockAtHeight(h)) if h == missing_block_height => {} - other => panic!("Unexpected response: {:?}", other), + other => panic!("Unexpected response: {other:?}"), } match storage.get_block_height_by_hash(missing_block_hash) { Err(engine_standalone_storage::Error::BlockNotFound(h)) if h == missing_block_hash => (), // ok - other => panic!("Unexpected response: {:?}", other), + other => panic!("Unexpected response: {other:?}"), } match storage.get_block_metadata(missing_block_hash) { Err(engine_standalone_storage::Error::BlockNotFound(h)) if h == missing_block_hash => (), // ok - other => panic!("Unexpected response: {:?}", other), + other => panic!("Unexpected response: {other:?}"), } // insert later block let next_height = block_height + 1; let next_hash = H256([0xaa; 32]); storage - .set_block_data(next_hash, next_height, block_metadata.clone()) + .set_block_data(next_hash, next_height, &block_metadata.clone()) .unwrap(); // check earliest+latest blocks are still correct @@ -231,7 +236,7 @@ fn test_block_index() { let prev_height = block_height - 1; let prev_hash = H256([0xbb; 32]); storage - .set_block_data(prev_hash, prev_height, block_metadata) + .set_block_data(prev_hash, prev_height, &block_metadata) .unwrap(); // check earliest+latest blocks are still correct @@ -312,15 +317,15 @@ fn test_transaction_index() { match storage.get_transaction_data(missing_tx_hash) { Err(engine_standalone_storage::Error::TransactionHashNotFound(h)) if h == missing_tx_hash => {} - other => panic!("Unexpected response: {:?}", other), + other => panic!("Unexpected response: {other:?}"), } match storage.get_transaction_by_position(tx_not_included) { Err(engine_standalone_storage::Error::TransactionNotFound(x)) if x == tx_not_included => (), // ok - other => panic!("Unexpected response: {:?}", other), + other => panic!("Unexpected response: {other:?}"), } match storage.get_transaction_diff(tx_not_included) { Err(engine_standalone_storage::Error::TransactionNotFound(x)) if x == tx_not_included => (), // ok - other => panic!("Unexpected response: {:?}", other), + other => panic!("Unexpected response: {other:?}"), } drop(storage); @@ -362,8 +367,10 @@ fn test_track_key() { let trace = runner.storage.track_engine_key(&balance_key).unwrap(); let mut expected_balance = initial_balance; for (i, (block_height, tx_hash, value)) in trace.into_iter().enumerate() { - let i = i as u64; - assert_eq!(block_height, created_block_height + i); + assert_eq!( + block_height, + created_block_height + u64::try_from(i).unwrap() + ); let transaction_included = engine_standalone_storage::TransactionIncluded { block_hash: runner .storage diff --git a/engine-tests/src/tests/standalone/sync.rs b/engine-tests/src/tests/standalone/sync.rs index 1aa6d2b60..5b4b57744 100644 --- a/engine-tests/src/tests/standalone/sync.rs +++ b/engine-tests/src/tests/standalone/sync.rs @@ -33,7 +33,7 @@ fn test_consume_block_message() { block_message.metadata, ); - runner.close() + runner.close(); } #[test] @@ -63,7 +63,7 @@ fn test_consume_deposit_message() { .unwrap(); let outcome = match outcome { sync::ConsumeMessageOutcome::TransactionIncluded(outcome) => outcome, - other => panic!("Unexpected outcome {:?}", other), + other => panic!("Unexpected outcome {other:?}"), }; let finish_deposit_args = match outcome.maybe_result.unwrap().unwrap() { @@ -71,7 +71,7 @@ fn test_consume_deposit_message() { let bytes = promise_args.callback.args; aurora_engine::parameters::FinishDepositCallArgs::try_from_slice(&bytes).unwrap() } - other => panic!("Unexpected result {:?}", other), + other => panic!("Unexpected result {other:?}"), }; // Now executing aurora callbacks, so predecessor_account_id = current_account_id runner.env.predecessor_account_id = runner.env.current_account_id.clone(); @@ -95,18 +95,15 @@ fn test_consume_deposit_message() { .unwrap(); let outcome = match outcome { sync::ConsumeMessageOutcome::TransactionIncluded(outcome) => outcome, - other => panic!("Unexpected outcome {:?}", other), + other => panic!("Unexpected outcome {other:?}"), }; let ft_on_transfer_args = match outcome.maybe_result.unwrap().unwrap() { sync::TransactionExecutionResult::Promise(promise_args) => { let bytes = promise_args.base.args; - let json = aurora_engine::json::parse_json(&bytes).unwrap(); - aurora_engine::parameters::NEP141FtOnTransferArgs::try_from(json) - .ok() - .unwrap() + serde_json::from_slice(&bytes).unwrap() } - other => panic!("Unexpected result {:?}", other), + other => panic!("Unexpected result {other:?}"), }; let transaction_message = sync::types::TransactionMessage { @@ -129,7 +126,7 @@ fn test_consume_deposit_message() { assert_eq!(runner.get_balance(&recipient_address), deposit_amount); - runner.close() + runner.close(); } #[test] @@ -177,7 +174,7 @@ fn test_consume_deploy_message() { assert_eq!(runner.get_code(&deployed_address), code); - runner.close() + runner.close(); } #[test] diff --git a/engine-tests/src/tests/standalone/tracing.rs b/engine-tests/src/tests/standalone/tracing.rs index 163569947..24b209731 100644 --- a/engine-tests/src/tests/standalone/tracing.rs +++ b/engine-tests/src/tests/standalone/tracing.rs @@ -10,11 +10,11 @@ use crate::test_utils::{self, standalone}; /// This test replays two transactions from Ethereum mainnet (listed below) and checks we obtain /// the same gas usage and transaction trace as reported by etherscan. /// Transactions: -/// * https://etherscan.io/tx/0x79f7f8f9b3ad98f29a3df5cbed1556397089701c3ce007c2844605849dfb0ad4 -/// * https://etherscan.io/tx/0x33db52b0e7fa03cd84e8c99fea90a1962b4f8d0e63c8bbe4c11373a233dc4f0e +/// * `https://etherscan.io/tx/0x79f7f8f9b3ad98f29a3df5cbed1556397089701c3ce007c2844605849dfb0ad4` +/// * `https://etherscan.io/tx/0x33db52b0e7fa03cd84e8c99fea90a1962b4f8d0e63c8bbe4c11373a233dc4f0e` /// Traces: -/// * https://etherscan.io/vmtrace?txhash=0x79f7f8f9b3ad98f29a3df5cbed1556397089701c3ce007c2844605849dfb0ad4 -/// * https://etherscan.io/vmtrace?txhash=0x33db52b0e7fa03cd84e8c99fea90a1962b4f8d0e63c8bbe4c11373a233dc4f0e +/// * `https://etherscan.io/vmtrace?txhash=0x79f7f8f9b3ad98f29a3df5cbed1556397089701c3ce007c2844605849dfb0ad4` +/// * `https://etherscan.io/vmtrace?txhash=0x33db52b0e7fa03cd84e8c99fea90a1962b4f8d0e63c8bbe4c11373a233dc4f0e` #[test] fn test_evm_tracing_with_storage() { let mut runner = standalone::StandaloneRunner::default(); @@ -44,7 +44,7 @@ fn test_evm_tracing_with_storage() { new_key[2..22].copy_from_slice(weth_address.as_bytes()); match value { engine_standalone_storage::diff::DiffValue::Modified(bytes) => { - diff.modify(new_key, bytes.clone()) + diff.modify(new_key, bytes.clone()); } engine_standalone_storage::diff::DiffValue::Deleted => diff.delete(new_key), } @@ -59,7 +59,7 @@ fn test_evm_tracing_with_storage() { }; runner .storage - .set_block_data(block_hash, block_height, block_metadata) + .set_block_data(block_hash, block_height, &block_metadata) .unwrap(); let tx = engine_standalone_storage::sync::TransactionIncludedOutcome { hash: H256::zero(), @@ -98,7 +98,7 @@ fn test_evm_tracing_with_storage() { // Check trace check_transaction_trace( - listener.finish(), + &listener.finish(), "src/tests/res/79f7f8f9b3ad98f29a3df5cbed1556397089701c3ce007c2844605849dfb0ad4_trace.json", ); @@ -121,14 +121,14 @@ fn test_evm_tracing_with_storage() { // Check trace check_transaction_trace( - listener.finish(), + &listener.finish(), "src/tests/res/33db52b0e7fa03cd84e8c99fea90a1962b4f8d0e63c8bbe4c11373a233dc4f0e_trace.json", ); } /// Test based on expected trace of -/// https://rinkeby.etherscan.io/tx/0xfc9359e49278b7ba99f59edac0e3de49956e46e530a53c15aa71226b7aa92c6f -/// (geth example found at https://gist.github.com/karalabe/c91f95ac57f5e57f8b950ec65ecc697f). +/// `https://rinkeby.etherscan.io/tx/0xfc9359e49278b7ba99f59edac0e3de49956e46e530a53c15aa71226b7aa92c6f` +/// (geth example found at `https://gist.github.com/karalabe/c91f95ac57f5e57f8b950ec65ecc697f`). #[test] fn test_evm_tracing() { let mut runner = standalone::StandaloneRunner::default(); @@ -173,7 +173,7 @@ fn test_evm_tracing() { .logs() .0 .iter() - .map(|l| l.program_counter.into_u32() as u8) + .filter_map(|l| u8::try_from(l.program_counter.into_u32()).ok()) .collect(); assert_eq!(positions.as_slice(), &EXPECTED_POSITIONS); @@ -181,7 +181,7 @@ fn test_evm_tracing() { .logs() .0 .iter() - .map(|l| l.gas_cost.as_u64() as u32) + .filter_map(|l| u32::try_from(l.gas_cost.as_u64()).ok()) .collect(); assert_eq!(costs.as_slice(), &EXPECTED_COSTS); @@ -205,7 +205,7 @@ const EXPECTED_OP_CODES: [u8; 27] = [ 91, 91, 91, 0, ]; -fn check_transaction_trace>(trace: TransactionTrace, expected_trace_path: P) { +fn check_transaction_trace>(trace: &TransactionTrace, expected_trace_path: P) { let expected_trace: Vec = { let file = std::fs::File::open(expected_trace_path).unwrap(); let reader = std::io::BufReader::new(file); diff --git a/engine-tests/src/tests/state_migration.rs b/engine-tests/src/tests/state_migration.rs index e175e0fca..c1cc0ee5d 100644 --- a/engine-tests/src/tests/state_migration.rs +++ b/engine-tests/src/tests/state_migration.rs @@ -1,5 +1,6 @@ use crate::prelude::U256; use crate::test_utils::{self, str_to_account_id, AuroraRunner}; +use aurora_engine::fungible_token::FungibleTokenMetadata; use aurora_engine::parameters::{InitCallArgs, NewCallArgs}; use borsh::BorshSerialize; use near_sdk_sim::{ExecutionResult, UserAccount}; @@ -56,7 +57,7 @@ pub fn deploy_evm() -> AuroraAccount { let init_args = InitCallArgs { prover_account, eth_custodian_address: "d045f7e19B2488924B97F9c145b5E51D0D895A65".to_string(), - metadata: Default::default(), + metadata: FungibleTokenMetadata::default(), }; contract_account .call( diff --git a/engine-tests/src/tests/uniswap.rs b/engine-tests/src/tests/uniswap.rs index 7712f9ec5..c0d9ebc1d 100644 --- a/engine-tests/src/tests/uniswap.rs +++ b/engine-tests/src/tests/uniswap.rs @@ -53,8 +53,7 @@ fn test_uniswap_exact_output() { let wasm_fraction = 100 * profile.wasm_gas() / profile.all_gas(); assert!( (40..=50).contains(&wasm_fraction), - "{}% is not between 40% and 50%", - wasm_fraction + "{wasm_fraction}% is not between 40% and 50%", ); let (_amount_in, profile) = @@ -63,20 +62,19 @@ fn test_uniswap_exact_output() { let wasm_fraction = 100 * profile.wasm_gas() / profile.all_gas(); assert!( (45..=55).contains(&wasm_fraction), - "{}% is not between 45% and 55%", - wasm_fraction + "{wasm_fraction}% is not between 45% and 55%", ); } #[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub(crate) struct LiquidityResult { +pub struct LiquidityResult { pub token_id: U256, pub liquidity: U256, pub amount0: U256, pub amount1: U256, } -pub(crate) struct UniswapTestContext { +pub struct UniswapTestContext { pub factory: Factory, pub manager: PositionManager, pub swap_router: SwapRouter, @@ -88,7 +86,7 @@ pub(crate) struct UniswapTestContext { impl UniswapTestContext { pub fn new(name: &str) -> Self { let mut runner = test_utils::deploy_evm(); - let mut rng = rand::rngs::StdRng::seed_from_u64(414243); + let mut rng = rand::rngs::StdRng::seed_from_u64(414_243); let source_account = SecretKey::random(&mut rng); let source_address = test_utils::address_from_secret_key(&source_account); runner.create_address( @@ -154,8 +152,8 @@ impl UniswapTestContext { } pub fn create_tokens(&mut self, n: usize, mint_amount: U256) -> Vec { - let names = ('a'..='z').into_iter().map(|c| format!("token_{}", c)); - let symbols = ('A'..='Z').into_iter().map(|c| format!("{}{}{}", c, c, c)); + let names = ('a'..='z').into_iter().map(|c| format!("token_{c}")); + let symbols = ('A'..='Z').into_iter().map(|c| format!("{c}{c}{c}")); let mut result: Vec = names .zip(symbols) .take(n) @@ -236,7 +234,7 @@ impl UniswapTestContext { let manager = &self.manager; let (result, profile) = self .runner - .submit_with_signer_profiled(&mut self.signer, |nonce| manager.mint(params, nonce)) + .submit_with_signer_profiled(&mut self.signer, |nonce| manager.mint(¶ms, nonce)) .unwrap(); assert!(result.status.is_ok()); @@ -262,7 +260,7 @@ impl UniswapTestContext { (result, profile) } - pub fn exact_input_params(&self, amount_in: U256, token_path: &[ERC20]) -> ExactInputParams { + pub fn exact_input_params(amount_in: U256, token_path: &[ERC20]) -> ExactInputParams { let path = token_path .iter() .skip(1) @@ -287,12 +285,12 @@ impl UniswapTestContext { for token in token_path.iter() { self.approve_erc20(token, self.swap_router.0.address, U256::MAX); } - let params = self.exact_input_params(amount_in, token_path); + let params = Self::exact_input_params(amount_in, token_path); let swap_router = &self.swap_router; let (result, profile) = self .runner .submit_with_signer_profiled(&mut self.signer, |nonce| { - swap_router.exact_input(params, nonce) + swap_router.exact_input(¶ms, nonce) }) .unwrap(); assert!(result.status.is_ok(), "Swap failed"); @@ -303,7 +301,6 @@ impl UniswapTestContext { } pub fn exact_output_single_params( - &self, amount_out: U256, token_in: &ERC20, token_out: &ERC20, @@ -330,12 +327,12 @@ impl UniswapTestContext { self.approve_erc20(token_in, self.swap_router.0.address, U256::MAX); self.approve_erc20(token_out, self.swap_router.0.address, U256::MAX); - let params = self.exact_output_single_params(amount_out, token_in, token_out); + let params = Self::exact_output_single_params(amount_out, token_in, token_out); let swap_router = &self.swap_router; let (result, profile) = self .runner .submit_with_signer_profiled(&mut self.signer, |nonce| { - swap_router.exact_output_single(params, nonce) + swap_router.exact_output_single(¶ms, nonce) }) .unwrap(); assert!(result.status.is_ok(), "Swap failed"); diff --git a/engine-tests/src/tests/xcc.rs b/engine-tests/src/tests/xcc.rs index 814986a23..18b2d866e 100644 --- a/engine-tests/src/tests/xcc.rs +++ b/engine-tests/src/tests/xcc.rs @@ -1,5 +1,5 @@ use crate::test_utils::erc20::{ERC20Constructor, ERC20}; -use crate::test_utils::{self, AuroraRunner}; +use crate::test_utils::{self, AuroraRunner, ORIGIN}; use crate::tests::erc20_connector::sim_tests; use crate::tests::state_migration::{deploy_evm, AuroraAccount}; use aurora_engine_precompiles::xcc::{self, costs, cross_contract_call}; @@ -20,17 +20,19 @@ use std::fs; use std::path::Path; const WNEAR_AMOUNT: u128 = 10 * near_sdk_sim::STORAGE_AMOUNT; +const ONE_NEAR: u128 = 1_000_000_000_000_000_000_000_000; #[test] +#[allow(clippy::too_many_lines)] fn test_xcc_eth_gas_cost() { let mut runner = test_utils::deploy_evm(); runner.standalone_runner = None; let xcc_wasm_bytes = contract_bytes(); - let _ = runner.call("factory_update", "aurora", xcc_wasm_bytes); + let _res = runner.call("factory_update", ORIGIN, xcc_wasm_bytes); let mut signer = test_utils::Signer::random(); let mut baseline_signer = test_utils::Signer::random(); runner.context.block_index = aurora_engine::engine::ZERO_ADDRESS_FIX_HEIGHT + 1; - // Need to use engine's deploy! + // Need to use for engine's deployment! let wnear_erc20 = deploy_erc20(&mut runner, &mut signer); approve_erc20( &wnear_erc20, @@ -44,9 +46,9 @@ fn test_xcc_eth_gas_cost() { &mut runner, &mut signer, ); - let _ = runner.call( + let _res = runner.call( "factory_set_wnear_address", - "aurora", + ORIGIN, wnear_erc20.0.address.as_bytes().to_vec(), ); @@ -63,9 +65,10 @@ fn test_xcc_eth_gas_cost() { ) }) .unwrap(); - if !baseline_result.status.is_ok() { - panic!("Unexpected baseline status: {:?}", baseline_result); - } + assert!( + baseline_result.status.is_ok(), + "Unexpected baseline status: {baseline_result:?}", + ); let mut profile_for_promise = |p: PromiseArgs| -> (u64, u64, u64) { let data = CrossContractCallArgs::Eager(p).try_to_vec().unwrap(); @@ -156,14 +159,98 @@ fn test_xcc_eth_gas_cost() { ); } +#[test] +fn test_xcc_external_fund() { + // In this test we intentionally do not bridge wNEAR into the Engine. + // The purpose of the `fund_xcc_sub_account` functionality is to allow using + // the XCC feature in an Engine instance where there is no bridged wNEAR. + + // Set up Engine contract + let aurora = deploy_evm(); + let chain_id = AuroraRunner::default().chain_id; + let mut signer = test_utils::Signer::new(libsecp256k1::SecretKey::parse(&[0xab; 32]).unwrap()); + let signer_address = test_utils::address_from_secret_key(&signer.secret_key); + let xcc_wasm_bytes = contract_bytes(); + aurora + .user + .call( + aurora.contract.account_id(), + "factory_update", + &xcc_wasm_bytes, + near_sdk_sim::DEFAULT_GAS, + 0, + ) + .assert_success(); + let wnear_account = deploy_wnear(&aurora); + + // Fund XCC sub-account + let fund_amount = 5 * ONE_NEAR; + let fund_args = aurora_engine::xcc::FundXccArgs { + target: signer_address, + wnear_account_id: Some(wnear_account.account_id.as_str().parse().unwrap()), + }; + aurora + .user + .call( + aurora.contract.account_id(), + "fund_xcc_sub_account", + &fund_args.try_to_vec().unwrap(), + near_sdk_sim::DEFAULT_GAS, + fund_amount, + ) + .assert_success(); + + let sub_account_id = format!( + "{}.{}", + signer_address.encode(), + aurora.contract.account_id.as_str() + ); + let sub_account = aurora + .user + .borrow_runtime() + .view_account(&sub_account_id) + .unwrap(); + assert_eq!((fund_amount - sub_account.amount()) / ONE_NEAR, 0); + + // Do an XCC call. This XCC call is to the Aurora Engine itself to deploy an EVM contract, + // but that is just for this test. The call could be to any contract to do any action. + let expected_code = hex::decode("deadbeef").unwrap(); + let deploy_code = + test_utils::create_deploy_transaction(expected_code.clone(), U256::zero()).data; + let promise = PromiseCreateArgs { + target_account_id: aurora.contract.account_id.as_str().parse().unwrap(), + method: "deploy_code".into(), + args: deploy_code, + attached_balance: Yocto::new(0), + attached_gas: NearGas::new(10_000_000_000_000), + }; + let xcc_args = CrossContractCallArgs::Eager(PromiseArgs::Create(promise)); + let _result = submit_xcc_transaction(&xcc_args, &aurora, &mut signer, chain_id); + + // This is known because we are using a fixed private key for the signer + let deployed_address = Address::decode("bda6e7f87c816d25718c38b1c753e280f9455350").unwrap(); + let code = match aurora + .call("get_code", deployed_address.as_bytes()) + .status() + { + near_primitives::transaction::ExecutionStatus::SuccessValue(bytes) => bytes, + other => panic!("Unexpected status {other:?}"), + }; + + assert_eq!( + code, expected_code, + "Failed to properly deploy EVM code via XCC" + ); +} + #[test] fn test_xcc_precompile_eager() { - test_xcc_precompile_common(false) + test_xcc_precompile_common(false); } #[test] fn test_xcc_precompile_scheduled() { - test_xcc_precompile_common(true) + test_xcc_precompile_common(true); } /// This test uses the XCC feature where the promise has many nested callbacks. @@ -192,7 +279,7 @@ fn test_xcc_multiple_callbacks() { let n = 6; let promise = make_fib_promise(n, &fib_account_id); let xcc_args = CrossContractCallArgs::Delayed(PromiseArgs::Recursive(promise)); - let _result = submit_xcc_transaction(xcc_args, &aurora, &mut signer, chain_id); + let _result = submit_xcc_transaction(&xcc_args, &aurora, &mut signer, chain_id); // 3. Make Fibonacci call let router_account = format!( @@ -211,7 +298,7 @@ fn test_xcc_multiple_callbacks() { // 4. Check the result is correct let output = result.unwrap_json_value(); - check_fib_result(output, n); + check_fib_result(&output, n); } /// This test is similar to `test_xcc_multiple_callbacks`, but instead of computing @@ -257,7 +344,7 @@ fn test_xcc_and_combinator() { }), }; let xcc_args = CrossContractCallArgs::Delayed(PromiseArgs::Recursive(promise)); - let _result = submit_xcc_transaction(xcc_args, &aurora, &mut signer, chain_id); + let _result = submit_xcc_transaction(&xcc_args, &aurora, &mut signer, chain_id); // 3. Make Fibonacci call let router_account = format!( @@ -276,10 +363,10 @@ fn test_xcc_and_combinator() { // 4. Check the result is correct let output = result.unwrap_json_value(); - check_fib_result(output, usize::try_from(n).unwrap()); + check_fib_result(&output, usize::try_from(n).unwrap()); } -fn check_fib_result(output: serde_json::Value, n: usize) { +fn check_fib_result(output: &serde_json::Value, n: usize) { let fib_numbers: [u8; 8] = [0, 1, 1, 2, 3, 5, 8, 13]; let get_number = |field_name: &str| -> u8 { output @@ -298,6 +385,7 @@ fn check_fib_result(output: serde_json::Value, n: usize) { assert_eq!(b, fib_numbers[n + 1]); } +#[allow(clippy::too_many_lines)] fn test_xcc_precompile_common(is_scheduled: bool) { let XccTestContext { aurora, @@ -344,9 +432,9 @@ fn test_xcc_precompile_common(is_scheduled: bool) { // 3. Give router some tokens let transfer_amount: u128 = 199; - let args = serde_json::json!({ + let args = json!({ "receiver_id": router_account, - "amount": format!("{}", transfer_amount), + "amount": format!("{transfer_amount}"), }) .to_string(); ft_owner @@ -364,9 +452,9 @@ fn test_xcc_precompile_common(is_scheduled: bool) { ); // 4. Use xcc precompile to send those tokens back - let args = serde_json::json!({ + let args = json!({ "receiver_id": ft_owner.account_id.as_str(), - "amount": format!("{}", transfer_amount), + "amount": format!("{transfer_amount}"), }) .to_string(); let promise = PromiseCreateArgs { @@ -379,7 +467,7 @@ fn test_xcc_precompile_common(is_scheduled: bool) { let callback = PromiseCreateArgs { target_account_id: nep_141_token.account_id.as_str().parse().unwrap(), method: "ft_balance_of".into(), - args: format!("{{\"account_id\":\"{}\"}}", router_account).into_bytes(), + args: format!("{{\"account_id\":\"{router_account}\"}}").into_bytes(), attached_balance: Yocto::new(0), attached_gas: NearGas::new(2_000_000_000_000), }; @@ -393,7 +481,7 @@ fn test_xcc_precompile_common(is_scheduled: bool) { CrossContractCallArgs::Eager(promise_args) }; let engine_balance_before_xcc = get_engine_near_balance(&aurora); - let _result = submit_xcc_transaction(xcc_args, &aurora, &mut signer, chain_id); + let _result = submit_xcc_transaction(&xcc_args, &aurora, &mut signer, chain_id); print_outcomes(&aurora); let engine_balance_after_xcc = get_engine_near_balance(&aurora); @@ -402,9 +490,7 @@ fn test_xcc_precompile_common(is_scheduled: bool) { engine_balance_after_xcc.max(engine_balance_before_xcc) - engine_balance_after_xcc.min(engine_balance_before_xcc) < 10_000_000_000_000_000_000_000, - "Engine lost too much NEAR funding xcc: Before={:?} After={:?}", - engine_balance_before_xcc, - engine_balance_after_xcc, + "Engine lost too much NEAR funding xcc: Before={engine_balance_before_xcc} After={engine_balance_after_xcc}", ); let router_balance = aurora .user @@ -415,8 +501,7 @@ fn test_xcc_precompile_common(is_scheduled: bool) { assert!( // router loses less than 0.01 NEAR from its allocated funds xcc::state::STORAGE_AMOUNT.as_u128() - router_balance < 10_000_000_000_000_000_000_000, - "Router lost too much NEAR: Balance={:?}", - router_balance, + "Router lost too much NEAR: Balance={router_balance}", ); // Router has no wNEAR balance because it all was unwrapped to actual NEAR assert_eq!( @@ -526,7 +611,7 @@ struct XccTestContext { } fn submit_xcc_transaction( - xcc_args: CrossContractCallArgs, + xcc_args: &CrossContractCallArgs, aurora: &AuroraAccount, signer: &mut test_utils::Signer, chain_id: u64, @@ -549,10 +634,16 @@ fn submit_xcc_transaction( 0, ); result.assert_success(); - let submit_result: aurora_engine::parameters::SubmitResult = result.unwrap_borsh(); - if !submit_result.status.is_ok() { - panic!("Unexpected result {:?}", submit_result); - } + let submit_result = match result.status() { + near_primitives::transaction::ExecutionStatus::SuccessValue(bytes) => { + aurora_engine::parameters::SubmitResult::try_from_slice(&bytes).unwrap() + } + other => panic!("Unexpected status {other:?}"), + }; + assert!( + submit_result.status.is_ok(), + "Unexpected result: {submit_result:?}", + ); result } @@ -567,7 +658,7 @@ fn get_engine_near_balance(aurora: &AuroraAccount) -> u128 { fn print_outcomes(aurora: &AuroraAccount) { let rt = aurora.user.borrow_runtime(); - for id in rt.last_outcomes.iter() { + for id in &rt.last_outcomes { println!("{:?}=={:?}\n\n", id, rt.outcome(id).unwrap()); } } @@ -586,7 +677,7 @@ fn test_xcc_schedule_gas() { let (maybe_outcome, maybe_error) = router.call( "schedule", - "aurora", + ORIGIN, PromiseArgs::Create(promise).try_to_vec().unwrap(), ); assert!(maybe_error.is_none()); @@ -629,7 +720,7 @@ fn test_xcc_exec_gas() { let args = PromiseArgs::Recursive(x); let (maybe_outcome, maybe_error) = - router.call("execute", "aurora", args.try_to_vec().unwrap()); + router.call("execute", ORIGIN, args.try_to_vec().unwrap()); assert!(maybe_error.is_none()); let outcome = maybe_outcome.unwrap(); @@ -643,7 +734,10 @@ fn test_xcc_exec_gas() { router_exec_cost ); - assert_eq!(outcome.action_receipts.len(), args.promise_count() as usize); + assert_eq!( + outcome.action_receipts.len(), + usize::try_from(args.promise_count()).unwrap() + ); for (target_account_id, receipt) in outcome.action_receipts { assert_eq!( target_account_id.as_str(), @@ -658,7 +752,7 @@ fn test_xcc_exec_gas() { assert_eq!(function_call.deposit, promise.attached_balance.as_u128()); assert_eq!(function_call.gas, promise.attached_gas.as_u64()); } - other => panic!("Unexpected action {:?}", other), + other => panic!("Unexpected action {other:?}"), }; } } @@ -688,11 +782,11 @@ fn deploy_router() -> AuroraRunner { }; router.context.current_account_id = "some_address.aurora".parse().unwrap(); - router.context.predecessor_account_id = "aurora".parse().unwrap(); + router.context.predecessor_account_id = ORIGIN.parse().unwrap(); let init_args = r#"{"wnear_account": "wrap.near", "must_register": true}"#; let (maybe_outcome, maybe_error) = - router.call("initialize", "aurora", init_args.as_bytes().to_vec()); + router.call("initialize", ORIGIN, init_args.as_bytes().to_vec()); assert!(maybe_error.is_none()); let outcome = maybe_outcome.unwrap(); assert!(outcome.used_gas < aurora_engine::xcc::INITIALIZE_GAS.as_u64()); @@ -816,7 +910,7 @@ fn approve_erc20( assert!(approve_result.status.is_ok()); } -pub(crate) fn contract_bytes() -> Vec { +pub fn contract_bytes() -> Vec { let base_path = Path::new("../etc").join("xcc-router"); let output_path = base_path.join("target/wasm32-unknown-unknown/release/xcc_router.wasm"); test_utils::rust::compile(base_path); diff --git a/engine-transactions/.catalog-info.yaml b/engine-transactions/.catalog-info.yaml new file mode 100644 index 000000000..9433298c8 --- /dev/null +++ b/engine-transactions/.catalog-info.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: aurora-engine-standalone-tracing + description: |- + Aurora engine transactions testing library. + tags: + - near + links: [] + annotations: + aurora.dev/security-tier: "1" +spec: + owner: engine-team + type: contract-tests + lifecycle: production + system: aurora-engine + interactsWith: [] diff --git a/engine-transactions/Cargo.toml b/engine-transactions/Cargo.toml index 9a57b6d19..07aaefe73 100644 --- a/engine-transactions/Cargo.toml +++ b/engine-transactions/Cargo.toml @@ -16,9 +16,9 @@ autobenches = false aurora-engine-types = { path = "../engine-types", default-features = false } aurora-engine-sdk = { path = "../engine-sdk", default-features = false } aurora-engine-precompiles = { path = "../engine-precompiles", default-features = false } -evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.3-aurora", default-features = false } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false } rlp = { version = "0.5.0", default-features = false } -serde = { version = "1", features = ["derive"], optional = true } +serde = { version = "1", default-features = false, features = ["alloc", "derive"], optional = true } [dev-dependencies] hex = { version = "0.4", default-features = false, features = ["alloc"] } diff --git a/engine-transactions/src/backwards_compatibility.rs b/engine-transactions/src/backwards_compatibility.rs index 9ba17d6e5..002562cfc 100644 --- a/engine-transactions/src/backwards_compatibility.rs +++ b/engine-transactions/src/backwards_compatibility.rs @@ -1,7 +1,7 @@ //! Warning: this module _incorrectly_ parses RLP-serialized Ethereum transactions. //! This is intentional and needed for our "standalone engine" to be able to reproduce //! the Aurora state on the NEAR blockchain before the time a bug was fixed. See -//! https://github.com/aurora-is-near/aurora-engine/pull/458 for more details, but external +//! `https://github.com/aurora-is-near/aurora-engine/pull/458` for more details, but external //! users of this library should _never_ use the adapter in this module. use crate::{Error, EthTransactionKind}; @@ -18,6 +18,7 @@ pub struct EthTransactionKindAdapter { } impl EthTransactionKindAdapter { + #[must_use] pub const fn new(bug_fix_height: u64) -> Self { Self { bug_fix_height } } diff --git a/engine-transactions/src/eip_1559.rs b/engine-transactions/src/eip_1559.rs index 17a9d9732..8ed96bf7d 100644 --- a/engine-transactions/src/eip_1559.rs +++ b/engine-transactions/src/eip_1559.rs @@ -50,11 +50,11 @@ impl Transaction1559 { s.append(&self.value.raw()); s.append(&self.data); s.begin_list(self.access_list.len()); - for tuple in self.access_list.iter() { + for tuple in &self.access_list { s.begin_list(2); s.append(&tuple.address); s.begin_list(tuple.storage_keys.len()); - for key in tuple.storage_keys.iter() { + for key in &tuple.storage_keys { s.append(key); } } diff --git a/engine-transactions/src/eip_2930.rs b/engine-transactions/src/eip_2930.rs index 5e2be5707..2f89289bb 100644 --- a/engine-transactions/src/eip_2930.rs +++ b/engine-transactions/src/eip_2930.rs @@ -29,7 +29,7 @@ impl Decodable for AccessTuple { } } -/// See https://eips.ethereum.org/EIPS/eip-2930 +/// See `https://eips.ethereum.org/EIPS/eip-2930` #[derive(Debug, Eq, PartialEq, Clone)] pub struct Transaction2930 { pub chain_id: u64, @@ -66,11 +66,11 @@ impl Transaction2930 { s.append(&self.value.raw()); s.append(&self.data); s.begin_list(self.access_list.len()); - for tuple in self.access_list.iter() { + for tuple in &self.access_list { s.begin_list(2); s.append(&tuple.address); s.begin_list(tuple.storage_keys.len()); - for key in tuple.storage_keys.iter() { + for key in &tuple.storage_keys { s.append(key); } } diff --git a/engine-transactions/src/legacy.rs b/engine-transactions/src/legacy.rs index aa7056d4b..00d2e8585 100644 --- a/engine-transactions/src/legacy.rs +++ b/engine-transactions/src/legacy.rs @@ -40,8 +40,9 @@ impl TransactionLegacy { } } - /// Returns self.gas as a u64, or None if self.gas > u64::MAX + /// Returns self.gas as a u64, or None if self.gas > `u64::MAX` #[allow(unused)] + #[must_use] pub fn get_gas_limit(&self) -> Option { self.gas_limit.try_into().ok() } @@ -83,7 +84,8 @@ impl LegacyEthSignedTransaction { } /// Returns chain id encoded in `v` parameter of the signature if that was done, otherwise None. - pub fn chain_id(&self) -> Option { + #[must_use] + pub const fn chain_id(&self) -> Option { match self.v { 0..=34 => None, _ => Some((self.v - 35) / 2), @@ -166,12 +168,12 @@ mod tests { tx.transaction, TransactionLegacy { nonce: U256::zero(), - gas_price: U256::from(234567897654321u128), - gas_limit: U256::from(2000000u128), + gas_price: U256::from(234_567_897_654_321_u128), + gas_limit: U256::from(2_000_000u128), to: Some(address_from_arr( &hex::decode("F0109fC8DF283027b6285cc889F5aA624EaC1F55").unwrap() )), - value: Wei::new_u64(1000000000), + value: Wei::new_u64(1_000_000_000), data: vec![], } ); diff --git a/engine-transactions/src/lib.rs b/engine-transactions/src/lib.rs index 03d250cc5..3d27c2753 100644 --- a/engine-transactions/src/lib.rs +++ b/engine-transactions/src/lib.rs @@ -1,6 +1,11 @@ #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(not(feature = "std"), feature(alloc_error_handler))] -#![deny(clippy::as_conversions)] +#![deny(clippy::pedantic, clippy::nursery)] +#![allow( + clippy::similar_names, + clippy::module_name_repetitions, + clippy::missing_panics_doc, + clippy::missing_errors_doc +)] use aurora_engine_types::types::{Address, Wei}; use aurora_engine_types::{vec, Vec, H160, U256}; @@ -12,7 +17,7 @@ pub mod eip_1559; pub mod eip_2930; pub mod legacy; -/// Typed Transaction Envelope (see https://eips.ethereum.org/EIPS/eip-2718) +/// Typed Transaction Envelope (see `https://eips.ethereum.org/EIPS/eip-2718`) #[derive(Debug, Eq, PartialEq, Clone)] pub enum EthTransactionKind { Legacy(legacy::LegacyEthSignedTransaction), @@ -45,8 +50,8 @@ impl TryFrom<&[u8]> for EthTransactionKind { } } -impl<'a> From<&'a EthTransactionKind> for Vec { - fn from(tx: &'a EthTransactionKind) -> Self { +impl From<&EthTransactionKind> for Vec { + fn from(tx: &EthTransactionKind) -> Self { let mut stream = rlp::RlpStream::new(); match &tx { EthTransactionKind::Legacy(tx) => { @@ -84,7 +89,7 @@ impl TryFrom for NormalizedEthTransaction { type Error = Error; fn try_from(kind: EthTransactionKind) -> Result { - use EthTransactionKind::*; + use EthTransactionKind::{Eip1559, Eip2930, Legacy}; Ok(match kind { Legacy(tx) => Self { address: tx.sender()?, @@ -127,6 +132,7 @@ impl TryFrom for NormalizedEthTransaction { } impl NormalizedEthTransaction { + #[allow(clippy::naive_bytecount)] pub fn intrinsic_gas(&self, config: &evm::Config) -> Result { let is_contract_creation = self.to.is_none(); @@ -196,11 +202,12 @@ pub enum Error { #[cfg(feature = "serde")] fn decoder_err_to_str(err: &DecoderError, ser: S) -> Result { - ser.serialize_str(&format!("{:?}", err)) + ser.serialize_str(&format!("{err:?}")) } impl Error { - pub fn as_str(&self) -> &'static str { + #[must_use] + pub const fn as_str(&self) -> &str { match self { Self::UnknownTransactionType => "ERR_UNKNOWN_TX_TYPE", Self::EmptyInput => "ERR_EMPTY_TX_INPUT", diff --git a/engine-types/.catalog-info.yaml b/engine-types/.catalog-info.yaml new file mode 100644 index 000000000..7153d4c3a --- /dev/null +++ b/engine-types/.catalog-info.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: aurora-engine-types + description: |- + Shared Engine Types + tags: + - contract-library + - near + links: [] + annotations: + aurora.dev/security-tier: "1" +spec: + owner: engine-team + type: contract-library + lifecycle: production + system: aurora-engine + interactsWith: [] diff --git a/engine-types/Cargo.toml b/engine-types/Cargo.toml index aee2ca266..4cb5b4c47 100644 --- a/engine-types/Cargo.toml +++ b/engine-types/Cargo.toml @@ -13,15 +13,22 @@ publish = false autobenches = false [dependencies] -borsh = { version = "0.9.3", default-features = false } +borsh = { version = "0.10", default-features = false } +borsh-compat = { version = "0.9", package = "borsh", default-features = false, optional = true } hex = { version = "0.4", default-features = false, features = ["alloc"] } -primitive-types = { version = "0.12", default-features = false, features = ["rlp"] } -serde = { version = "1", features = ["derive"], optional = true } +primitive-types = { version = "0.12", default-features = false, features = ["rlp", "serde_no_std"] } +serde = { version = "1", default-features = false, features = ["alloc", "derive"] } +serde_json = { version = "1", default-features = false, features = ["alloc"] } [dev-dependencies] rand = "0.8.5" [features] default = ["std"] -std = ["borsh/std", "hex/std", "primitive-types/std"] -impl-serde = ["primitive-types/impl-serde", "serde"] +std = ["borsh/std", "hex/std", "primitive-types/std", "primitive-types/serde", "serde/std", "serde_json/std"] +# `primitive-types/std` is excluded because its `std` implementation includes a transitive +# dependency on `getrandom` which uses OS call to obtain entropy. Such calls are not +# available in Wasm, therefore we cannot use the `std` implementation of `primitive-types` +# in other Rust contracts. +contracts-std = ["borsh/std", "hex/std"] +impl-serde = ["primitive-types/impl-serde"] diff --git a/engine-types/src/account_id.rs b/engine-types/src/account_id.rs index 8b30388ce..1a884a34a 100644 --- a/engine-types/src/account_id.rs +++ b/engine-types/src/account_id.rs @@ -1,20 +1,33 @@ -//! Guarantees all properly constructed AccountId's are valid for the NEAR network. +//! Guarantees all properly constructed `AccountId`'s are valid for the NEAR network. //! -//! Inpired by: https://github.com/near/nearcore/tree/master/core/account-id +//! Inspired by: `https://github.com/near/nearcore/tree/master/core/account-id` -use crate::{fmt, str, str::FromStr, Box, String, Vec}; -use borsh::{BorshDeserialize, BorshSerialize}; +use crate::{fmt, str, str::FromStr, Box, String, ToString, Vec}; +#[cfg(not(feature = "borsh-compat"))] +use borsh::{maybestd::io, BorshDeserialize, BorshSerialize}; +#[cfg(feature = "borsh-compat")] +use borsh_compat::{self as borsh, maybestd::io, BorshDeserialize, BorshSerialize}; +use serde::{Deserialize, Serialize}; pub const MIN_ACCOUNT_ID_LEN: usize = 2; pub const MAX_ACCOUNT_ID_LEN: usize = 64; /// Account identifier. /// -/// This guarantees all properly constructed AccountId's are valid for the NEAR network. +/// This guarantees all properly constructed `AccountId`'s are valid for the NEAR network. #[derive( - BorshSerialize, BorshDeserialize, Default, Eq, Ord, Hash, Clone, Debug, PartialEq, PartialOrd, + Default, + BorshSerialize, + Serialize, + Deserialize, + Eq, + Ord, + Hash, + Clone, + Debug, + PartialEq, + PartialOrd, )] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AccountId(Box); impl AccountId { @@ -23,6 +36,7 @@ impl AccountId { Ok(Self(account_id.into())) } + #[must_use] pub fn as_bytes(&self) -> &[u8] { self.as_ref().as_bytes() } @@ -62,6 +76,7 @@ impl AccountId { } } + #[must_use] pub fn is_top_level_account_id(&self) -> bool { self.0.len() >= MIN_ACCOUNT_ID_LEN && self.0.len() <= MAX_ACCOUNT_ID_LEN @@ -69,8 +84,9 @@ impl AccountId { && !self.as_ref().contains('.') } - /// Returns true if the signer_id can create a direct sub-account with the given account Id. - pub fn is_sub_account_of(&self, parent_account_id: &AccountId) -> bool { + /// Returns true if the `signer_id` can create a direct sub-account with the given account Id. + #[must_use] + pub fn is_sub_account_of(&self, parent_account_id: &Self) -> bool { if parent_account_id.0.len() >= self.0.len() { return false; } @@ -82,11 +98,39 @@ impl AccountId { } } +#[cfg(not(feature = "borsh-compat"))] +impl BorshDeserialize for AccountId { + fn deserialize_reader(reader: &mut R) -> io::Result { + let account: String = BorshDeserialize::deserialize_reader(reader)?; + + // It's for saving backward compatibility. + if account.is_empty() { + return Ok(Self::default()); + } + + Self::new(&account).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string())) + } +} + +#[cfg(feature = "borsh-compat")] +impl BorshDeserialize for AccountId { + fn deserialize(buf: &mut &[u8]) -> io::Result { + let account: String = BorshDeserialize::deserialize(buf)?; + + // It's for saving backward compatibility. + if account.is_empty() { + return Ok(Self::default()); + } + + Self::new(&account).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string())) + } +} + impl TryFrom for AccountId { type Error = ParseAccountError; fn try_from(account_id: String) -> Result { - AccountId::new(&account_id) + Self::new(&account_id) } } @@ -95,7 +139,7 @@ impl TryFrom<&[u8]> for AccountId { fn try_from(account_id: &[u8]) -> Result { let account_id = str::from_utf8(account_id).map_err(|_| ParseAccountError::Invalid)?; - AccountId::new(account_id) + Self::new(account_id) } } @@ -103,7 +147,7 @@ impl TryFrom> for AccountId { type Error = ParseAccountError; fn try_from(account_id: Vec) -> Result { - AccountId::try_from(&account_id[..]) + Self::try_from(&account_id[..]) } } @@ -129,13 +173,13 @@ impl fmt::Display for AccountId { } impl From for Box { - fn from(value: AccountId) -> Box { + fn from(value: AccountId) -> Self { value.0 } } impl From for Vec { - fn from(account_id: AccountId) -> Vec { + fn from(account_id: AccountId) -> Self { account_id.as_bytes().to_vec() } } @@ -160,9 +204,9 @@ pub enum ParseAccountError { impl AsRef<[u8]> for ParseAccountError { fn as_ref(&self) -> &[u8] { match self { - ParseAccountError::TooLong => b"ERR_ACCOUNT_ID_TO_LONG", - ParseAccountError::TooShort => b"ERR_ACCOUNT_ID_TO_SHORT", - ParseAccountError::Invalid => b"ERR_ACCOUNT_ID_TO_INVALID", + Self::TooLong => b"ERR_ACCOUNT_ID_TO_LONG", + Self::TooShort => b"ERR_ACCOUNT_ID_TO_SHORT", + Self::Invalid => b"ERR_ACCOUNT_ID_TO_INVALID", } } } @@ -170,7 +214,7 @@ impl AsRef<[u8]> for ParseAccountError { impl fmt::Display for ParseAccountError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let msg = String::from_utf8(self.as_ref().to_vec()).unwrap(); - write!(f, "{}", msg) + write!(f, "{msg}") } } @@ -244,16 +288,17 @@ mod tests { #[test] fn test_is_valid_account_id() { - for account_id in OK_ACCOUNT_IDS.iter().cloned() { + for account_id in OK_ACCOUNT_IDS { if let Err(err) = AccountId::validate(account_id) { - panic!("Valid account id {:?} marked invalid: {}", account_id, err); + panic!("Valid account id {account_id:?} marked invalid: {err}"); } } - for account_id in BAD_ACCOUNT_IDS.iter().cloned() { - if AccountId::validate(account_id).is_ok() { - panic!("Valid account id {:?} marked valid", account_id); - } + for account_id in BAD_ACCOUNT_IDS { + assert!( + AccountId::validate(account_id).is_err(), + "Valid account id {account_id:?} marked valid" + ); } } @@ -280,8 +325,7 @@ mod tests { account_id .parse::() .map_or(false, |account_id| account_id.is_top_level_account_id()), - "Valid top level account id {:?} marked invalid", - account_id + "Valid top level account id {account_id:?} marked invalid", ); } @@ -327,8 +371,7 @@ mod tests { !account_id .parse::() .map_or(false, |account_id| account_id.is_top_level_account_id()), - "Invalid top level account id {:?} marked valid", - account_id + "Invalid top level account id {account_id:?} marked valid", ); } } @@ -352,9 +395,7 @@ mod tests { (signer_id.parse::(), sub_account_id.parse::()), (Ok(signer_id), Ok(sub_account_id)) if sub_account_id.is_sub_account_of(&signer_id) ), - "Failed to create sub-account {:?} by account {:?}", - sub_account_id, - signer_id + "Failed to create sub-account {sub_account_id:?} by account {signer_id:?}", ); } @@ -408,9 +449,7 @@ mod tests { (signer_id.parse::(), sub_account_id.parse::()), (Ok(signer_id), Ok(sub_account_id)) if sub_account_id.is_sub_account_of(&signer_id) ), - "Invalid sub-account {:?} created by account {:?}", - sub_account_id, - signer_id + "Invalid sub-account {sub_account_id:?} created by account {signer_id:?}", ); } } @@ -430,13 +469,11 @@ mod tests { valid_account_id.parse::(), Ok(account_id) if is_implicit(account_id.as_ref()) ), - "Account ID {} should be valid 64-len hex", - valid_account_id + "Account ID {valid_account_id} should be valid 64-len hex", ); assert!( is_implicit(valid_account_id), - "Account ID {} should be valid 64-len hex", - valid_account_id + "Account ID {valid_account_id} should be valid 64-len hex", ); } @@ -454,13 +491,11 @@ mod tests { invalid_account_id.parse::(), Ok(account_id) if is_implicit(account_id.as_ref()) ), - "Account ID {} should be invalid 64-len hex", - invalid_account_id + "Account ID {invalid_account_id} should be invalid 64-len hex", ); assert!( !is_implicit(invalid_account_id), - "Account ID {} should be invalid 64-len hex", - invalid_account_id + "Account ID {invalid_account_id} should be invalid 64-len hex", ); } } diff --git a/engine-types/src/lib.rs b/engine-types/src/lib.rs index da10bbe53..6f47cd984 100644 --- a/engine-types/src/lib.rs +++ b/engine-types/src/lib.rs @@ -1,7 +1,10 @@ -#![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(not(feature = "std"), feature(alloc_error_handler))] -#![cfg_attr(feature = "log", feature(panic_info_message))] -#![deny(clippy::as_conversions)] +#![cfg_attr(not(any(feature = "std", feature = "contracts-std")), no_std)] +#![deny(clippy::pedantic, clippy::nursery)] +#![allow( + clippy::missing_errors_doc, + clippy::missing_panics_doc, + clippy::module_name_repetitions +)] pub mod account_id; pub mod parameters; diff --git a/engine-types/src/parameters/engine.rs b/engine-types/src/parameters/engine.rs new file mode 100644 index 000000000..a600cd115 --- /dev/null +++ b/engine-types/src/parameters/engine.rs @@ -0,0 +1,229 @@ +use crate::{ + account_id::AccountId, + types::{Address, RawH256, RawU256, WeiU256}, + Vec, +}; +#[cfg(not(feature = "borsh-compat"))] +use borsh::{BorshDeserialize, BorshSerialize}; +#[cfg(feature = "borsh-compat")] +use borsh_compat::{self as borsh, BorshDeserialize, BorshSerialize}; + +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +#[cfg_attr(feature = "impl-serde", derive(serde::Serialize, serde::Deserialize))] +pub struct ResultLog { + pub address: Address, + pub topics: Vec, + pub data: Vec, +} + +/// The status of a transaction. +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] +#[cfg_attr(feature = "impl-serde", derive(serde::Serialize, serde::Deserialize))] +pub enum TransactionStatus { + Succeed(Vec), + Revert(Vec), + OutOfGas, + OutOfFund, + OutOfOffset, + CallTooDeep, +} + +impl TransactionStatus { + #[must_use] + pub const fn is_ok(&self) -> bool { + matches!(*self, Self::Succeed(_)) + } + + #[must_use] + pub const fn is_revert(&self) -> bool { + matches!(*self, Self::Revert(_)) + } + + #[must_use] + pub fn is_fail(&self) -> bool { + *self == Self::OutOfGas + || *self == Self::OutOfFund + || *self == Self::OutOfOffset + || *self == Self::CallTooDeep + } +} + +impl AsRef<[u8]> for TransactionStatus { + fn as_ref(&self) -> &[u8] { + match self { + Self::Succeed(_) => b"SUCCESS", + Self::Revert(_) => errors::ERR_REVERT, + Self::OutOfFund => errors::ERR_OUT_OF_FUNDS, + Self::OutOfGas => errors::ERR_OUT_OF_GAS, + Self::OutOfOffset => errors::ERR_OUT_OF_OFFSET, + Self::CallTooDeep => errors::ERR_CALL_TOO_DEEP, + } + } +} + +/// Borsh-encoded parameters for the `call`, `call_with_args`, `deploy_code`, +/// and `deploy_with_input` methods. +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +#[cfg_attr(feature = "impl-serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SubmitResult { + version: u8, + pub status: TransactionStatus, + pub gas_used: u64, + pub logs: Vec, +} + +impl SubmitResult { + /// Must be incremented when making breaking changes to the `SubmitResult` ABI. + /// The current value of 7 is chosen because previously a `TransactionStatus` object + /// was first in the serialization, which is an enum with less than 7 variants. + /// Therefore, no previous `SubmitResult` would have began with a leading 7 byte, + /// and this can be used to distinguish the new ABI (with version byte) from the old. + const VERSION: u8 = 7; + + #[must_use] + pub fn new(status: TransactionStatus, gas_used: u64, logs: Vec) -> Self { + Self { + version: Self::VERSION, + status, + gas_used, + logs, + } + } +} + +/// Borsh-encoded parameters for the engine `call` function. +#[derive(BorshSerialize, BorshDeserialize, Debug, PartialEq, Eq, Clone)] +pub struct FunctionCallArgsV2 { + pub contract: Address, + /// Wei compatible Borsh-encoded value field to attach an ETH balance to the transaction + pub value: WeiU256, + pub input: Vec, +} + +/// Legacy Borsh-encoded parameters for the engine `call` function, to provide backward type compatibility +#[derive(BorshSerialize, BorshDeserialize, Debug, PartialEq, Eq, Clone)] +pub struct FunctionCallArgsV1 { + pub contract: Address, + pub input: Vec, +} + +/// Deserialized values from bytes to current or legacy Borsh-encoded parameters +/// for passing to the engine `call` function, and to provide backward type compatibility +#[derive(BorshSerialize, BorshDeserialize, Debug, PartialEq, Eq, Clone)] +pub enum CallArgs { + V2(FunctionCallArgsV2), + V1(FunctionCallArgsV1), +} + +impl CallArgs { + #[must_use] + pub fn deserialize(bytes: &[u8]) -> Option { + Self::try_from_slice(bytes).map_or_else( + |_| { + FunctionCallArgsV1::try_from_slice(bytes) + .map_or(None, |value| Some(Self::V1(value))) + }, + Some, + ) + } +} + +/// Borsh-encoded parameters for the `view` function. +#[derive(BorshSerialize, BorshDeserialize, Debug, Eq, PartialEq)] +pub struct ViewCallArgs { + pub sender: Address, + pub address: Address, + pub amount: RawU256, + pub input: Vec, +} + +/// Borsh-encoded parameters for `deploy_erc20_token` function. +#[derive(BorshSerialize, BorshDeserialize, Debug, Eq, PartialEq, Clone)] +pub struct DeployErc20TokenArgs { + pub nep141: AccountId, +} + +/// Borsh-encoded parameters for `get_erc20_from_nep141` function. +pub type GetErc20FromNep141CallArgs = DeployErc20TokenArgs; + +/// Borsh-encoded parameters for the `get_storage_at` function. +#[derive(BorshSerialize, BorshDeserialize)] +pub struct GetStorageAtArgs { + pub address: Address, + pub key: RawH256, +} + +pub mod errors { + pub const ERR_REVERT: &[u8; 10] = b"ERR_REVERT"; + pub const ERR_OUT_OF_FUNDS: &[u8; 16] = b"ERR_OUT_OF_FUNDS"; + pub const ERR_CALL_TOO_DEEP: &[u8; 17] = b"ERR_CALL_TOO_DEEP"; + pub const ERR_OUT_OF_OFFSET: &[u8; 17] = b"ERR_OUT_OF_OFFSET"; + pub const ERR_OUT_OF_GAS: &[u8; 14] = b"ERR_OUT_OF_GAS"; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_view_call_fail() { + let bytes = [0; 71]; + let _args = ViewCallArgs::try_from_slice(&bytes).unwrap_err(); + } + + #[test] + fn test_roundtrip_view_call() { + let x = ViewCallArgs { + sender: Address::from_array([1; 20]), + address: Address::from_array([2; 20]), + amount: [3; 32], + input: vec![1, 2, 3], + }; + let bytes = x.try_to_vec().unwrap(); + let res = ViewCallArgs::try_from_slice(&bytes).unwrap(); + assert_eq!(x, res); + } + + #[test] + fn test_call_args_deserialize() { + let new_input = FunctionCallArgsV2 { + contract: Address::from_array([0u8; 20]), + value: WeiU256::default(), + input: Vec::new(), + }; + let legacy_input = FunctionCallArgsV1 { + contract: Address::from_array([0u8; 20]), + input: Vec::new(), + }; + + // Parsing bytes in a new input format - data structures (wrapped into call args enum) with new arguments, + // made for flexibility and extensibility. + + // Using new input format (wrapped into call args enum) and data structure with new argument (`value` field). + let input_bytes = CallArgs::V2(new_input.clone()).try_to_vec().unwrap(); + let parsed_data = CallArgs::deserialize(&input_bytes); + assert_eq!(parsed_data, Some(CallArgs::V2(new_input.clone()))); + + // Using new input format (wrapped into call args enum) and old data structure with legacy arguments, + // this is allowed for compatibility reason. + let input_bytes = CallArgs::V1(legacy_input.clone()).try_to_vec().unwrap(); + let parsed_data = CallArgs::deserialize(&input_bytes); + assert_eq!(parsed_data, Some(CallArgs::V1(legacy_input.clone()))); + + // Parsing bytes in an old input format - raw data structure (not wrapped into call args enum) with legacy arguments, + // made for backward compatibility. + + // Using old input format (not wrapped into call args enum) - raw data structure with legacy arguments. + let input_bytes = legacy_input.try_to_vec().unwrap(); + let parsed_data = CallArgs::deserialize(&input_bytes); + assert_eq!(parsed_data, Some(CallArgs::V1(legacy_input))); + + // Using old input format (not wrapped into call args enum) - raw data structure with new argument (`value` field). + // Data structures with new arguments allowed only in new input format for future extensibility reason. + // Raw data structure (old input format) allowed only with legacy arguments for backward compatibility reason. + // Unrecognized input should be handled and result as an exception in a call site. + let input_bytes = new_input.try_to_vec().unwrap(); + let parsed_data = CallArgs::deserialize(&input_bytes); + assert_eq!(parsed_data, None); + } +} diff --git a/engine-types/src/parameters.rs b/engine-types/src/parameters/mod.rs similarity index 83% rename from engine-types/src/parameters.rs rename to engine-types/src/parameters/mod.rs index 5cd6c9eb4..65521c6b1 100644 --- a/engine-types/src/parameters.rs +++ b/engine-types/src/parameters/mod.rs @@ -1,8 +1,14 @@ -use crate::account_id::*; -use crate::types::*; -use crate::*; -use borsh::maybestd::io; -use borsh::{BorshDeserialize, BorshSerialize}; +use crate::{ + account_id::AccountId, + types::{Address, NEP141Wei, NearGas, RawU256, Yocto}, + Box, String, Vec, +}; +#[cfg(not(feature = "borsh-compat"))] +use borsh::{maybestd::io, BorshDeserialize, BorshSerialize}; +#[cfg(feature = "borsh-compat")] +use borsh_compat::{self as borsh, maybestd::io, BorshDeserialize, BorshSerialize}; + +pub mod engine; #[must_use] #[derive(Debug, BorshSerialize, BorshDeserialize)] @@ -14,6 +20,7 @@ pub enum PromiseArgs { impl PromiseArgs { /// Counts the total number of promises this call creates (including callbacks). + #[must_use] pub fn promise_count(&self) -> u64 { match self { Self::Create(_) => 1, @@ -22,6 +29,7 @@ impl PromiseArgs { } } + #[must_use] pub fn total_gas(&self) -> NearGas { match self { Self::Create(call) => call.attached_gas, @@ -30,6 +38,7 @@ impl PromiseArgs { } } + #[must_use] pub fn total_near(&self) -> Yocto { match self { Self::Create(call) => call.attached_balance, @@ -46,6 +55,7 @@ pub enum SimpleNearPromise { } impl SimpleNearPromise { + #[must_use] pub fn total_gas(&self) -> NearGas { match self { Self::Create(call) => call.attached_gas, @@ -66,6 +76,7 @@ impl SimpleNearPromise { } } + #[must_use] pub fn total_near(&self) -> Yocto { match self { Self::Create(call) => call.attached_balance, @@ -100,6 +111,7 @@ pub enum NearPromise { } impl NearPromise { + #[must_use] pub fn promise_count(&self) -> u64 { match self { Self::Simple(_) => 1, @@ -108,6 +120,7 @@ impl NearPromise { } } + #[must_use] pub fn total_gas(&self) -> NearGas { match self { Self::Simple(x) => x.total_gas(), @@ -119,6 +132,7 @@ impl NearPromise { } } + #[must_use] pub fn total_near(&self) -> Yocto { match self { Self::Simple(x) => x.total_near(), @@ -152,6 +166,40 @@ impl BorshSerialize for NearPromise { } } +#[cfg(not(feature = "borsh-compat"))] +impl BorshDeserialize for NearPromise { + fn deserialize_reader(reader: &mut R) -> io::Result { + let variant_byte = { + let mut buf = [0u8; 1]; + reader.read_exact(&mut buf)?; + buf[0] + }; + match variant_byte { + 0x00 => { + let inner = SimpleNearPromise::deserialize_reader(reader)?; + Ok(Self::Simple(inner)) + } + 0x01 => { + let base = Self::deserialize_reader(reader)?; + let callback = SimpleNearPromise::deserialize_reader(reader)?; + Ok(Self::Then { + base: Box::new(base), + callback, + }) + } + 0x02 => { + let promises: Vec = Vec::deserialize_reader(reader)?; + Ok(Self::And(promises)) + } + _ => Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Invalid variant byte for NearPromise", + )), + } + } +} + +#[cfg(feature = "borsh-compat")] impl BorshDeserialize for NearPromise { fn deserialize(buf: &mut &[u8]) -> io::Result { let variant_byte = buf[0]; @@ -268,7 +316,7 @@ pub struct RefundCallArgs { /// Args passed to the the cross contract call precompile. /// That precompile is used by Aurora contracts to make calls to the broader NEAR ecosystem. -/// See https://github.com/aurora-is-near/AIPs/pull/2 for design details. +/// See `https://github.com/aurora-is-near/AIPs/pull/2` for design details. #[derive(Debug, BorshSerialize, BorshDeserialize)] pub enum CrossContractCallArgs { /// The promise is to be executed immediately (as part of the same NEAR transaction as the EVM call). diff --git a/engine-types/src/storage.rs b/engine-types/src/storage.rs index e1b1be281..3df7adf1d 100644 --- a/engine-types/src/storage.rs +++ b/engine-types/src/storage.rs @@ -1,6 +1,8 @@ -use crate::types::Address; -use crate::*; +use crate::{types::Address, Vec, H256}; +#[cfg(not(feature = "borsh-compat"))] use borsh::{BorshDeserialize, BorshSerialize}; +#[cfg(feature = "borsh-compat")] +use borsh_compat::{self as borsh, BorshDeserialize, BorshSerialize}; // NOTE: We start at 0x7 as our initial value as our original storage was not // version prefixed and ended as 0x6. @@ -34,19 +36,18 @@ pub enum KeyPrefix { impl From for u8 { fn from(k: KeyPrefix) -> Self { - use KeyPrefix::*; match k { - Config => 0x0, - Nonce => 0x1, - Balance => 0x2, - Code => 0x3, - Storage => 0x4, - RelayerEvmAddressMap => 0x5, - EthConnector => 0x6, - Generation => 0x7, - Nep141Erc20Map => 0x8, - Erc20Nep141Map => 0x9, - CrossContractCall => 0xa, + KeyPrefix::Config => 0x0, + KeyPrefix::Nonce => 0x1, + KeyPrefix::Balance => 0x2, + KeyPrefix::Code => 0x3, + KeyPrefix::Storage => 0x4, + KeyPrefix::RelayerEvmAddressMap => 0x5, + KeyPrefix::EthConnector => 0x6, + KeyPrefix::Generation => 0x7, + KeyPrefix::Nep141Erc20Map => 0x8, + KeyPrefix::Erc20Nep141Map => 0x9, + KeyPrefix::CrossContractCall => 0xa, } } } @@ -64,14 +65,13 @@ pub enum EthConnectorStorageId { impl From for u8 { fn from(id: EthConnectorStorageId) -> Self { - use EthConnectorStorageId::*; match id { - Contract => 0x0, - FungibleToken => 0x1, - UsedEvent => 0x2, - PausedMask => 0x3, - StatisticsAuroraAccountsCounter => 0x4, - FungibleTokenMetadata => 0x5, + EthConnectorStorageId::Contract => 0x0, + EthConnectorStorageId::FungibleToken => 0x1, + EthConnectorStorageId::UsedEvent => 0x2, + EthConnectorStorageId::PausedMask => 0x3, + EthConnectorStorageId::StatisticsAuroraAccountsCounter => 0x4, + EthConnectorStorageId::FungibleTokenMetadata => 0x5, } } } @@ -100,11 +100,13 @@ impl From for KeyPrefix { } #[allow(dead_code)] +#[must_use] pub fn bytes_to_key(prefix: KeyPrefix, bytes: &[u8]) -> Vec { [&[u8::from(VersionPrefix::V1)], &[u8::from(prefix)], bytes].concat() } #[allow(dead_code)] +#[must_use] pub fn address_to_key(prefix: KeyPrefix, address: &Address) -> [u8; 22] { let mut result = [0u8; 22]; result[0] = u8::from(VersionPrefix::V1); @@ -120,14 +122,14 @@ pub enum StorageKeyKind { impl AsRef<[u8]> for StorageKeyKind { fn as_ref(&self) -> &[u8] { - use StorageKeyKind::*; match &self { - Normal(v) => v, - Generation(v) => v, + Self::Normal(v) => v, + Self::Generation(v) => v, } } } +#[must_use] pub fn storage_to_key(address: &Address, key: &H256, generation: u32) -> StorageKeyKind { if generation == 0 { StorageKeyKind::Normal(normal_storage_key(address, key)) diff --git a/engine-types/src/types/address.rs b/engine-types/src/types/address.rs index 13be5223d..dfa7ce54f 100755 --- a/engine-types/src/types/address.rs +++ b/engine-types/src/types/address.rs @@ -1,40 +1,44 @@ use crate::{format, String, H160}; -use borsh::maybestd::io; -use borsh::{BorshDeserialize, BorshSerialize}; -#[cfg(feature = "serde")] +#[cfg(not(feature = "borsh-compat"))] +use borsh::{maybestd::io, BorshDeserialize, BorshSerialize}; +#[cfg(feature = "borsh-compat")] +use borsh_compat::{maybestd::io, BorshDeserialize, BorshSerialize}; use serde::{Deserialize, Serialize}; /// Base Eth Address type -#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)] pub struct Address(H160); impl Address { /// Construct Address from H160 + #[must_use] pub const fn new(val: H160) -> Self { Self(val) } /// Get raw H160 data - pub fn raw(&self) -> H160 { + #[must_use] + pub const fn raw(&self) -> H160 { self.0 } /// Encode address to string + #[must_use] pub fn encode(&self) -> String { hex::encode(self.0.as_bytes()) } - pub fn decode(address: &str) -> Result { + pub fn decode(address: &str) -> Result { if address.len() != 40 { return Err(error::AddressError::IncorrectLength); } let mut result = [0u8; 20]; hex::decode_to_slice(address, &mut result) .map_err(|_| error::AddressError::FailedDecodeHex)?; - Ok(Address::new(H160(result))) + Ok(Self::new(H160(result))) } + #[must_use] pub fn as_bytes(&self) -> &[u8] { self.0.as_bytes() } @@ -46,12 +50,14 @@ impl Address { Ok(Self::new(H160::from_slice(raw_addr))) } + #[must_use] pub const fn from_array(array: [u8; 20]) -> Self { Self(H160(array)) } + #[must_use] pub const fn zero() -> Self { - Address::new(H160([0u8; 20])) + Self::new(H160([0u8; 20])) } } @@ -69,6 +75,24 @@ impl BorshSerialize for Address { } } +#[cfg(not(feature = "borsh-compat"))] +impl BorshDeserialize for Address { + fn deserialize_reader(reader: &mut R) -> io::Result { + let mut buf = [0u8; 20]; + let maybe_read = reader.read_exact(&mut buf); + if maybe_read.as_ref().err().map(io::Error::kind) == Some(io::ErrorKind::UnexpectedEof) { + return Err(io::Error::new( + io::ErrorKind::Other, + format!("{}", error::AddressError::IncorrectLength), + )); + } + maybe_read?; + let address = Self(H160(buf)); + Ok(address) + } +} + +#[cfg(feature = "borsh-compat")] impl BorshDeserialize for Address { fn deserialize(buf: &mut &[u8]) -> io::Result { if buf.len() < 20 { @@ -86,7 +110,7 @@ impl BorshDeserialize for Address { impl Default for Address { fn default() -> Self { - Address::zero() + Self::zero() } } @@ -168,7 +192,7 @@ pub mod error { impl fmt::Display for AddressError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let msg = String::from_utf8(self.as_ref().to_vec()).unwrap(); - write!(f, "{}", msg) + write!(f, "{msg}") } } } diff --git a/engine-types/src/types/balance.rs b/engine-types/src/types/balance.rs index 92c985f1c..4a37b10c0 100644 --- a/engine-types/src/types/balance.rs +++ b/engine-types/src/types/balance.rs @@ -1,6 +1,10 @@ use crate::fmt::Formatter; -use crate::{Add, Display, Sub}; +use crate::{format, Add, Display, Sub, ToString}; +#[cfg(not(feature = "borsh-compat"))] use borsh::{BorshDeserialize, BorshSerialize}; +#[cfg(feature = "borsh-compat")] +use borsh_compat::{self as borsh, BorshDeserialize, BorshSerialize}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; pub const ZERO_BALANCE: Balance = Balance::new(0); pub const ZERO_YOCTO: Yocto = Yocto::new(0); @@ -22,21 +26,62 @@ impl Display for Balance { impl Balance { /// Constructs a new `Balance` with a given u128 value. - pub const fn new(amount: u128) -> Balance { + #[must_use] + pub const fn new(amount: u128) -> Self { Self(amount) } /// Consumes `Balance` and returns the underlying type. - pub fn as_u128(self) -> u128 { + #[must_use] + pub const fn as_u128(self) -> u128 { self.0 } } +impl Serialize for Balance { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let value = self.0.to_string(); + serializer.serialize_str(&value) + } +} + +impl<'de> Deserialize<'de> for Balance { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + D::Error: serde::de::Error, + { + use serde::de::Error; + + let value = serde_json::Value::deserialize(deserializer)?; + Ok(Self( + value + .as_str() + .ok_or_else(|| Error::custom(format!("Wait for a string but got: {value}"))) + .and_then(|value| value.parse().map_err(Error::custom))?, + )) + } +} + #[derive( - Default, BorshSerialize, BorshDeserialize, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, + Default, + BorshSerialize, + BorshDeserialize, + Serialize, + Deserialize, + Debug, + Clone, + Copy, + Eq, + PartialEq, + Ord, + PartialOrd, )] /// Near Yocto type which wraps an underlying u128. -/// 1 NEAR = 10^24 yoctoNEAR +/// 1 NEAR = 10^24 `yoctoNEAR` pub struct Yocto(u128); impl Display for Yocto { @@ -47,17 +92,19 @@ impl Display for Yocto { impl Yocto { /// Constructs a new `Yocto NEAR` with a given u128 value. - pub const fn new(yocto: u128) -> Yocto { + #[must_use] + pub const fn new(yocto: u128) -> Self { Self(yocto) } /// Consumes `Yocto NEAR` and returns the underlying type. - pub fn as_u128(self) -> u128 { + #[must_use] + pub const fn as_u128(self) -> u128 { self.0 } } -impl Add for Yocto { +impl Add for Yocto { type Output = Self; fn add(self, rhs: Self) -> Self::Output { @@ -65,7 +112,7 @@ impl Add for Yocto { } } -impl Sub for Yocto { +impl Sub for Yocto { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { @@ -88,7 +135,39 @@ pub mod error { impl fmt::Display for BalanceOverflowError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let msg = String::from_utf8(self.as_ref().to_vec()).unwrap(); - write!(f, "{}", msg) + write!(f, "{msg}") } } } + +#[cfg(test)] +mod tests { + use super::Balance; + use serde::{Deserialize, Serialize}; + + #[derive(Deserialize, Serialize)] + struct SomeStruct { + balance: Balance, + } + + #[test] + fn test_deserialize_balance() { + let json = r#"{"balance": "340282366920938463463374607431768211455"}"#; + let result: SomeStruct = serde_json::from_str(json).unwrap(); + assert_eq!(result.balance, Balance::new(u128::MAX)); + + let json = r#"{"balance": "340282366920938463463374607431768211456"}"#; // Overflow + let result = serde_json::from_str::(json); + assert!(result.is_err()); + } + + #[test] + fn test_serialize_balance() { + let json = r#"{"balance":"340282366920938463463374607431768211455"}"#; + let result = SomeStruct { + balance: Balance::new(340_282_366_920_938_463_463_374_607_431_768_211_455), + }; + + assert_eq!(&serde_json::to_string(&result).unwrap(), json); + } +} diff --git a/engine-types/src/types/fee.rs b/engine-types/src/types/fee.rs index 1de4e3816..b372c8007 100644 --- a/engine-types/src/types/fee.rs +++ b/engine-types/src/types/fee.rs @@ -1,7 +1,10 @@ use crate::fmt::Formatter; use crate::types::NEP141Wei; use crate::{Add, Display}; +#[cfg(not(feature = "borsh-compat"))] use borsh::{BorshDeserialize, BorshSerialize}; +#[cfg(feature = "borsh-compat")] +use borsh_compat::{self as borsh, BorshDeserialize, BorshSerialize}; #[derive( Default, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, BorshSerialize, BorshDeserialize, @@ -17,21 +20,23 @@ impl Display for Fee { impl Fee { /// Constructs a new `Fee` with a given u128 value. - pub const fn new(fee: NEP141Wei) -> Fee { + #[must_use] + pub const fn new(fee: NEP141Wei) -> Self { Self(fee) } /// Consumes `Fee` and returns the underlying type. - pub fn as_u128(self) -> u128 { + #[must_use] + pub const fn as_u128(self) -> u128 { self.0.as_u128() } } -impl Add for Fee { - type Output = Fee; +impl Add for Fee { + type Output = Self; - fn add(self, rhs: Fee) -> Self::Output { - Fee(self.0 + rhs.0) + fn add(self, rhs: Self) -> Self::Output { + Self(self.0 + rhs.0) } } diff --git a/engine-types/src/types/gas.rs b/engine-types/src/types/gas.rs index 0232b776d..f3e121deb 100644 --- a/engine-types/src/types/gas.rs +++ b/engine-types/src/types/gas.rs @@ -1,7 +1,10 @@ use crate::fmt::Formatter; use crate::{Add, AddAssign, Display, Div, Mul, Sub}; +#[cfg(not(feature = "borsh-compat"))] use borsh::{BorshDeserialize, BorshSerialize}; -#[cfg(feature = "serde")] +#[cfg(feature = "borsh-compat")] +use borsh_compat::{self as borsh, BorshDeserialize, BorshSerialize}; +use core::num::NonZeroU64; use serde::{Deserialize, Serialize}; #[derive( @@ -16,36 +19,37 @@ impl Display for NearGas { } } -impl Sub for NearGas { - type Output = NearGas; +impl Sub for NearGas { + type Output = Self; - fn sub(self, rhs: NearGas) -> Self::Output { + fn sub(self, rhs: Self) -> Self::Output { Self(self.0 - rhs.0) } } -impl Add for NearGas { - type Output = NearGas; +impl Add for NearGas { + type Output = Self; - fn add(self, rhs: NearGas) -> Self::Output { + fn add(self, rhs: Self) -> Self::Output { Self(self.0 + rhs.0) } } impl NearGas { /// Constructs a new `NearGas` with a given u64 value. - pub const fn new(gas: u64) -> NearGas { + #[must_use] + pub const fn new(gas: u64) -> Self { Self(gas) } /// Consumes `NearGas` and returns the underlying type. - pub fn as_u64(self) -> u64 { + #[must_use] + pub const fn as_u64(self) -> u64 { self.0 } } -#[derive(Default, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[derive(Default, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)] /// Ethereum gas type which wraps an underlying u64. pub struct EthGas(u64); @@ -57,35 +61,49 @@ impl Display for EthGas { impl EthGas { /// Constructs a new `EthGas` with a given u64 value. - pub const fn new(gas: u64) -> EthGas { + #[must_use] + pub const fn new(gas: u64) -> Self { Self(gas) } /// Consumes `EthGas` and returns the underlying type. - pub fn as_u64(self) -> u64 { + #[must_use] + pub const fn as_u64(self) -> u64 { self.0 } + + pub fn checked_sub(self, rhs: Self) -> Option { + self.0.checked_sub(rhs.0).map(Self) + } + + pub fn checked_add(self, rhs: Self) -> Option { + self.0.checked_add(rhs.0).map(Self) + } + + pub fn checked_mul(self, rhs: Self) -> Option { + self.0.checked_mul(rhs.0).map(Self) + } } -impl Add for EthGas { - type Output = EthGas; +impl Add for EthGas { + type Output = Self; - fn add(self, rhs: EthGas) -> Self::Output { - EthGas(self.0 + rhs.0) + fn add(self, rhs: Self) -> Self::Output { + Self(self.0 + rhs.0) } } -impl AddAssign for EthGas { - fn add_assign(&mut self, rhs: EthGas) { - self.0 += rhs.0 +impl AddAssign for EthGas { + fn add_assign(&mut self, rhs: Self) { + self.0 += rhs.0; } } -impl Div for EthGas { - type Output = EthGas; +impl Div for EthGas { + type Output = Self; - fn div(self, rhs: u64) -> Self::Output { - EthGas(self.0 / rhs) + fn div(self, rhs: NonZeroU64) -> Self::Output { + Self(self.0 / rhs) } } @@ -98,18 +116,18 @@ impl Mul for u32 { } impl Mul for EthGas { - type Output = EthGas; + type Output = Self; fn mul(self, rhs: u32) -> Self::Output { - EthGas(self.0 * u64::from(rhs)) + Self(self.0 * u64::from(rhs)) } } impl Mul for EthGas { - type Output = EthGas; + type Output = Self; fn mul(self, rhs: u64) -> Self::Output { - EthGas(self.0 * rhs) + Self(self.0 * rhs) } } diff --git a/engine-types/src/types/mod.rs b/engine-types/src/types/mod.rs index 82e666199..abfc2816f 100644 --- a/engine-types/src/types/mod.rs +++ b/engine-types/src/types/mod.rs @@ -1,5 +1,8 @@ use crate::{str, vec, String, Vec, U256}; +#[cfg(not(feature = "borsh-compat"))] use borsh::{BorshDeserialize, BorshSerialize}; +#[cfg(feature = "borsh-compat")] +use borsh_compat::{self as borsh, BorshDeserialize, BorshSerialize}; pub mod address; pub mod balance; @@ -21,7 +24,7 @@ pub type StorageUsage = u64; /// Selector to call mint function in ERC 20 contract /// -/// keccak("mint(address,uint256)".as_bytes())[..4]; +/// `keccak("mint(address,uint256)".as_bytes())[..4];` #[allow(dead_code)] pub const ERC20_MINT_SELECTOR: &[u8] = &[64, 193, 15, 25]; @@ -71,6 +74,7 @@ pub enum PromiseResult { } impl PromiseResult { + #[must_use] pub fn size(&self) -> usize { match self { Self::Failed | Self::NotReady => 1, @@ -79,7 +83,7 @@ impl PromiseResult { } } -/// ft_resolve_transfer result of eth-connector +/// `ft_resolve_transfer` result of eth-connector pub struct FtResolveTransferResult { pub amount: Balance, pub refund_amount: Balance, @@ -88,6 +92,7 @@ pub struct FtResolveTransferResult { const HEX_ALPHABET: &[u8; 16] = b"0123456789abcdef"; #[allow(dead_code)] +#[must_use] pub fn bytes_to_hex(v: &[u8]) -> String { let mut result = String::new(); for x in v { @@ -104,6 +109,7 @@ pub struct Stack { } impl Stack { + #[must_use] pub fn new() -> Self { Self { stack: Vec::new(), @@ -128,11 +134,14 @@ impl Stack { self.stack.push(value); } + #[must_use] + #[allow(clippy::missing_const_for_fn)] pub fn into_vec(self) -> Vec { self.stack } } +#[must_use] pub fn str_from_slice(inp: &[u8]) -> &str { str::from_utf8(inp).unwrap() } @@ -154,8 +163,8 @@ mod tests { let mut res = vec![]; let mut pnt = 0; - for &pos in stack.boundaries.iter() { - while pnt < pos { + for pos in &stack.boundaries { + while pnt < *pos { res.push(Some(stack.stack[pnt])); pnt += 1; } @@ -170,7 +179,7 @@ mod tests { res } - fn check_stack(stack: &Stack, expected: Vec>) { + fn check_stack(stack: &Stack, expected: &[Option]) { if let Some(&last) = stack.boundaries.last() { assert!(last <= stack.stack.len()); } @@ -180,48 +189,45 @@ mod tests { #[test] fn test_stack() { let mut stack = Stack::new(); // [ $ ] - check_stack(&stack, vec![None]); + check_stack(&stack, &[None]); stack.push(1); // [ $, 1] - check_stack(&stack, vec![None, Some(1)]); + check_stack(&stack, &[None, Some(1)]); stack.push(2); // [ $, 1, 2 ] - check_stack(&stack, vec![None, Some(1), Some(2)]); + check_stack(&stack, &[None, Some(1), Some(2)]); stack.enter(); // [$, 1, 2, $] - check_stack(&stack, vec![None, Some(1), Some(2), None]); + check_stack(&stack, &[None, Some(1), Some(2), None]); stack.push(3); // [$, 1, 2, $, 3] - check_stack(&stack, vec![None, Some(1), Some(2), None, Some(3)]); + check_stack(&stack, &[None, Some(1), Some(2), None, Some(3)]); stack.discard(); // [$, 1, 2] - check_stack(&stack, vec![None, Some(1), Some(2)]); + check_stack(&stack, &[None, Some(1), Some(2)]); stack.enter(); - check_stack(&stack, vec![None, Some(1), Some(2), None]); + check_stack(&stack, &[None, Some(1), Some(2), None]); stack.push(4); // [$, 1, 2, $, 4] - check_stack(&stack, vec![None, Some(1), Some(2), None, Some(4)]); + check_stack(&stack, &[None, Some(1), Some(2), None, Some(4)]); stack.enter(); // [$, 1, 2, $, 4, $] - check_stack(&stack, vec![None, Some(1), Some(2), None, Some(4), None]); + check_stack(&stack, &[None, Some(1), Some(2), None, Some(4), None]); stack.push(5); // [$, 1, 2, $, 4, $, 5] check_stack( &stack, - vec![None, Some(1), Some(2), None, Some(4), None, Some(5)], + &[None, Some(1), Some(2), None, Some(4), None, Some(5)], ); stack.commit(); // [$, 1, 2, $, 4, 5] - check_stack(&stack, vec![None, Some(1), Some(2), None, Some(4), Some(5)]); + check_stack(&stack, &[None, Some(1), Some(2), None, Some(4), Some(5)]); stack.discard(); // [$, 1, 2] - check_stack(&stack, vec![None, Some(1), Some(2)]); + check_stack(&stack, &[None, Some(1), Some(2)]); stack.push(6); // [$, 1, 2, 6] - check_stack(&stack, vec![None, Some(1), Some(2), Some(6)]); + check_stack(&stack, &[None, Some(1), Some(2), Some(6)]); stack.enter(); // [$, 1, 2, 6, $] - check_stack(&stack, vec![None, Some(1), Some(2), Some(6), None]); + check_stack(&stack, &[None, Some(1), Some(2), Some(6), None]); stack.enter(); // [$, 1, 2, 6, $, $] - check_stack(&stack, vec![None, Some(1), Some(2), Some(6), None, None]); + check_stack(&stack, &[None, Some(1), Some(2), Some(6), None, None]); stack.enter(); // [$, 1, 2, 6, $, $, $] - check_stack( - &stack, - vec![None, Some(1), Some(2), Some(6), None, None, None], - ); + check_stack(&stack, &[None, Some(1), Some(2), Some(6), None, None, None]); stack.commit(); // [$, 1, 2, 6, $, $] - check_stack(&stack, vec![None, Some(1), Some(2), Some(6), None, None]); + check_stack(&stack, &[None, Some(1), Some(2), Some(6), None, None]); stack.discard(); // [$, 1, 2, 6, $] - check_stack(&stack, vec![None, Some(1), Some(2), Some(6), None]); + check_stack(&stack, &[None, Some(1), Some(2), Some(6), None]); stack.push(7); // [$, 1, 2, 6, $, 7] assert_eq!(stack.into_vec(), vec![1, 2, 6, 7]); diff --git a/engine-types/src/types/wei.rs b/engine-types/src/types/wei.rs index ea50a18b9..4baefa5d4 100644 --- a/engine-types/src/types/wei.rs +++ b/engine-types/src/types/wei.rs @@ -1,10 +1,12 @@ use crate::fmt::Formatter; use crate::types::balance::error; use crate::types::Fee; -use crate::{Add, Display, Sub, SubAssign, U256}; +use crate::{format, Add, Display, Sub, SubAssign, ToString, U256}; +#[cfg(not(feature = "borsh-compat"))] use borsh::{BorshDeserialize, BorshSerialize}; -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; +#[cfg(feature = "borsh-compat")] +use borsh_compat::{self as borsh, BorshDeserialize, BorshSerialize}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; pub const ZERO_NEP141_WEI: NEP141Wei = NEP141Wei::new(0); pub const ZERO_WEI: Wei = Wei::new_u64(0); @@ -16,9 +18,36 @@ pub type WeiU256 = [u8; 32]; #[derive( Default, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, BorshSerialize, BorshDeserialize, )] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct NEP141Wei(u128); +impl Serialize for NEP141Wei { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let value = self.0.to_string(); + serializer.serialize_str(&value) + } +} + +impl<'de> Deserialize<'de> for NEP141Wei { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + D::Error: serde::de::Error, + { + use serde::de::Error; + + let value = serde_json::Value::deserialize(deserializer)?; + Ok(Self( + value + .as_str() + .ok_or_else(|| Error::custom(format!("Wait for a string but got: {value}"))) + .and_then(|value| value.parse().map_err(Error::custom))?, + )) + } +} + impl Display for NEP141Wei { fn fmt(&self, f: &mut Formatter<'_>) -> crate::fmt::Result { self.0.fmt(f) @@ -27,6 +56,7 @@ impl Display for NEP141Wei { impl NEP141Wei { /// Constructs a new `NEP141Wei` with a given u128 value. + #[must_use] pub const fn new(amount: u128) -> Self { Self(amount) } @@ -40,12 +70,13 @@ impl NEP141Wei { } /// Consumes `NEP141Wei` and returns the underlying type. - pub fn as_u128(self) -> u128 { + #[must_use] + pub const fn as_u128(self) -> u128 { self.0 } } -impl Sub for NEP141Wei { +impl Sub for NEP141Wei { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { @@ -53,7 +84,7 @@ impl Sub for NEP141Wei { } } -impl Add for NEP141Wei { +impl Add for NEP141Wei { type Output = Self; fn add(self, rhs: Self) -> Self::Output { @@ -61,24 +92,25 @@ impl Add for NEP141Wei { } } -impl SubAssign for NEP141Wei { +impl SubAssign for NEP141Wei { fn sub_assign(&mut self, rhs: Self) { *self = *self - rhs; } } -/// Newtype to distinguish balances (denominated in Wei) from other U256 types. -#[derive(Default, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +/// New type to distinguish balances (denominated in Wei) from other U256 types. +#[derive(Default, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)] pub struct Wei(U256); impl Wei { const ETH_TO_WEI: U256 = U256([1_000_000_000_000_000_000, 0, 0, 0]); + #[must_use] pub const fn zero() -> Self { Self(U256([0, 0, 0, 0])) } + #[must_use] pub const fn new(amount: U256) -> Self { Self(amount) } @@ -88,23 +120,34 @@ impl Wei { // `amount.into()` without thinking too hard about the units. Explicitly writing // `Wei` reminds the developer to think about whether the amount they enter is really // in units of `Wei` or not. + #[must_use] pub const fn new_u64(amount: u64) -> Self { Self(U256([amount, 0, 0, 0])) } + #[must_use] + pub fn new_u128(amount: u128) -> Self { + Self::new(U256::from(amount)) + } + + #[must_use] pub fn from_eth(amount: U256) -> Option { amount.checked_mul(Self::ETH_TO_WEI).map(Self) } + #[must_use] pub fn to_bytes(self) -> [u8; 32] { u256_to_arr(&self.0) } + #[must_use] + #[allow(clippy::missing_const_for_fn)] // older version of primitive-types has non-const `is_zero()` pub fn is_zero(&self) -> bool { self.0.is_zero() } - pub fn raw(self) -> U256 { + #[must_use] + pub const fn raw(self) -> U256 { self.0 } @@ -129,16 +172,16 @@ impl Display for Wei { } } -impl Add for Wei { - type Output = Wei; +impl Add for Wei { + type Output = Self; fn add(self, rhs: Self) -> Self::Output { Self(self.0 + rhs.0) } } -impl Sub for Wei { - type Output = Wei; +impl Sub for Wei { + type Output = Self; fn sub(self, rhs: Self) -> Self::Output { Self(self.0 - rhs.0) @@ -148,23 +191,24 @@ impl Sub for Wei { /// Type casting from Wei compatible Borsh-encoded raw value into the Wei value, to attach an ETH balance to the transaction impl From for Wei { fn from(value: WeiU256) -> Self { - Wei(U256::from_big_endian(&value)) + Self(U256::from_big_endian(&value)) } } impl From for Wei { fn from(value: Fee) -> Self { - Wei(U256::from(value.as_u128())) + Self(U256::from(value.as_u128())) } } impl From for Wei { fn from(value: NEP141Wei) -> Self { - Wei(U256::from(value.as_u128())) + Self(U256::from(value.as_u128())) } } #[allow(dead_code)] +#[must_use] pub fn u256_to_arr(value: &U256) -> [u8; 32] { let mut result = [0u8; 32]; value.to_big_endian(&mut result); diff --git a/engine/Cargo.toml b/engine/Cargo.toml index 15c8922fd..45cc25d2f 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aurora-engine" -version = "2.8.1" +version = "2.9.0" authors = ["Aurora Labs "] edition = "2021" description = "" @@ -20,30 +20,27 @@ aurora-engine-types = { path = "../engine-types", default-features = false } aurora-engine-sdk = { path = "../engine-sdk", default-features = false } aurora-engine-precompiles = { path = "../engine-precompiles", default-features = false } aurora-engine-transactions = { path = "../engine-transactions", default-features = false } -base64 = { version = "0.13.0", default-features = false, features = ["alloc"] } bitflags = { version = "1.3", default-features = false } -borsh = { version = "0.9.3", default-features = false } +borsh = { version = "0.10", default-features = false } byte-slice-cast = { version = "1.0", default-features = false } ethabi = { version = "18.0", default-features = false } -evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.3-aurora", default-features = false } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false } hex = { version = "0.4", default-features = false, features = ["alloc"] } -rjson = { git = "https://github.com/aurora-is-near/rjson", rev = "cc3da949", default-features = false, features = ["integer"] } rlp = { version = "0.5.0", default-features = false } -serde = { version = "1", features = ["derive"], optional = true } +serde = { version = "1", default-features = false, features = ["alloc", "derive"] } +serde_json = { version = "1", default-features = false, features = ["alloc"] } [target.'cfg(target_arch = "wasm32")'.dependencies] wee_alloc = { version = "0.4.5", default-features = false } [dev-dependencies] aurora-engine-test-doubles = { path = "../engine-test-doubles" } -serde_json = "1" test-case = "2.1" -sha3 = "0.10" digest = "0.10" [features] default = ["std"] -std = ["aurora-engine-types/std", "aurora-engine-sdk/std", "aurora-engine-precompiles/std", "aurora-engine-transactions/std", "base64/std", "borsh/std", "byte-slice-cast/std", "ethabi/std", "evm/std", "hex/std", "rjson/std", "rlp/std"] +std = ["aurora-engine-types/std", "aurora-engine-sdk/std", "aurora-engine-precompiles/std", "aurora-engine-transactions/std", "borsh/std", "byte-slice-cast/std", "ethabi/std", "evm/std", "hex/std", "rlp/std", "serde/std", "serde_json/std"] contract = ["aurora-engine-sdk/contract", "aurora-engine-precompiles/contract"] evm_bully = [] log = ["aurora-engine-sdk/log", "aurora-engine-precompiles/log"] @@ -53,4 +50,4 @@ integration-test = ["log"] all-promise-actions = ["aurora-engine-sdk/all-promise-actions"] mainnet = ["contract", "log", "aurora-engine-sdk/mainnet"] testnet = ["contract", "log", "aurora-engine-sdk/testnet"] -impl-serde = ["aurora-engine-types/impl-serde", "serde", "aurora-engine-transactions/impl-serde", "evm/with-serde"] +impl-serde = ["aurora-engine-types/impl-serde", "aurora-engine-transactions/impl-serde", "evm/with-serde"] diff --git a/engine/src/accounting.rs b/engine/src/accounting.rs index 5cfa3a9a7..2a53baaaf 100644 --- a/engine/src/accounting.rs +++ b/engine/src/accounting.rs @@ -30,6 +30,7 @@ impl Accounting { self.lost = self.lost.saturating_add(amount); } + #[must_use] pub fn net(&self) -> Net { match self.gained.cmp(&self.lost) { Ordering::Equal => Net::Zero, diff --git a/engine/src/admin_controlled.rs b/engine/src/admin_controlled.rs index 8121c0005..99f4aa214 100644 --- a/engine/src/admin_controlled.rs +++ b/engine/src/admin_controlled.rs @@ -43,7 +43,7 @@ mod tests { } impl MockAdminControlled { - pub fn new() -> Self { + pub const fn new() -> Self { Self { mask: 0 } } } @@ -54,7 +54,7 @@ mod tests { } fn set_paused(&mut self, paused: PausedMask) { - self.mask = paused + self.mask = paused; } } diff --git a/engine/src/connector.rs b/engine/src/connector.rs index 60bcc141d..c4f9b3b32 100644 --- a/engine/src/connector.rs +++ b/engine/src/connector.rs @@ -40,7 +40,7 @@ pub const PAUSE_WITHDRAW: PausedMask = 1 << 1; /// Contains: /// * connector specific data /// * Fungible token data -/// * paused_mask - admin control flow data +/// * `paused_mask` - admin control flow data /// * io - I/O trait handler pub struct EthConnectorContract { contract: EthConnector, @@ -64,10 +64,10 @@ impl EthConnectorContract { /// Used as single point of contract access for various contract actions pub fn init_instance(io: I) -> Result { Ok(Self { - contract: get_contract_data(&io, &EthConnectorStorageId::Contract)?, - ft: get_contract_data::(&io, &EthConnectorStorageId::FungibleToken)? + contract: get_contract_data(&io, EthConnectorStorageId::Contract)?, + ft: get_contract_data::(&io, EthConnectorStorageId::FungibleToken)? .ops(io), - paused_mask: get_contract_data(&io, &EthConnectorStorageId::PausedMask)?, + paused_mask: get_contract_data(&io, EthConnectorStorageId::PausedMask)?, io, }) } @@ -77,12 +77,12 @@ impl EthConnectorContract { /// Initialized contract data stored in the storage. pub fn create_contract( mut io: I, - owner_id: AccountId, + owner_id: &AccountId, args: InitCallArgs, ) -> Result<(), error::InitContractError> { // Check is it already initialized let contract_key_exists = - io.storage_has_key(&construct_contract_key(&EthConnectorStorageId::Contract)); + io.storage_has_key(&construct_contract_key(EthConnectorStorageId::Contract)); if contract_key_exists { return Err(error::InitContractError::AlreadyInitialized); } @@ -101,11 +101,11 @@ impl EthConnectorContract { let mut ft = FungibleTokenOps::new(io); // Register FT account for current contract - ft.internal_register_account(&owner_id); + ft.internal_register_account(owner_id); let paused_mask = UNPAUSE_ALL; io.write_borsh( - &construct_contract_key(&EthConnectorStorageId::PausedMask), + &construct_contract_key(EthConnectorStorageId::PausedMask), &paused_mask, ); @@ -257,7 +257,7 @@ impl EthConnectorContract { // Mint tokens to recipient minus fee if let Some(msg) = data.msg { // Mint - calculate new balances - self.mint_eth_on_near(data.new_owner_id, data.amount)?; + self.mint_eth_on_near(&data.new_owner_id, data.amount)?; // Store proof only after `mint` calculations self.record_proof(&data.proof_key)?; // Save new contract data @@ -273,10 +273,10 @@ impl EthConnectorContract { } else { // Mint - calculate new balances self.mint_eth_on_near( - data.new_owner_id.clone(), + &data.new_owner_id.clone(), data.amount - NEP141Wei::new(data.fee.as_u128()), )?; - self.mint_eth_on_near(data.relayer_id, NEP141Wei::new(data.fee.as_u128()))?; + self.mint_eth_on_near(&data.relayer_id, NEP141Wei::new(data.fee.as_u128()))?; // Store proof only after `mint` calculations self.record_proof(&data.proof_key)?; // Save new contract data @@ -307,18 +307,18 @@ impl EthConnectorContract { Ok(()) } - /// Mint nETH tokens + /// Mint `nETH` tokens fn mint_eth_on_near( &mut self, - owner_id: AccountId, + owner_id: &AccountId, amount: NEP141Wei, ) -> Result<(), fungible_token::error::DepositError> { sdk::log!("Mint {} nETH tokens for: {}", amount, owner_id); - if self.ft.get_account_eth_balance(&owner_id).is_none() { - self.ft.accounts_insert(&owner_id, ZERO_NEP141_WEI); + if self.ft.get_account_eth_balance(owner_id).is_none() { + self.ft.accounts_insert(owner_id, ZERO_NEP141_WEI); } - self.ft.internal_deposit_eth_to_near(&owner_id, amount) + self.ft.internal_deposit_eth_to_near(owner_id, amount) } /// Mint ETH tokens @@ -339,13 +339,13 @@ impl EthConnectorContract { self.ft.internal_withdraw_eth_from_aurora(amount) } - /// Withdraw nETH from NEAR accounts + /// Withdraw `nETH` from NEAR accounts /// NOTE: it should be without any log data pub fn withdraw_eth_from_near( &mut self, current_account_id: &AccountId, predecessor_account_id: &AccountId, - args: WithdrawCallArgs, + args: &WithdrawCallArgs, ) -> Result { // Check is current account id is owner let is_owner = current_account_id == predecessor_account_id; @@ -366,12 +366,12 @@ impl EthConnectorContract { }) } - /// Returns total ETH supply on NEAR (nETH as NEP-141 token) + /// Returns total ETH supply on NEAR (`nETH` as NEP-141 token) pub fn ft_total_eth_supply_on_near(&mut self) { let total_supply = self.ft.ft_total_eth_supply_on_near(); sdk::log!("Total ETH supply on NEAR: {}", total_supply); self.io - .return_output(format!("\"{}\"", total_supply).as_bytes()); + .return_output(format!("\"{total_supply}\"").as_bytes()); } /// Returns total ETH supply on Aurora (ETH in Aurora EVM) @@ -379,27 +379,27 @@ impl EthConnectorContract { let total_supply = self.ft.ft_total_eth_supply_on_aurora(); sdk::log!("Total ETH supply on Aurora: {}", total_supply); self.io - .return_output(format!("\"{}\"", total_supply).as_bytes()); + .return_output(format!("\"{total_supply}\"").as_bytes()); } - /// Return balance of nETH (ETH on Near) - pub fn ft_balance_of(&mut self, args: BalanceOfCallArgs) { + /// Return balance of `nETH` (ETH on Near) + pub fn ft_balance_of(&mut self, args: &BalanceOfCallArgs) { let balance = self.ft.ft_balance_of(&args.account_id); sdk::log!("Balance of nETH [{}]: {}", args.account_id, balance); - self.io.return_output(format!("\"{}\"", balance).as_bytes()); + self.io.return_output(format!("\"{balance}\"").as_bytes()); } /// Return balance of ETH (ETH in Aurora EVM) pub fn ft_balance_of_eth_on_aurora( &mut self, - args: BalanceOfEthCallArgs, + args: &BalanceOfEthCallArgs, ) -> Result<(), crate::prelude::types::balance::error::BalanceOverflowError> { let balance = self .ft .internal_unwrap_balance_of_eth_on_aurora(&args.address); sdk::log!("Balance of ETH [{}]: {}", args.address.encode(), balance); - self.io.return_output(format!("\"{}\"", balance).as_bytes()); + self.io.return_output(format!("\"{balance}\"").as_bytes()); Ok(()) } @@ -407,7 +407,7 @@ impl EthConnectorContract { pub fn ft_transfer( &mut self, predecessor_account_id: &AccountId, - args: TransferCallArgs, + args: &TransferCallArgs, ) -> Result<(), fungible_token::error::TransferError> { self.ft.internal_transfer_eth_on_near( predecessor_account_id, @@ -428,7 +428,7 @@ impl EthConnectorContract { /// FT resolve transfer logic pub fn ft_resolve_transfer( &mut self, - args: ResolveTransferCallArgs, + args: &ResolveTransferCallArgs, promise_result: PromiseResult, ) { let amount = self.ft.ft_resolve_transfer( @@ -444,7 +444,7 @@ impl EthConnectorContract { ); // `ft_resolve_transfer` can change `total_supply` so we should save the contract self.save_ft_contract(); - self.io.return_output(format!("\"{}\"", amount).as_bytes()); + self.io.return_output(format!("\"{amount}\"").as_bytes()); } /// FT transfer call from sender account (invoker account) to receiver @@ -558,7 +558,7 @@ impl EthConnectorContract { pub fn storage_withdraw( &mut self, account_id: &AccountId, - args: StorageWithdrawCallArgs, + args: &StorageWithdrawCallArgs, ) -> Result<(), fungible_token::error::StorageFundingError> { let res = self.ft.storage_withdraw(account_id, args.amount)?; self.save_ft_contract(); @@ -567,15 +567,15 @@ impl EthConnectorContract { } /// Get balance of storage - pub fn storage_balance_of(&mut self, args: StorageBalanceOfCallArgs) { + pub fn storage_balance_of(&mut self, args: &StorageBalanceOfCallArgs) { self.io .return_output(&self.ft.storage_balance_of(&args.account_id).to_json_bytes()); } - /// ft_on_transfer callback function - pub fn ft_on_transfer<'env, E: Env>( + /// `ft_on_transfer` callback function + pub fn ft_on_transfer( &mut self, - engine: &Engine<'env, I, E>, + engine: &Engine, args: &NEP141FtOnTransferArgs, ) -> Result<(), error::FtTransferCallError> { sdk::log!("Call ft_on_transfer"); @@ -589,10 +589,10 @@ impl EthConnectorContract { let relayer = engine.get_relayer(message_data.relayer.as_bytes()); match (wei_fee, relayer) { (fee, Some(evm_relayer_address)) if fee > ZERO_WEI => { - self.mint_eth_on_aurora( - message_data.recipient, - Wei::new(U256::from(args.amount.as_u128())) - fee, - )?; + let eth_amount = Wei::new_u128(args.amount.as_u128()) + .checked_sub(fee) + .ok_or(error::FtTransferCallError::InsufficientAmountForFee)?; + self.mint_eth_on_aurora(message_data.recipient, eth_amount)?; self.mint_eth_on_aurora(evm_relayer_address, fee)?; } _ => self.mint_eth_on_aurora( @@ -601,7 +601,7 @@ impl EthConnectorContract { )?, } self.save_ft_contract(); - self.io.return_output("\"0\"".as_bytes()); + self.io.return_output(b"\"0\""); Ok(()) } @@ -612,37 +612,37 @@ impl EthConnectorContract { .return_output(&self.ft.get_accounts_counter().to_le_bytes()); } - pub fn get_bridge_prover(&self) -> &AccountId { + pub const fn get_bridge_prover(&self) -> &AccountId { &self.contract.prover_account } /// Save eth-connector fungible token contract data fn save_ft_contract(&mut self) { self.io.write_borsh( - &construct_contract_key(&EthConnectorStorageId::FungibleToken), + &construct_contract_key(EthConnectorStorageId::FungibleToken), &self.ft.data(), ); } /// Generate key for used events from Proof - fn used_event_key(&self, key: &str) -> Vec { - let mut v = construct_contract_key(&EthConnectorStorageId::UsedEvent).to_vec(); + fn used_event_key(key: &str) -> Vec { + let mut v = construct_contract_key(EthConnectorStorageId::UsedEvent); v.extend_from_slice(key.as_bytes()); v } /// Save already used event proof as hash key fn save_used_event(&mut self, key: &str) { - self.io.write_borsh(&self.used_event_key(key), &0u8); + self.io.write_borsh(&Self::used_event_key(key), &0u8); } /// Check is event of proof already used fn is_used_event(&self, key: &str) -> bool { - self.io.storage_has_key(&self.used_event_key(key)) + self.io.storage_has_key(&Self::used_event_key(key)) } /// Checks whether the provided proof was already used - pub fn is_used_proof(&self, proof: Proof) -> bool { + pub fn is_used_proof(&self, proof: &Proof) -> bool { self.is_used_event(&proof.key()) } @@ -652,7 +652,7 @@ impl EthConnectorContract { } /// Set Eth connector paused flags - pub fn set_paused_flags(&mut self, args: PauseEthConnectorCallArgs) { + pub fn set_paused_flags(&mut self, args: &PauseEthConnectorCallArgs) { self.set_paused(args.paused_mask); } } @@ -667,19 +667,19 @@ impl AdminControlled for EthConnectorContract { fn set_paused(&mut self, paused_mask: PausedMask) { self.paused_mask = paused_mask; self.io.write_borsh( - &construct_contract_key(&EthConnectorStorageId::PausedMask), + &construct_contract_key(EthConnectorStorageId::PausedMask), &self.paused_mask, ); } } -fn construct_contract_key(suffix: &EthConnectorStorageId) -> Vec { - crate::prelude::bytes_to_key(KeyPrefix::EthConnector, &[u8::from(*suffix)]) +fn construct_contract_key(suffix: EthConnectorStorageId) -> Vec { + crate::prelude::bytes_to_key(KeyPrefix::EthConnector, &[u8::from(suffix)]) } fn get_contract_data( io: &I, - suffix: &EthConnectorStorageId, + suffix: EthConnectorStorageId, ) -> Result { io.read_storage(&construct_contract_key(suffix)) .ok_or(error::StorageReadError::KeyNotFound) @@ -701,22 +701,22 @@ pub fn set_contract_data( }; // Save eth-connector specific data io.write_borsh( - &construct_contract_key(&EthConnectorStorageId::Contract), + &construct_contract_key(EthConnectorStorageId::Contract), &contract_data, ); io.write_borsh( - &construct_contract_key(&EthConnectorStorageId::FungibleTokenMetadata), + &construct_contract_key(EthConnectorStorageId::FungibleTokenMetadata), &args.metadata, ); Ok(contract_data) } -/// Return metdata +/// Return metadata pub fn get_metadata(io: &I) -> Option { io.read_storage(&construct_contract_key( - &EthConnectorStorageId::FungibleTokenMetadata, + EthConnectorStorageId::FungibleTokenMetadata, )) .and_then(|data| data.to_value().ok()) } diff --git a/engine/src/deposit_event.rs b/engine/src/deposit_event.rs index 50f09dfde..f23743eb7 100644 --- a/engine/src/deposit_event.rs +++ b/engine/src/deposit_event.rs @@ -47,12 +47,10 @@ impl FtTransferMessageData { return Err(error::ParseOnTransferMessageError::WrongMessageFormat); } - // Parse fee from message slice. It should contain 32 bytes - // But after that in will be parse to u128 - // That logic for compatability. - let mut raw_fee: [u8; 32] = Default::default(); - raw_fee.copy_from_slice(&msg[..32]); - let fee_u128: u128 = U256::from_little_endian(&raw_fee) + // Parse the fee from the message slice. It should contain 32 bytes, + // but after that, it will be parsed to u128. + // This logic is for compatibility. + let fee_u128: u128 = U256::from_little_endian(&msg[..32]) .try_into() .map_err(|_| error::ParseOnTransferMessageError::OverflowNumber)?; let fee: Fee = fee_u128.into(); @@ -60,7 +58,7 @@ impl FtTransferMessageData { // Get recipient Eth address from message slice let recipient = Address::try_from_slice(&msg[32..52]).unwrap(); - Ok(FtTransferMessageData { + Ok(Self { relayer: account_id, recipient, fee, @@ -68,6 +66,7 @@ impl FtTransferMessageData { } /// Encode to String with specific rules + #[must_use] pub fn encode(&self) -> String { // The first data section should contain fee data. // Pay attention, that for compatibility reasons we used U256 type @@ -132,7 +131,7 @@ impl TokenMessageData { pub fn parse_event_message_and_prepare_token_message_data( message: &str, fee: Fee, - ) -> Result { + ) -> Result { let data: Vec<_> = message.split(':').collect(); // Data array can contain 1 or 2 elements if data.len() >= 3 { @@ -143,7 +142,7 @@ impl TokenMessageData { // If data array contain only one element it should return NEAR account id if data.len() == 1 { - Ok(TokenMessageData::Near(account_id)) + Ok(Self::Near(account_id)) } else { let raw_message = data[1].into(); let message = FtTransferMessageData::prepare_message_for_on_transfer( @@ -152,7 +151,7 @@ impl TokenMessageData { raw_message, )?; - Ok(TokenMessageData::Eth { + Ok(Self::Eth { receiver_id: account_id, message, }) @@ -160,6 +159,7 @@ impl TokenMessageData { } // Get recipient account id from Eth part of Token message data + #[must_use] pub fn recipient(&self) -> AccountId { match self { Self::Near(acc) => acc.clone(), @@ -221,6 +221,7 @@ pub struct DepositedEvent { impl DepositedEvent { #[allow(dead_code)] + #[must_use] pub fn event_params() -> EventParams { vec![ EventParam { @@ -295,7 +296,7 @@ impl DepositedEvent { } pub mod error { - use super::*; + use super::AddressError; use crate::errors; #[derive(Debug)] diff --git a/engine/src/engine.rs b/engine/src/engine.rs index 27c045213..8cdf0ebf3 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -1,19 +1,21 @@ -use crate::parameters::{CallArgs, NEP141FtOnTransferArgs, ResultLog, SubmitResult, ViewCallArgs}; +use crate::parameters::{ + CallArgs, NEP141FtOnTransferArgs, ResultLog, SubmitArgs, SubmitResult, ViewCallArgs, +}; use core::mem; use evm::backend::{Apply, ApplyBackend, Backend, Basic, Log}; use evm::executor; use evm::{Config, CreateScheme, ExitError, ExitFatal, ExitReason}; use crate::connector::EthConnectorContract; -use crate::errors; use crate::map::BijectionMap; +use crate::{errors, state}; use aurora_engine_sdk::caching::FullCache; use aurora_engine_sdk::env::Env; use aurora_engine_sdk::io::{StorageIntermediate, IO}; use aurora_engine_sdk::promise::{PromiseHandler, PromiseId, ReadOnlyPromiseHandler}; use crate::accounting; -use crate::parameters::{DeployErc20TokenArgs, NewCallArgs, TransactionStatus}; +use crate::parameters::{DeployErc20TokenArgs, TransactionStatus}; use crate::pausables::{ EngineAuthorizer, EnginePrecompilesPauser, PausedPrecompilesChecker, PrecompileFlags, }; @@ -24,9 +26,10 @@ use crate::prelude::precompiles::Precompiles; use crate::prelude::transactions::{EthTransactionKind, NormalizedEthTransaction}; use crate::prelude::{ address_to_key, bytes_to_key, sdk, storage_to_key, u256_to_arr, vec, AccountId, Address, - BTreeMap, BorshDeserialize, BorshSerialize, KeyPrefix, PromiseArgs, PromiseCreateArgs, - ToString, Vec, Wei, Yocto, ERC20_MINT_SELECTOR, H160, H256, U256, + BTreeMap, BorshDeserialize, KeyPrefix, PromiseArgs, PromiseCreateArgs, ToString, Vec, Wei, + Yocto, ERC20_MINT_SELECTOR, H160, H256, U256, }; +use crate::state::EngineState; use aurora_engine_precompiles::PrecompileConstructorContext; use core::cell::RefCell; use core::iter::once; @@ -38,12 +41,12 @@ const BLOCK_HASH_PREFIX_SIZE: usize = 1; const BLOCK_HEIGHT_SIZE: usize = 8; const CHAIN_ID_SIZE: usize = 32; -#[cfg(not(feature = "contract"))] /// Block height where the bug fix for parsing transactions to the zero address /// is deployed. The current value is only approximate; will be updated once the /// fix is actually deployed. -pub const ZERO_ADDRESS_FIX_HEIGHT: u64 = 61200152; +pub const ZERO_ADDRESS_FIX_HEIGHT: u64 = 61_200_152; +#[must_use] pub fn current_address(current_account_id: &AccountId) -> Address { aurora_engine_sdk::types::near_account_to_evm_address(current_account_id.as_bytes()) } @@ -72,7 +75,7 @@ macro_rules! assert_or_finish { } #[derive(Debug, Clone, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(feature = "impl-serde", derive(serde::Serialize))] pub struct EngineError { pub kind: EngineErrorKind, pub gas_used: u64, @@ -92,7 +95,7 @@ impl AsRef<[u8]> for EngineError { /// Errors with the EVM engine. #[derive(Debug, Clone, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(feature = "impl-serde", derive(serde::Serialize))] pub enum EngineErrorKind { /// Normal EVM errors. EvmError(ExitError), @@ -110,41 +113,34 @@ pub enum EngineErrorKind { } impl EngineErrorKind { - pub fn with_gas_used(self, gas_used: u64) -> EngineError { - EngineError { - kind: self, - gas_used, - } - } - + #[must_use] pub fn as_bytes(&self) -> &[u8] { - use EngineErrorKind::*; match self { - EvmError(ExitError::StackUnderflow) => errors::ERR_STACK_UNDERFLOW, - EvmError(ExitError::StackOverflow) => errors::ERR_STACK_OVERFLOW, - EvmError(ExitError::InvalidJump) => errors::ERR_INVALID_JUMP, - EvmError(ExitError::InvalidRange) => errors::ERR_INVALID_RANGE, - EvmError(ExitError::DesignatedInvalid) => errors::ERR_DESIGNATED_INVALID, - EvmError(ExitError::CallTooDeep) => errors::ERR_CALL_TOO_DEEP, - EvmError(ExitError::CreateCollision) => errors::ERR_CREATE_COLLISION, - EvmError(ExitError::CreateContractLimit) => errors::ERR_CREATE_CONTRACT_LIMIT, - EvmError(ExitError::OutOfOffset) => errors::ERR_OUT_OF_OFFSET, - EvmError(ExitError::OutOfGas) => errors::ERR_OUT_OF_GAS, - EvmError(ExitError::OutOfFund) => errors::ERR_OUT_OF_FUND, - EvmError(ExitError::Other(m)) => m.as_bytes(), - EvmError(_) => unreachable!(), // unused misc - EvmFatal(ExitFatal::NotSupported) => errors::ERR_NOT_SUPPORTED, - EvmFatal(ExitFatal::UnhandledInterrupt) => errors::ERR_UNHANDLED_INTERRUPT, - EvmFatal(ExitFatal::Other(m)) => m.as_bytes(), - EvmFatal(_) => unreachable!(), // unused misc - IncorrectNonce => errors::ERR_INCORRECT_NONCE, - FailedTransactionParse(e) => e.as_ref(), - InvalidChainId => errors::ERR_INVALID_CHAIN_ID, - InvalidSignature => errors::ERR_INVALID_ECDSA_SIGNATURE, - IntrinsicGasNotMet => errors::ERR_INTRINSIC_GAS, - MaxPriorityGasFeeTooLarge => errors::ERR_MAX_PRIORITY_FEE_GREATER, - GasPayment(e) => e.as_ref(), - GasOverflow => errors::ERR_GAS_OVERFLOW, + Self::EvmError(ExitError::StackUnderflow) => errors::ERR_STACK_UNDERFLOW, + Self::EvmError(ExitError::StackOverflow) => errors::ERR_STACK_OVERFLOW, + Self::EvmError(ExitError::InvalidJump) => errors::ERR_INVALID_JUMP, + Self::EvmError(ExitError::InvalidRange) => errors::ERR_INVALID_RANGE, + Self::EvmError(ExitError::DesignatedInvalid) => errors::ERR_DESIGNATED_INVALID, + 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::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::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)) => { + m.as_bytes() + } + Self::IncorrectNonce => errors::ERR_INCORRECT_NONCE, + Self::FailedTransactionParse(e) => e.as_ref(), + Self::InvalidChainId => errors::ERR_INVALID_CHAIN_ID, + Self::InvalidSignature => errors::ERR_INVALID_ECDSA_SIGNATURE, + Self::IntrinsicGasNotMet => errors::ERR_INTRINSIC_GAS, + Self::MaxPriorityGasFeeTooLarge => errors::ERR_MAX_PRIORITY_FEE_GREATER, + Self::GasPayment(e) => e.as_ref(), + Self::GasOverflow => errors::ERR_GAS_OVERFLOW, + Self::EvmFatal(_) | Self::EvmError(_) => unreachable!(), // unused misc } } } @@ -157,13 +153,13 @@ impl AsRef<[u8]> for EngineErrorKind { impl From for EngineErrorKind { fn from(e: ExitError) -> Self { - EngineErrorKind::EvmError(e) + Self::EvmError(e) } } impl From for EngineErrorKind { fn from(e: ExitFatal) -> Self { - EngineErrorKind::EvmFatal(e) + Self::EvmFatal(e) } } @@ -177,21 +173,20 @@ trait ExitIntoResult { impl ExitIntoResult for ExitReason { fn into_result(self, data: Vec) -> Result { - use ExitReason::*; match self { - Succeed(_) => Ok(TransactionStatus::Succeed(data)), - Revert(_) => Ok(TransactionStatus::Revert(data)), - Error(ExitError::OutOfOffset) => Ok(TransactionStatus::OutOfOffset), - Error(ExitError::OutOfFund) => Ok(TransactionStatus::OutOfFund), - Error(ExitError::OutOfGas) => Ok(TransactionStatus::OutOfGas), - Error(e) => Err(e.into()), - Fatal(e) => Err(e.into()), + Self::Succeed(_) => Ok(TransactionStatus::Succeed(data)), + Self::Revert(_) => Ok(TransactionStatus::Revert(data)), + Self::Error(ExitError::OutOfOffset) => Ok(TransactionStatus::OutOfOffset), + Self::Error(ExitError::OutOfFund) => Ok(TransactionStatus::OutOfFund), + Self::Error(ExitError::OutOfGas) => Ok(TransactionStatus::OutOfGas), + Self::Error(e) => Err(e.into()), + Self::Fatal(e) => Err(e.into()), } } } #[derive(Debug, Clone, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "impl-serde", derive(serde::Serialize, serde::Deserialize))] pub struct BalanceOverflow; impl AsRef<[u8]> for BalanceOverflow { @@ -202,7 +197,7 @@ impl AsRef<[u8]> for BalanceOverflow { /// Errors resulting from trying to pay for gas #[derive(Debug, Clone, Eq, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "impl-serde", derive(serde::Serialize, serde::Deserialize))] pub enum GasPaymentError { /// Overflow adding ETH to an account balance (should never happen) BalanceOverflow(BalanceOverflow), @@ -230,7 +225,7 @@ impl From for GasPaymentError { #[derive(Debug)] pub enum DeployErc20Error { - State(EngineStateError), + State(state::EngineStateError), Failed(TransactionStatus), Engine(EngineError), Register(RegisterTokenError), @@ -302,7 +297,8 @@ pub enum GetErc20FromNep141Error { } impl GetErc20FromNep141Error { - pub fn to_str(&self) -> &str { + #[must_use] + pub const fn to_str(&self) -> &str { match self { Self::InvalidNep141AccountId => ERR_INVALID_NEP141_ACCOUNT_ID, Self::Nep141NotFound => "ERR_NEP141_NOT_FOUND", @@ -323,7 +319,8 @@ pub enum RegisterTokenError { } impl RegisterTokenError { - pub fn to_str(&self) -> &str { + #[must_use] + pub const fn to_str(&self) -> &str { match self { Self::InvalidNep141AccountId => ERR_INVALID_NEP141_ACCOUNT_ID, Self::TokenAlreadyRegistered => "ERR_NEP141_TOKEN_ALREADY_REGISTERED", @@ -337,28 +334,13 @@ impl AsRef<[u8]> for RegisterTokenError { } } -#[derive(Debug)] -pub enum EngineStateError { - NotFound, - DeserializationFailed, -} - -impl AsRef<[u8]> for EngineStateError { - fn as_ref(&self) -> &[u8] { - match self { - Self::NotFound => errors::ERR_STATE_NOT_FOUND, - Self::DeserializationFailed => errors::ERR_STATE_CORRUPTED, - } - } -} - pub struct StackExecutorParams<'a, I, E, H> { precompiles: Precompiles<'a, I, E, H>, gas_limit: u64, } impl<'env, I: IO + Copy, E: Env, H: ReadOnlyPromiseHandler> StackExecutorParams<'env, I, E, H> { - fn new(gas_limit: u64, precompiles: Precompiles<'env, I, E, H>) -> Self { + const fn new(gas_limit: u64, precompiles: Precompiles<'env, I, E, H>) -> Self { Self { precompiles, gas_limit, @@ -387,33 +369,6 @@ pub struct GasPaymentResult { pub priority_fee_per_gas: U256, } -/// Engine internal state, mostly configuration. -/// Should not contain anything large or enumerable. -#[derive(BorshSerialize, BorshDeserialize, Default, Clone, PartialEq, Eq, Debug)] -pub struct EngineState { - /// Chain id, according to the EIP-155 / ethereum-lists spec. - pub chain_id: [u8; 32], - /// Account which can upgrade this contract. - /// Use empty to disable updatability. - pub owner_id: AccountId, - /// Account of the bridge prover. - /// Use empty to not use base token as bridged asset. - pub bridge_prover_id: AccountId, - /// How many blocks after staging upgrade can deploy it. - pub upgrade_delay_blocks: u64, -} - -impl From for EngineState { - fn from(args: NewCallArgs) -> Self { - EngineState { - chain_id: args.chain_id, - owner_id: args.owner_id, - bridge_prover_id: args.bridge_prover_id, - upgrade_delay_blocks: args.upgrade_delay_blocks, - } - } -} - pub struct Engine<'env, I: IO, E: Env> { state: EngineState, origin: Address, @@ -429,17 +384,15 @@ pub struct Engine<'env, I: IO, E: Env> { pub(crate) const CONFIG: &Config = &Config::london(); -/// Key for storing the state of the engine. -const STATE_KEY: &[u8; 5] = b"STATE"; - impl<'env, I: IO + Copy, E: Env> Engine<'env, I, E> { pub fn new( origin: Address, current_account_id: AccountId, io: I, env: &'env E, - ) -> Result { - get_state(&io).map(|state| Self::new_with_state(state, origin, current_account_id, io, env)) + ) -> Result { + state::get_state(&io) + .map(|state| Self::new_with_state(state, origin, current_account_id, io, env)) } pub fn new_with_state( @@ -467,6 +420,7 @@ impl<'env, I: IO + Copy, E: Env> Engine<'env, I, E> { &mut self, sender: &Address, transaction: &NormalizedEthTransaction, + max_gas_price: Option, ) -> Result { if transaction.max_fee_per_gas.is_zero() { return Ok(GasPaymentResult::default()); @@ -475,6 +429,9 @@ impl<'env, I: IO + Copy, E: Env> Engine<'env, I, E> { let priority_fee_per_gas = transaction .max_priority_fee_per_gas .min(transaction.max_fee_per_gas - self.block_base_fee_per_gas()); + let priority_fee_per_gas = max_gas_price.map_or(priority_fee_per_gas, |price| { + price.min(priority_fee_per_gas) + }); let effective_gas_price = priority_fee_per_gas + self.block_base_fee_per_gas(); let gas_limit = transaction.gas_limit; let prepaid_amount = gas_limit @@ -533,13 +490,7 @@ impl<'env, I: IO + Copy, E: Env> Engine<'env, I, E> { }; let used_gas = executor.used_gas(); - let status = match exit_reason.into_result(result) { - Ok(status) => status, - Err(e) => { - increment_nonce(&mut self.io, &origin); - return Err(e.with_gas_used(used_gas)); - } - }; + let status = exit_reason.into_result(result)?; let (values, logs) = executor.into_state().deconstruct(); let logs = filter_promises_from_logs(&self.io, handler, logs, &self.current_account_id); @@ -614,19 +565,11 @@ impl<'env, I: IO + Copy, E: Env> Engine<'env, I, E> { ); let used_gas = executor.used_gas(); - let status = match exit_reason.into_result(result) { - Ok(status) => status, - Err(e) => { - increment_nonce(&mut self.io, origin); - return Err(e.with_gas_used(used_gas)); - } - }; + let status = exit_reason.into_result(result)?; let (values, logs) = executor.into_state().deconstruct(); let logs = filter_promises_from_logs(&self.io, handler, logs, &self.current_account_id); - - // There is no way to return the logs to the NEAR log method as it only - // allows a return of UTF-8 strings. + // The logs could be encoded as base64 or hex string. self.apply(values, Vec::::new(), true); Ok(SubmitResult::new(status, used_gas, logs)) @@ -735,7 +678,7 @@ impl<'env, I: IO + Copy, E: Env> Engine<'env, I, E> { /// with the input, or 0 if tokens were minted successfully. /// /// The output will be serialized as a String - /// https://github.com/near/NEPs/discussions/146 + /// `https://github.com/near/NEPs/discussions/146` /// /// IMPORTANT: This function should not panic, otherwise it won't /// be possible to return the tokens to the sender. @@ -757,7 +700,9 @@ impl<'env, I: IO + Copy, E: Env> Engine<'env, I, E> { assert_or_finish!(message.len() >= 40, output_on_fail, self.io); Address::new(H160(unwrap_res_or_finish!( - hex::decode(&message[..40]).unwrap().as_slice().try_into(), + unwrap_res_or_finish!(hex::decode(&message[..40]), output_on_fail, self.io) + .as_slice() + .try_into(), output_on_fail, self.io ))) @@ -839,27 +784,13 @@ impl<'env, I: IO + Copy, E: Env> Engine<'env, I, E> { let env = self.env; let ro_promise_handler = handler.read_only(); - let precompiles = if cfg!(all(feature = "mainnet", not(feature = "integration-test"))) { - let mut tmp = Precompiles::new_london(PrecompileConstructorContext { - current_account_id, - random_seed, - io, - env, - promise_handler: ro_promise_handler, - }); - // Cross contract calls are not enabled on mainnet yet. - tmp.all_precompiles - .remove(&aurora_engine_precompiles::xcc::cross_contract_call::ADDRESS); - tmp - } else { - Precompiles::new_london(PrecompileConstructorContext { - current_account_id, - random_seed, - io, - env, - promise_handler: ro_promise_handler, - }) - }; + let precompiles = Precompiles::new_london(PrecompileConstructorContext { + current_account_id, + random_seed, + io, + env, + promise_handler: ro_promise_handler, + }); Self::apply_pause_flags_to_precompiles(precompiles, pause_flags) } @@ -883,7 +814,7 @@ impl<'env, I: IO + Copy, E: Env> Engine<'env, I, E> { pub fn submit( mut io: I, env: &E, - transaction_bytes: &[u8], + args: &SubmitArgs, state: EngineState, current_account_id: AccountId, relayer_address: Address, @@ -891,7 +822,7 @@ pub fn submit( ) -> EngineResult { #[cfg(feature = "contract")] let transaction = NormalizedEthTransaction::try_from( - EthTransactionKind::try_from(transaction_bytes) + EthTransactionKind::try_from(args.tx_data.as_slice()) .map_err(EngineErrorKind::FailedTransactionParse)?, ) .map_err(|_e| EngineErrorKind::InvalidSignature)?; @@ -907,7 +838,7 @@ pub fn submit( ); let block_height = env.block_height(); let tx: EthTransactionKind = adapter - .try_parse_bytes(transaction_bytes, block_height) + .try_parse_bytes(args.tx_data.as_slice(), block_height) .map_err(EngineErrorKind::FailedTransactionParse)?; tx.try_into() .map_err(|_e| EngineErrorKind::InvalidSignature)? @@ -944,17 +875,13 @@ pub fn submit( } let mut engine = Engine::new_with_state(state, sender, current_account_id, io, env); - let prepaid_amount = match engine.charge_gas(&sender, &transaction) { - Ok(gas_result) => gas_result, - Err(GasPaymentError::OutOfFund) => { - increment_nonce(&mut io, &sender); - let result = SubmitResult::new(TransactionStatus::OutOfFund, 0, vec![]); - return Ok(result); - } - Err(err) => { - return Err(EngineErrorKind::GasPayment(err).into()); - } - }; + let prepaid_amount = + match engine.charge_gas(&sender, &transaction, args.max_gas_price.map(Into::into)) { + Ok(gas_result) => gas_result, + Err(err) => { + return Err(EngineErrorKind::GasPayment(err).into()); + } + }; let gas_limit: u64 = transaction .gas_limit .try_into() @@ -993,17 +920,23 @@ pub fn submit( Ok(submit_result) => submit_result.gas_used, Err(engine_err) => engine_err.gas_used, }; - refund_unused_gas(&mut io, &sender, gas_used, prepaid_amount, &relayer_address).map_err( - |e| EngineError { - gas_used, - kind: EngineErrorKind::GasPayment(e), - }, - )?; + refund_unused_gas( + &mut io, + &sender, + gas_used, + &prepaid_amount, + &relayer_address, + ) + .map_err(|e| EngineError { + gas_used, + kind: EngineErrorKind::GasPayment(e), + })?; // return result to user result } +#[must_use] pub fn setup_refund_on_error_input(amount: U256, refund_address: Address) -> Vec { let selector = ERC20_MINT_SELECTOR; let mint_args = ethabi::encode(&[ @@ -1018,51 +951,47 @@ pub fn refund_on_error( io: I, env: &E, state: EngineState, - args: RefundCallArgs, + args: &RefundCallArgs, handler: &mut P, ) -> EngineResult { let current_account_id = env.current_account_id(); - match args.erc20_address { + if let Some(erc20_address) = args.erc20_address { // ERC-20 exit; re-mint burned tokens - Some(erc20_address) => { - let erc20_admin_address = current_address(¤t_account_id); - let mut engine = - Engine::new_with_state(state, erc20_admin_address, current_account_id, io, env); - let erc20_address = erc20_address; - let refund_address = args.recipient_address; - let amount = U256::from_big_endian(&args.amount); - let input = setup_refund_on_error_input(amount, refund_address); - - engine.call( - &erc20_admin_address, - &erc20_address, - Wei::zero(), - input, - u64::MAX, - Vec::new(), - handler, - ) - } + let erc20_admin_address = current_address(¤t_account_id); + let mut engine = + Engine::new_with_state(state, erc20_admin_address, current_account_id, io, env); + let erc20_address = erc20_address; + let refund_address = args.recipient_address; + let amount = U256::from_big_endian(&args.amount); + let input = setup_refund_on_error_input(amount, refund_address); + + engine.call( + &erc20_admin_address, + &erc20_address, + Wei::zero(), + input, + u64::MAX, + Vec::new(), + handler, + ) + } else { // ETH exit; transfer ETH back from precompile address - None => { - let exit_address = aurora_engine_precompiles::native::exit_to_near::ADDRESS; - let mut engine = - Engine::new_with_state(state, exit_address, current_account_id, io, env); - let refund_address = args.recipient_address; - let amount = Wei::new(U256::from_big_endian(&args.amount)); - engine.call( - &exit_address, - &refund_address, - amount, - Vec::new(), - u64::MAX, - vec![ - (exit_address.raw(), Vec::new()), - (refund_address.raw(), Vec::new()), - ], - handler, - ) - } + let exit_address = aurora_engine_precompiles::native::exit_to_near::ADDRESS; + let mut engine = Engine::new_with_state(state, exit_address, current_account_id, io, env); + let refund_address = args.recipient_address; + let amount = Wei::new(U256::from_big_endian(&args.amount)); + engine.call( + &exit_address, + &refund_address, + amount, + Vec::new(), + u64::MAX, + vec![ + (exit_address.raw(), Vec::new()), + (refund_address.raw(), Vec::new()), + ], + handler, + ) } } @@ -1077,6 +1006,7 @@ pub fn refund_on_error( /// engine_account_id, /// )) /// ``` +#[must_use] pub fn compute_block_hash(chain_id: [u8; 32], block_height: u64, account_id: &[u8]) -> H256 { debug_assert_eq!(BLOCK_HASH_PREFIX_SIZE, mem::size_of_val(&BLOCK_HASH_PREFIX)); debug_assert_eq!(BLOCK_HEIGHT_SIZE, mem::size_of_val(&block_height)); @@ -1092,34 +1022,19 @@ pub fn compute_block_hash(chain_id: [u8; 32], block_height: u64, account_id: &[u sdk::sha256(&data) } -pub fn get_state(io: &I) -> Result { - match io.read_storage(&bytes_to_key(KeyPrefix::Config, STATE_KEY)) { - None => Err(EngineStateError::NotFound), - Some(bytes) => EngineState::try_from_slice(&bytes.to_vec()) - .map_err(|_| EngineStateError::DeserializationFailed), - } -} - -/// Saves state into the storage. -pub fn set_state(io: &mut I, state: EngineState) { - io.write_storage( - &bytes_to_key(KeyPrefix::Config, STATE_KEY), - &state.try_to_vec().expect("ERR_SER"), - ); -} - -pub fn get_authorizer() -> EngineAuthorizer { - // TODO: a temporary account until the engine adapts std with near-plugins - let account = AccountId::new("aurora").expect("Failed to parse account from string"); - - EngineAuthorizer::from_accounts(once(account)) +#[must_use] +pub fn get_authorizer(io: &I) -> EngineAuthorizer { + // TODO: a temporary use the owner account only until the engine adapts std with near-plugins + state::get_state(io) + .map(|state| EngineAuthorizer::from_accounts(once(state.owner_id))) + .unwrap_or_default() } pub fn refund_unused_gas( io: &mut I, sender: &Address, gas_used: u64, - gas_result: GasPaymentResult, + gas_result: &GasPaymentResult, relayer: &Address, ) -> Result<(), GasPaymentError> { if gas_result.effective_gas_price.is_zero() { @@ -1147,6 +1062,7 @@ pub fn refund_unused_gas( Ok(()) } +#[must_use] pub fn setup_receive_erc20_tokens_input( args: &NEP141FtOnTransferArgs, recipient: &Address, @@ -1160,6 +1076,7 @@ pub fn setup_receive_erc20_tokens_input( [selector, tail.as_slice()].concat() } +#[must_use] pub fn setup_deploy_erc20_input(current_account_id: &AccountId) -> Vec { #[cfg(feature = "error_refund")] let erc20_contract = include_bytes!("../../etc/eth-contracts/res/EvmErc20V2.bin"); @@ -1175,7 +1092,7 @@ pub fn setup_deploy_erc20_input(current_account_id: &AccountId) -> Vec { ethabi::Token::Address(erc20_admin_address.raw()), ]); - ([erc20_contract, deploy_args.as_slice()].concat()).to_vec() + [erc20_contract, deploy_args.as_slice()].concat() } /// Used to bridge NEP-141 tokens from NEAR to Aurora. On Aurora the NEP-141 becomes an ERC-20. @@ -1267,13 +1184,25 @@ pub fn get_nonce(io: &I, address: &Address) -> U256 { .unwrap_or_else(|_| U256::zero()) } +#[cfg(test)] pub fn increment_nonce(io: &mut I, address: &Address) { let account_nonce = get_nonce(io, address); let new_nonce = account_nonce.saturating_add(U256::one()); set_nonce(io, address, &new_nonce); } -pub fn nep141_erc20_map(io: I) -> BijectionMap { +#[must_use] +pub fn create_legacy_address(caller: &Address, nonce: &U256) -> Address { + let mut stream = rlp::RlpStream::new_list(2); + stream.append(&caller.raw()); + stream.append(nonce); + let hash = aurora_engine_sdk::keccak(&stream.out()); + let hash_bytes = hash.as_bytes(); + Address::try_from_slice(&hash_bytes[12..]).unwrap() +} + +#[must_use] +pub const fn nep141_erc20_map(io: I) -> BijectionMap { BijectionMap::new(KeyPrefix::Nep141Erc20Map, KeyPrefix::Erc20Nep141Map, io) } @@ -1360,12 +1289,11 @@ pub fn set_generation(io: &mut I, address: &Address, generation: u32) { pub fn get_generation(io: &I, address: &Address) -> u32 { io.read_storage(&address_to_key(KeyPrefix::Generation, address)) - .map(|value| { + .map_or(0, |value| { let mut bytes = [0u8; 4]; value.copy_to_slice(&mut bytes); u32::from_be_bytes(bytes) }) - .unwrap_or(0) } /// Removes all storage for the given address. @@ -1433,7 +1361,7 @@ where // The exit precompiles do produce externally consumable logs in // addition to the promises. The external logs have a non-empty // `topics` field. - Some(log.into()) + Some(evm_log_to_result_log(log)) } } else if log.address == cross_contract_call::ADDRESS.raw() { if log.topics[0] == cross_contract_call::AMOUNT_TOPIC { @@ -1446,7 +1374,7 @@ where crate::xcc::handle_precompile_promise( io, handler, - promise, + &promise, required_near, current_account_id, ); @@ -1455,12 +1383,25 @@ where // do not pass on these "internal logs" to caller None } else { - Some(log.into()) + Some(evm_log_to_result_log(log)) } }) .collect() } +fn evm_log_to_result_log(log: Log) -> ResultLog { + let topics = log + .topics + .into_iter() + .map(|topic| topic.0) + .collect::>(); + ResultLog { + address: Address::new(log.address), + topics, + data: log.data, + } +} + unsafe fn schedule_promise( handler: &mut P, promise: &PromiseCreateArgs, @@ -1513,7 +1454,7 @@ impl<'env, I: IO + Copy, E: Env> evm::backend::Backend for Engine<'env, I, E> { /// [nearcore#3456](https://github.com/near/nearcore/issues/3456) for more /// details. /// - /// See: https://doc.aurora.dev/develop/compat/evm#blockhash + /// See: `https://doc.aurora.dev/develop/compat/evm#blockhash` fn block_hash(&self, number: U256) -> H256 { let idx = U256::from(self.env.block_height()); if idx.saturating_sub(U256::from(256)) <= number && number < idx { @@ -1536,7 +1477,7 @@ impl<'env, I: IO + Copy, E: Env> evm::backend::Backend for Engine<'env, I, E> { /// Returns a mocked coinbase which is the EVM address for the Aurora /// account, being 0x4444588443C3a91288c5002483449Aba1054192b. /// - /// See: https://doc.aurora.dev/develop/compat/evm#coinbase + /// See: `https://doc.aurora.dev/develop/compat/evm#coinbase` fn block_coinbase(&self) -> H160 { H160([ 0x44, 0x44, 0x58, 0x84, 0x43, 0xC3, 0xa9, 0x12, 0x88, 0xc5, 0x00, 0x24, 0x83, 0x44, @@ -1551,7 +1492,7 @@ impl<'env, I: IO + Copy, E: Env> evm::backend::Backend for Engine<'env, I, E> { /// Returns the current block difficulty. /// - /// See: https://doc.aurora.dev/develop/compat/evm#difficulty + /// See: `https://doc.aurora.dev/develop/compat/evm#difficulty` fn block_difficulty(&self) -> U256 { U256::zero() } @@ -1562,7 +1503,7 @@ impl<'env, I: IO + Copy, E: Env> evm::backend::Backend for Engine<'env, I, E> { /// as there isn't a gas limit alternative right now but this may change in /// the future. /// - /// See: https://doc.aurora.dev/develop/compat/evm#gaslimit + /// See: `https://doc.aurora.dev/develop/compat/evm#gaslimit` fn block_gas_limit(&self) -> U256 { U256::max_value() } @@ -1640,7 +1581,7 @@ impl<'env, I: IO + Copy, E: Env> evm::backend::Backend for Engine<'env, I, E> { /// Get original storage value of address at index, if available. /// - /// Since SputnikVM collects storage changes in memory until the transaction is over, + /// Since `SputnikVM` collects storage changes in memory until the transaction is over, /// the "original storage" will always be the same as the storage because no values /// are written to storage until after the transaction is complete. fn original_storage(&self, address: H160, index: H256) -> Option { @@ -1700,9 +1641,9 @@ impl<'env, J: IO + Copy, E: Env> ApplyBackend for Engine<'env, J, E> { for (index, value) in storage { if value == H256::default() { - remove_storage(&mut self.io, &address, &index, next_generation) + remove_storage(&mut self.io, &address, &index, next_generation); } else { - set_storage(&mut self.io, &address, &index, &value, next_generation) + set_storage(&mut self.io, &address, &index, &value, next_generation); } writes_counter += 1; } @@ -1781,17 +1722,15 @@ mod tests { use aurora_engine_sdk::promise::Noop; use aurora_engine_test_doubles::io::{Storage, StoragePointer}; use aurora_engine_test_doubles::promise::PromiseTracker; - use aurora_engine_types::types::RawU256; - use sha3::{Digest, Keccak256}; - use std::sync::RwLock; + use aurora_engine_types::types::{Balance, NearGas, RawU256}; + use std::cell::RefCell; #[test] fn test_view_call_to_empty_contract_without_input_returns_empty_data() { let origin = Address::zero(); let current_account_id = AccountId::default(); let env = Fixed::default(); - let storage = Storage::default(); - let storage = RwLock::new(storage); + let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); add_balance(&mut io, &origin, Wei::new_u64(22000)).unwrap(); let engine = @@ -1817,8 +1756,7 @@ mod tests { let origin = Address::zero(); let current_account_id = AccountId::default(); let env = Fixed::default(); - let storage = Storage::default(); - let storage = RwLock::new(storage); + let storage = RefCell::new(Storage::default()); let io = StoragePointer(&storage); let mut engine = Engine::new_with_state(EngineState::default(), origin, current_account_id, io, &env); @@ -1829,7 +1767,7 @@ mod tests { let actual_result = engine.deploy_code_with_input(input, &mut handler).unwrap(); let nonce = U256::zero(); - let expected_address = create_legacy_address(origin.raw(), nonce).0.to_vec(); + let expected_address = create_legacy_address(&origin, &nonce).as_bytes().to_vec(); let expected_status = TransactionStatus::Succeed(expected_address); let expected_gas_used = 53000; let expected_logs = Vec::new(); @@ -1843,8 +1781,7 @@ mod tests { let origin = Address::zero(); let current_account_id = AccountId::default(); let env = Fixed::default(); - let storage = Storage::default(); - let storage = RwLock::new(storage); + let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); add_balance(&mut io, &origin, Wei::new_u64(22000)).unwrap(); let mut engine = @@ -1875,8 +1812,7 @@ mod tests { let origin = Address::zero(); let current_account_id = AccountId::default(); let env = Fixed::default(); - let storage = Storage::default(); - let storage = RwLock::new(storage); + let storage = RefCell::new(Storage::default()); let io = StoragePointer(&storage); let mut engine = Engine::new_with_state(EngineState::default(), origin, current_account_id, io, &env); @@ -1905,8 +1841,7 @@ mod tests { let origin = Address::zero(); let current_account_id = AccountId::default(); let env = Fixed::default(); - let storage = Storage::default(); - let storage = RwLock::new(storage); + let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); add_balance(&mut io, &origin, Wei::new_u64(22000)).unwrap(); let mut engine = @@ -1934,8 +1869,7 @@ mod tests { let origin = Address::zero(); let current_account_id = AccountId::default(); let env = Fixed::default(); - let storage = Storage::default(); - let storage = RwLock::new(storage); + let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); add_balance(&mut io, &origin, Wei::new_u64(22000)).unwrap(); let mut engine = @@ -1961,8 +1895,7 @@ mod tests { let origin = Address::zero(); let current_account_id = AccountId::default(); let env = Fixed::default(); - let storage = Storage::default(); - let storage = RwLock::new(storage); + let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); add_balance(&mut io, &origin, Wei::new_u64(22000)).unwrap(); let mut engine = @@ -1981,8 +1914,7 @@ mod tests { let origin = Address::zero(); let current_account_id = AccountId::default(); let env = Fixed::default(); - let storage = Storage::default(); - let storage = RwLock::new(storage); + let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); set_balance(&mut io, &origin, &Wei::new_u64(22000)); let mut engine = Engine::new_with_state( @@ -1997,8 +1929,8 @@ mod tests { let erc20_token = make_address(4, 5); let nep141_token = AccountId::new("testcoin").unwrap(); let args = NEP141FtOnTransferArgs { - sender_id: Default::default(), - amount: Default::default(), + sender_id: AccountId::default(), + amount: Balance::default(), msg: receiver.encode(), }; let mut handler = Noop; @@ -2007,9 +1939,9 @@ mod tests { .unwrap(); engine.receive_erc20_tokens(&nep141_token, &args, ¤t_account_id, &mut handler); - let storage_read = storage.read().unwrap(); - let actual_output = std::str::from_utf8(storage_read.output.as_slice()).unwrap(); - let expected_output = "\"0\""; + let storage = storage.borrow(); + let actual_output = storage.output.as_slice(); + let expected_output = b"\"0\""; assert_eq!(expected_output, actual_output); } @@ -2020,11 +1952,10 @@ mod tests { let origin = aurora_engine_sdk::types::near_account_to_evm_address( env.predecessor_account_id().as_bytes(), ); - let storage = Storage::default(); - let storage = RwLock::new(storage); + let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); add_balance(&mut io, &origin, Wei::new_u64(22000)).unwrap(); - set_state(&mut io, EngineState::default()); + state::set_state(&mut io, &EngineState::default()).unwrap(); let nep141_token = AccountId::new("testcoin").unwrap(); let mut handler = Noop; @@ -2032,7 +1963,7 @@ mod tests { nep141: nep141_token, }; let nonce = U256::zero(); - let expected_address = Address::new(create_legacy_address(origin.raw(), nonce)); + let expected_address = create_legacy_address(&origin, &nonce); let actual_address = deploy_erc20_token(args, io, &env, &mut handler).unwrap(); assert_eq!(expected_address, actual_address); @@ -2043,26 +1974,25 @@ mod tests { let origin = Address::zero(); let current_account_id = AccountId::default(); let env = Fixed::default(); - let storage = Storage::default(); - let storage = RwLock::new(storage); + let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); add_balance(&mut io, &origin, Wei::new_u64(22000)).unwrap(); let mut engine = Engine::new_with_state(EngineState::default(), origin, current_account_id, io, &env); let transaction = NormalizedEthTransaction { - address: Default::default(), + address: Address::default(), chain_id: None, - nonce: Default::default(), + nonce: U256::default(), gas_limit: U256::MAX, - max_priority_fee_per_gas: Default::default(), + max_priority_fee_per_gas: U256::default(), max_fee_per_gas: U256::MAX, to: None, - value: Default::default(), + value: Wei::default(), data: vec![], access_list: vec![], }; - let actual_result = engine.charge_gas(&origin, &transaction).unwrap(); + let actual_result = engine.charge_gas(&origin, &transaction, None).unwrap(); let expected_result = GasPaymentResult { prepaid_amount: Wei::zero(), @@ -2080,11 +2010,11 @@ mod tests { let mut promise_tracker = PromiseTracker::default(); let args = PromiseCreateArgs { - target_account_id: Default::default(), - method: "".to_string(), + target_account_id: AccountId::default(), + method: String::new(), args: vec![], - attached_balance: Default::default(), - attached_gas: Default::default(), + attached_balance: Yocto::default(), + attached_gas: NearGas::default(), }; // This is safe because it's just a test let actual_id = unsafe { schedule_promise(&mut promise_tracker, &args) }; @@ -2105,11 +2035,11 @@ mod tests { let mut promise_tracker = PromiseTracker::default(); let args = PromiseCreateArgs { - target_account_id: Default::default(), - method: "".to_string(), + target_account_id: AccountId::default(), + method: String::new(), args: vec![], - attached_balance: Default::default(), - attached_gas: Default::default(), + attached_balance: Yocto::default(), + attached_gas: NearGas::default(), }; let base_id = PromiseId::new(6); // This is safe because it's just a test @@ -2135,8 +2065,7 @@ mod tests { let origin = Address::zero(); let current_account_id = AccountId::default(); let env = Fixed::default(); - let storage = Storage::default(); - let storage = RwLock::new(storage); + let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); let engine = Engine::new_with_state(EngineState::default(), origin, current_account_id, io, &env); @@ -2155,11 +2084,10 @@ mod tests { let origin = Address::zero(); let current_account_id = AccountId::default(); let env = Fixed::default(); - let storage = Storage::default(); - let storage = RwLock::new(storage); + let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); let expected_state = EngineState::default(); - set_state(&mut io, expected_state.clone()); + state::set_state(&mut io, &expected_state).unwrap(); let engine = Engine::new(origin, current_account_id, io, &env).unwrap(); let actual_state = engine.state; @@ -2170,20 +2098,19 @@ mod tests { fn test_refund_transfer_eth_back_from_precompile_address() { let recipient_address = make_address(1, 1); let env = Fixed::default(); - let storage = Storage::default(); - let storage = RwLock::new(storage); + let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); let expected_state = EngineState::default(); let refund_amount = Wei::new_u64(1000); add_balance(&mut io, &exit_to_near::ADDRESS, refund_amount).unwrap(); - set_state(&mut io, expected_state.clone()); + state::set_state(&mut io, &expected_state).unwrap(); let args = RefundCallArgs { recipient_address, erc20_address: None, amount: RawU256::from(refund_amount.raw()), }; let mut handler = Noop; - let actual_result = refund_on_error(io, &env, expected_state, args, &mut handler).unwrap(); + let actual_result = refund_on_error(io, &env, expected_state, &args, &mut handler).unwrap(); let expected_result = SubmitResult::new(TransactionStatus::Succeed(Vec::new()), 25800, Vec::new()); @@ -2194,19 +2121,18 @@ mod tests { fn test_refund_remint_burned_erc20_tokens() { let origin = Address::zero(); let env = Fixed::default(); - let storage = Storage::default(); - let storage = RwLock::new(storage); + let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); let expected_state = EngineState::default(); - set_state(&mut io, expected_state.clone()); + state::set_state(&mut io, &expected_state).unwrap(); let value = Wei::new_u64(1000); let args = RefundCallArgs { - recipient_address: Default::default(), + recipient_address: Address::default(), erc20_address: Some(origin), amount: RawU256::from(value.raw()), }; let mut handler = Noop; - let actual_result = refund_on_error(io, &env, expected_state, args, &mut handler).unwrap(); + let actual_result = refund_on_error(io, &env, expected_state, &args, &mut handler).unwrap(); let expected_result = SubmitResult::new(TransactionStatus::Succeed(Vec::new()), 21344, Vec::new()); @@ -2216,29 +2142,27 @@ mod tests { #[test] fn test_refund_free_effective_gas_does_nothing() { let origin = Address::zero(); - let storage = Storage::default(); - let storage = RwLock::new(storage); + let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); let expected_state = EngineState::default(); - set_state(&mut io, expected_state); + state::set_state(&mut io, &expected_state).unwrap(); let relayer = make_address(1, 1); let gas_result = GasPaymentResult { - prepaid_amount: Default::default(), + prepaid_amount: Wei::default(), effective_gas_price: U256::zero(), priority_fee_per_gas: U256::zero(), }; - refund_unused_gas(&mut io, &origin, 1000, gas_result, &relayer).unwrap(); + refund_unused_gas(&mut io, &origin, 1000, &gas_result, &relayer).unwrap(); } #[test] fn test_refund_gas_pays_expected_amount() { let origin = Address::zero(); - let storage = Storage::default(); - let storage = RwLock::new(storage); + let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); let expected_state = EngineState::default(); - set_state(&mut io, expected_state); + state::set_state(&mut io, &expected_state).unwrap(); let relayer = make_address(1, 1); let gas_result = GasPaymentResult { prepaid_amount: Wei::new_u64(8000), @@ -2247,7 +2171,7 @@ mod tests { }; let gas_used = 4000; - refund_unused_gas(&mut io, &origin, gas_used, gas_result, &relayer).unwrap(); + refund_unused_gas(&mut io, &origin, gas_used, &gas_result, &relayer).unwrap(); let actual_refund = get_balance(&io, &origin); let expected_refund = Wei::new_u64(gas_used); @@ -2258,8 +2182,7 @@ mod tests { #[test] fn test_check_nonce_with_increment_succeeds() { let origin = Address::zero(); - let storage = Storage::default(); - let storage = RwLock::new(storage); + let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); increment_nonce(&mut io, &origin); @@ -2269,72 +2192,47 @@ mod tests { #[test] fn test_check_nonce_without_increment_fails() { let origin = Address::zero(); - let storage = Storage::default(); - let storage = RwLock::new(storage); + let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); increment_nonce(&mut io, &origin); let actual_error_kind = check_nonce(&io, &origin, &U256::from(0u64)).unwrap_err(); - let actual_error_kind = std::str::from_utf8(actual_error_kind.as_bytes()).unwrap(); - let expected_error_kind = std::str::from_utf8(errors::ERR_INCORRECT_NONCE).unwrap(); - - assert_eq!(expected_error_kind, actual_error_kind); - } - - #[test] - fn test_missing_engine_state_is_not_found() { - let storage = Storage::default(); - let storage = RwLock::new(storage); - let io = StoragePointer(&storage); - - let actual_error = get_state(&io).unwrap_err(); - let actual_error = std::str::from_utf8(actual_error.as_ref()).unwrap(); - let expected_error = std::str::from_utf8(errors::ERR_STATE_NOT_FOUND).unwrap(); - assert_eq!(expected_error, actual_error); + assert_eq!(actual_error_kind.as_bytes(), errors::ERR_INCORRECT_NONCE); } #[test] - fn test_empty_engine_state_is_corrupted() { - let storage = Storage::default(); - let storage = RwLock::new(storage); - let mut io = StoragePointer(&storage); - - io.write_storage(&bytes_to_key(KeyPrefix::Config, STATE_KEY), &[]); - let actual_error = get_state(&io).unwrap_err(); - let actual_error = std::str::from_utf8(actual_error.as_ref()).unwrap(); - let expected_error = std::str::from_utf8(errors::ERR_STATE_CORRUPTED).unwrap(); - - assert_eq!(expected_error, actual_error); + fn test_create_legacy_address() { + // Aurora transaction hash (aurorascan.dev): 0xfc94bb484a9b144b1588a2d7238a497b425db343f0217ab66eb6e5171b3b4645 + let caller = Address::decode("3160f7328df59c14d85dfd09addad4ef18ae3e2c").unwrap(); + let nonce = U256::from_dec_str("109438").unwrap(); + let created_address = create_legacy_address(&caller, &nonce); + + assert_eq!( + created_address.encode(), + "140e8a21d08cbb530929b012581a7c7e696145ef" + ); } #[test] fn test_filtering_promises_from_logs_with_none_keeps_all() { - let storage = Storage::default(); - let storage = RwLock::new(storage); + let storage = RefCell::new(Storage::default()); let io = StoragePointer(&storage); let current_account_id = AccountId::default(); let mut handler = Noop; let logs = vec![Log { - address: Default::default(), + address: H160::default(), topics: vec![], data: vec![], }]; let actual_logs = filter_promises_from_logs(&io, &mut handler, logs, ¤t_account_id); let expected_logs = vec![ResultLog { - address: Default::default(), + address: Address::default(), topics: vec![], data: vec![], }]; assert_eq!(expected_logs, actual_logs); } - - fn create_legacy_address(address: H160, nonce: U256) -> H160 { - let mut stream = rlp::RlpStream::new_list(2); - stream.append(&address); - stream.append(&nonce); - H256::from_slice(Keccak256::digest(&stream.out()).as_slice()).into() - } } diff --git a/engine/src/errors.rs b/engine/src/errors.rs index 57993de31..5387f23c9 100644 --- a/engine/src/errors.rs +++ b/engine/src/errors.rs @@ -1,3 +1,7 @@ +pub use aurora_engine_types::parameters::engine::errors::{ + ERR_CALL_TOO_DEEP, ERR_OUT_OF_FUNDS, ERR_OUT_OF_GAS, ERR_OUT_OF_OFFSET, ERR_REVERT, +}; + pub const ERR_NOT_A_JSON_TYPE: &[u8; 19] = b"ERR_NOT_A_JSON_TYPE"; pub const ERR_JSON_MISSING_VALUE: &[u8; 22] = b"ERR_JSON_MISSING_VALUE"; pub const ERR_FAILED_PARSE_U8: &[u8; 19] = b"ERR_FAILED_PARSE_U8"; @@ -32,11 +36,8 @@ pub const ERR_STACK_OVERFLOW: &[u8; 18] = b"ERR_STACK_OVERFLOW"; pub const ERR_INVALID_JUMP: &[u8; 16] = b"ERR_INVALID_JUMP"; 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_CALL_TOO_DEEP: &[u8; 17] = b"ERR_CALL_TOO_DEEP"; 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_OUT_OF_OFFSET: &[u8; 17] = b"ERR_OUT_OF_OFFSET"; -pub const ERR_OUT_OF_GAS: &[u8; 14] = b"ERR_OUT_OF_GAS"; pub const ERR_OUT_OF_FUND: &[u8; 15] = b"ERR_OUT_OF_FUND"; pub const ERR_NOT_SUPPORTED: &[u8; 17] = b"ERR_NOT_SUPPORTED"; pub const ERR_UNHANDLED_INTERRUPT: &[u8; 23] = b"ERR_UNHANDLED_INTERRUPT"; @@ -82,8 +83,6 @@ pub const ERR_NO_AVAILABLE_BALANCE: &[u8; 24] = b"ERR_NO_AVAILABLE_BALANCE"; pub const ERR_ATTACHED_DEPOSIT_NOT_ENOUGH: &[u8; 31] = b"ERR_ATTACHED_DEPOSIT_NOT_ENOUGH"; pub const ERR_FAILED_UNREGISTER_ACCOUNT_POSITIVE_BALANCE: &[u8; 46] = b"ERR_FAILED_UNREGISTER_ACCOUNT_POSITIVE_BALANCE"; +pub const ERR_SAME_OWNER: &[u8; 14] = b"ERR_SAME_OWNER"; pub const ERR_ACCOUNTS_COUNTER_OVERFLOW: &str = "ERR_ACCOUNTS_COUNTER_OVERFLOW"; - -pub const ERR_REVERT: &[u8; 10] = b"ERR_REVERT"; -pub const ERR_OUT_OF_FUNDS: &[u8; 16] = b"ERR_OUT_OF_FUNDS"; diff --git a/engine/src/fungible_token.rs b/engine/src/fungible_token.rs index 045e68aec..1f63006ea 100644 --- a/engine/src/fungible_token.rs +++ b/engine/src/fungible_token.rs @@ -1,18 +1,18 @@ use crate::connector::ZERO_ATTACHED_BALANCE; use crate::engine; -use crate::json::{parse_json, JsonValue}; use crate::parameters::{NEP141FtOnTransferArgs, ResolveTransferCallArgs, StorageBalance}; use crate::prelude::account_id::AccountId; use crate::prelude::Wei; use crate::prelude::{ - sdk, storage, vec, Address, BTreeMap, Balance, BorshDeserialize, BorshSerialize, NearGas, - PromiseAction, PromiseBatchAction, PromiseCreateArgs, PromiseResult, PromiseWithCallbackArgs, + sdk, storage, vec, Address, Balance, BorshDeserialize, BorshSerialize, NearGas, PromiseAction, + PromiseBatchAction, PromiseCreateArgs, PromiseResult, PromiseWithCallbackArgs, StorageBalanceBounds, StorageUsage, String, ToString, Vec, }; use aurora_engine_sdk::io::{StorageIntermediate, IO}; use aurora_engine_types::types::{NEP141Wei, Yocto, ZERO_NEP141_WEI, ZERO_YOCTO}; +use serde::{Deserialize, Serialize}; -/// Gas for `resolve_transfer`: 5 TGas +/// Gas for `resolve_transfer`: 5 `TGas` const GAS_FOR_RESOLVE_TRANSFER: NearGas = NearGas::new(5_000_000_000_000); /// Gas for `ft_on_transfer` const GAS_FOR_FT_TRANSFER_CALL: NearGas = NearGas::new(35_000_000_000_000); @@ -56,14 +56,15 @@ pub struct FungibleTokenOps { } /// Fungible token Reference hash type. -/// Used for FungibleTokenMetadata -#[derive(Debug, BorshDeserialize, BorshSerialize, Clone, PartialEq, Eq)] +/// Used for `FungibleTokenMetadata` +#[derive(Debug, BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone, PartialEq, Eq)] pub struct FungibleReferenceHash([u8; 32]); impl FungibleReferenceHash { /// Encode to base64-encoded string + #[must_use] pub fn encode(&self) -> String { - base64::encode(self) + aurora_engine_sdk::base64::encode(self) } } @@ -73,7 +74,7 @@ impl AsRef<[u8]> for FungibleReferenceHash { } } -#[derive(Debug, BorshDeserialize, BorshSerialize, Clone, PartialEq, Eq)] +#[derive(Debug, BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone, PartialEq, Eq)] pub struct FungibleTokenMetadata { pub spec: String, pub name: String, @@ -98,42 +99,6 @@ impl Default for FungibleTokenMetadata { } } -impl From for JsonValue { - fn from(metadata: FungibleTokenMetadata) -> Self { - let mut kvs = BTreeMap::new(); - kvs.insert("spec".to_string(), JsonValue::String(metadata.spec)); - kvs.insert("name".to_string(), JsonValue::String(metadata.name)); - kvs.insert("symbol".to_string(), JsonValue::String(metadata.symbol)); - kvs.insert( - "icon".to_string(), - metadata - .icon - .map(JsonValue::String) - .unwrap_or(JsonValue::Null), - ); - kvs.insert( - "reference".to_string(), - metadata - .reference - .map(JsonValue::String) - .unwrap_or(JsonValue::Null), - ); - kvs.insert( - "reference_hash".to_string(), - metadata - .reference_hash - .map(|hash| JsonValue::String(hash.encode())) - .unwrap_or(JsonValue::Null), - ); - kvs.insert( - "decimals".to_string(), - JsonValue::U64(u64::from(metadata.decimals)), - ); - - JsonValue::Object(kvs) - } -} - impl FungibleTokenOps { pub fn new(io: I) -> Self { FungibleToken::default().ops(io) @@ -156,7 +121,7 @@ impl FungibleTokenOps { engine::get_balance(&self.io, address) } - /// Internal ETH deposit to NEAR - nETH (NEP-141) + /// Internal ETH deposit to NEAR - `nETH` (NEP-141) pub fn internal_deposit_eth_to_near( &mut self, account_id: &AccountId, @@ -246,7 +211,7 @@ impl FungibleTokenOps { // Register receiver_id account with 0 balance. We need it because // when we retire to get the balance of `receiver_id` it will fail // if it does not exist. - self.internal_register_account(receiver_id) + self.internal_register_account(receiver_id); } self.internal_withdraw_eth_from_near(sender_id, amount)?; self.internal_deposit_eth_to_near(receiver_id, amount)?; @@ -259,14 +224,14 @@ impl FungibleTokenOps { } pub fn internal_register_account(&mut self, account_id: &AccountId) { - self.accounts_insert(account_id, ZERO_NEP141_WEI) + self.accounts_insert(account_id, ZERO_NEP141_WEI); } - pub fn ft_total_eth_supply_on_near(&self) -> NEP141Wei { + pub const fn ft_total_eth_supply_on_near(&self) -> NEP141Wei { self.total_eth_supply_on_near } - pub fn ft_total_eth_supply_on_aurora(&self) -> Wei { + pub const fn ft_total_eth_supply_on_aurora(&self) -> Wei { self.total_eth_supply_on_aurora } @@ -286,16 +251,22 @@ impl FungibleTokenOps { current_account_id: AccountId, prepaid_gas: NearGas, ) -> Result { + // check balance to prevent setting an arbitrary value for `amount` for (receiver_id == receiver_id). + let balance = self + .get_account_eth_balance(&sender_id) + .unwrap_or(ZERO_NEP141_WEI); + if amount > balance { + return Err(error::TransferError::InsufficientFunds); + } // Special case for Aurora transfer itself - we shouldn't transfer if sender_id != receiver_id { self.internal_transfer_eth_on_near(&sender_id, &receiver_id, amount, memo)?; } - let data1: String = NEP141FtOnTransferArgs { + let args = serde_json::to_vec(&NEP141FtOnTransferArgs { + sender_id: sender_id.clone(), amount: Balance::new(amount.as_u128()), msg, - sender_id: sender_id.clone(), - } - .try_into() + }) .unwrap(); let data2 = ResolveTransferCallArgs { @@ -309,7 +280,7 @@ impl FungibleTokenOps { let ft_on_transfer_call = PromiseCreateArgs { target_account_id: receiver_id, method: "ft_on_transfer".to_string(), - args: data1.into_bytes(), + args, attached_balance: ZERO_ATTACHED_BALANCE, attached_gas: prepaid_gas - GAS_FOR_FT_TRANSFER_CALL - GAS_FOR_RESOLVE_TRANSFER, }; @@ -336,20 +307,14 @@ impl FungibleTokenOps { // Get the unused amount from the `ft_on_transfer` call result. let unused_amount = match promise_result { PromiseResult::NotReady => unreachable!(), - PromiseResult::Successful(value) => { - if let Some(raw_unused_amount) = - parse_json(value.as_slice()).and_then(|x| (&x).try_into().ok()) - { - let unused_amount = NEP141Wei::new(raw_unused_amount); - // let unused_amount = Balance::from(raw_unused_amount); + PromiseResult::Successful(bytes) => { + serde_json::from_slice(&bytes).map_or(amount, |unused_amount| { if amount > unused_amount { unused_amount } else { amount } - } else { - amount - } + }) } PromiseResult::Failed => amount, }; @@ -503,24 +468,24 @@ impl FungibleTokenOps { Ok((balance, promise)) } + #[allow(clippy::option_if_let_else)] pub fn storage_withdraw( &mut self, account_id: &AccountId, amount: Option, ) -> Result { - if let Some(storage_balance) = self.internal_storage_balance_of(account_id) { - match amount { + self.internal_storage_balance_of(account_id).map_or( + Err(error::StorageFundingError::NotRegistered), + |storage_balance| match amount { Some(amount) if amount > ZERO_YOCTO => { // The available balance is always zero because `StorageBalanceBounds::max` is - // equal to `StorageBalanceBounds::min`. Therefore it is impossible to withdraw + // equal to `StorageBalanceBounds::min`. Therefore, it is impossible to withdraw // a positive amount. Err(error::StorageFundingError::NoAvailableBalance) } _ => Ok(storage_balance), - } - } else { - Err(error::StorageFundingError::NotRegistered) - } + }, + ) } /// Insert account. @@ -554,7 +519,7 @@ impl FungibleTokenOps { self.io.remove_storage(&Self::account_to_key(account_id)); } - /// Balance of nETH (ETH on NEAR token) + /// Balance of `nETH` (ETH on NEAR token) pub fn get_account_eth_balance(&self, account_id: &AccountId) -> Option { self.io .read_storage(&Self::account_to_key(account_id)) diff --git a/engine/src/json.rs b/engine/src/json.rs deleted file mode 100644 index ad06710a4..000000000 --- a/engine/src/json.rs +++ /dev/null @@ -1,603 +0,0 @@ -use crate::prelude::{BTreeMap, String, Vec}; - -use crate::errors; -use core::convert::From; -use rjson::{Array, Null, Object, Value}; - -#[derive(PartialEq)] -pub enum JsonValue { - Null, - F64(f64), - I64(i64), - U64(u64), - Bool(bool), - String(String), - Array(Vec), - Object(BTreeMap), -} - -#[derive(Ord, PartialOrd, Eq, PartialEq)] -pub enum JsonError { - NotJsonType, - MissingValue, - InvalidU8, - InvalidU64, - InvalidU128, - InvalidBool, - InvalidString, - ExpectedStringGotNumber, - OutOfRange(JsonOutOfRangeError), -} - -#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)] -pub enum JsonOutOfRangeError { - OutOfRangeU8, - OutOfRangeU128, -} - -#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)] -pub enum ParseError { - InvalidAccountId, -} - -pub struct JsonArray(Vec); -pub struct JsonObject(BTreeMap); - -impl JsonValue { - #[allow(dead_code)] - pub fn string(&self, key: &str) -> Result { - match self { - JsonValue::Object(o) => match o.get(key).ok_or(JsonError::MissingValue)? { - JsonValue::String(s) => Ok(s.into()), - _ => Err(JsonError::InvalidString), - }, - _ => Err(JsonError::NotJsonType), - } - } - - #[allow(dead_code)] - pub fn u64(&self, key: &str) -> Result { - match self { - JsonValue::Object(o) => match o.get(key).ok_or(JsonError::MissingValue)? { - JsonValue::U64(n) => Ok(*n), - _ => Err(JsonError::InvalidU64), - }, - _ => Err(JsonError::NotJsonType), - } - } - - #[allow(dead_code)] - pub fn u128(&self, key: &str) -> Result { - match self { - JsonValue::Object(o) => o.get(key).ok_or(JsonError::MissingValue)?.try_into(), - _ => Err(JsonError::NotJsonType), - } - } - - #[allow(dead_code)] - pub fn bool(&self, key: &str) -> Result { - match self { - JsonValue::Object(o) => match o.get(key).ok_or(JsonError::MissingValue)? { - JsonValue::Bool(n) => Ok(*n), - _ => Err(JsonError::InvalidBool), - }, - _ => Err(JsonError::NotJsonType), - } - } - - #[allow(dead_code)] - pub fn parse_u8(v: &JsonValue) -> Result { - match v { - JsonValue::U64(n) => match u8::try_from(*n) { - Ok(v) => Ok(v), - Err(_e) => Err(JsonError::OutOfRange(JsonOutOfRangeError::OutOfRangeU8)), - }, - _ => Err(JsonError::InvalidU8), - } - } -} - -impl AsRef<[u8]> for JsonError { - fn as_ref(&self) -> &[u8] { - match self { - Self::NotJsonType => errors::ERR_NOT_A_JSON_TYPE, - Self::MissingValue => errors::ERR_JSON_MISSING_VALUE, - Self::InvalidU8 => errors::ERR_FAILED_PARSE_U8, - Self::InvalidU64 => errors::ERR_FAILED_PARSE_U64, - Self::InvalidU128 => errors::ERR_FAILED_PARSE_U128, - Self::InvalidBool => errors::ERR_FAILED_PARSE_BOOL, - Self::InvalidString => errors::ERR_FAILED_PARSE_STRING, - Self::ExpectedStringGotNumber => errors::ERR_EXPECTED_STRING_GOT_NUMBER, - Self::OutOfRange(err) => err.as_ref(), - } - } -} - -impl AsRef<[u8]> for JsonOutOfRangeError { - fn as_ref(&self) -> &[u8] { - match self { - Self::OutOfRangeU8 => errors::ERR_OUT_OF_RANGE_U8, - Self::OutOfRangeU128 => errors::ERR_OUT_OF_RANGE_U128, - } - } -} - -impl Array for JsonArray { - fn new() -> Self { - JsonArray(Vec::new()) - } - fn push(&mut self, v: JsonValue) { - self.0.push(v) - } -} - -impl Object for JsonObject { - fn new<'b>() -> Self { - JsonObject(BTreeMap::new()) - } - fn insert(&mut self, k: String, v: JsonValue) { - self.0.insert(k, v); - } -} - -impl Null for JsonValue { - fn new() -> Self { - JsonValue::Null - } -} - -impl Value for JsonValue {} - -impl From for JsonValue { - fn from(v: f64) -> Self { - JsonValue::F64(v) - } -} - -impl From for JsonValue { - fn from(v: i64) -> Self { - JsonValue::I64(v) - } -} - -impl From for JsonValue { - fn from(v: u64) -> Self { - JsonValue::U64(v) - } -} - -impl From for JsonValue { - fn from(v: bool) -> Self { - JsonValue::Bool(v) - } -} - -impl From for JsonValue { - fn from(v: String) -> Self { - JsonValue::String(v) - } -} - -impl From for JsonValue { - fn from(v: JsonArray) -> Self { - JsonValue::Array(v.0) - } -} - -impl From for JsonValue { - fn from(v: JsonObject) -> Self { - JsonValue::Object(v.0) - } -} - -impl TryFrom<&JsonValue> for u128 { - type Error = JsonError; - - fn try_from(value: &JsonValue) -> Result { - match value { - JsonValue::String(n) => { - if let Ok(x) = n.parse::() { - Ok(x) - } else if n.parse::().is_ok() { - Err(JsonError::OutOfRange(JsonOutOfRangeError::OutOfRangeU128)) - } else { - Err(JsonError::InvalidU128) - } - } - JsonValue::F64(_) => Err(JsonError::ExpectedStringGotNumber), - JsonValue::I64(_) => Err(JsonError::ExpectedStringGotNumber), - JsonValue::U64(_) => Err(JsonError::ExpectedStringGotNumber), - _ => Err(JsonError::InvalidU128), - } - } -} - -impl core::fmt::Debug for JsonValue { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - match self { - JsonValue::Null => f.write_str("null"), - JsonValue::String(v) => f.write_fmt(format_args!("\"{}\"", v)), - JsonValue::F64(v) => f.write_fmt(format_args!("{}", v)), - JsonValue::I64(v) => f.write_fmt(format_args!("{}", v)), - JsonValue::U64(v) => f.write_fmt(format_args!("{}", v)), - JsonValue::Bool(v) => f.write_fmt(format_args!("{}", v)), - JsonValue::Array(arr) => { - f.write_str("[")?; - let mut items = arr.iter(); - if let Some(item) = items.next() { - f.write_fmt(format_args!("{:?}", item))?; - } - for item in items { - f.write_fmt(format_args!(", {:?}", item))?; - } - f.write_str("]") - } - JsonValue::Object(kvs) => { - f.write_str("{")?; - let mut pairs = kvs.iter(); - if let Some((key, value)) = pairs.next() { - f.write_fmt(format_args!("\"{}\": {:?}", key, value))?; - } - for (key, value) in pairs { - f.write_fmt(format_args!(", \"{}\": {:?}", key, value))?; - } - f.write_str("}") - } - } - } -} - -impl core::fmt::Display for JsonValue { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - f.write_fmt(format_args!("{:?}", *self)) - } -} - -pub fn parse_json(data: &[u8]) -> Option { - let data_array: Vec = data.iter().map(|b| char::from(*b)).collect::>(); - let mut index = 0; - rjson::parse::(&data_array, &mut index) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_json_all_types_fail_to_parse_missing_key() { - let expected_err = std::str::from_utf8(errors::ERR_JSON_MISSING_VALUE).unwrap(); - let json = parse_json(r#"{"foo": 123}"#.as_bytes()).unwrap(); - - let actual_err = json.string("missing_key").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let actual_err = json.bool("missing_key").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let actual_err = json.u64("missing_key").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let actual_err = json.u128("missing_key").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - } - - #[test] - fn test_json_type_string() { - let json = parse_json(r#"{"foo": "abcd"}"#.as_bytes()).unwrap(); - let string_data = json.string("foo").ok().unwrap(); - assert_eq!(string_data, "abcd"); - - let expected_err = std::str::from_utf8(errors::ERR_FAILED_PARSE_STRING).unwrap(); - let json = parse_json(r#"{"foo": 123}"#.as_bytes()).unwrap(); - let actual_err = json.string("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": true}"#.as_bytes()).unwrap(); - let actual_err = json.string("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": ["abcd"]}"#.as_bytes()).unwrap(); - let actual_err = json.string("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": {}}"#.as_bytes()).unwrap(); - let actual_err = json.string("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": null}"#.as_bytes()).unwrap(); - let actual_err = json.string("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let expected_err = std::str::from_utf8(errors::ERR_NOT_A_JSON_TYPE).unwrap(); - let json = JsonValue::Null; - let actual_err = json.string("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - } - - #[test] - #[should_panic(expected = "overflow")] - fn test_json_type_u64_with_u128_value() { - let _ = parse_json(format!(r#"{{"foo": {} }}"#, u128::MAX).as_bytes()); - } - - #[test] - fn test_json_type_u64() { - let json = parse_json(r#"{"foo": 123}"#.as_bytes()).unwrap(); - let val = json.u64("foo").ok().unwrap(); - assert_eq!(val, 123); - - let json = parse_json(format!(r#"{{"foo": {} }}"#, u64::MAX).as_bytes()).unwrap(); - let val = json.u64("foo").ok().unwrap(); - assert_eq!(val, u64::MAX); - - let expected_err = std::str::from_utf8(errors::ERR_FAILED_PARSE_U64).unwrap(); - let json = parse_json(r#"{"foo": 12.99}"#.as_bytes()).unwrap(); - let actual_err = json.u64("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": -123}"#.as_bytes()).unwrap(); - let actual_err = json.u64("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": "abcd"}"#.as_bytes()).unwrap(); - let actual_err = json.u64("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": "123"}"#.as_bytes()).unwrap(); - let actual_err = json.u64("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": true}"#.as_bytes()).unwrap(); - let actual_err = json.u64("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": [123]}"#.as_bytes()).unwrap(); - let actual_err = json.u64("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": {}}"#.as_bytes()).unwrap(); - let actual_err = json.u64("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": null}"#.as_bytes()).unwrap(); - let actual_err = json.u64("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let expected_err = std::str::from_utf8(errors::ERR_NOT_A_JSON_TYPE).unwrap(); - let json = JsonValue::Null; - let actual_err = json.u64("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - } - - #[test] - fn test_json_type_u128() { - let json = parse_json(r#"{"foo": "123"}"#.as_bytes()).unwrap(); - let val = json.u128("foo").ok().unwrap(); - assert_eq!(val, 123); - - let expected_err = - std::str::from_utf8(JsonOutOfRangeError::OutOfRangeU128.as_ref()).unwrap(); - let json = parse_json(r#"{"foo": "-123"}"#.as_bytes()).unwrap(); - let actual_err = json.u128("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let expected_err = std::str::from_utf8(errors::ERR_EXPECTED_STRING_GOT_NUMBER).unwrap(); - let json = parse_json(r#"{"foo": 123}"#.as_bytes()).unwrap(); - let actual_err = json.u128("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": 12.3}"#.as_bytes()).unwrap(); - let actual_err = json.u128("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let expected_err = std::str::from_utf8(errors::ERR_FAILED_PARSE_U128).unwrap(); - let json = parse_json(r#"{"foo": "12.3"}"#.as_bytes()).unwrap(); - let actual_err = json.u128("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": "abcd"}"#.as_bytes()).unwrap(); - let actual_err = json.u128("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": true}"#.as_bytes()).unwrap(); - let actual_err = json.u128("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": ["123"]}"#.as_bytes()).unwrap(); - let actual_err = json.u128("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": {}}"#.as_bytes()).unwrap(); - let actual_err = json.u128("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": null}"#.as_bytes()).unwrap(); - let actual_err = json.u128("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let expected_err = std::str::from_utf8(errors::ERR_NOT_A_JSON_TYPE).unwrap(); - let json = JsonValue::Null; - let actual_err = json.u128("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - } - - #[test] - fn test_json_type_bool() { - let json = parse_json(r#"{"foo": true}"#.as_bytes()).unwrap(); - let val = json.bool("foo").ok().unwrap(); - assert!(val); - - let json = parse_json(r#"{"foo": false}"#.as_bytes()).unwrap(); - let val = json.bool("foo").ok().unwrap(); - assert!(!val); - - let expected_err = std::str::from_utf8(errors::ERR_FAILED_PARSE_BOOL).unwrap(); - let json = parse_json(r#"{"foo": "true"}"#.as_bytes()).unwrap(); - let actual_err = json.bool("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": "false"}"#.as_bytes()).unwrap(); - let actual_err = json.bool("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": [true]}"#.as_bytes()).unwrap(); - let actual_err = json.bool("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": 123}"#.as_bytes()).unwrap(); - let actual_err = json.bool("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": 12.3}"#.as_bytes()).unwrap(); - let actual_err = json.bool("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": "abcd"}"#.as_bytes()).unwrap(); - let actual_err = json.bool("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": {}}"#.as_bytes()).unwrap(); - let actual_err = json.bool("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let json = parse_json(r#"{"foo": null}"#.as_bytes()).unwrap(); - let actual_err = json.bool("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let expected_err = std::str::from_utf8(errors::ERR_NOT_A_JSON_TYPE).unwrap(); - let json = JsonValue::Null; - let actual_err = json.bool("foo").unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - } - - #[test] - fn test_json_type_u8() { - let json = JsonValue::from(123_u64); - let val = JsonValue::parse_u8(&json).ok().unwrap(); - assert_eq!(val, 123); - - let expected_err = std::str::from_utf8(errors::ERR_FAILED_PARSE_U8).unwrap(); - let json = JsonValue::from(-1_i64); - let actual_err = JsonValue::parse_u8(&json).unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let expected_err = std::str::from_utf8(JsonOutOfRangeError::OutOfRangeU8.as_ref()).unwrap(); - let json = JsonValue::from(256_u64); - let actual_err = JsonValue::parse_u8(&json).unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - - let expected_err = std::str::from_utf8(errors::ERR_FAILED_PARSE_U8).unwrap(); - let json = JsonValue::from("abcd".to_string()); - let actual_err = JsonValue::parse_u8(&json).unwrap_err(); - let actual_err = std::str::from_utf8(actual_err.as_ref()).unwrap(); - assert_eq!(actual_err, expected_err); - } - - #[test] - fn test_json_serialization() { - // Test showing valid json (without trailing commas) is produced from the - // `Display` impl on `JsonValue`. - - // empty object - let object = JsonValue::Object(BTreeMap::new()); - assert_eq!(&format!("{}", object), "{}"); - - // object with 1 field - let object = JsonValue::Object( - vec![("pi".to_string(), JsonValue::F64(std::f64::consts::PI))] - .into_iter() - .collect(), - ); - assert_eq!(&format!("{}", object), "{\"pi\": 3.141592653589793}"); - - // object with 2 fields - let object = JsonValue::Object( - vec![ - ("pi".to_string(), JsonValue::F64(std::f64::consts::PI)), - ("Pie".to_string(), JsonValue::String("Apple".to_string())), - ] - .into_iter() - .collect(), - ); - assert_eq!( - &format!("{}", object), - "{\"Pie\": \"Apple\", \"pi\": 3.141592653589793}" - ); - - // object with empty array - let object = JsonValue::Object( - vec![("empty".to_string(), JsonValue::Array(vec![]))] - .into_iter() - .collect(), - ); - assert_eq!(&format!("{}", object), "{\"empty\": []}"); - - // object with single element array - let object = JsonValue::Object( - vec![( - "numbers".to_string(), - JsonValue::Array(vec![JsonValue::U64(42)]), - )] - .into_iter() - .collect(), - ); - assert_eq!(&format!("{}", object), "{\"numbers\": [42]}"); - - // object with two-element array - let object = JsonValue::Object( - vec![( - "words".to_string(), - JsonValue::Array(vec![ - JsonValue::String("Hello".to_string()), - JsonValue::String("World".to_string()), - ]), - )] - .into_iter() - .collect(), - ); - assert_eq!( - &format!("{}", object), - "{\"words\": [\"Hello\", \"World\"]}" - ); - } -} diff --git a/engine/src/lib.rs b/engine/src/lib.rs index ff133643a..b555c8939 100644 --- a/engine/src/lib.rs +++ b/engine/src/lib.rs @@ -4,7 +4,13 @@ all(feature = "log", target_arch = "wasm32"), feature(panic_info_message) )] -#![deny(clippy::as_conversions)] +#![deny(clippy::pedantic, clippy::nursery)] +#![allow( + clippy::missing_errors_doc, + clippy::missing_panics_doc, + clippy::module_name_repetitions, + clippy::unreadable_literal +)] use aurora_engine_types::parameters::PromiseCreateArgs; @@ -25,10 +31,10 @@ pub mod deposit_event; pub mod engine; pub mod errors; pub mod fungible_token; -pub mod json; pub mod log_entry; pub mod pausables; mod prelude; +pub mod state; pub mod xcc; #[cfg(target_arch = "wasm32")] @@ -69,16 +75,17 @@ pub unsafe fn on_alloc_error(_: core::alloc::Layout) -> ! { #[cfg(feature = "contract")] mod contract { use borsh::{BorshDeserialize, BorshSerialize}; + use parameters::SetOwnerArgs; use crate::connector::{self, EthConnectorContract}; - use crate::engine::{self, Engine, EngineState}; + use crate::engine::{self, Engine}; use crate::fungible_token::FungibleTokenMetadata; - use crate::json::parse_json; + use crate::parameters::error::ParseTypeFromJsonError; use crate::parameters::{ self, CallArgs, DeployErc20TokenArgs, GetErc20FromNep141CallArgs, GetStorageAtArgs, InitCallArgs, IsUsedProofCallArgs, NEP141FtOnTransferArgs, NewCallArgs, PauseEthConnectorCallArgs, PausePrecompilesCallArgs, ResolveTransferCallArgs, - SetContractDataCallArgs, StorageDepositCallArgs, StorageWithdrawCallArgs, + SetContractDataCallArgs, StorageDepositCallArgs, StorageWithdrawCallArgs, SubmitArgs, TransferCallCallArgs, ViewCallArgs, }; #[cfg(feature = "evm_bully")] @@ -93,10 +100,8 @@ mod contract { near_account_to_evm_address, SdkExpect, SdkProcess, SdkUnwrap, }; use crate::prelude::storage::{bytes_to_key, KeyPrefix}; - use crate::prelude::{ - sdk, u256_to_arr, Address, PromiseResult, ToString, Yocto, ERR_FAILED_PARSE, H256, - }; - use crate::{errors, pausables}; + use crate::prelude::{sdk, u256_to_arr, Address, PromiseResult, Yocto, ERR_FAILED_PARSE, H256}; + use crate::{errors, pausables, state}; use aurora_engine_sdk::env::Env; use aurora_engine_sdk::io::{StorageIntermediate, IO}; use aurora_engine_sdk::near_runtime::{Runtime, ViewEnv}; @@ -117,33 +122,46 @@ mod contract { #[no_mangle] pub extern "C" fn new() { let mut io = Runtime; - if let Ok(state) = engine::get_state(&io) { + if let Ok(state) = state::get_state(&io) { require_owner_only(&state, &io.predecessor_account_id()); } let args: NewCallArgs = io.read_input_borsh().sdk_unwrap(); - engine::set_state(&mut io, args.into()); + state::set_state(&mut io, &args.into()).sdk_unwrap(); } /// Get version of the contract. #[no_mangle] pub extern "C" fn get_version() { let mut io = Runtime; - let version = match option_env!("NEAR_EVM_VERSION") { - Some(v) => v.as_bytes(), - None => include_bytes!("../../VERSION"), - }; - io.return_output(version) + let version = option_env!("NEAR_EVM_VERSION") + .map_or(&include_bytes!("../../VERSION")[..], str::as_bytes); + io.return_output(version); } /// Get owner account id for this contract. #[no_mangle] pub extern "C" fn get_owner() { let mut io = Runtime; - let state = engine::get_state(&io).sdk_unwrap(); + let state = state::get_state(&io).sdk_unwrap(); io.return_output(state.owner_id.as_bytes()); } + /// Set owner account id for this contract. + #[no_mangle] + pub extern "C" fn set_owner() { + let mut io = Runtime; + let mut state = state::get_state(&io).sdk_unwrap(); + require_owner_only(&state, &io.predecessor_account_id()); + let args: SetOwnerArgs = io.read_input_borsh().sdk_unwrap(); + if state.owner_id == args.new_owner { + sdk::panic_utf8(errors::ERR_SAME_OWNER); + } else { + state.owner_id = args.new_owner; + state::set_state(&mut io, &state).sdk_unwrap(); + } + } + /// Get bridge prover id for this contract. #[no_mangle] pub extern "C" fn get_bridge_prover() { @@ -156,28 +174,27 @@ mod contract { #[no_mangle] pub extern "C" fn get_chain_id() { let mut io = Runtime; - io.return_output(&engine::get_state(&io).sdk_unwrap().chain_id) + io.return_output(&state::get_state(&io).sdk_unwrap().chain_id); } #[no_mangle] pub extern "C" fn get_upgrade_index() { let mut io = Runtime; - let state = engine::get_state(&io).sdk_unwrap(); let index = internal_get_upgrade_index(); - io.return_output(&(index + state.upgrade_delay_blocks).to_le_bytes()) + io.return_output(&index.to_le_bytes()); } /// Stage new code for deployment. #[no_mangle] pub extern "C" fn stage_upgrade() { let mut io = Runtime; - let state = engine::get_state(&io).sdk_unwrap(); - let block_height = io.block_height(); + let state = state::get_state(&io).sdk_unwrap(); + let delay_block_height = io.block_height() + state.upgrade_delay_blocks; require_owner_only(&state, &io.predecessor_account_id()); io.read_input_and_store(&bytes_to_key(KeyPrefix::Config, CODE_KEY)); io.write_storage( &bytes_to_key(KeyPrefix::Config, CODE_STAGE_KEY), - &block_height.to_le_bytes(), + &delay_block_height.to_le_bytes(), ); } @@ -185,10 +202,10 @@ mod contract { #[no_mangle] pub extern "C" fn deploy_upgrade() { let io = Runtime; - let state = engine::get_state(&io).sdk_unwrap(); + let state = state::get_state(&io).sdk_unwrap(); require_owner_only(&state, &io.predecessor_account_id()); let index = internal_get_upgrade_index(); - if io.block_height() <= index + state.upgrade_delay_blocks { + if io.block_height() <= index { sdk::panic_utf8(errors::ERR_NOT_ALLOWED_TOO_EARLY); } Runtime::self_deploy(&bytes_to_key(KeyPrefix::Config, CODE_KEY)); @@ -198,6 +215,7 @@ mod contract { /// to make any necessary changes to the state such that it aligns with the newly deployed /// code. #[no_mangle] + #[allow(clippy::missing_const_for_fn)] pub extern "C" fn state_migration() { // TODO: currently we don't have migrations } @@ -208,7 +226,7 @@ mod contract { #[no_mangle] pub extern "C" fn resume_precompiles() { let io = Runtime; - let state = engine::get_state(&io).sdk_unwrap(); + let state = state::get_state(&io).sdk_unwrap(); let predecessor_account_id = io.predecessor_account_id(); require_owner_only(&state, &predecessor_account_id); @@ -223,10 +241,10 @@ mod contract { #[no_mangle] pub extern "C" fn pause_precompiles() { let io = Runtime; - let authorizer: pausables::EngineAuthorizer = engine::get_authorizer(); + let authorizer: pausables::EngineAuthorizer = engine::get_authorizer(&io); if !authorizer.is_authorized(&io.predecessor_account_id()) { - sdk::panic_utf8("ERR_UNAUTHORIZED".as_bytes()); + sdk::panic_utf8(b"ERR_UNAUTHORIZED"); } let args: PausePrecompilesCallArgs = io.read_input_borsh().sdk_unwrap(); @@ -275,8 +293,21 @@ mod contract { let bytes = io.read_input().to_vec(); let args = CallArgs::deserialize(&bytes).sdk_expect(errors::ERR_BORSH_DESERIALIZE); let current_account_id = io.current_account_id(); + let predecessor_account_id = io.predecessor_account_id(); + + // During the XCC flow the Engine will call itself to move wNEAR + // to the user's sub-account. We do not want this move to happen + // if prior promises in the flow have failed. + if current_account_id == predecessor_account_id { + let check_promise: Result<(), &[u8]> = match io.promise_result_check() { + Some(true) | None => Ok(()), + Some(false) => Err(b"ERR_CALLBACK_OF_FAILED_PROMISE"), + }; + check_promise.sdk_unwrap(); + } + let mut engine = Engine::new( - predecessor_address(&io.predecessor_account_id()), + predecessor_address(&predecessor_account_id), current_account_id, io, &io, @@ -289,18 +320,46 @@ mod contract { } /// Process signed Ethereum transaction. - /// Must match CHAIN_ID to make sure it's signed for given chain vs replayed from another chain. + /// Must match `CHAIN_ID` to make sure it's signed for given chain vs replayed from another chain. #[no_mangle] pub extern "C" fn submit() { let io = Runtime; - let input = io.read_input().to_vec(); + let tx_data = io.read_input().to_vec(); + let current_account_id = io.current_account_id(); + let state = state::get_state(&io).sdk_unwrap(); + let relayer_address = predecessor_address(&io.predecessor_account_id()); + let args = SubmitArgs { + tx_data, + ..Default::default() + }; + let result = engine::submit( + io, + &io, + &args, + state, + current_account_id, + relayer_address, + &mut Runtime, + ); + + result + .map(|res| res.try_to_vec().sdk_expect(errors::ERR_SERIALIZE)) + .sdk_process(); + } + + /// Analog of the `submit` function, but waits for the `SubmitArgs` structure rather than + /// the array of bytes representing the transaction. + #[no_mangle] + pub extern "C" fn submit_with_args() { + let io = Runtime; + let args: SubmitArgs = io.read_input_borsh().sdk_unwrap(); let current_account_id = io.current_account_id(); - let state = engine::get_state(&io).sdk_unwrap(); + let state = state::get_state(&io).sdk_unwrap(); let relayer_address = predecessor_address(&io.predecessor_account_id()); let result = engine::submit( io, &io, - &input, + &args, state, current_account_id, relayer_address, @@ -338,7 +397,7 @@ mod contract { #[no_mangle] pub extern "C" fn factory_update() { let mut io = Runtime; - let state = engine::get_state(&io).sdk_unwrap(); + let state = state::get_state(&io).sdk_unwrap(); require_owner_only(&state, &io.predecessor_account_id()); let bytes = io.read_input().to_vec(); let router_bytecode = crate::xcc::RouterCode::new(bytes); @@ -350,10 +409,11 @@ mod contract { #[no_mangle] pub extern "C" fn factory_update_address_version() { let mut io = Runtime; + // The function is only set to be private, otherwise callback error will happen. io.assert_private_call().sdk_unwrap(); - let check_deploy: Result<(), &[u8]> = match io.promise_result(0) { - Some(PromiseResult::Successful(_)) => Ok(()), - Some(_) => Err(b"ERR_ROUTER_DEPLOY_FAILED"), + let check_deploy: Result<(), &[u8]> = match io.promise_result_check() { + Some(true) => Ok(()), + Some(false) => Err(b"ERR_ROUTER_DEPLOY_FAILED"), None => Err(b"ERR_ROUTER_UPDATE_NOT_CALLBACK"), }; check_deploy.sdk_unwrap(); @@ -361,22 +421,38 @@ mod contract { crate::xcc::set_code_version_of_address(&mut io, &args.address, args.version); } - /// Sets the address for the wNEAR ERC-20 contract. This contract will be used by the + /// Sets the address for the `wNEAR` ERC-20 contract. This contract will be used by the /// cross-contract calls feature to have users pay for their NEAR transactions. #[no_mangle] pub extern "C" fn factory_set_wnear_address() { let mut io = Runtime; - let state = engine::get_state(&io).sdk_unwrap(); + let state = state::get_state(&io).sdk_unwrap(); require_owner_only(&state, &io.predecessor_account_id()); let address = io.read_input_arr20().sdk_unwrap(); crate::xcc::set_wnear_address(&mut io, &Address::from_array(address)); } + /// 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. + #[no_mangle] + pub extern "C" fn fund_xcc_sub_account() { + let io = Runtime; + let state = state::get_state(&io).sdk_unwrap(); + // This method can only be called by the owner because it allows specifying the + // account ID of the wNEAR account. This information must be accurate for the + // sub-account to work properly, therefore this method can only be called by + // a trusted user. + require_owner_only(&state, &io.predecessor_account_id()); + let args: crate::xcc::FundXccArgs = io.read_input_borsh().sdk_unwrap(); + crate::xcc::fund_xcc_sub_account(&io, &mut Runtime, &io, args).sdk_unwrap(); + } + /// Allow receiving NEP141 tokens to the EVM contract. /// /// This function returns the amount of tokens to return to the sender. - /// Either all tokens are transferred tokens are returned in case of an - /// error, or no token is returned if tx was successful. + /// Either all tokens are transferred and tokens are returned + /// in case of an error, or no token is returned if the transaction was successful. #[no_mangle] pub extern "C" fn ft_on_transfer() { let io = Runtime; @@ -390,9 +466,8 @@ mod contract { ) .sdk_unwrap(); - let args: NEP141FtOnTransferArgs = parse_json(io.read_input().to_vec().as_slice()) - .sdk_unwrap() - .try_into() + let args: NEP141FtOnTransferArgs = serde_json::from_slice(&io.read_input().to_vec()) + .map_err(Into::::into) .sdk_unwrap(); if predecessor_account_id == current_account_id { @@ -447,9 +522,9 @@ mod contract { } else { // Exit call failed; need to refund tokens let args: RefundCallArgs = io.read_input_borsh().sdk_unwrap(); - let state = engine::get_state(&io).sdk_unwrap(); + let state = state::get_state(&io).sdk_unwrap(); let refund_result = - engine::refund_on_error(io, &io, state, args, &mut Runtime).sdk_unwrap(); + engine::refund_on_error(io, &io, state, &args, &mut Runtime).sdk_unwrap(); if !refund_result.status.is_ok() { sdk::panic_utf8(errors::ERR_REFUND_FAILURE); @@ -476,12 +551,12 @@ mod contract { let mut io = Runtime; let block_height = io.read_input_borsh().sdk_unwrap(); let account_id = io.current_account_id(); - let chain_id = engine::get_state(&io) + let chain_id = state::get_state(&io) .map(|state| state.chain_id) .sdk_unwrap(); let block_hash = crate::engine::compute_block_hash(chain_id, block_height, account_id.as_bytes()); - io.return_output(block_hash.as_bytes()) + io.return_output(block_hash.as_bytes()); } #[no_mangle] @@ -489,7 +564,7 @@ mod contract { let mut io = Runtime; let address = io.read_input_arr20().sdk_unwrap(); let code = engine::get_code(&io, &Address::from_array(address)); - io.return_output(&code) + io.return_output(&code); } #[no_mangle] @@ -497,7 +572,7 @@ mod contract { let mut io = Runtime; let address = io.read_input_arr20().sdk_unwrap(); let balance = engine::get_balance(&io, &Address::from_array(address)); - io.return_output(&balance.to_bytes()) + io.return_output(&balance.to_bytes()); } #[no_mangle] @@ -505,7 +580,7 @@ mod contract { let mut io = Runtime; let address = io.read_input_arr20().sdk_unwrap(); let nonce = engine::get_nonce(&io, &Address::from_array(address)); - io.return_output(&u256_to_arr(&nonce)) + io.return_output(&u256_to_arr(&nonce)); } #[no_mangle] @@ -515,7 +590,7 @@ mod contract { let address = args.address; let generation = engine::get_generation(&io, &address); let value = engine::get_storage(&io, &args.address, &H256(args.key), generation); - io.return_output(&value.0) + io.return_output(&value.0); } /// @@ -526,28 +601,28 @@ mod contract { pub extern "C" fn begin_chain() { use crate::prelude::U256; let mut io = Runtime; - let mut state = engine::get_state(&io).sdk_unwrap(); + let mut state = state::get_state(&io).sdk_unwrap(); require_owner_only(&state, &io.predecessor_account_id()); let args: BeginChainArgs = io.read_input_borsh().sdk_unwrap(); state.chain_id = args.chain_id; - engine::set_state(&mut io, state); + state::set_state(&mut io, &state).sdk_unwrap(); // set genesis block balances for account_balance in args.genesis_alloc { engine::set_balance( &mut io, &account_balance.address, &crate::prelude::Wei::new(U256::from(account_balance.balance)), - ) + ); } // return new chain ID - io.return_output(&engine::get_state(&io).sdk_unwrap().chain_id) + io.return_output(&state::get_state(&io).sdk_unwrap().chain_id); } #[cfg(feature = "evm_bully")] #[no_mangle] pub extern "C" fn begin_block() { let io = Runtime; - let state = engine::get_state(&io).sdk_unwrap(); + let state = state::get_state(&io).sdk_unwrap(); require_owner_only(&state, &io.predecessor_account_id()); let _args: BeginBlockArgs = io.read_input_borsh().sdk_unwrap(); // TODO: https://github.com/aurora-is-near/aurora-engine/issues/2 @@ -557,26 +632,33 @@ mod contract { pub extern "C" fn new_eth_connector() { let io = Runtime; // Only the owner can initialize the EthConnector - io.assert_private_call().sdk_unwrap(); + let is_private = io.assert_private_call(); + if is_private.is_err() { + let state = state::get_state(&io).sdk_unwrap(); + require_owner_only(&state, &io.predecessor_account_id()); + } let args: InitCallArgs = io.read_input_borsh().sdk_unwrap(); let owner_id = io.current_account_id(); - EthConnectorContract::create_contract(io, owner_id, args).sdk_unwrap(); + EthConnectorContract::create_contract(io, &owner_id, args).sdk_unwrap(); } #[no_mangle] pub extern "C" fn set_eth_connector_contract_data() { let mut io = Runtime; // Only the owner can set the EthConnector contract data - io.assert_private_call().sdk_unwrap(); + let is_private = io.assert_private_call(); + if is_private.is_err() { + let state = state::get_state(&io).sdk_unwrap(); + require_owner_only(&state, &io.predecessor_account_id()); + } let args: SetContractDataCallArgs = io.read_input_borsh().sdk_unwrap(); connector::set_contract_data(&mut io, args).sdk_unwrap(); } #[no_mangle] - pub extern "C" fn withdraw() { let io = Runtime; io.assert_one_yocto().sdk_unwrap(); @@ -585,7 +667,7 @@ mod contract { let predecessor_account_id = io.predecessor_account_id(); let result = EthConnectorContract::init_instance(io) .sdk_unwrap() - .withdraw_eth_from_near(¤t_account_id, &predecessor_account_id, args) + .withdraw_eth_from_near(¤t_account_id, &predecessor_account_id, &args) .sdk_unwrap(); let result_bytes = result.try_to_vec().sdk_expect(errors::ERR_SERIALIZE); // We intentionally do not go through the `io` struct here because we must bypass @@ -664,7 +746,7 @@ mod contract { let is_used_proof = EthConnectorContract::init_instance(io) .sdk_unwrap() - .is_used_proof(args.proof); + .is_used_proof(&args.proof); let res = is_used_proof.try_to_vec().unwrap(); io.return_output(&res[..]); } @@ -696,13 +778,12 @@ mod contract { #[no_mangle] pub extern "C" fn ft_balance_of() { let io = Runtime; - let args = parameters::BalanceOfCallArgs::try_from( - parse_json(&io.read_input().to_vec()).sdk_unwrap(), - ) - .sdk_unwrap(); + let args: parameters::BalanceOfCallArgs = serde_json::from_slice(&io.read_input().to_vec()) + .map_err(Into::::into) + .sdk_unwrap(); EthConnectorContract::init_instance(io) .sdk_unwrap() - .ft_balance_of(args); + .ft_balance_of(&args); } #[no_mangle] @@ -711,7 +792,7 @@ mod contract { let args: parameters::BalanceOfEthCallArgs = io.read_input().to_value().sdk_unwrap(); EthConnectorContract::init_instance(io) .sdk_unwrap() - .ft_balance_of_eth_on_aurora(args) + .ft_balance_of_eth_on_aurora(&args) .sdk_unwrap(); } @@ -720,13 +801,12 @@ mod contract { let io = Runtime; io.assert_one_yocto().sdk_unwrap(); let predecessor_account_id = io.predecessor_account_id(); - let args = parameters::TransferCallArgs::try_from( - parse_json(&io.read_input().to_vec()).sdk_unwrap(), - ) - .sdk_unwrap(); + let args: parameters::TransferCallArgs = serde_json::from_slice(&io.read_input().to_vec()) + .map_err(Into::::into) + .sdk_unwrap(); EthConnectorContract::init_instance(io) .sdk_unwrap() - .ft_transfer(&predecessor_account_id, args) + .ft_transfer(&predecessor_account_id, &args) .sdk_unwrap(); } @@ -744,20 +824,18 @@ mod contract { EthConnectorContract::init_instance(io) .sdk_unwrap() - .ft_resolve_transfer(args, promise_result); + .ft_resolve_transfer(&args, promise_result); } #[no_mangle] pub extern "C" fn ft_transfer_call() { - use sdk::types::ExpectUtf8; let mut io = Runtime; // Check is payable io.assert_one_yocto().sdk_unwrap(); - let args = TransferCallCallArgs::try_from( - parse_json(&io.read_input().to_vec()).expect_utf8(ERR_FAILED_PARSE.as_bytes()), - ) - .sdk_unwrap(); + let args: TransferCallCallArgs = serde_json::from_slice(&io.read_input().to_vec()) + .map_err(Into::::into) + .sdk_unwrap(); let current_account_id = io.current_account_id(); let predecessor_account_id = io.predecessor_account_id(); let promise_args = EthConnectorContract::init_instance(io) @@ -778,7 +856,9 @@ mod contract { #[no_mangle] pub extern "C" fn storage_deposit() { let mut io = Runtime; - let args = StorageDepositCallArgs::from(parse_json(&io.read_input().to_vec()).sdk_unwrap()); + let args: StorageDepositCallArgs = serde_json::from_slice(&io.read_input().to_vec()) + .map_err(Into::::into) + .sdk_unwrap(); let predecessor_account_id = io.predecessor_account_id(); let amount = Yocto::new(io.attached_deposit()); let maybe_promise = EthConnectorContract::init_instance(io) @@ -797,7 +877,9 @@ mod contract { let mut io = Runtime; io.assert_one_yocto().sdk_unwrap(); let predecessor_account_id = io.predecessor_account_id(); - let force = parse_json(&io.read_input().to_vec()).and_then(|args| args.bool("force").ok()); + let force = serde_json::from_slice::(&io.read_input().to_vec()) + .ok() + .and_then(|args| args["force"].as_bool()); let maybe_promise = EthConnectorContract::init_instance(io) .sdk_unwrap() .storage_unregister(predecessor_account_id, force) @@ -812,25 +894,26 @@ mod contract { pub extern "C" fn storage_withdraw() { let io = Runtime; io.assert_one_yocto().sdk_unwrap(); - let args = - StorageWithdrawCallArgs::from(parse_json(&io.read_input().to_vec()).sdk_unwrap()); + let args: StorageWithdrawCallArgs = serde_json::from_slice(&io.read_input().to_vec()) + .map_err(Into::::into) + .sdk_unwrap(); let predecessor_account_id = io.predecessor_account_id(); EthConnectorContract::init_instance(io) .sdk_unwrap() - .storage_withdraw(&predecessor_account_id, args) - .sdk_unwrap() + .storage_withdraw(&predecessor_account_id, &args) + .sdk_unwrap(); } #[no_mangle] pub extern "C" fn storage_balance_of() { let io = Runtime; - let args = parameters::StorageBalanceOfCallArgs::try_from( - parse_json(&io.read_input().to_vec()).sdk_unwrap(), - ) - .sdk_unwrap(); + let args: parameters::StorageBalanceOfCallArgs = + serde_json::from_slice(&io.read_input().to_vec()) + .map_err(Into::::into) + .sdk_unwrap(); EthConnectorContract::init_instance(io) .sdk_unwrap() - .storage_balance_of(args) + .storage_balance_of(&args); } #[no_mangle] @@ -846,12 +929,15 @@ mod contract { #[no_mangle] pub extern "C" fn set_paused_flags() { let io = Runtime; - io.assert_private_call().sdk_unwrap(); - + let is_private = io.assert_private_call(); + if is_private.is_err() { + let state = state::get_state(&io).sdk_unwrap(); + require_owner_only(&state, &io.predecessor_account_id()); + } let args: PauseEthConnectorCallArgs = io.read_input_borsh().sdk_unwrap(); EthConnectorContract::init_instance(io) .sdk_unwrap() - .set_paused_flags(args); + .set_paused_flags(&args); } #[no_mangle] @@ -891,8 +977,8 @@ mod contract { pub extern "C" fn ft_metadata() { let mut io = Runtime; let metadata: FungibleTokenMetadata = connector::get_metadata(&io).unwrap_or_default(); - let json_data = crate::json::JsonValue::from(metadata); - io.return_output(json_data.to_string().as_bytes()) + let bytes = serde_json::to_vec(&metadata).unwrap_or_default(); + io.return_output(&bytes); } #[cfg(feature = "integration-test")] @@ -946,14 +1032,14 @@ mod contract { }; let verify_call = aurora_engine_types::parameters::PromiseCreateArgs { target_account_id: aurora_account_id.clone(), - method: "verify_log_entry".to_string(), + method: crate::prelude::String::from("verify_log_entry"), args: crate::prelude::Vec::new(), attached_balance: ZERO_ATTACHED_BALANCE, attached_gas: GAS_FOR_VERIFY, }; let finish_call = aurora_engine_types::parameters::PromiseCreateArgs { target_account_id: aurora_account_id, - method: "finish_deposit".to_string(), + method: crate::prelude::String::from("finish_deposit"), args: args.try_to_vec().unwrap(), attached_balance: ZERO_ATTACHED_BALANCE, attached_gas: GAS_FOR_FINISH, @@ -984,7 +1070,7 @@ mod contract { } } - fn require_owner_only(state: &EngineState, predecessor_account_id: &AccountId) { + fn require_owner_only(state: &state::EngineState, predecessor_account_id: &AccountId) { if &state.owner_id != predecessor_account_id { sdk::panic_utf8(errors::ERR_NOT_ALLOWED); } diff --git a/engine/src/log_entry.rs b/engine/src/log_entry.rs index a4d74bee3..8af2ee1e2 100644 --- a/engine/src/log_entry.rs +++ b/engine/src/log_entry.rs @@ -9,7 +9,7 @@ pub struct LogEntry { impl rlp::Decodable for LogEntry { fn decode(rlp: &rlp::Rlp) -> Result { - let result = LogEntry { + let result = Self { address: rlp.val_at(0usize)?, topics: rlp.list_at(1usize)?, data: rlp.val_at(2usize)?, diff --git a/engine/src/map.rs b/engine/src/map.rs index 464f73f81..48d86c18a 100644 --- a/engine/src/map.rs +++ b/engine/src/map.rs @@ -15,7 +15,7 @@ pub struct BijectionMap { impl + TryFrom>, R: AsRef<[u8]> + TryFrom>, I: IO> BijectionMap { - pub fn new(left_prefix: KeyPrefix, right_prefix: KeyPrefix, io: I) -> Self { + pub const fn new(left_prefix: KeyPrefix, right_prefix: KeyPrefix, io: I) -> Self { Self { left_prefix, right_prefix, @@ -66,9 +66,9 @@ mod tests { use aurora_engine_test_doubles::io::{Storage, StoragePointer}; use aurora_engine_types::account_id::AccountId; use aurora_engine_types::types::Address; - use std::sync::RwLock; + use std::cell::RefCell; - let storage = RwLock::new(Storage::default()); + let storage = RefCell::new(Storage::default()); let storage = StoragePointer(&storage); let left_prefix = KeyPrefix::Nep141Erc20Map; let right_prefix = KeyPrefix::Erc20Nep141Map; diff --git a/engine/src/parameters.rs b/engine/src/parameters.rs index 4a6ecfa73..f13038199 100644 --- a/engine/src/parameters.rs +++ b/engine/src/parameters.rs @@ -1,16 +1,14 @@ use crate::admin_controlled::PausedMask; -use crate::errors; use crate::fungible_token::FungibleTokenMetadata; -use crate::json::{JsonError, JsonValue}; use crate::prelude::account_id::AccountId; -use crate::prelude::{ - format, Address, Balance, BorshDeserialize, BorshSerialize, RawH256, RawU256, String, Vec, - WeiU256, -}; +use crate::prelude::{Address, Balance, BorshDeserialize, BorshSerialize, RawU256, String, Vec}; use crate::proof::Proof; +pub use aurora_engine_types::parameters::engine::{ + CallArgs, DeployErc20TokenArgs, FunctionCallArgsV1, FunctionCallArgsV2, + GetErc20FromNep141CallArgs, GetStorageAtArgs, ResultLog, SubmitResult, TransactionStatus, + ViewCallArgs, +}; use aurora_engine_types::types::{Fee, NEP141Wei, Yocto}; -use evm::backend::Log; -#[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; /// Borsh-encoded parameters for the `new` function. @@ -28,166 +26,10 @@ pub struct NewCallArgs { pub upgrade_delay_blocks: u64, } -/// Borsh-encoded log for use in a `SubmitResult`. -#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct ResultLog { - pub address: Address, - pub topics: Vec, - pub data: Vec, -} - -impl From for ResultLog { - fn from(log: Log) -> Self { - let topics = log - .topics - .into_iter() - .map(|topic| topic.0) - .collect::>(); - ResultLog { - address: Address::new(log.address), - topics, - data: log.data, - } - } -} - -/// The status of a transaction. -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub enum TransactionStatus { - Succeed(Vec), - Revert(Vec), - OutOfGas, - OutOfFund, - OutOfOffset, - CallTooDeep, -} - -impl TransactionStatus { - pub fn is_ok(&self) -> bool { - matches!(*self, TransactionStatus::Succeed(_)) - } - - pub fn is_revert(&self) -> bool { - matches!(*self, TransactionStatus::Revert(_)) - } - - pub fn is_fail(&self) -> bool { - *self == TransactionStatus::OutOfGas - || *self == TransactionStatus::OutOfFund - || *self == TransactionStatus::OutOfOffset - || *self == TransactionStatus::CallTooDeep - } -} - -impl AsRef<[u8]> for TransactionStatus { - fn as_ref(&self) -> &[u8] { - match self { - Self::Succeed(_) => b"SUCCESS", - Self::Revert(_) => errors::ERR_REVERT, - Self::OutOfFund => errors::ERR_OUT_OF_FUNDS, - Self::OutOfGas => errors::ERR_OUT_OF_GAS, - Self::OutOfOffset => errors::ERR_OUT_OF_OFFSET, - Self::CallTooDeep => errors::ERR_CALL_TOO_DEEP, - } - } -} - -/// Borsh-encoded parameters for the `call`, `call_with_args`, `deploy_code`, -/// and `deploy_with_input` methods. -#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct SubmitResult { - version: u8, - pub status: TransactionStatus, - pub gas_used: u64, - pub logs: Vec, -} - -impl SubmitResult { - /// Must be incremented when making breaking changes to the SubmitResult ABI. - /// The current value of 7 is chosen because previously a `TransactionStatus` object - /// was first in the serialization, which is an enum with less than 7 variants. - /// Therefore, no previous `SubmitResult` would have began with a leading 7 byte, - /// and this can be used to distinguish the new ABI (with version byte) from the old. - const VERSION: u8 = 7; - - pub fn new(status: TransactionStatus, gas_used: u64, logs: Vec) -> Self { - Self { - version: Self::VERSION, - status, - gas_used, - logs, - } - } -} - -/// Borsh-encoded parameters for the engine `call` function. -#[derive(BorshSerialize, BorshDeserialize, Debug, PartialEq, Eq, Clone)] -pub struct FunctionCallArgsV2 { - pub contract: Address, - /// Wei compatible Borsh-encoded value field to attach an ETH balance to the transaction - pub value: WeiU256, - pub input: Vec, -} - -/// Legacy Borsh-encoded parameters for the engine `call` function, to provide backward type compatibility -#[derive(BorshSerialize, BorshDeserialize, Debug, PartialEq, Eq, Clone)] -pub struct FunctionCallArgsV1 { - pub contract: Address, - pub input: Vec, -} - -/// Deserialized values from bytes to current or legacy Borsh-encoded parameters -/// for passing to the engine `call` function, and to provide backward type compatibility -#[derive(BorshSerialize, BorshDeserialize, Debug, PartialEq, Eq, Clone)] -pub enum CallArgs { - V2(FunctionCallArgsV2), - V1(FunctionCallArgsV1), -} - -impl CallArgs { - pub fn deserialize(bytes: &[u8]) -> Option { - // For handling new input format (wrapped into call args enum) - for data structures with new arguments, - // made for flexibility and extensibility. - if let Ok(value) = Self::try_from_slice(bytes) { - Some(value) - // Fallback, for handling old input format, - // i.e. input, formed as a raw (not wrapped into call args enum) data structure with legacy arguments, - // made for backward compatibility. - } else if let Ok(value) = FunctionCallArgsV1::try_from_slice(bytes) { - Some(Self::V1(value)) - // Dealing with unrecognized input should be handled and result as an exception in a call site. - } else { - None - } - } -} - -/// Borsh-encoded parameters for the `view` function. -#[derive(BorshSerialize, BorshDeserialize, Debug, Eq, PartialEq)] -pub struct ViewCallArgs { - pub sender: Address, - pub address: Address, - pub amount: RawU256, - pub input: Vec, -} - -/// Borsh-encoded parameters for `deploy_erc20_token` function. -#[derive(BorshSerialize, BorshDeserialize, Debug, Eq, PartialEq, Clone)] -pub struct DeployErc20TokenArgs { - pub nep141: AccountId, -} - -/// Borsh-encoded parameters for `get_erc20_from_nep141` function. -pub type GetErc20FromNep141CallArgs = DeployErc20TokenArgs; - -/// Borsh-encoded parameters for the `get_storage_at` function. -#[derive(BorshSerialize, BorshDeserialize)] -pub struct GetStorageAtArgs { - pub address: Address, - pub key: RawH256, +/// Borsh-encoded parameters for the `set_owner` function. +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Serialize, Deserialize)] +pub struct SetOwnerArgs { + pub new_owner: AccountId, } /// Borsh-encoded (genesis) account balance used by the `begin_chain` function. @@ -198,6 +40,17 @@ pub struct AccountBalance { pub balance: RawU256, } +/// Borsh-encoded submit arguments used by the `submit_with_args` function. +#[derive(Default, Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +pub struct SubmitArgs { + /// Bytes of the transaction. + pub tx_data: Vec, + /// Max gas price the user is ready to pay for the transaction. + pub max_gas_price: Option, + /// Address of the `ERC20` token the user prefers to pay in. + pub gas_token_address: Option
, +} + /// Borsh-encoded parameters for the `begin_chain` function. #[cfg(feature = "evm_bully")] #[derive(BorshSerialize, BorshDeserialize)] @@ -226,7 +79,7 @@ pub struct BeginBlockArgs { /// Borsh-encoded parameters for the `ft_transfer_call` function /// for regular NEP-141 tokens. -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq)] pub struct NEP141FtOnTransferArgs { pub sender_id: AccountId, /// Balance can be for Eth on Near and for Eth to Aurora @@ -235,31 +88,6 @@ pub struct NEP141FtOnTransferArgs { pub msg: String, } -impl TryFrom for NEP141FtOnTransferArgs { - type Error = JsonError; - - fn try_from(value: JsonValue) -> Result { - Ok(Self { - sender_id: AccountId::try_from(value.string("sender_id")?) - .map_err(|_| JsonError::InvalidString)?, - amount: Balance::new(value.u128("amount")?), - msg: value.string("msg")?, - }) - } -} - -impl From for String { - fn from(value: NEP141FtOnTransferArgs) -> Self { - format!( - r#"{{"sender_id": "{}", "amount": "{}", "msg": "{}"}}"#, - value.sender_id, - value.amount, - // Escape message to avoid json injection attacks - value.msg.replace('\\', "\\\\").replace('"', "\\\"") - ) - } -} - /// Eth-connector deposit arguments #[derive(BorshSerialize, BorshDeserialize)] pub struct DepositCallArgs { @@ -269,7 +97,7 @@ pub struct DepositCallArgs { pub relayer_eth_account: Option
, } -/// Eth-connector isUsedProof arguments +/// Eth-connector `isUsedProof` arguments #[derive(BorshSerialize, BorshDeserialize)] pub struct IsUsedProofCallArgs { /// Proof data @@ -286,23 +114,20 @@ pub struct WithdrawResult { } /// Fungible token storage balance -#[derive(Default)] +#[derive(Default, Deserialize, Serialize)] pub struct StorageBalance { pub total: Yocto, pub available: Yocto, } impl StorageBalance { + #[must_use] pub fn to_json_bytes(&self) -> Vec { - format!( - "{{\"total\": \"{}\", \"available\": \"{}\"}}", - self.total, self.available - ) - .into_bytes() + serde_json::to_vec(self).unwrap_or_default() } } -/// ft_resolve_transfer eth-connector call args +/// `ft_resolve_transfer` eth-connector call args #[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] pub struct ResolveTransferCallArgs { pub sender_id: AccountId, @@ -310,18 +135,6 @@ pub struct ResolveTransferCallArgs { pub receiver_id: AccountId, } -impl TryFrom for ResolveTransferCallArgs { - type Error = error::ParseTypeFromJsonError; - - fn try_from(v: JsonValue) -> Result { - Ok(Self { - sender_id: AccountId::try_from(v.string("sender_id")?)?, - receiver_id: AccountId::try_from(v.string("receiver_id")?)?, - amount: NEP141Wei::new(v.u128("amount")?), - }) - } -} - /// Finish deposit NEAR eth-connector call args #[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] pub struct FinishDepositCallArgs { @@ -362,7 +175,7 @@ pub struct InitCallArgs { pub type SetContractDataCallArgs = InitCallArgs; /// transfer eth-connector call args -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq)] pub struct TransferCallCallArgs { pub receiver_id: AccountId, pub amount: NEP141Wei, @@ -370,122 +183,50 @@ pub struct TransferCallCallArgs { pub msg: String, } -impl TryFrom for TransferCallCallArgs { - type Error = error::ParseTypeFromJsonError; - - fn try_from(v: JsonValue) -> Result { - let receiver_id = AccountId::try_from(v.string("receiver_id")?)?; - let amount = NEP141Wei::new(v.u128("amount")?); - let memo = v.string("memo").ok(); - let msg = v.string("msg")?; - Ok(Self { - receiver_id, - amount, - memo, - msg, - }) - } -} - -/// storage_balance_of eth-connector call args -#[derive(BorshSerialize, BorshDeserialize)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +/// `storage_balance_of` eth-connector call args +#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize)] pub struct StorageBalanceOfCallArgs { pub account_id: AccountId, } -impl TryFrom for StorageBalanceOfCallArgs { - type Error = error::ParseTypeFromJsonError; - - fn try_from(v: JsonValue) -> Result { - let account_id = AccountId::try_from(v.string("account_id")?)?; - Ok(Self { account_id }) - } -} - -/// storage_deposit eth-connector call args -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] +/// `storage_deposit` eth-connector call args +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq)] pub struct StorageDepositCallArgs { pub account_id: Option, pub registration_only: Option, } -impl From for StorageDepositCallArgs { - fn from(v: JsonValue) -> Self { - Self { - account_id: v - .string("account_id") - .map_or(None, |acc| AccountId::try_from(acc).ok()), - registration_only: v.bool("registration_only").ok(), - } - } -} - -/// storage_withdraw eth-connector call args -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] +/// `storage_withdraw` eth-connector call args +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq)] pub struct StorageWithdrawCallArgs { pub amount: Option, } -impl From for StorageWithdrawCallArgs { - fn from(v: JsonValue) -> Self { - Self { - amount: v.u128("amount").map(Yocto::new).ok(), - } - } -} - /// transfer args for json invocation -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq)] pub struct TransferCallArgs { pub receiver_id: AccountId, pub amount: NEP141Wei, pub memo: Option, } -impl TryFrom for TransferCallArgs { - type Error = error::ParseTypeFromJsonError; - - fn try_from(v: JsonValue) -> Result { - Ok(Self { - receiver_id: AccountId::try_from(v.string("receiver_id")?)?, - amount: NEP141Wei::new(v.u128("amount")?), - memo: v.string("memo").ok(), - }) - } -} - -/// balance_of args for json invocation -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +/// `balance_of` args for json invocation +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Serialize, Deserialize)] pub struct BalanceOfCallArgs { pub account_id: AccountId, } -#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Serialize, Deserialize)] pub struct BalanceOfEthCallArgs { pub address: Address, } -impl TryFrom for BalanceOfCallArgs { - type Error = error::ParseTypeFromJsonError; - - fn try_from(v: JsonValue) -> Result { - Ok(Self { - account_id: AccountId::try_from(v.string("account_id")?)?, - }) - } -} - #[derive(BorshSerialize, BorshDeserialize)] pub struct RegisterRelayerCallArgs { pub address: Address, } -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Serialize, Deserialize)] pub struct PauseEthConnectorCallArgs { pub paused_mask: PausedMask, } @@ -496,17 +237,17 @@ pub struct PausePrecompilesCallArgs { } pub mod error { - use crate::json::JsonError; - use aurora_engine_types::account_id::ParseAccountError; + use aurora_engine_types::{account_id::ParseAccountError, String, ToString}; + #[derive(Debug)] pub enum ParseTypeFromJsonError { - Json(JsonError), + Json(String), InvalidAccount(ParseAccountError), } - impl From for ParseTypeFromJsonError { - fn from(e: JsonError) -> Self { - Self::Json(e) + impl From for ParseTypeFromJsonError { + fn from(e: serde_json::Error) -> Self { + Self::Json(e.to_string()) } } @@ -519,76 +260,9 @@ pub mod error { impl AsRef<[u8]> for ParseTypeFromJsonError { fn as_ref(&self) -> &[u8] { match self { - Self::Json(e) => e.as_ref(), + Self::Json(e) => e.as_bytes(), Self::InvalidAccount(e) => e.as_ref(), } } } } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_view_call_fail() { - let bytes = [0; 71]; - let _ = ViewCallArgs::try_from_slice(&bytes).unwrap_err(); - } - - #[test] - fn test_roundtrip_view_call() { - let x = ViewCallArgs { - sender: Address::from_array([1; 20]), - address: Address::from_array([2; 20]), - amount: [3; 32], - input: vec![1, 2, 3], - }; - let bytes = x.try_to_vec().unwrap(); - let res = ViewCallArgs::try_from_slice(&bytes).unwrap(); - assert_eq!(x, res); - } - - #[test] - fn test_call_args_deserialize() { - let new_input = FunctionCallArgsV2 { - contract: Address::from_array([0u8; 20]), - value: WeiU256::default(), - input: Vec::new(), - }; - let legacy_input = FunctionCallArgsV1 { - contract: Address::from_array([0u8; 20]), - input: Vec::new(), - }; - - // Parsing bytes in a new input format - data structures (wrapped into call args enum) with new arguments, - // made for flexibility and extensibility. - - // Using new input format (wrapped into call args enum) and data structure with new argument (`value` field). - let input_bytes = CallArgs::V2(new_input.clone()).try_to_vec().unwrap(); - let parsed_data = CallArgs::deserialize(&input_bytes); - assert_eq!(parsed_data, Some(CallArgs::V2(new_input.clone()))); - - // Using new input format (wrapped into call args enum) and old data structure with legacy arguments, - // this is allowed for compatibility reason. - let input_bytes = CallArgs::V1(legacy_input.clone()).try_to_vec().unwrap(); - let parsed_data = CallArgs::deserialize(&input_bytes); - assert_eq!(parsed_data, Some(CallArgs::V1(legacy_input.clone()))); - - // Parsing bytes in an old input format - raw data structure (not wrapped into call args enum) with legacy arguments, - // made for backward compatibility. - - // Using old input format (not wrapped into call args enum) - raw data structure with legacy arguments. - let input_bytes = legacy_input.try_to_vec().unwrap(); - let parsed_data = CallArgs::deserialize(&input_bytes); - assert_eq!(parsed_data, Some(CallArgs::V1(legacy_input))); - - // Using old input format (not wrapped into call args enum) - raw data structure with new argument (`value` field). - // Data structures with new arguments allowed only in new input format for future extensibility reason. - // Raw data structure (old input format) allowed only with legacy arguments for backward compatibility reason. - // Unrecognized input should be handled and result as an exception in a call site. - let input_bytes = new_input.try_to_vec().unwrap(); - let parsed_data = CallArgs::deserialize(&input_bytes); - assert_eq!(parsed_data, None); - } -} diff --git a/engine/src/pausables.rs b/engine/src/pausables.rs index 297c237c9..459b5af23 100644 --- a/engine/src/pausables.rs +++ b/engine/src/pausables.rs @@ -15,22 +15,21 @@ bitflags! { } impl PrecompileFlags { + #[must_use] pub fn from_address(address: &Address) -> Option { Some(if address == &exit_to_ethereum::ADDRESS { - PrecompileFlags::EXIT_TO_ETHEREUM + Self::EXIT_TO_ETHEREUM } else if address == &exit_to_near::ADDRESS { - PrecompileFlags::EXIT_TO_NEAR + Self::EXIT_TO_NEAR } else { return None; }) } /// Checks if the precompile belonging to the `address` is marked as paused. + #[must_use] pub fn is_paused_by_address(&self, address: &Address) -> bool { - match Self::from_address(address) { - Some(precompile_flag) => self.contains(precompile_flag), - None => false, - } + Self::from_address(address).map_or(false, |precompile_flag| self.contains(precompile_flag)) } } @@ -89,7 +88,7 @@ pub struct EngineAuthorizer { } impl EngineAuthorizer { - /// Creates new [EngineAuthorizer] and grants permission to pause precompiles for all given `accounts`. + /// Creates new [`EngineAuthorizer`] and grants permission to pause precompiles for all given `accounts`. pub fn from_accounts(accounts: impl Iterator) -> Self { Self { acl: accounts.collect(), @@ -104,31 +103,24 @@ pub struct EnginePrecompilesPauser { } impl EnginePrecompilesPauser { - /// Key for storing [PrecompileFlags]. + /// Key for storing [`PrecompileFlags`]. const PAUSE_FLAGS_KEY: &'static [u8; 11] = b"PAUSE_FLAGS"; - /// Creates new [EnginePrecompilesPauser] instance that reads from and writes into storage accessed using `io`. - pub fn from_io(io: I) -> Self { + /// Creates new [`EnginePrecompilesPauser`] instance that reads from and writes into storage accessed using `io`. + pub const fn from_io(io: I) -> Self { Self { io } } fn read_flags_from_storage(&self) -> PrecompileFlags { - match self.io.read_storage(&Self::storage_key()) { - None => PrecompileFlags::empty(), - Some(bytes) => { - let int_length = core::mem::size_of::(); - let input = bytes.to_vec(); - - if input.len() < int_length { - return PrecompileFlags::empty(); - } - - let (int_bytes, _) = input.split_at(int_length); - PrecompileFlags::from_bits_truncate(u32::from_le_bytes( - int_bytes.try_into().unwrap(), - )) - } - } + self.io + .read_storage(&Self::storage_key()) + .map_or_else(PrecompileFlags::empty, |bytes| { + const U32_SIZE: usize = core::mem::size_of::(); + assert_eq!(bytes.len(), U32_SIZE, "PrecompileFlags value is corrupted"); + let mut buffer = [0u8; U32_SIZE]; + bytes.copy_to_slice(&mut buffer); + PrecompileFlags::from_bits_truncate(u32::from_le_bytes(buffer)) + }) } fn write_flags_into_storage(&mut self, pause_flags: PrecompileFlags) { @@ -175,8 +167,8 @@ impl PausedPrecompilesManager for EnginePrecompilesPauser { mod tests { use super::*; use aurora_engine_test_doubles::io::{Storage, StoragePointer}; + use std::cell::RefCell; use std::iter::once; - use std::sync::RwLock; use test_case::test_case; #[test_case(PrecompileFlags::EXIT_TO_ETHEREUM, exit_to_ethereum::ADDRESS)] @@ -198,7 +190,7 @@ mod tests { #[test] fn test_pausing_precompile_marks_it_as_paused() { - let storage = RwLock::new(Storage::default()); + let storage = RefCell::new(Storage::default()); let io = StoragePointer(&storage); let mut pauser = EnginePrecompilesPauser::from_io(io); let flags = PrecompileFlags::EXIT_TO_NEAR; @@ -210,7 +202,7 @@ mod tests { #[test] fn test_resuming_precompile_removes_its_mark_as_paused() { - let storage = RwLock::new(Storage::default()); + let storage = RefCell::new(Storage::default()); let io = StoragePointer(&storage); let mut pauser = EnginePrecompilesPauser::from_io(io); let flags = PrecompileFlags::EXIT_TO_NEAR; @@ -238,15 +230,13 @@ mod tests { } #[test] + #[should_panic] fn test_no_precompile_is_paused_if_storage_contains_too_few_bytes() { let key = EnginePrecompilesPauser::::storage_key(); - let storage = RwLock::new(Storage::default()); + let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); io.write_storage(key.as_slice(), &[7u8]); let pauser = EnginePrecompilesPauser::from_io(io); - - let expected_paused = PrecompileFlags::empty(); - let actual_paused = pauser.paused(); - assert_eq!(expected_paused, actual_paused); + let _paused = pauser.paused(); // panic here !!! } } diff --git a/engine/src/proof.rs b/engine/src/proof.rs index c7d3365c6..507dc2789 100644 --- a/engine/src/proof.rs +++ b/engine/src/proof.rs @@ -12,6 +12,7 @@ pub struct Proof { } impl Proof { + #[must_use] pub fn key(&self) -> String { let mut data = self.log_index.try_to_vec().unwrap(); data.extend(self.receipt_index.try_to_vec().unwrap()); @@ -19,7 +20,7 @@ impl Proof { sdk::sha256(&data[..]) .0 .iter() - .map(|n| n.to_string()) + .map(ToString::to_string) .collect() } } diff --git a/engine/src/state.rs b/engine/src/state.rs new file mode 100644 index 000000000..166d4bf10 --- /dev/null +++ b/engine/src/state.rs @@ -0,0 +1,122 @@ +use crate::parameters::NewCallArgs; +use aurora_engine_sdk::io::{StorageIntermediate, IO}; +use aurora_engine_types::account_id::AccountId; +use aurora_engine_types::storage::{bytes_to_key, KeyPrefix}; +use borsh::{BorshDeserialize, BorshSerialize}; + +pub use error::EngineStateError; + +/// Key for storing the state of the engine. +const STATE_KEY: &[u8; 5] = b"STATE"; + +/// Engine internal state, mostly configuration. +/// Should not contain anything large or enumerable. +#[derive(BorshSerialize, BorshDeserialize, Default, Clone, PartialEq, Eq, Debug)] +pub struct EngineState { + /// Chain id, according to the EIP-155 / ethereum-lists spec. + pub chain_id: [u8; 32], + /// Account which can upgrade this contract. + /// Use empty to disable updatability. + pub owner_id: AccountId, + /// Account of the bridge prover. + /// Use empty to not use base token as bridged asset. + pub bridge_prover_id: AccountId, + /// How many blocks after staging upgrade can deploy it. + pub upgrade_delay_blocks: u64, +} + +impl From for EngineState { + fn from(args: NewCallArgs) -> Self { + Self { + chain_id: args.chain_id, + owner_id: args.owner_id, + bridge_prover_id: args.bridge_prover_id, + upgrade_delay_blocks: args.upgrade_delay_blocks, + } + } +} + +/// Gets the state from storage, if it exists otherwise it will error. +pub fn get_state(io: &I) -> Result { + io.read_storage(&bytes_to_key(KeyPrefix::Config, STATE_KEY)) + .map_or_else( + || Err(EngineStateError::NotFound), + |bytes| { + EngineState::try_from_slice(&bytes.to_vec()) + .map_err(|_| EngineStateError::DeserializationFailed) + }, + ) +} + +/// Saves state into the storage. Does not return the previous state. +pub fn set_state(io: &mut I, state: &EngineState) -> Result<(), EngineStateError> { + io.write_storage( + &bytes_to_key(KeyPrefix::Config, STATE_KEY), + &state + .try_to_vec() + .map_err(|_| error::EngineStateError::SerializationFailed)?, + ); + + Ok(()) +} + +/// Engine state error module. +pub mod error { + pub const ERR_STATE_NOT_FOUND: &[u8; 19] = b"ERR_STATE_NOT_FOUND"; + pub const ERR_STATE_SERIALIZATION_FAILED: &[u8; 26] = b"ERR_STATE_SERIALIZE_FAILED"; + pub const ERR_STATE_CORRUPTED: &[u8; 19] = b"ERR_STATE_CORRUPTED"; + + #[derive(Debug)] + /// Engine state error kinds. + pub enum EngineStateError { + /// The engine state is missing from storage, need to initialize with contract `new` method. + NotFound, + /// The engine state serialized had failed. + SerializationFailed, + /// The state of the engine is corrupted, possibly due to failed state migration. + DeserializationFailed, + } + + impl AsRef<[u8]> for EngineStateError { + fn as_ref(&self) -> &[u8] { + match self { + Self::NotFound => ERR_STATE_NOT_FOUND, + Self::SerializationFailed => ERR_STATE_SERIALIZATION_FAILED, + Self::DeserializationFailed => ERR_STATE_CORRUPTED, + } + } + } +} + +#[cfg(test)] +#[cfg(feature = "std")] +mod tests { + use super::*; + use aurora_engine_test_doubles::io::{Storage, StoragePointer}; + use std::cell::RefCell; + + #[test] + fn test_missing_engine_state_is_not_found() { + let storage = RefCell::new(Storage::default()); + let io = StoragePointer(&storage); + + let actual_error = get_state(&io).unwrap_err(); + let actual_error = std::str::from_utf8(actual_error.as_ref()).unwrap(); + let expected_error = std::str::from_utf8(error::ERR_STATE_NOT_FOUND).unwrap(); + + assert_eq!(expected_error, actual_error); + } + + #[test] + fn test_empty_engine_state_is_corrupted() { + let storage = RefCell::new(Storage::default()); + let mut io = StoragePointer(&storage); + + io.write_storage(&bytes_to_key(KeyPrefix::Config, STATE_KEY), &[]); + let actual_error = get_state(&io).unwrap_err(); + let actual_error = std::str::from_utf8(actual_error.as_ref()).unwrap(); + let expected_error = std::str::from_utf8(error::ERR_STATE_CORRUPTED).unwrap(); + + assert_eq!(expected_error, actual_error); + } +} diff --git a/engine/src/xcc.rs b/engine/src/xcc.rs index 514a0bdc9..8bc30ec59 100644 --- a/engine/src/xcc.rs +++ b/engine/src/xcc.rs @@ -1,5 +1,7 @@ +use crate::errors::ERR_SERIALIZE; use crate::parameters::{CallArgs, FunctionCallArgsV2}; -use aurora_engine_precompiles::xcc::state; +use aurora_engine_precompiles::xcc::state::{self, ERR_MISSING_WNEAR_ADDRESS}; +use aurora_engine_sdk::env::Env; use aurora_engine_sdk::io::{StorageIntermediate, IO}; use aurora_engine_sdk::promise::PromiseHandler; use aurora_engine_types::account_id::AccountId; @@ -18,8 +20,8 @@ pub const VERSION_UPDATE_GAS: NearGas = NearGas::new(5_000_000_000_000); pub const INITIALIZE_GAS: NearGas = NearGas::new(15_000_000_000_000); pub const UNWRAP_AND_REFUND_GAS: NearGas = NearGas::new(25_000_000_000_000); pub const WITHDRAW_GAS: NearGas = NearGas::new(30_000_000_000_000); -/// Solidity selector for the withdrawToNear function -/// https://www.4byte.directory/signatures/?bytes4_signature=0x6b351848 +/// Solidity selector for the `withdrawToNear` function +/// `https://www.4byte.directory/signatures/?bytes4_signature=0x6b351848` pub const WITHDRAW_TO_NEAR_SELECTOR: [u8; 4] = [0x6b, 0x35, 0x18, 0x48]; pub use aurora_engine_precompiles::xcc::state::{ @@ -32,11 +34,13 @@ pub use aurora_engine_precompiles::xcc::state::{ pub struct RouterCode<'a>(pub Cow<'a, [u8]>); impl<'a> RouterCode<'a> { + #[must_use] pub fn new(bytes: Vec) -> Self { Self(Cow::Owned(bytes)) } - pub fn borrowed(bytes: &'a [u8]) -> Self { + #[must_use] + pub const fn borrowed(bytes: &'a [u8]) -> Self { Self(Cow::Borrowed(bytes)) } } @@ -47,10 +51,119 @@ pub struct AddressVersionUpdateArgs { pub version: CodeVersion, } +#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize)] +pub struct FundXccArgs { + pub target: Address, + pub wnear_account_id: Option, +} + +pub fn fund_xcc_sub_account( + io: &I, + handler: &mut P, + env: &E, + args: FundXccArgs, +) -> Result<(), FundXccError> +where + P: PromiseHandler, + I: IO + Copy, + E: Env, +{ + let current_account_id = env.current_account_id(); + let target_account_id = AccountId::new(&format!( + "{}.{}", + args.target.encode(), + current_account_id.as_ref() + ))?; + + let latest_code_version = get_latest_code_version(io); + let target_code_version = get_code_version_of_address(io, &args.target); + let deploy_needed = AddressVersionStatus::new(latest_code_version, target_code_version); + + let fund_amount = Yocto::new(env.attached_deposit()); + + let mut promise_actions = Vec::with_capacity(4); + + // If account needs to be created and/or updated then include those actions. + if let AddressVersionStatus::DeployNeeded { create_needed } = deploy_needed { + if create_needed { + if fund_amount < STORAGE_AMOUNT { + return Err(FundXccError::InsufficientBalance); + } + + promise_actions.push(PromiseAction::CreateAccount); + } + promise_actions.push(PromiseAction::Transfer { + amount: fund_amount, + }); + promise_actions.push(PromiseAction::DeployContract { + code: get_router_code(io).0.into_owned(), + }); + // Either we need to assume it is set in the Engine or we need to accept it as input. + let wnear_account = if let Some(wnear_account) = args.wnear_account_id { + wnear_account + } else { + // If the wnear account is not specified then we must look it up based on the + // bridged token registry for the engine. + let wnear_address = get_wnear_address(io); + crate::engine::nep141_erc20_map(*io) + .lookup_right(&crate::engine::ERC20Address(wnear_address)) + .ok_or(FundXccError::MissingWNearAddress)? + .0 + }; + let init_args = format!( + r#"{{"wnear_account": "{}", "must_register": {}}}"#, + wnear_account.as_ref(), + create_needed, + ); + promise_actions.push(PromiseAction::FunctionCall { + name: "initialize".into(), + args: init_args.into_bytes(), + attached_yocto: ZERO_YOCTO, + gas: INITIALIZE_GAS, + }); + } else { + // No matter what include the transfer of the funding amount + promise_actions.push(PromiseAction::Transfer { + amount: fund_amount, + }); + } + + let batch = PromiseBatchAction { + target_account_id, + actions: promise_actions, + }; + // Safety: same as safety in `handle_precompile_promise` + let promise_id = unsafe { handler.promise_create_batch(&batch) }; + + if let AddressVersionStatus::DeployNeeded { .. } = deploy_needed { + // If a create and/or deploy was needed then we must attach a callback to update + // the Engine's record of the account. + + let args = AddressVersionUpdateArgs { + address: args.target, + version: latest_code_version, + }; + let callback = PromiseCreateArgs { + target_account_id: current_account_id, + method: "factory_update_address_version".into(), + args: args + .try_to_vec() + .map_err(|_| FundXccError::SerializationFailure)?, + attached_balance: ZERO_YOCTO, + attached_gas: VERSION_UPDATE_GAS, + }; + // Safety: same as safety in `handle_precompile_promise` + let _promise_id = unsafe { handler.promise_attach_callback(promise_id, &callback) }; + } + + Ok(()) +} + +#[allow(clippy::too_many_lines)] pub fn handle_precompile_promise( io: &I, handler: &mut P, - promise: PromiseCreateArgs, + promise: &PromiseCreateArgs, required_near: Yocto, current_account_id: &AccountId, ) where @@ -62,32 +175,19 @@ pub fn handle_precompile_promise( // Confirm target_account is of the form `{address}.{aurora}` // Address prefix parsed above, so only need to check `.{aurora}` - assert_eq!(&target_account[40..41], ".", "{}", ERR_INVALID_ACCOUNT); + assert_eq!(&target_account[40..41], ".", "{ERR_INVALID_ACCOUNT}"); assert_eq!( &target_account[41..], current_account_id.as_ref(), - "{}", - ERR_INVALID_ACCOUNT + "{ERR_INVALID_ACCOUNT}" ); // Confirm there is 0 NEAR attached to the promise // (the precompile should not drain the engine's balance). - assert_eq!( - promise.attached_balance, ZERO_YOCTO, - "{}", - ERR_ATTACHED_NEAR - ); + assert_eq!(promise.attached_balance, ZERO_YOCTO, "{ERR_ATTACHED_NEAR}"); let latest_code_version = get_latest_code_version(io); let sender_code_version = get_code_version_of_address(io, &sender); - let deploy_needed = match sender_code_version { - None => AddressVersionStatus::DeployNeeded { - create_needed: true, - }, - Some(version) if version < latest_code_version => AddressVersionStatus::DeployNeeded { - create_needed: false, - }, - Some(_version) => AddressVersionStatus::UpToDate, - }; + let deploy_needed = AddressVersionStatus::new(latest_code_version, sender_code_version); // 1. If the router contract account does not exist or is out of date then we start // with a batch transaction to deploy the router. This batch also has an attached // callback to update the engine's storage with the new version of that router account. @@ -103,8 +203,8 @@ pub fn handle_precompile_promise( promise_actions.push(PromiseAction::DeployContract { code: get_router_code(io).0.into_owned(), }); - // After a deploy we call the contract's initialize function - let wnear_address = state::get_wnear_address(io); + // After the deployment we call the contract's initialize function + let wnear_address = get_wnear_address(io); let wnear_account = crate::engine::nep141_erc20_map(*io) .lookup_right(&crate::engine::ERC20Address(wnear_address)) .unwrap(); @@ -210,8 +310,8 @@ pub fn handle_precompile_promise( // the engine make arbitrary calls. let _promise_id = unsafe { match withdraw_id { - None => handler.promise_create_call(&promise), - Some(withdraw_id) => handler.promise_attach_callback(withdraw_id, &promise), + None => handler.promise_create_call(promise), + Some(withdraw_id) => handler.promise_attach_callback(withdraw_id, promise), } }; } @@ -232,7 +332,7 @@ pub fn update_router_code(io: &mut I, code: &RouterCode) { set_latest_code_version(io, current_version.increment()); } -/// Set the address of the wNEAR ERC-20 contract +/// Set the address of the `wNEAR` ERC-20 contract pub fn set_wnear_address(io: &mut I, address: &Address) { let key = storage::bytes_to_key(KeyPrefix::CrossContractCall, WNEAR_KEY); io.write_storage(&key, address.as_bytes()); @@ -245,6 +345,31 @@ pub fn set_code_version_of_address(io: &mut I, address: &Address, version io.write_storage(&key, &value_bytes); } +#[derive(Debug, Clone, Copy)] +pub enum FundXccError { + InsufficientBalance, + InvalidAccount, + MissingWNearAddress, + SerializationFailure, +} + +impl From for FundXccError { + fn from(_: aurora_engine_types::account_id::ParseAccountError) -> Self { + Self::InvalidAccount + } +} + +impl AsRef<[u8]> for FundXccError { + fn as_ref(&self) -> &[u8] { + match self { + Self::InsufficientBalance => b"ERR_INSUFFICIENT_FUNDING_OF_NEW_XCC_ACCOUNT", + Self::InvalidAccount => ERR_INVALID_ACCOUNT.as_bytes(), + Self::MissingWNearAddress => ERR_MISSING_WNEAR_ADDRESS.as_bytes(), + Self::SerializationFailure => ERR_SERIALIZE.as_bytes(), + } + } +} + /// Sets the latest router contract version. This function is intentionally private because /// it should never be set manually. The version is managed automatically by `update_router_code`. fn set_latest_code_version(io: &mut I, version: CodeVersion) { @@ -259,6 +384,20 @@ enum AddressVersionStatus { DeployNeeded { create_needed: bool }, } +impl AddressVersionStatus { + fn new(latest_code_version: CodeVersion, target_code_version: Option) -> Self { + match target_code_version { + None => Self::DeployNeeded { + create_needed: true, + }, + Some(version) if version < latest_code_version => Self::DeployNeeded { + create_needed: false, + }, + Some(_version) => Self::UpToDate, + } + } +} + fn withdraw_to_near_args(recipient: &AccountId, amount: Yocto) -> Vec { let args = ethabi::encode(&[ ethabi::Token::Bytes(recipient.as_bytes().to_vec()), diff --git a/etc/eth-contracts/.solhint.json b/etc/eth-contracts/.solhint.json new file mode 100644 index 000000000..ce11a730f --- /dev/null +++ b/etc/eth-contracts/.solhint.json @@ -0,0 +1,8 @@ +{ + "extends": "solhint:recommended", + "rules": { + "compiler-version": ["error", "^0.8.0"], + "func-visibility": ["warn", { "ignoreConstructors": true }], + "not-rely-on-time": false + } +} diff --git a/etc/eth-contracts/.solhintignore b/etc/eth-contracts/.solhintignore new file mode 100644 index 000000000..3c3629e64 --- /dev/null +++ b/etc/eth-contracts/.solhintignore @@ -0,0 +1 @@ +node_modules diff --git a/etc/eth-contracts/contracts/AdminControlled.sol b/etc/eth-contracts/contracts/AdminControlled.sol index 079367f0a..35090e8fd 100644 --- a/etc/eth-contracts/contracts/AdminControlled.sol +++ b/etc/eth-contracts/contracts/AdminControlled.sol @@ -3,10 +3,12 @@ pragma solidity ^0.8.0; contract AdminControlled { + // slither-disable-next-line immutable-states address public admin; uint public paused; constructor(address _admin, uint flags) { + // slither-disable-next-line missing-zero-check admin = _admin; // Add the possibility to set pause flags on the initialization @@ -34,12 +36,14 @@ contract AdminControlled { } function adminSendEth(address payable destination, uint amount) public onlyAdmin { + // slither-disable-next-line missing-zero-check destination.transfer(amount); } function adminReceiveEth() public payable onlyAdmin {} function adminDelegatecall(address target, bytes memory data) public payable onlyAdmin returns (bytes memory) { + // slither-disable-next-line controlled-delegatecall,low-level-calls,missing-zero-check (bool success, bytes memory rdata) = target.delegatecall(data); require(success); return rdata; diff --git a/etc/eth-contracts/contracts/EvmErc20.sol b/etc/eth-contracts/contracts/EvmErc20.sol index 58443774b..80af3653a 100644 --- a/etc/eth-contracts/contracts/EvmErc20.sol +++ b/etc/eth-contracts/contracts/EvmErc20.sol @@ -17,6 +17,7 @@ contract EvmErc20 is ERC20, AdminControlled, IExit { string private _symbol; uint8 private _decimals; + // slither-disable-next-line shadowing-local constructor (string memory metadata_name, string memory metadata_symbol, uint8 metadata_decimals, address admin) ERC20(metadata_name, metadata_symbol) AdminControlled(admin, 0) @@ -38,6 +39,7 @@ contract EvmErc20 is ERC20, AdminControlled, IExit { return _decimals; } + // slither-disable-next-line events-maths function setMetadata(string memory metadata_name, string memory metadata_symbol, uint8 metadata_decimals) external onlyAdmin { _name = metadata_name; _symbol = metadata_symbol; diff --git a/etc/eth-contracts/contracts/EvmErc20V2.sol b/etc/eth-contracts/contracts/EvmErc20V2.sol index 8a6155445..0621e28fe 100644 --- a/etc/eth-contracts/contracts/EvmErc20V2.sol +++ b/etc/eth-contracts/contracts/EvmErc20V2.sol @@ -17,6 +17,7 @@ contract EvmErc20V2 is ERC20, AdminControlled, IExit { string private _symbol; uint8 private _decimals; + // slither-disable-next-line shadowing-local constructor (string memory metadata_name, string memory metadata_symbol, uint8 metadata_decimals, address admin) ERC20(metadata_name, metadata_symbol) AdminControlled(admin, 0) @@ -38,6 +39,7 @@ contract EvmErc20V2 is ERC20, AdminControlled, IExit { return _decimals; } + // slither-disable-next-line events-maths function setMetadata(string memory metadata_name, string memory metadata_symbol, uint8 metadata_decimals) external onlyAdmin { _name = metadata_name; _symbol = metadata_symbol; diff --git a/etc/eth-contracts/package.json b/etc/eth-contracts/package.json index da735939d..9ec3d69f1 100644 --- a/etc/eth-contracts/package.json +++ b/etc/eth-contracts/package.json @@ -18,12 +18,12 @@ "eth-gas-reporter": "^0.2.25", "ethereum-waffle": "^3.4.4", "ethers": "^5.6.9", - "hardhat": "^2.12.0", + "hardhat": "^2.12.7", "hardhat-storage-layout": "^0.1.6", "rainbow-bridge-lib": "^3.0.0", "solc": "0.8.15", + "solhint": "^3.3.8", "solidity-coverage": "^0.7.21", - "solium": "^1.2.5", "typescript": ">=3.7.0" }, "scripts": { @@ -33,8 +33,8 @@ "coverage": "hardhat coverage", "lint:js": "eslint .", "lint:js:fix": "eslint . --fix", - "lint:sol": "solium -d .", - "lint:sol:fix": "solium -d . --fix", + "lint:sol": "solhint 'contracts/**/*.sol'", + "lint:sol:fix": "solhint --fix 'contracts/**/*.sol'", "lint": "yarn lint:js && yarn lint:sol", "lint:fix": "yarn lint:js:fix && yarn lint:sol:fix" } diff --git a/etc/eth-contracts/res/EvmErc20.bin b/etc/eth-contracts/res/EvmErc20.bin index b0786ce5d..2cfa548e2 100644 Binary files a/etc/eth-contracts/res/EvmErc20.bin and b/etc/eth-contracts/res/EvmErc20.bin differ diff --git a/etc/eth-contracts/res/EvmErc20.hex b/etc/eth-contracts/res/EvmErc20.hex index c444e090c..0c49d136b 100644 --- a/etc/eth-contracts/res/EvmErc20.hex +++ b/etc/eth-contracts/res/EvmErc20.hex @@ -1 +1 @@ -0x60806040523480156200001157600080fd5b506040516200181a3803806200181a833981016040819052620000349162000186565b80600085856003620000478382620002b9565b506004620000568282620002b9565b5050600580546001600160a01b0319166001600160a01b0394909416939093179092556006555060076200008b8582620002b9565b5060086200009a8482620002b9565b50506009805460ff191660ff9290921691909117905550620003859050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000e157600080fd5b81516001600160401b0380821115620000fe57620000fe620000b9565b604051601f8301601f19908116603f01168101908282118183101715620001295762000129620000b9565b816040528381526020925086838588010111156200014657600080fd5b600091505b838210156200016a57858201830151818301840152908201906200014b565b838211156200017c5760008385830101525b9695505050505050565b600080600080608085870312156200019d57600080fd5b84516001600160401b0380821115620001b557600080fd5b620001c388838901620000cf565b95506020870151915080821115620001da57600080fd5b50620001e987828801620000cf565b935050604085015160ff811681146200020157600080fd5b60608601519092506001600160a01b03811681146200021f57600080fd5b939692955090935050565b600181811c908216806200023f57607f821691505b6020821081036200026057634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002b457600081815260208120601f850160051c810160208610156200028f5750805b601f850160051c820191505b81811015620002b0578281556001016200029b565b5050505b505050565b81516001600160401b03811115620002d557620002d5620000b9565b620002ed81620002e684546200022a565b8462000266565b602080601f8311600181146200032557600084156200030c5750858301515b600019600386901b1c1916600185901b178555620002b0565b600085815260208120601f198616915b82811015620003565788860151825594840194600190910190840162000335565b5085821015620003755787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b61148580620003956000396000f3fe6080604052600436106101755760003560e01c80636b351848116100cb578063a9059cbb1161007f578063dd62ed3e11610059578063dd62ed3e146103ec578063f48ab4e014610432578063f851a4401461043a57600080fd5b8063a9059cbb14610399578063b8e9744c146103b9578063be831a2e146103cc57600080fd5b80638d32caf4116100b05780638d32caf41461034457806395d89b4114610364578063a457c2d71461037957600080fd5b80636b351848146102ee57806370a082311461030e57600080fd5b8063313ce5671161012d57806340c10f191161010757806340c10f1914610298578063530208f2146102b85780635c975abb146102d857600080fd5b8063313ce5671461023657806337d2c2f414610258578063395093511461027857600080fd5b806318160ddd1161015e57806318160ddd146101d557806323b872dd146101f45780632692c59f1461021457600080fd5b806306fdde031461017a578063095ea7b3146101a5575b600080fd5b34801561018657600080fd5b5061018f610472565b60405161019c9190610f90565b60405180910390f35b3480156101b157600080fd5b506101c56101c0366004610fc2565b610504565b604051901515815260200161019c565b3480156101e157600080fd5b506002545b60405190815260200161019c565b34801561020057600080fd5b506101c561020f366004610fee565b61051c565b34801561022057600080fd5b5061023461022f36600461102f565b610540565b005b34801561024257600080fd5b5060095460405160ff909116815260200161019c565b34801561026457600080fd5b506102346102733660046110eb565b61055c565b34801561028457600080fd5b506101c5610293366004610fc2565b6105a5565b3480156102a457600080fd5b506102346102b3366004610fc2565b6105e4565b3480156102c457600080fd5b506102346102d3366004610fc2565b610609565b3480156102e457600080fd5b506101e660065481565b3480156102fa57600080fd5b50610234610309366004611169565b61065b565b34801561031a57600080fd5b506101e66103293660046111ae565b6001600160a01b031660009081526020819052604090205490565b34801561035057600080fd5b5061023461035f366004610fc2565b6106cb565b34801561037057600080fd5b5061018f610747565b34801561038557600080fd5b506101c5610394366004610fc2565b610756565b3480156103a557600080fd5b506101c56103b4366004610fc2565b610805565b61018f6103c73660046111cb565b610813565b3480156103d857600080fd5b506102346103e736600461121b565b61089f565b3480156103f857600080fd5b506101e661040736600461123d565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6102346108ba565b34801561044657600080fd5b5060055461045a906001600160a01b031681565b6040516001600160a01b03909116815260200161019c565b60606007805461048190611276565b80601f01602080910402602001604051908101604052809291908181526020018280546104ad90611276565b80156104fa5780601f106104cf576101008083540402835291602001916104fa565b820191906000526020600020905b8154815290600101906020018083116104dd57829003601f168201915b5050505050905090565b6000336105128185856108d3565b5060019392505050565b60003361052a858285610a2b565b610535858585610abd565b506001949350505050565b6005546001600160a01b0316331461055757600080fd5b600655565b6005546001600160a01b0316331461057357600080fd5b600761057f84826112fe565b50600861058c83826112fe565b506009805460ff191660ff929092169190911790555050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490919061051290829086906105df9087906113d4565b6108d3565b6005546001600160a01b031633146105fb57600080fd5b6106058282610cd4565b5050565b6005546001600160a01b0316331461062057600080fd5b6040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015610656573d6000803e3d6000fd5b505050565b610666335b82610db3565b604051819060009061067e90839086906020016113ec565b604051602081830303815290604052905060008451602161069f91906113d4565b9050602060008260208501600073e9217bc70b7ed1f598ddd3199e80b093fa71124f5af1505050505050565b6106d433610660565b604051600160f81b602082015260218101829052606083901b6bffffffffffffffffffffffff1981166041830152829160009060550160408051601f198184030181529190529050603560206000828285018273b0bd02f6a392af548bdf1cfaee5dfa0eefcc8eab5af150505050505050565b60606008805461048190611276565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909190838110156107f85760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61053582868684036108d3565b600033610512818585610abd565b6005546060906001600160a01b0316331461082d57600080fd5b600080846001600160a01b031684604051610848919061141c565b600060405180830381855af49150503d8060008114610883576040519150601f19603f3d011682016040523d82523d6000602084013e610888565b606091505b50915091508161089757600080fd5b949350505050565b6005546001600160a01b031633146108b657600080fd5b9055565b6005546001600160a01b031633146108d157600080fd5b565b6001600160a01b03831661094e5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016107ef565b6001600160a01b0382166109ca5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016107ef565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b038381166000908152600160209081526040808320938616835292905220546000198114610ab75781811015610aaa5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016107ef565b610ab784848484036108d3565b50505050565b6001600160a01b038316610b395760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016107ef565b6001600160a01b038216610bb55760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016107ef565b6001600160a01b03831660009081526020819052604090205481811015610c445760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016107ef565b6001600160a01b03808516600090815260208190526040808220858503905591851681529081208054849290610c7b9084906113d4565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610cc791815260200190565b60405180910390a3610ab7565b6001600160a01b038216610d2a5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016107ef565b8060026000828254610d3c91906113d4565b90915550506001600160a01b03821660009081526020819052604081208054839290610d699084906113d4565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b038216610e2f5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016107ef565b6001600160a01b03821660009081526020819052604090205481811015610ebe5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016107ef565b6001600160a01b0383166000908152602081905260408120838303905560028054849290610eed908490611438565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b60005b83811015610f53578181015183820152602001610f3b565b83811115610ab75750506000910152565b60008151808452610f7c816020860160208601610f38565b601f01601f19169290920160200192915050565b602081526000610fa36020830184610f64565b9392505050565b6001600160a01b0381168114610fbf57600080fd5b50565b60008060408385031215610fd557600080fd5b8235610fe081610faa565b946020939093013593505050565b60008060006060848603121561100357600080fd5b833561100e81610faa565b9250602084013561101e81610faa565b929592945050506040919091013590565b60006020828403121561104157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261106f57600080fd5b813567ffffffffffffffff8082111561108a5761108a611048565b604051601f8301601f19908116603f011681019082821181831017156110b2576110b2611048565b816040528381528660208588010111156110cb57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561110057600080fd5b833567ffffffffffffffff8082111561111857600080fd5b6111248783880161105e565b9450602086013591508082111561113a57600080fd5b506111478682870161105e565b925050604084013560ff8116811461115e57600080fd5b809150509250925092565b6000806040838503121561117c57600080fd5b823567ffffffffffffffff81111561119357600080fd5b61119f8582860161105e565b95602094909401359450505050565b6000602082840312156111c057600080fd5b8135610fa381610faa565b600080604083850312156111de57600080fd5b82356111e981610faa565b9150602083013567ffffffffffffffff81111561120557600080fd5b6112118582860161105e565b9150509250929050565b6000806040838503121561122e57600080fd5b50508035926020909101359150565b6000806040838503121561125057600080fd5b823561125b81610faa565b9150602083013561126b81610faa565b809150509250929050565b600181811c9082168061128a57607f821691505b6020821081036112aa57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561065657600081815260208120601f850160051c810160208610156112d75750805b601f850160051c820191505b818110156112f6578281556001016112e3565b505050505050565b815167ffffffffffffffff81111561131857611318611048565b61132c816113268454611276565b846112b0565b602080601f83116001811461136157600084156113495750858301515b600019600386901b1c1916600185901b1785556112f6565b600085815260208120601f198616915b8281101561139057888601518255948401946001909101908401611371565b50858210156113ae5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b600082198211156113e7576113e76113be565b500190565b600160f81b81528260018201526000825161140e816021850160208701610f38565b919091016021019392505050565b6000825161142e818460208701610f38565b9190910192915050565b60008282101561144a5761144a6113be565b50039056fea2646970667358221220b231e3177ebd68f3996750307b59e00d2cf6edfa54922a143d1cd57e24842b5e64736f6c634300080f0033 \ No newline at end of file +0x60806040523480156200001157600080fd5b506040516200181a3803806200181a833981016040819052620000349162000186565b80600085856003620000478382620002b9565b506004620000568282620002b9565b5050600580546001600160a01b0319166001600160a01b0394909416939093179092556006555060076200008b8582620002b9565b5060086200009a8482620002b9565b50506009805460ff191660ff9290921691909117905550620003859050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000e157600080fd5b81516001600160401b0380821115620000fe57620000fe620000b9565b604051601f8301601f19908116603f01168101908282118183101715620001295762000129620000b9565b816040528381526020925086838588010111156200014657600080fd5b600091505b838210156200016a57858201830151818301840152908201906200014b565b838211156200017c5760008385830101525b9695505050505050565b600080600080608085870312156200019d57600080fd5b84516001600160401b0380821115620001b557600080fd5b620001c388838901620000cf565b95506020870151915080821115620001da57600080fd5b50620001e987828801620000cf565b935050604085015160ff811681146200020157600080fd5b60608601519092506001600160a01b03811681146200021f57600080fd5b939692955090935050565b600181811c908216806200023f57607f821691505b6020821081036200026057634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002b457600081815260208120601f850160051c810160208610156200028f5750805b601f850160051c820191505b81811015620002b0578281556001016200029b565b5050505b505050565b81516001600160401b03811115620002d557620002d5620000b9565b620002ed81620002e684546200022a565b8462000266565b602080601f8311600181146200032557600084156200030c5750858301515b600019600386901b1c1916600185901b178555620002b0565b600085815260208120601f198616915b82811015620003565788860151825594840194600190910190840162000335565b5085821015620003755787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b61148580620003956000396000f3fe6080604052600436106101755760003560e01c80636b351848116100cb578063a9059cbb1161007f578063dd62ed3e11610059578063dd62ed3e146103ec578063f48ab4e014610432578063f851a4401461043a57600080fd5b8063a9059cbb14610399578063b8e9744c146103b9578063be831a2e146103cc57600080fd5b80638d32caf4116100b05780638d32caf41461034457806395d89b4114610364578063a457c2d71461037957600080fd5b80636b351848146102ee57806370a082311461030e57600080fd5b8063313ce5671161012d57806340c10f191161010757806340c10f1914610298578063530208f2146102b85780635c975abb146102d857600080fd5b8063313ce5671461023657806337d2c2f414610258578063395093511461027857600080fd5b806318160ddd1161015e57806318160ddd146101d557806323b872dd146101f45780632692c59f1461021457600080fd5b806306fdde031461017a578063095ea7b3146101a5575b600080fd5b34801561018657600080fd5b5061018f610472565b60405161019c9190610f90565b60405180910390f35b3480156101b157600080fd5b506101c56101c0366004610fc2565b610504565b604051901515815260200161019c565b3480156101e157600080fd5b506002545b60405190815260200161019c565b34801561020057600080fd5b506101c561020f366004610fee565b61051c565b34801561022057600080fd5b5061023461022f36600461102f565b610540565b005b34801561024257600080fd5b5060095460405160ff909116815260200161019c565b34801561026457600080fd5b506102346102733660046110eb565b61055c565b34801561028457600080fd5b506101c5610293366004610fc2565b6105a5565b3480156102a457600080fd5b506102346102b3366004610fc2565b6105e4565b3480156102c457600080fd5b506102346102d3366004610fc2565b610609565b3480156102e457600080fd5b506101e660065481565b3480156102fa57600080fd5b50610234610309366004611169565b61065b565b34801561031a57600080fd5b506101e66103293660046111ae565b6001600160a01b031660009081526020819052604090205490565b34801561035057600080fd5b5061023461035f366004610fc2565b6106cb565b34801561037057600080fd5b5061018f610747565b34801561038557600080fd5b506101c5610394366004610fc2565b610756565b3480156103a557600080fd5b506101c56103b4366004610fc2565b610805565b61018f6103c73660046111cb565b610813565b3480156103d857600080fd5b506102346103e736600461121b565b61089f565b3480156103f857600080fd5b506101e661040736600461123d565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6102346108ba565b34801561044657600080fd5b5060055461045a906001600160a01b031681565b6040516001600160a01b03909116815260200161019c565b60606007805461048190611276565b80601f01602080910402602001604051908101604052809291908181526020018280546104ad90611276565b80156104fa5780601f106104cf576101008083540402835291602001916104fa565b820191906000526020600020905b8154815290600101906020018083116104dd57829003601f168201915b5050505050905090565b6000336105128185856108d3565b5060019392505050565b60003361052a858285610a2b565b610535858585610abd565b506001949350505050565b6005546001600160a01b0316331461055757600080fd5b600655565b6005546001600160a01b0316331461057357600080fd5b600761057f84826112fe565b50600861058c83826112fe565b506009805460ff191660ff929092169190911790555050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490919061051290829086906105df9087906113d4565b6108d3565b6005546001600160a01b031633146105fb57600080fd5b6106058282610cd4565b5050565b6005546001600160a01b0316331461062057600080fd5b6040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015610656573d6000803e3d6000fd5b505050565b610666335b82610db3565b604051819060009061067e90839086906020016113ec565b604051602081830303815290604052905060008451602161069f91906113d4565b9050602060008260208501600073e9217bc70b7ed1f598ddd3199e80b093fa71124f5af1505050505050565b6106d433610660565b604051600160f81b602082015260218101829052606083901b6bffffffffffffffffffffffff1981166041830152829160009060550160408051601f198184030181529190529050603560206000828285018273b0bd02f6a392af548bdf1cfaee5dfa0eefcc8eab5af150505050505050565b60606008805461048190611276565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909190838110156107f85760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61053582868684036108d3565b600033610512818585610abd565b6005546060906001600160a01b0316331461082d57600080fd5b600080846001600160a01b031684604051610848919061141c565b600060405180830381855af49150503d8060008114610883576040519150601f19603f3d011682016040523d82523d6000602084013e610888565b606091505b50915091508161089757600080fd5b949350505050565b6005546001600160a01b031633146108b657600080fd5b9055565b6005546001600160a01b031633146108d157600080fd5b565b6001600160a01b03831661094e5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016107ef565b6001600160a01b0382166109ca5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016107ef565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b038381166000908152600160209081526040808320938616835292905220546000198114610ab75781811015610aaa5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016107ef565b610ab784848484036108d3565b50505050565b6001600160a01b038316610b395760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016107ef565b6001600160a01b038216610bb55760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016107ef565b6001600160a01b03831660009081526020819052604090205481811015610c445760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016107ef565b6001600160a01b03808516600090815260208190526040808220858503905591851681529081208054849290610c7b9084906113d4565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610cc791815260200190565b60405180910390a3610ab7565b6001600160a01b038216610d2a5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016107ef565b8060026000828254610d3c91906113d4565b90915550506001600160a01b03821660009081526020819052604081208054839290610d699084906113d4565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b038216610e2f5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016107ef565b6001600160a01b03821660009081526020819052604090205481811015610ebe5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016107ef565b6001600160a01b0383166000908152602081905260408120838303905560028054849290610eed908490611438565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b60005b83811015610f53578181015183820152602001610f3b565b83811115610ab75750506000910152565b60008151808452610f7c816020860160208601610f38565b601f01601f19169290920160200192915050565b602081526000610fa36020830184610f64565b9392505050565b6001600160a01b0381168114610fbf57600080fd5b50565b60008060408385031215610fd557600080fd5b8235610fe081610faa565b946020939093013593505050565b60008060006060848603121561100357600080fd5b833561100e81610faa565b9250602084013561101e81610faa565b929592945050506040919091013590565b60006020828403121561104157600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261106f57600080fd5b813567ffffffffffffffff8082111561108a5761108a611048565b604051601f8301601f19908116603f011681019082821181831017156110b2576110b2611048565b816040528381528660208588010111156110cb57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561110057600080fd5b833567ffffffffffffffff8082111561111857600080fd5b6111248783880161105e565b9450602086013591508082111561113a57600080fd5b506111478682870161105e565b925050604084013560ff8116811461115e57600080fd5b809150509250925092565b6000806040838503121561117c57600080fd5b823567ffffffffffffffff81111561119357600080fd5b61119f8582860161105e565b95602094909401359450505050565b6000602082840312156111c057600080fd5b8135610fa381610faa565b600080604083850312156111de57600080fd5b82356111e981610faa565b9150602083013567ffffffffffffffff81111561120557600080fd5b6112118582860161105e565b9150509250929050565b6000806040838503121561122e57600080fd5b50508035926020909101359150565b6000806040838503121561125057600080fd5b823561125b81610faa565b9150602083013561126b81610faa565b809150509250929050565b600181811c9082168061128a57607f821691505b6020821081036112aa57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561065657600081815260208120601f850160051c810160208610156112d75750805b601f850160051c820191505b818110156112f6578281556001016112e3565b505050505050565b815167ffffffffffffffff81111561131857611318611048565b61132c816113268454611276565b846112b0565b602080601f83116001811461136157600084156113495750858301515b600019600386901b1c1916600185901b1785556112f6565b600085815260208120601f198616915b8281101561139057888601518255948401946001909101908401611371565b50858210156113ae5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b600082198211156113e7576113e76113be565b500190565b600160f81b81528260018201526000825161140e816021850160208701610f38565b919091016021019392505050565b6000825161142e818460208701610f38565b9190910192915050565b60008282101561144a5761144a6113be565b50039056fea26469706673582212207c21d7af109a1f9c7a3ce12a4788331457c5da1d0cfd105deb473a015e3731fc64736f6c634300080f0033 \ No newline at end of file diff --git a/etc/eth-contracts/res/EvmErc20V2.bin b/etc/eth-contracts/res/EvmErc20V2.bin index 72bf8d39c..ed148de91 100644 Binary files a/etc/eth-contracts/res/EvmErc20V2.bin and b/etc/eth-contracts/res/EvmErc20V2.bin differ diff --git a/etc/eth-contracts/res/EvmErc20V2.hex b/etc/eth-contracts/res/EvmErc20V2.hex index a2167d82d..f797337fa 100644 --- a/etc/eth-contracts/res/EvmErc20V2.hex +++ b/etc/eth-contracts/res/EvmErc20V2.hex @@ -1 +1 @@ -0x60806040523480156200001157600080fd5b506040516200183738038062001837833981016040819052620000349162000186565b80600085856003620000478382620002b9565b506004620000568282620002b9565b5050600580546001600160a01b0319166001600160a01b0394909416939093179092556006555060076200008b8582620002b9565b5060086200009a8482620002b9565b50506009805460ff191660ff9290921691909117905550620003859050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000e157600080fd5b81516001600160401b0380821115620000fe57620000fe620000b9565b604051601f8301601f19908116603f01168101908282118183101715620001295762000129620000b9565b816040528381526020925086838588010111156200014657600080fd5b600091505b838210156200016a57858201830151818301840152908201906200014b565b838211156200017c5760008385830101525b9695505050505050565b600080600080608085870312156200019d57600080fd5b84516001600160401b0380821115620001b557600080fd5b620001c388838901620000cf565b95506020870151915080821115620001da57600080fd5b50620001e987828801620000cf565b935050604085015160ff811681146200020157600080fd5b60608601519092506001600160a01b03811681146200021f57600080fd5b939692955090935050565b600181811c908216806200023f57607f821691505b6020821081036200026057634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002b457600081815260208120601f850160051c810160208610156200028f5750805b601f850160051c820191505b81811015620002b0578281556001016200029b565b5050505b505050565b81516001600160401b03811115620002d557620002d5620000b9565b620002ed81620002e684546200022a565b8462000266565b602080601f8311600181146200032557600084156200030c5750858301515b600019600386901b1c1916600185901b178555620002b0565b600085815260208120601f198616915b82811015620003565788860151825594840194600190910190840162000335565b5085821015620003755787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6114a280620003956000396000f3fe6080604052600436106101755760003560e01c80636b351848116100cb578063a9059cbb1161007f578063dd62ed3e11610059578063dd62ed3e146103ec578063f48ab4e014610432578063f851a4401461043a57600080fd5b8063a9059cbb14610399578063b8e9744c146103b9578063be831a2e146103cc57600080fd5b80638d32caf4116100b05780638d32caf41461034457806395d89b4114610364578063a457c2d71461037957600080fd5b80636b351848146102ee57806370a082311461030e57600080fd5b8063313ce5671161012d57806340c10f191161010757806340c10f1914610298578063530208f2146102b85780635c975abb146102d857600080fd5b8063313ce5671461023657806337d2c2f414610258578063395093511461027857600080fd5b806318160ddd1161015e57806318160ddd146101d557806323b872dd146101f45780632692c59f1461021457600080fd5b806306fdde031461017a578063095ea7b3146101a5575b600080fd5b34801561018657600080fd5b5061018f610472565b60405161019c9190610f94565b60405180910390f35b3480156101b157600080fd5b506101c56101c0366004610fc6565b610504565b604051901515815260200161019c565b3480156101e157600080fd5b506002545b60405190815260200161019c565b34801561020057600080fd5b506101c561020f366004610ff2565b61051c565b34801561022057600080fd5b5061023461022f366004611033565b610540565b005b34801561024257600080fd5b5060095460405160ff909116815260200161019c565b34801561026457600080fd5b506102346102733660046110ef565b61055c565b34801561028457600080fd5b506101c5610293366004610fc6565b6105a5565b3480156102a457600080fd5b506102346102b3366004610fc6565b6105e4565b3480156102c457600080fd5b506102346102d3366004610fc6565b610609565b3480156102e457600080fd5b506101e660065481565b3480156102fa57600080fd5b5061023461030936600461116d565b61065b565b34801561031a57600080fd5b506101e66103293660046111b2565b6001600160a01b031660009081526020819052604090205490565b34801561035057600080fd5b5061023461035f366004610fc6565b6106ce565b34801561037057600080fd5b5061018f61074b565b34801561038557600080fd5b506101c5610394366004610fc6565b61075a565b3480156103a557600080fd5b506101c56103b4366004610fc6565b610809565b61018f6103c73660046111cf565b610817565b3480156103d857600080fd5b506102346103e736600461121f565b6108a3565b3480156103f857600080fd5b506101e6610407366004611241565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6102346108be565b34801561044657600080fd5b5060055461045a906001600160a01b031681565b6040516001600160a01b03909116815260200161019c565b6060600780546104819061127a565b80601f01602080910402602001604051908101604052809291908181526020018280546104ad9061127a565b80156104fa5780601f106104cf576101008083540402835291602001916104fa565b820191906000526020600020905b8154815290600101906020018083116104dd57829003601f168201915b5050505050905090565b6000336105128185856108d7565b5060019392505050565b60003361052a858285610a2f565b610535858585610ac1565b506001949350505050565b6005546001600160a01b0316331461055757600080fd5b600655565b6005546001600160a01b0316331461057357600080fd5b600761057f8482611302565b50600861058c8382611302565b506009805460ff191660ff929092169190911790555050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490919061051290829086906105df9087906113d8565b6108d7565b6005546001600160a01b031633146105fb57600080fd5b6106058282610cd8565b5050565b6005546001600160a01b0316331461062057600080fd5b6040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015610656573d6000803e3d6000fd5b505050565b336106668183610db7565b6040518290600090610680908490849088906020016113f0565b60405160208183030381529060405290506000855160356106a191906113d8565b9050602060008260208501600073e9217bc70b7ed1f598ddd3199e80b093fa71124f5af150505050505050565b6106d83382610db7565b604051600160f81b602082015260218101829052606083901b6bffffffffffffffffffffffff1981166041830152829160009060550160408051601f198184030181529190529050603560206000828285018273b0bd02f6a392af548bdf1cfaee5dfa0eefcc8eab5af150505050505050565b6060600880546104819061127a565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909190838110156107fc5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61053582868684036108d7565b600033610512818585610ac1565b6005546060906001600160a01b0316331461083157600080fd5b600080846001600160a01b03168460405161084c9190611439565b600060405180830381855af49150503d8060008114610887576040519150601f19603f3d011682016040523d82523d6000602084013e61088c565b606091505b50915091508161089b57600080fd5b949350505050565b6005546001600160a01b031633146108ba57600080fd5b9055565b6005546001600160a01b031633146108d557600080fd5b565b6001600160a01b0383166109525760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016107f3565b6001600160a01b0382166109ce5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016107f3565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b038381166000908152600160209081526040808320938616835292905220546000198114610abb5781811015610aae5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016107f3565b610abb84848484036108d7565b50505050565b6001600160a01b038316610b3d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016107f3565b6001600160a01b038216610bb95760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016107f3565b6001600160a01b03831660009081526020819052604090205481811015610c485760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016107f3565b6001600160a01b03808516600090815260208190526040808220858503905591851681529081208054849290610c7f9084906113d8565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610ccb91815260200190565b60405180910390a3610abb565b6001600160a01b038216610d2e5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016107f3565b8060026000828254610d4091906113d8565b90915550506001600160a01b03821660009081526020819052604081208054839290610d6d9084906113d8565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b038216610e335760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016107f3565b6001600160a01b03821660009081526020819052604090205481811015610ec25760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016107f3565b6001600160a01b0383166000908152602081905260408120838303905560028054849290610ef1908490611455565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b60005b83811015610f57578181015183820152602001610f3f565b83811115610abb5750506000910152565b60008151808452610f80816020860160208601610f3c565b601f01601f19169290920160200192915050565b602081526000610fa76020830184610f68565b9392505050565b6001600160a01b0381168114610fc357600080fd5b50565b60008060408385031215610fd957600080fd5b8235610fe481610fae565b946020939093013593505050565b60008060006060848603121561100757600080fd5b833561101281610fae565b9250602084013561102281610fae565b929592945050506040919091013590565b60006020828403121561104557600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261107357600080fd5b813567ffffffffffffffff8082111561108e5761108e61104c565b604051601f8301601f19908116603f011681019082821181831017156110b6576110b661104c565b816040528381528660208588010111156110cf57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561110457600080fd5b833567ffffffffffffffff8082111561111c57600080fd5b61112887838801611062565b9450602086013591508082111561113e57600080fd5b5061114b86828701611062565b925050604084013560ff8116811461116257600080fd5b809150509250925092565b6000806040838503121561118057600080fd5b823567ffffffffffffffff81111561119757600080fd5b6111a385828601611062565b95602094909401359450505050565b6000602082840312156111c457600080fd5b8135610fa781610fae565b600080604083850312156111e257600080fd5b82356111ed81610fae565b9150602083013567ffffffffffffffff81111561120957600080fd5b61121585828601611062565b9150509250929050565b6000806040838503121561123257600080fd5b50508035926020909101359150565b6000806040838503121561125457600080fd5b823561125f81610fae565b9150602083013561126f81610fae565b809150509250929050565b600181811c9082168061128e57607f821691505b6020821081036112ae57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561065657600081815260208120601f850160051c810160208610156112db5750805b601f850160051c820191505b818110156112fa578281556001016112e7565b505050505050565b815167ffffffffffffffff81111561131c5761131c61104c565b6113308161132a845461127a565b846112b4565b602080601f831160018114611365576000841561134d5750858301515b600019600386901b1c1916600185901b1785556112fa565b600085815260208120601f198616915b8281101561139457888601518255948401946001909101908401611375565b50858210156113b25787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b600082198211156113eb576113eb6113c2565b500190565b600160f81b81526bffffffffffffffffffffffff198460601b1660018201528260158201526000825161142a816035850160208701610f3c565b91909101603501949350505050565b6000825161144b818460208701610f3c565b9190910192915050565b600082821015611467576114676113c2565b50039056fea26469706673582212205d8ca0a44d87333d5df15908f23ec17189834c0b160973fa5806bd2f7f5c4c2964736f6c634300080f0033 \ No newline at end of file +0x60806040523480156200001157600080fd5b506040516200183738038062001837833981016040819052620000349162000186565b80600085856003620000478382620002b9565b506004620000568282620002b9565b5050600580546001600160a01b0319166001600160a01b0394909416939093179092556006555060076200008b8582620002b9565b5060086200009a8482620002b9565b50506009805460ff191660ff9290921691909117905550620003859050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000e157600080fd5b81516001600160401b0380821115620000fe57620000fe620000b9565b604051601f8301601f19908116603f01168101908282118183101715620001295762000129620000b9565b816040528381526020925086838588010111156200014657600080fd5b600091505b838210156200016a57858201830151818301840152908201906200014b565b838211156200017c5760008385830101525b9695505050505050565b600080600080608085870312156200019d57600080fd5b84516001600160401b0380821115620001b557600080fd5b620001c388838901620000cf565b95506020870151915080821115620001da57600080fd5b50620001e987828801620000cf565b935050604085015160ff811681146200020157600080fd5b60608601519092506001600160a01b03811681146200021f57600080fd5b939692955090935050565b600181811c908216806200023f57607f821691505b6020821081036200026057634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002b457600081815260208120601f850160051c810160208610156200028f5750805b601f850160051c820191505b81811015620002b0578281556001016200029b565b5050505b505050565b81516001600160401b03811115620002d557620002d5620000b9565b620002ed81620002e684546200022a565b8462000266565b602080601f8311600181146200032557600084156200030c5750858301515b600019600386901b1c1916600185901b178555620002b0565b600085815260208120601f198616915b82811015620003565788860151825594840194600190910190840162000335565b5085821015620003755787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6114a280620003956000396000f3fe6080604052600436106101755760003560e01c80636b351848116100cb578063a9059cbb1161007f578063dd62ed3e11610059578063dd62ed3e146103ec578063f48ab4e014610432578063f851a4401461043a57600080fd5b8063a9059cbb14610399578063b8e9744c146103b9578063be831a2e146103cc57600080fd5b80638d32caf4116100b05780638d32caf41461034457806395d89b4114610364578063a457c2d71461037957600080fd5b80636b351848146102ee57806370a082311461030e57600080fd5b8063313ce5671161012d57806340c10f191161010757806340c10f1914610298578063530208f2146102b85780635c975abb146102d857600080fd5b8063313ce5671461023657806337d2c2f414610258578063395093511461027857600080fd5b806318160ddd1161015e57806318160ddd146101d557806323b872dd146101f45780632692c59f1461021457600080fd5b806306fdde031461017a578063095ea7b3146101a5575b600080fd5b34801561018657600080fd5b5061018f610472565b60405161019c9190610f94565b60405180910390f35b3480156101b157600080fd5b506101c56101c0366004610fc6565b610504565b604051901515815260200161019c565b3480156101e157600080fd5b506002545b60405190815260200161019c565b34801561020057600080fd5b506101c561020f366004610ff2565b61051c565b34801561022057600080fd5b5061023461022f366004611033565b610540565b005b34801561024257600080fd5b5060095460405160ff909116815260200161019c565b34801561026457600080fd5b506102346102733660046110ef565b61055c565b34801561028457600080fd5b506101c5610293366004610fc6565b6105a5565b3480156102a457600080fd5b506102346102b3366004610fc6565b6105e4565b3480156102c457600080fd5b506102346102d3366004610fc6565b610609565b3480156102e457600080fd5b506101e660065481565b3480156102fa57600080fd5b5061023461030936600461116d565b61065b565b34801561031a57600080fd5b506101e66103293660046111b2565b6001600160a01b031660009081526020819052604090205490565b34801561035057600080fd5b5061023461035f366004610fc6565b6106ce565b34801561037057600080fd5b5061018f61074b565b34801561038557600080fd5b506101c5610394366004610fc6565b61075a565b3480156103a557600080fd5b506101c56103b4366004610fc6565b610809565b61018f6103c73660046111cf565b610817565b3480156103d857600080fd5b506102346103e736600461121f565b6108a3565b3480156103f857600080fd5b506101e6610407366004611241565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6102346108be565b34801561044657600080fd5b5060055461045a906001600160a01b031681565b6040516001600160a01b03909116815260200161019c565b6060600780546104819061127a565b80601f01602080910402602001604051908101604052809291908181526020018280546104ad9061127a565b80156104fa5780601f106104cf576101008083540402835291602001916104fa565b820191906000526020600020905b8154815290600101906020018083116104dd57829003601f168201915b5050505050905090565b6000336105128185856108d7565b5060019392505050565b60003361052a858285610a2f565b610535858585610ac1565b506001949350505050565b6005546001600160a01b0316331461055757600080fd5b600655565b6005546001600160a01b0316331461057357600080fd5b600761057f8482611302565b50600861058c8382611302565b506009805460ff191660ff929092169190911790555050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490919061051290829086906105df9087906113d8565b6108d7565b6005546001600160a01b031633146105fb57600080fd5b6106058282610cd8565b5050565b6005546001600160a01b0316331461062057600080fd5b6040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015610656573d6000803e3d6000fd5b505050565b336106668183610db7565b6040518290600090610680908490849088906020016113f0565b60405160208183030381529060405290506000855160356106a191906113d8565b9050602060008260208501600073e9217bc70b7ed1f598ddd3199e80b093fa71124f5af150505050505050565b6106d83382610db7565b604051600160f81b602082015260218101829052606083901b6bffffffffffffffffffffffff1981166041830152829160009060550160408051601f198184030181529190529050603560206000828285018273b0bd02f6a392af548bdf1cfaee5dfa0eefcc8eab5af150505050505050565b6060600880546104819061127a565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909190838110156107fc5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61053582868684036108d7565b600033610512818585610ac1565b6005546060906001600160a01b0316331461083157600080fd5b600080846001600160a01b03168460405161084c9190611439565b600060405180830381855af49150503d8060008114610887576040519150601f19603f3d011682016040523d82523d6000602084013e61088c565b606091505b50915091508161089b57600080fd5b949350505050565b6005546001600160a01b031633146108ba57600080fd5b9055565b6005546001600160a01b031633146108d557600080fd5b565b6001600160a01b0383166109525760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016107f3565b6001600160a01b0382166109ce5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016107f3565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b038381166000908152600160209081526040808320938616835292905220546000198114610abb5781811015610aae5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016107f3565b610abb84848484036108d7565b50505050565b6001600160a01b038316610b3d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016107f3565b6001600160a01b038216610bb95760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016107f3565b6001600160a01b03831660009081526020819052604090205481811015610c485760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016107f3565b6001600160a01b03808516600090815260208190526040808220858503905591851681529081208054849290610c7f9084906113d8565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610ccb91815260200190565b60405180910390a3610abb565b6001600160a01b038216610d2e5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016107f3565b8060026000828254610d4091906113d8565b90915550506001600160a01b03821660009081526020819052604081208054839290610d6d9084906113d8565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b038216610e335760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016107f3565b6001600160a01b03821660009081526020819052604090205481811015610ec25760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016107f3565b6001600160a01b0383166000908152602081905260408120838303905560028054849290610ef1908490611455565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b60005b83811015610f57578181015183820152602001610f3f565b83811115610abb5750506000910152565b60008151808452610f80816020860160208601610f3c565b601f01601f19169290920160200192915050565b602081526000610fa76020830184610f68565b9392505050565b6001600160a01b0381168114610fc357600080fd5b50565b60008060408385031215610fd957600080fd5b8235610fe481610fae565b946020939093013593505050565b60008060006060848603121561100757600080fd5b833561101281610fae565b9250602084013561102281610fae565b929592945050506040919091013590565b60006020828403121561104557600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261107357600080fd5b813567ffffffffffffffff8082111561108e5761108e61104c565b604051601f8301601f19908116603f011681019082821181831017156110b6576110b661104c565b816040528381528660208588010111156110cf57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561110457600080fd5b833567ffffffffffffffff8082111561111c57600080fd5b61112887838801611062565b9450602086013591508082111561113e57600080fd5b5061114b86828701611062565b925050604084013560ff8116811461116257600080fd5b809150509250925092565b6000806040838503121561118057600080fd5b823567ffffffffffffffff81111561119757600080fd5b6111a385828601611062565b95602094909401359450505050565b6000602082840312156111c457600080fd5b8135610fa781610fae565b600080604083850312156111e257600080fd5b82356111ed81610fae565b9150602083013567ffffffffffffffff81111561120957600080fd5b61121585828601611062565b9150509250929050565b6000806040838503121561123257600080fd5b50508035926020909101359150565b6000806040838503121561125457600080fd5b823561125f81610fae565b9150602083013561126f81610fae565b809150509250929050565b600181811c9082168061128e57607f821691505b6020821081036112ae57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561065657600081815260208120601f850160051c810160208610156112db5750805b601f850160051c820191505b818110156112fa578281556001016112e7565b505050505050565b815167ffffffffffffffff81111561131c5761131c61104c565b6113308161132a845461127a565b846112b4565b602080601f831160018114611365576000841561134d5750858301515b600019600386901b1c1916600185901b1785556112fa565b600085815260208120601f198616915b8281101561139457888601518255948401946001909101908401611375565b50858210156113b25787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b600082198211156113eb576113eb6113c2565b500190565b600160f81b81526bffffffffffffffffffffffff198460601b1660018201528260158201526000825161142a816035850160208701610f3c565b91909101603501949350505050565b6000825161144b818460208701610f3c565b9190910192915050565b600082821015611467576114676113c2565b50039056fea2646970667358221220dabbb1e826cd432bc7e41ccd3a33f475a52267161211c315b8e231bf499b8cb264736f6c634300080f0033 \ No newline at end of file diff --git a/etc/eth-contracts/yarn.lock b/etc/eth-contracts/yarn.lock index 2e425e2e9..44a08486d 100644 --- a/etc/eth-contracts/yarn.lock +++ b/etc/eth-contracts/yarn.lock @@ -2,6 +2,27 @@ # yarn lockfile v1 +"@babel/code-frame@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" + integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== + dependencies: + "@babel/highlight" "^7.18.6" + +"@babel/helper-validator-identifier@^7.18.6": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== + +"@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" + chalk "^2.0.0" + js-tokens "^4.0.0" + "@ensdomains/ens@^0.4.4": version "0.4.5" resolved "https://registry.yarnpkg.com/@ensdomains/ens/-/ens-0.4.5.tgz#e0aebc005afdc066447c6e22feb4eda89a5edbfc" @@ -1401,6 +1422,13 @@ dependencies: antlr4ts "^0.5.0-alpha.4" +"@solidity-parser/parser@^0.14.5": + version "0.14.5" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.5.tgz#87bc3cc7b068e08195c219c91cd8ddff5ef1a804" + integrity sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg== + dependencies: + antlr4ts "^0.5.0-alpha.4" + "@szmarczak/http-timer@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" @@ -1675,19 +1703,24 @@ abstract-leveldown@~2.6.0: dependencies: xtend "~4.0.0" -accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== +accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" + mime-types "~2.1.34" + negotiator "0.6.3" -acorn-jsx@^5.3.2: +acorn-jsx@^5.0.0, acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== +acorn@^6.0.7: + version "6.4.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" + integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== + acorn@^8.7.1: version "8.7.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" @@ -1728,17 +1761,7 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv@^5.2.2: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - -ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: +ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.6.1, ajv@^6.9.1: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -1763,6 +1786,11 @@ ansi-colors@4.1.1, ansi-colors@^4.1.1: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== +ansi-escapes@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== + ansi-escapes@^4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -1773,12 +1801,12 @@ ansi-escapes@^4.3.0: ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" + integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== ansi-regex@^4.1.0: version "4.1.0" @@ -1814,6 +1842,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +antlr4@4.7.1: + version "4.7.1" + resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.7.1.tgz#69984014f096e9e775f53dd9744bf994d8959773" + integrity sha512-haHyTW7Y9joE5MVs37P2lNYfU2RWBLfcRDD8OWldcdZm5TiCE91B5Xl1oWSwiDUSd4rlExpt2pu1fksYQjRBYQ== + antlr4ts@^0.5.0-alpha.4: version "0.5.0-alpha.4" resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" @@ -1824,14 +1857,6 @@ any-promise@1.3.0: resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= -anymatch@^1.3.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" - integrity sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA== - dependencies: - micromatch "^2.1.5" - normalize-path "^2.0.0" - anymatch@~3.1.1, anymatch@~3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" @@ -1852,19 +1877,12 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= - dependencies: - arr-flatten "^1.0.1" - arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== -arr-flatten@^1.0.1, arr-flatten@^1.1.0: +arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== @@ -1872,7 +1890,7 @@ arr-flatten@^1.0.1, arr-flatten@^1.1.0: arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== array-back@^1.0.3, array-back@^1.0.4: version "1.0.4" @@ -1914,15 +1932,10 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= - array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== array.prototype.flat@^1.2.5: version "1.3.0" @@ -1969,12 +1982,17 @@ assertion-error@^1.1.0: assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== -async-each@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== +ast-parents@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/ast-parents/-/ast-parents-0.0.1.tgz#508fd0f05d0c48775d9eccda2e174423261e8dd3" + integrity sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA== + +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== async-eventemitter@^0.2.2, async-eventemitter@^0.2.4: version "0.2.4" @@ -2619,23 +2637,11 @@ bignumber.js@^9.0.0: resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== - binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -bindings@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - bip39@2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.5.0.tgz#51cbd5179460504a63ea3c000db3f787ca051235" @@ -2690,7 +2696,25 @@ bn.js@^5.2.1: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== -body-parser@1.19.0, body-parser@^1.16.0: +body-parser@1.20.1: + version "1.20.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" + integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== + dependencies: + bytes "3.1.2" + content-type "~1.0.4" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" + +body-parser@^1.16.0: version "1.19.0" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== @@ -2721,15 +2745,6 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" @@ -2768,11 +2783,6 @@ browser-level@^1.0.1: module-error "^1.0.2" run-parallel-limit "^1.1.0" -browser-stdout@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" - integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= - browser-stdout@1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" @@ -2936,11 +2946,23 @@ builtins@^5.0.1: dependencies: semver "^7.0.0" +busboy@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" + integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== + dependencies: + streamsearch "^1.1.0" + bytes@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + bytewise-core@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/bytewise-core/-/bytewise-core-1.2.3.tgz#3fb410c7e91558eb1ab22a82834577aa6bd61d42" @@ -3000,6 +3022,25 @@ call-bind@^1.0.0, call-bind@^1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ== + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A== + dependencies: + caller-callsite "^2.0.0" + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ== + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -3018,11 +3059,6 @@ camelcase@^3.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= -camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= - camelcase@^5.0.0: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" @@ -3086,7 +3122,7 @@ chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -3129,6 +3165,11 @@ change-case@^4.1.1: snake-case "^3.0.4" tslib "^2.0.3" +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + "charenc@>= 0.0.1": version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" @@ -3176,22 +3217,6 @@ chokidar@3.5.3: optionalDependencies: fsevents "~2.3.2" -chokidar@^1.6.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" - integrity sha1-eY5ol3gVHIB2tLNg5e3SjNortGg= - dependencies: - anymatch "^1.3.0" - async-each "^1.0.0" - glob-parent "^2.0.0" - inherits "^2.0.1" - is-binary-path "^1.0.0" - is-glob "^2.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.0.0" - optionalDependencies: - fsevents "^1.0.0" - chokidar@^3.4.0: version "3.5.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" @@ -3267,6 +3292,13 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw== + dependencies: + restore-cursor "^2.0.0" + cli-table3@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" @@ -3277,6 +3309,11 @@ cli-table3@^0.5.0: optionalDependencies: colors "^1.1.2" +cli-width@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" + integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== + cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" @@ -3286,15 +3323,6 @@ cliui@^3.2.0: strip-ansi "^3.0.1" wrap-ansi "^2.0.0" -cliui@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" - integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== - dependencies: - string-width "^2.1.1" - strip-ansi "^4.0.0" - wrap-ansi "^2.0.0" - cliui@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" @@ -3325,20 +3353,15 @@ clone@2.1.2, clone@^2.0.0: resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw== dependencies: map-visit "^1.0.0" object-visit "^1.0.0" @@ -3393,17 +3416,17 @@ command-line-args@^4.0.7: find-replace "^1.0.3" typical "^2.6.1" -commander@2.11.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" - integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== +commander@2.18.0: + version "2.18.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" + integrity sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ== commander@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== -commander@^2.8.1, commander@^2.9.0: +commander@^2.8.1: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -3461,12 +3484,12 @@ constant-case@^3.0.4: tslib "^2.0.3" upper-case "^2.0.2" -content-disposition@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== dependencies: - safe-buffer "5.1.2" + safe-buffer "5.2.1" content-hash@^2.5.2: version "2.5.2" @@ -3494,10 +3517,10 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== cookie@^0.4.1: version "0.4.1" @@ -3505,14 +3528,14 @@ cookie@^0.4.1: integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== cookiejar@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" - integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== + version "2.1.4" + resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b" + integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw== copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== core-js-pure@^3.0.1: version "3.11.2" @@ -3524,11 +3547,16 @@ core-js@^2.4.0, core-js@^2.5.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== -core-util-is@1.0.2, core-util-is@~1.0.0: +core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + cors@^2.8.1: version "2.8.5" resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" @@ -3537,6 +3565,16 @@ cors@^2.8.1: object-assign "^4" vary "^1" +cosmiconfig@^5.0.7: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + crc-32@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208" @@ -3584,15 +3622,6 @@ cross-fetch@^2.1.0, cross-fetch@^2.1.1: node-fetch "^2.6.7" whatwg-fetch "^2.0.4" -cross-spawn@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= - dependencies: - lru-cache "^4.0.1" - shebang-command "^1.2.0" - which "^1.2.9" - cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -3667,13 +3696,6 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6. dependencies: ms "2.0.0" -debug@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - debug@3.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" @@ -3688,7 +3710,7 @@ debug@4, debug@^4.1.1: dependencies: ms "2.1.2" -debug@4.3.4, debug@^4.3.2, debug@^4.3.3: +debug@4.3.4, debug@^4.0.1, debug@^4.3.2, debug@^4.3.3: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -3713,9 +3735,9 @@ decamelize@^4.0.0: integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== decompress-response@^3.2.0, decompress-response@^3.3.0: version "3.3.0" @@ -3844,14 +3866,14 @@ define-properties@^1.1.4: define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA== dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA== dependencies: is-descriptor "^1.0.0" @@ -3873,7 +3895,7 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -depd@^2.0.0: +depd@2.0.0, depd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== @@ -3891,10 +3913,10 @@ des.js@^1.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== detect-indent@^4.0.0: version "4.0.0" @@ -3911,12 +3933,7 @@ detect-port@^1.3.0: address "^1.0.1" debug "^2.6.0" -diff@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" - integrity sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww== - -diff@3.5.0, diff@^3.5.0: +diff@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== @@ -4094,11 +4111,6 @@ env-paths@^2.2.0: resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== -eol@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/eol/-/eol-0.9.1.tgz#f701912f504074be35c6117a5c4ade49cd547acd" - integrity sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg== - errno@~0.1.1: version "0.1.8" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" @@ -4106,7 +4118,7 @@ errno@~0.1.1: dependencies: prr "~1.0.1" -error-ex@^1.2.0: +error-ex@^1.2.0, error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== @@ -4334,6 +4346,14 @@ eslint-plugin-promise@^6.0.0: resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-6.0.0.tgz#017652c07c9816413a41e11c30adc42c3d55ff18" integrity sha512-7GPezalm5Bfi/E22PnQxDWH2iW9GTvAlUNTztemeHb6c1BniSyoeTrM87JkC0wYdi6aQrZX9p2qEiAno8aTcbw== +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + eslint-scope@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" @@ -4342,6 +4362,13 @@ eslint-scope@^7.1.1: esrecurse "^4.3.0" estraverse "^5.2.0" +eslint-utils@^1.3.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" + integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== + dependencies: + eslint-visitor-keys "^1.1.0" + eslint-utils@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" @@ -4356,7 +4383,7 @@ eslint-utils@^3.0.0: dependencies: eslint-visitor-keys "^2.0.0" -eslint-visitor-keys@^1.1.0: +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== @@ -4371,6 +4398,48 @@ eslint-visitor-keys@^3.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== +eslint@^5.6.0: + version "5.16.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" + integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.9.1" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^4.0.3" + eslint-utils "^1.3.1" + eslint-visitor-keys "^1.0.0" + espree "^5.0.1" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^11.7.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^6.2.2" + js-yaml "^3.13.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.11" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^5.5.1" + strip-ansi "^4.0.0" + strip-json-comments "^2.0.1" + table "^5.2.3" + text-table "^0.2.0" + eslint@^8.18.0: version "8.18.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.18.0.tgz#78d565d16c993d0b73968c523c0446b13da784fd" @@ -4412,6 +4481,15 @@ eslint@^8.18.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" +espree@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" + integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== + dependencies: + acorn "^6.0.7" + acorn-jsx "^5.0.0" + eslint-visitor-keys "^1.0.0" + espree@^9.3.2: version "9.3.2" resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.2.tgz#f58f77bd334731182801ced3380a8cc859091596" @@ -4431,14 +4509,14 @@ esprima@^4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.0: +esquery@^1.0.1, esquery@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== dependencies: estraverse "^5.1.0" -esrecurse@^4.3.0: +esrecurse@^4.1.0, esrecurse@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== @@ -4450,6 +4528,11 @@ estraverse@^1.9.1: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + estraverse@^5.1.0, estraverse@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" @@ -5062,35 +5145,15 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - exit-on-epipe@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692" integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw== -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= - dependencies: - is-posix-bracket "^0.1.0" - expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA== dependencies: debug "^2.3.3" define-property "^0.2.5" @@ -5100,45 +5163,39 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= - dependencies: - fill-range "^2.1.0" - express@^4.14.0: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== + version "4.18.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" + integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== dependencies: - accepts "~1.3.7" + accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" + body-parser "1.20.1" + content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.4.0" + cookie "0.5.0" cookie-signature "1.0.6" debug "2.6.9" - depd "~1.1.2" + depd "2.0.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "~1.1.2" + finalhandler "1.2.0" fresh "0.5.2" + http-errors "2.0.0" merge-descriptors "1.0.1" methods "~1.1.2" - on-finished "~2.3.0" + on-finished "2.4.1" parseurl "~1.3.3" path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" + proxy-addr "~2.0.7" + qs "6.11.0" range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" type-is "~1.6.18" utils-merge "1.0.1" vary "~1.1.2" @@ -5153,14 +5210,14 @@ ext@^1.1.2: extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== dependencies: assign-symbols "^1.0.0" is-extendable "^1.0.1" @@ -5170,12 +5227,14 @@ extend@~3.0.2: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== dependencies: - is-extglob "^1.0.0" + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" extglob@^2.0.4: version "2.0.4" @@ -5208,16 +5267,16 @@ fake-merkle-patricia-tree@^1.0.1: dependencies: checkpoint-store "^1.1.0" -fast-deep-equal@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" - integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + fast-glob@^3.0.3: version "3.2.5" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.5.tgz#7939af2a656de79a4f1901903ee8adcaa7cb9661" @@ -5261,6 +5320,20 @@ fetch-ponyfill@^4.0.0: dependencies: node-fetch "~1.7.1" +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA== + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + dependencies: + flat-cache "^2.0.1" + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -5283,31 +5356,10 @@ file-type@^6.1.0: resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== -file-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= - -fill-range@^2.1.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" - integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^3.0.0" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ== dependencies: extend-shallow "^2.0.1" is-number "^3.0.0" @@ -5321,17 +5373,17 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== dependencies: debug "2.6.9" encodeurl "~1.0.2" escape-html "~1.0.3" - on-finished "~2.3.0" + on-finished "2.4.1" parseurl "~1.3.3" - statuses "~1.5.0" + statuses "2.0.1" unpipe "~1.0.0" find-replace@^1.0.3: @@ -5368,7 +5420,7 @@ find-up@^1.0.0: find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== dependencies: locate-path "^2.0.0" @@ -5387,6 +5439,15 @@ find-yarn-workspace-root@^2.0.0: dependencies: micromatch "^4.0.2" +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -5407,6 +5468,11 @@ flat@^5.0.2: resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== +flatted@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" + integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== + flatted@^3.1.0: version "3.2.6" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.6.tgz#022e9218c637f9f3fc9c35ab9c9193f05add60b2" @@ -5429,17 +5495,10 @@ for-each@^0.3.3, for-each@~0.3.3: dependencies: is-callable "^1.1.3" -for-in@^1.0.1, for-in@^1.0.2: +for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - -for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= - dependencies: - for-in "^1.0.1" + integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== foreach@^2.0.5: version "2.0.5" @@ -5478,10 +5537,10 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -forwarded@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== fp-ts@1.19.3: version "1.19.3" @@ -5496,7 +5555,7 @@ fp-ts@^1.0.0: fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA== dependencies: map-cache "^0.2.2" @@ -5565,14 +5624,6 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@^1.0.0: - version "1.2.13" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" - integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== - dependencies: - bindings "^1.5.0" - nan "^2.12.1" - fsevents@~2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" @@ -5694,7 +5745,7 @@ get-stream@^2.2.0: get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= + integrity sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ== get-stream@^4.1.0: version "4.1.0" @@ -5721,7 +5772,7 @@ get-symbol-description@^1.0.0: get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== getpass@^0.1.1: version "0.1.7" @@ -5738,21 +5789,6 @@ ghost-testrpc@^0.0.2: chalk "^2.4.2" node-emoji "^1.10.0" -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= - dependencies: - is-glob "^2.0.0" - glob-parent@^5.1.0, glob-parent@~5.1.0, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -5767,18 +5803,6 @@ glob-parent@^6.0.1: dependencies: is-glob "^4.0.3" -glob@7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" @@ -5862,6 +5886,11 @@ global@~4.4.0: min-document "^2.19.0" process "^0.11.10" +globals@^11.7.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + globals@^13.15.0: version "13.15.0" resolved "https://registry.yarnpkg.com/globals/-/globals-13.15.0.tgz#38113218c907d2f7e98658af246cef8b77e90bac" @@ -5925,15 +5954,15 @@ got@^7.1.0: url-parse-lax "^1.0.0" url-to-options "^1.0.1" -graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: +graceful-fs@^4.1.10, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: version "4.2.6" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== -growl@1.10.3: - version "1.10.3" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" - integrity sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q== +graceful-fs@^4.1.11: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== growl@1.10.5: version "1.10.5" @@ -5972,10 +6001,10 @@ hardhat-storage-layout@^0.1.6: dependencies: console-table-printer "^2.9.0" -hardhat@^2.12.0: - version "2.12.0" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.12.0.tgz#51e59f1ff4991bcb66d1a380ea807e6c15fcac34" - integrity sha512-mNJFbVG479HwOzxiaLxobyvED2M1aEAuPPYhEo1+88yicMDSTrU2JIS7vV+V0GSNQKaDoiHCmV6bcKjiljT/dQ== +hardhat@^2.12.7: + version "2.12.7" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.12.7.tgz#d8de2dc32e9a2956d53cf26ef4cd5857e57a3138" + integrity sha512-voWoN6zn5d8BOEaczSyK/1PyfdeOeI3SbGCFb36yCHTJUt6OIqLb+ZDX30VhA1UsYKzLqG7UnWl3fKJUuANc6A== dependencies: "@ethersproject/abi" "^5.1.2" "@metamask/eth-sig-util" "^4.0.0" @@ -6024,7 +6053,7 @@ hardhat@^2.12.0: source-map-support "^0.5.13" stacktrace-parser "^0.1.10" tsort "0.0.1" - undici "^5.4.0" + undici "^5.14.0" uuid "^8.3.2" ws "^7.4.6" @@ -6050,11 +6079,6 @@ has-flag@^1.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= -has-flag@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" - integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -6104,7 +6128,7 @@ has-tostringtag@^1.0.0: has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q== dependencies: get-value "^2.0.3" has-values "^0.1.4" @@ -6113,7 +6137,7 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw== dependencies: get-value "^2.0.6" has-values "^1.0.0" @@ -6122,12 +6146,12 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ== has-values@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ== dependencies: is-number "^3.0.0" kind-of "^4.0.0" @@ -6164,11 +6188,6 @@ hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: inherits "^2.0.3" minimalistic-assert "^1.0.1" -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= - he@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -6220,9 +6239,9 @@ http-basic@^8.1.1: parse-cache-control "^1.0.1" http-cache-semantics@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + version "4.1.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== http-errors@1.7.2: version "1.7.2" @@ -6235,7 +6254,7 @@ http-errors@1.7.2: statuses ">= 1.5.0 < 2" toidentifier "1.0.0" -http-errors@1.7.3, http-errors@~1.7.2: +http-errors@1.7.3: version "1.7.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== @@ -6246,6 +6265,17 @@ http-errors@1.7.3, http-errors@~1.7.2: statuses ">= 1.5.0 < 2" toidentifier "1.0.0" +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + http-errors@^1.7.2: version "1.8.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.0.tgz#75d1bbe497e1044f51e4ee9e704a62f28d336507" @@ -6286,7 +6316,7 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" -iconv-lite@0.4.24: +iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -6312,6 +6342,11 @@ ieee754@^1.1.13, ieee754@^1.2.1: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + ignore@^5.1.1: version "5.1.8" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" @@ -6337,6 +6372,14 @@ immutable@^4.0.0-rc.12: resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0-rc.12.tgz#ca59a7e4c19ae8d9bf74a97bdf0f6e2f2a5d0217" integrity sha512-0M2XxkZLx/mi3t8NVwIm1g8nHoEmM9p9UBl/G9k4+hm0kBgOVdMV/B3CY5dQ8qG8qc80NN4gDV4HQv6FTJ5q7A== +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg== + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -6378,6 +6421,25 @@ ini@^1.3.5: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== +inquirer@^6.2.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" + integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== + dependencies: + ansi-escapes "^3.2.0" + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^2.0.0" + lodash "^4.17.12" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^6.4.0" + string-width "^2.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + internal-slot@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" @@ -6402,7 +6464,7 @@ invariant@^2.2.2: invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= + integrity sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ== io-ts@1.10.4: version "1.10.4" @@ -6419,7 +6481,7 @@ ipaddr.js@1.9.1: is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + integrity sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A== dependencies: kind-of "^3.0.2" @@ -6447,13 +6509,6 @@ is-bigint@^1.0.1: resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.2.tgz#ffb381442503235ad245ea89e45b3dbff040ee5a" integrity sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA== -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -6512,7 +6567,7 @@ is-core-module@^2.8.1, is-core-module@^2.9.0: is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + integrity sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg== dependencies: kind-of "^3.0.2" @@ -6546,27 +6601,20 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== + is-docker@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= - dependencies: - is-primitive "^2.0.0" - is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== is-extendable@^1.0.1: version "1.0.1" @@ -6575,11 +6623,6 @@ is-extendable@^1.0.1: dependencies: is-plain-object "^2.0.4" -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= - is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -6598,14 +6641,14 @@ is-fn@^1.0.0: is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== is-fullwidth-code-point@^3.0.0: version "3.0.0" @@ -6622,13 +6665,6 @@ is-generator-function@^1.0.7: resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.8.tgz#dfb5c2b120e02b0a8d9d2c6806cd5621aa922f7b" integrity sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ== -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= - dependencies: - is-extglob "^1.0.0" - is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" @@ -6668,25 +6704,13 @@ is-number-object@^1.0.4: resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197" integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw== -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= - dependencies: - kind-of "^3.0.2" - is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg== dependencies: kind-of "^3.0.2" -is-number@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== - is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -6719,16 +6743,6 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= - is-regex@^1.0.4: version "1.1.3" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.3.tgz#d029f9aff6448b93ebbe3f33dac71511fdcbef9f" @@ -6854,24 +6868,24 @@ isarray@0.0.1: isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== isstream@~0.1.2: version "0.1.2" @@ -6901,12 +6915,7 @@ js-sha3@0.8.0, js-sha3@^0.8.0: resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== -js-string-escape@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" - integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= - -"js-tokens@^3.0.0 || ^4.0.0": +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== @@ -6924,7 +6933,7 @@ js-yaml@3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@3.x: +js-yaml@3.x, js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== @@ -6959,6 +6968,11 @@ json-buffer@3.0.0: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= +json-parse-better-errors@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: version "3.8.0" resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" @@ -6983,11 +6997,6 @@ json-rpc-random-id@^1.0.0: resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" integrity sha1-uknZat7RRE27jaPSA3SKy7zeyMg= -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= - json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -7088,14 +7097,14 @@ keyv@^3.0.0: kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw== dependencies: is-buffer "^1.1.5" @@ -7126,7 +7135,7 @@ klaw@^1.0.0: lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= + integrity sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw== dependencies: invert-kv "^1.0.0" @@ -7291,6 +7300,14 @@ levelup@^1.2.1: semver "~5.4.1" xtend "~4.0.0" +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -7299,14 +7316,6 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" @@ -7321,7 +7330,7 @@ load-json-file@^1.0.0: locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== dependencies: p-locate "^2.0.0" path-exists "^3.0.0" @@ -7361,7 +7370,7 @@ lodash@4.17.20: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== -lodash@^4.14.2, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4: +lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -7436,14 +7445,6 @@ lru-cache@^3.2.0: dependencies: pseudomap "^1.0.1" -lru-cache@^4.0.1: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -7483,12 +7484,12 @@ make-dir@^3.0.0: map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w== dependencies: object-visit "^1.0.0" @@ -7497,11 +7498,6 @@ markdown-table@^1.1.3: resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60" integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q== -math-random@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" - integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== - mcl-wasm@^0.7.1: version "0.7.6" resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.6.tgz#c1789ebda5565d49b77d2ee195ff3e4d282f1554" @@ -7521,13 +7517,6 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= -mem@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= - dependencies: - mimic-fn "^1.0.0" - memdown@^1.0.0: version "1.4.1" resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" @@ -7608,26 +7597,7 @@ methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= -micromatch@^2.1.5: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" - -micromatch@^3.1.10, micromatch@^3.1.4: +micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== @@ -7667,6 +7637,11 @@ mime-db@1.47.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.47.0.tgz#8cb313e59965d3c05cfbf898915a267af46a335c" integrity sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw== +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.19, mime-types@~2.1.24: version "2.1.30" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.30.tgz#6e7be8b4c479825f85ed6326695db73f9305d62d" @@ -7674,6 +7649,13 @@ mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.19, mime-types@~2.1.24: dependencies: mime-db "1.47.0" +mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + mime@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" @@ -7706,7 +7688,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.4: +"minimatch@2 || 3", minimatch@3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -7720,27 +7702,17 @@ minimatch@5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@^3.1.1, minimatch@^3.1.2: +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@^1.2.0, minimist@^1.2.5, minimist@~1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - -minimist@^1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== +minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@~1.2.5: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== minipass@^2.6.0, minipass@^2.9.0: version "2.9.0" @@ -7777,13 +7749,6 @@ mkdirp@*: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mkdirp@0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - mkdirp@0.5.5, mkdirp@0.5.x, mkdirp@^0.5.1, mkdirp@^0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" @@ -7825,22 +7790,6 @@ mocha@^10.0.0: yargs-parser "20.2.4" yargs-unparser "2.0.0" -mocha@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" - integrity sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA== - dependencies: - browser-stdout "1.3.0" - commander "2.11.0" - debug "3.1.0" - diff "3.3.1" - escape-string-regexp "1.0.5" - glob "7.1.2" - growl "1.10.3" - he "1.1.1" - mkdirp "0.5.1" - supports-color "4.4.0" - mocha@^7.1.1: version "7.2.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.2.0.tgz#01cc227b00d875ab1eed03a75106689cfed5a604" @@ -7884,7 +7833,7 @@ module-error@^1.0.1, module-error@^1.0.2: ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== ms@2.1.1: version "2.1.1" @@ -7946,7 +7895,12 @@ mustache@^4.0.0: resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64" integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ== -nan@^2.12.1, nan@^2.14.0: +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + integrity sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ== + +nan@^2.14.0: version "2.14.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== @@ -8005,10 +7959,10 @@ near-api-js@^0.26.0: text-encoding-utf-8 "^1.0.2" tweetnacl "^1.0.1" -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== neo-async@^2.6.0: version "2.6.2" @@ -8095,13 +8049,6 @@ normalize-package-data@^2.3.2: semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" -normalize-path@^2.0.0, normalize-path@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -8112,17 +8059,10 @@ normalize-url@^4.1.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= - dependencies: - path-key "^2.0.0" - number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== number-to-bn@1.7.0: version "1.7.0" @@ -8152,7 +8092,7 @@ object-assign@^4, object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1 object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ== dependencies: copy-descriptor "^0.1.0" define-property "^0.2.5" @@ -8194,7 +8134,7 @@ object-keys@~0.4.0: object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA== dependencies: isobject "^3.0.0" @@ -8227,18 +8167,10 @@ object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.1 define-properties "^1.1.3" es-abstract "^1.18.0-next.2" -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ== dependencies: isobject "^3.0.1" @@ -8270,6 +8202,13 @@ oboe@2.1.5: dependencies: http-https "^1.0.0" +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" @@ -8284,6 +8223,13 @@ once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ== + dependencies: + mimic-fn "^1.0.0" + open@^7.4.2: version "7.4.2" resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" @@ -8292,7 +8238,7 @@ open@^7.4.2: is-docker "^2.0.0" is-wsl "^2.1.1" -optionator@^0.8.1: +optionator@^0.8.1, optionator@^0.8.2: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== @@ -8328,15 +8274,6 @@ os-locale@^1.4.0: dependencies: lcid "^1.0.0" -os-locale@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== - dependencies: - execa "^0.7.0" - lcid "^1.0.0" - mem "^1.1.0" - os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -8355,7 +8292,7 @@ p-cancelable@^1.0.0: p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== p-limit@^1.1.0: version "1.3.0" @@ -8381,7 +8318,7 @@ p-limit@^3.0.2: p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== dependencies: p-limit "^1.1.0" @@ -8416,7 +8353,7 @@ p-timeout@^1.1.1: p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== p-try@^2.0.0: version "2.2.0" @@ -8454,16 +8391,6 @@ parse-cache-control@^1.0.1: resolved "https://registry.yarnpkg.com/parse-cache-control/-/parse-cache-control-1.0.1.tgz#8eeab3e54fa56920fe16ba38f77fa21aacc2d74e" integrity sha1-juqz5U+laSD+Fro493+iGqzC104= -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - parse-headers@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.3.tgz#5e8e7512383d140ba02f0c7aa9f49b4399c92515" @@ -8476,6 +8403,14 @@ parse-json@^2.2.0: dependencies: error-ex "^1.2.0" +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -8492,7 +8427,7 @@ pascal-case@^3.1.2: pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== patch-package@6.2.2: version "6.2.2" @@ -8554,7 +8489,7 @@ path-exists@^2.0.0: path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== path-exists@^4.0.0: version "4.0.0" @@ -8566,7 +8501,12 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-key@^2.0.0, path-key@^2.0.1: +path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== + +path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= @@ -8616,11 +8556,6 @@ pbkdf2@^3.0.17, pbkdf2@^3.0.3, pbkdf2@^3.0.9: safe-buffer "^5.0.1" sha.js "^2.4.8" -pegjs@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.10.0.tgz#cf8bafae6eddff4b5a7efb185269eaaf4610ddbd" - integrity sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0= - pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" @@ -8666,7 +8601,7 @@ pinkie@^2.0.0: posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== postinstall-postinstall@^2.1.0: version "2.1.0" @@ -8698,10 +8633,10 @@ prepend-http@^2.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= +prettier@^1.14.3: + version "1.19.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" + integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== prettier@^2.1.2: version "2.3.2" @@ -8728,6 +8663,11 @@ process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + promise-to-callback@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" @@ -8748,12 +8688,12 @@ promisfy@^1.2.0: resolved "https://registry.yarnpkg.com/promisfy/-/promisfy-1.2.0.tgz#d34cfec196bddd6a2cfa0bf64eaca53dbc9250a8" integrity sha512-9S6NY6pVlmrvQX/KIZn4V8EPcKNAC0l5nEKXTa5K1/uzqnMOn4ivWtQY+IbSE/f9uLUa1T/kbDsASSzi05X3dA== -proxy-addr@~2.0.5: - version "2.0.6" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" - integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw== +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== dependencies: - forwarded "~0.1.2" + forwarded "0.2.0" ipaddr.js "1.9.1" prr@~1.0.1: @@ -8761,7 +8701,7 @@ prr@~1.0.1: resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= -pseudomap@^1.0.1, pseudomap@^1.0.2: +pseudomap@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= @@ -8854,22 +8794,29 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + qs@6.7.0: version "6.7.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== qs@^6.4.0, qs@^6.7.0: - version "6.10.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.1.tgz#4931482fa8d647a5aab799c5271d2133b981fb6a" - integrity sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg== + version "6.11.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.1.tgz#6c29dff97f0c0060765911ba65cbc9764186109f" + integrity sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ== dependencies: side-channel "^1.0.4" qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== query-string@^5.0.1: version "5.1.1" @@ -8913,15 +8860,6 @@ rainbow-bridge-lib@^3.0.0: tweetnacl "^1.0.3" web3 "=1.2.6" -randomatic@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" - integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== - dependencies: - is-number "^4.0.0" - kind-of "^6.0.0" - math-random "^1.0.1" - randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.0.6, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -8952,6 +8890,16 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" +raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + raw-body@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c" @@ -8989,7 +8937,7 @@ readable-stream@^1.0.33: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.2.2, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: +readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.2, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -9021,15 +8969,6 @@ readable-stream@~1.0.15: isarray "0.0.1" string_decoder "~0.10.x" -readdirp@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - readdirp@~3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" @@ -9084,13 +9023,6 @@ regenerator-transform@^0.10.0: babel-types "^6.19.0" private "^0.1.6" -regex-cache@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== - dependencies: - is-equal-shallow "^0.1.3" - regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -9116,6 +9048,11 @@ regexp.prototype.flags@^1.4.3: define-properties "^1.1.3" functions-have-names "^1.2.2" +regexpp@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" + integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== + regexpp@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" @@ -9147,20 +9084,15 @@ regjsparser@^0.1.4: dependencies: jsesc "~0.5.0" -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - repeat-element@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== -repeat-string@^1.5.2, repeat-string@^1.6.1: +repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== repeating@^2.0.0: version "2.0.1" @@ -9228,7 +9160,7 @@ request@^2.79.0, request@^2.85.0, request@^2.88.0: require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== require-from-string@^1.1.0: version "1.2.1" @@ -9243,7 +9175,7 @@ require-from-string@^2.0.0: require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + integrity sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug== require-main-filename@^2.0.0: version "2.0.0" @@ -9263,7 +9195,7 @@ resolve-from@^4.0.0: resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== resolve@1.1.x: version "1.1.7" @@ -9310,6 +9242,14 @@ responselike@^1.0.2: dependencies: lowercase-keys "^1.0.0" +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q== + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + resumer@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" @@ -9327,6 +9267,13 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== +rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + rimraf@^2.2.8, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" @@ -9356,6 +9303,11 @@ rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4: dependencies: bn.js "^4.11.1" +run-async@^2.2.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + run-parallel-limit@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz#be80e936f5768623a38a963262d6bef8ff11e7ba" @@ -9375,16 +9327,23 @@ rustbn.js@~0.2.0: resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +rxjs@^6.4.0: + version "6.6.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + safe-event-emitter@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz#5b692ef22329ed8f69fdce607e50ca734f6f20af" @@ -9395,7 +9354,7 @@ safe-event-emitter@^1.0.1: safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== dependencies: ret "~0.1.10" @@ -9477,7 +9436,7 @@ semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.1.0: resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0: +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -9506,24 +9465,24 @@ semver@~5.4.1: resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== dependencies: debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" + depd "2.0.0" + destroy "1.2.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" fresh "0.5.2" - http-errors "~1.7.2" + http-errors "2.0.0" mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" + ms "2.1.3" + on-finished "2.4.1" range-parser "~1.2.1" - statuses "~1.5.0" + statuses "2.0.1" sentence-case@^3.0.4: version "3.0.4" @@ -9541,15 +9500,15 @@ serialize-javascript@6.0.0: dependencies: randombytes "^2.1.0" -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" parseurl "~1.3.3" - send "0.17.1" + send "0.18.0" servify@^0.1.12: version "0.1.12" @@ -9565,7 +9524,7 @@ servify@^0.1.12: set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== set-immediate-shim@^1.0.1: version "1.0.1" @@ -9621,7 +9580,7 @@ sha1@^1.1.1: shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== dependencies: shebang-regex "^1.0.0" @@ -9635,7 +9594,7 @@ shebang-command@^2.0.0: shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== shebang-regex@^3.0.0: version "3.0.0" @@ -9660,7 +9619,7 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" -signal-exit@^3.0.0, signal-exit@^3.0.2: +signal-exit@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== @@ -9699,6 +9658,15 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + snake-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" @@ -9737,16 +9705,6 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -sol-digger@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/sol-digger/-/sol-digger-0.0.2.tgz#406c4a9d31e269e7f88eb1c2ea101318e5e09025" - integrity sha1-QGxKnTHiaef4jrHC6hATGOXgkCU= - -sol-explore@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/sol-explore/-/sol-explore-1.6.1.tgz#b59f073c69fe332560d5a10c32ba8ca7f2986cfb" - integrity sha1-tZ8HPGn+MyVg1aEMMrqMp/KYbPs= - solc@0.7.3: version "0.7.3" resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" @@ -9800,6 +9758,28 @@ solc@^0.6.3: semver "^5.5.0" tmp "0.0.33" +solhint@^3.3.8: + version "3.3.8" + resolved "https://registry.yarnpkg.com/solhint/-/solhint-3.3.8.tgz#b1773c881cfaf0b5008c78ad658a69603d3fa051" + integrity sha512-TkYyJ6uUJCaiqRKuhHhFuoAoyco9Ia+RDKhl3usjG/rkaNk8/LdLRla2Xln7MVdBTaPKNAU8ezTRSit50Yy4qw== + dependencies: + "@solidity-parser/parser" "^0.14.5" + ajv "^6.6.1" + antlr4 "4.7.1" + ast-parents "0.0.1" + chalk "^2.4.2" + commander "2.18.0" + cosmiconfig "^5.0.7" + eslint "^5.6.0" + fast-diff "^1.1.2" + glob "^7.1.3" + ignore "^4.0.6" + js-yaml "^3.12.0" + lodash "^4.17.11" + semver "^6.3.0" + optionalDependencies: + prettier "^1.14.3" + solidity-coverage@^0.7.21: version "0.7.21" resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.7.21.tgz#20c5615a3a543086b243c2ca36e2951a75316b40" @@ -9824,39 +9804,6 @@ solidity-coverage@^0.7.21: shelljs "^0.8.3" web3-utils "^1.3.0" -solium-plugin-security@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/solium-plugin-security/-/solium-plugin-security-0.1.1.tgz#2a87bcf8f8c3abf7d198e292e4ac080284e3f3f6" - integrity sha512-kpLirBwIq4mhxk0Y/nn5cQ6qdJTI+U1LO3gpoNIcqNaW+sI058moXBe2UiHs+9wvF9IzYD49jcKhFTxcR9u9SQ== - -solium@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/solium/-/solium-1.2.5.tgz#d036c30e2901e22137bbf342f106b17529ff22a8" - integrity sha512-NuNrm7fp8JcDN/P+SAdM5TVa4wYDtwVtLY/rG4eBOZrC5qItsUhmQKR/YhjszaEW4c8tNUYhkhQcwOsS25znpw== - dependencies: - ajv "^5.2.2" - chokidar "^1.6.0" - colors "^1.1.2" - commander "^2.9.0" - diff "^3.5.0" - eol "^0.9.1" - js-string-escape "^1.0.1" - lodash "^4.14.2" - sol-digger "0.0.2" - sol-explore "1.6.1" - solium-plugin-security "0.1.1" - solparse "2.2.8" - text-table "^0.2.0" - -solparse@2.2.8: - version "2.2.8" - resolved "https://registry.yarnpkg.com/solparse/-/solparse-2.2.8.tgz#d13e42dbed95ce32f43894f5ec53f00d14cf9f11" - integrity sha512-Tm6hdfG72DOxD40SD+T5ddbekWglNWjzDRSNq7ZDIOHVsyaJSeeunUuWNj4DE7uDrJK3tGQuX0ZTDZWNYsGPMA== - dependencies: - mocha "^4.0.1" - pegjs "^0.10.0" - yargs "^10.0.3" - source-map-resolve@^0.5.0: version "0.5.3" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" @@ -9976,12 +9923,17 @@ stacktrace-parser@^0.1.10: static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== dependencies: define-property "^0.2.5" object-copy "^0.1.0" -"statuses@>= 1.5.0 < 2", statuses@~1.5.0: +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +"statuses@>= 1.5.0 < 2": version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= @@ -9999,6 +9951,11 @@ stream-to-pull-stream@^1.7.1: looper "^3.0.0" pull-stream "^3.2.3" +streamsearch@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" + integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== + strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" @@ -10007,13 +9964,13 @@ strict-uri-encode@^1.0.0: string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2", string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -10113,14 +10070,14 @@ string_decoder@~1.1.1: strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== dependencies: ansi-regex "^2.0.0" strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== dependencies: ansi-regex "^3.0.0" @@ -10164,11 +10121,6 @@ strip-dirs@^2.0.0: dependencies: is-natural-number "^4.0.1" -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= - strip-hex-prefix@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" @@ -10176,7 +10128,7 @@ strip-hex-prefix@1.0.0: dependencies: is-hex-prefixed "1.0.0" -strip-json-comments@2.0.1: +strip-json-comments@2.0.1, strip-json-comments@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= @@ -10186,13 +10138,6 @@ strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1. resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -supports-color@4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" - integrity sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ== - dependencies: - has-flag "^2.0.0" - supports-color@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" @@ -10289,6 +10234,16 @@ sync-rpc@^1.2.1: dependencies: get-port "^3.1.0" +table@^5.2.3: + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== + dependencies: + ajv "^6.10.2" + lodash "^4.17.14" + slice-ansi "^2.1.0" + string-width "^3.0.0" + tape@^4.6.3: version "4.13.3" resolved "https://registry.yarnpkg.com/tape/-/tape-4.13.3.tgz#51b3d91c83668c7a45b1a594b607dee0a0b46278" @@ -10357,7 +10312,7 @@ text-encoding-utf-8@^1.0.2: text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== then-request@^6.0.0: version "6.0.2" @@ -10384,7 +10339,7 @@ through2@^2.0.3: readable-stream "~2.3.6" xtend "~4.0.1" -through@^2.3.8, through@~2.3.4, through@~2.3.8: +through@^2.3.6, through@^2.3.8, through@~2.3.4, through@~2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -10421,7 +10376,7 @@ to-fast-properties@^1.0.3: to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== dependencies: kind-of "^3.0.2" @@ -10433,7 +10388,7 @@ to-readable-stream@^1.0.0: to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== dependencies: is-number "^3.0.0" repeat-string "^1.6.1" @@ -10460,6 +10415,11 @@ toidentifier@1.0.0: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + tough-cookie@^2.3.3, tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" @@ -10513,7 +10473,7 @@ tsconfig-paths@^3.14.1: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.9.3: +tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -10707,10 +10667,12 @@ underscore@1.9.1: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== -undici@^5.4.0: - version "5.5.1" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.5.1.tgz#baaf25844a99eaa0b22e1ef8d205bffe587c8f43" - integrity sha512-MEvryPLf18HvlCbLSzCW0U00IMftKGI5udnjrQbC5D4P0Hodwffhv+iGfWuJwg16Y/TK11ZFK8i+BPVW2z/eAw== +undici@^5.14.0: + version "5.20.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.20.0.tgz#6327462f5ce1d3646bcdac99da7317f455bcc263" + integrity sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g== + dependencies: + busboy "^1.6.0" union-value@^1.0.0: version "1.0.1" @@ -10747,7 +10709,7 @@ unpipe@1.0.0, unpipe@~1.0.0: unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== dependencies: has-value "^0.3.1" isobject "^3.0.0" @@ -10776,7 +10738,7 @@ uri-js@^4.2.2: urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== url-parse-lax@^1.0.0: version "1.0.0" @@ -10830,7 +10792,7 @@ utf8@3.0.0, utf8@^3.0.0: util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== util.promisify@^1.0.0: version "1.1.1" @@ -11730,7 +11692,7 @@ which-module@^1.0.0: which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q== which-typed-array@^1.1.2: version "1.1.4" @@ -11789,7 +11751,7 @@ workerpool@6.2.1: wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + integrity sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw== dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" @@ -11815,7 +11777,7 @@ wrap-ansi@^7.0.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== write-file-atomic@^3.0.0: version "3.0.3" @@ -11827,6 +11789,13 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1" + ws@7.4.6: version "7.4.6" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" @@ -11932,11 +11901,6 @@ yaeti@^0.0.6: resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= - yallist@^3.0.0, yallist@^3.0.2, yallist@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" @@ -11973,13 +11937,6 @@ yargs-parser@^20.2.2: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== -yargs-parser@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" - integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ== - dependencies: - camelcase "^4.1.0" - yargs-unparser@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" @@ -12028,24 +11985,6 @@ yargs@16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^10.0.3: - version "10.1.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" - integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig== - dependencies: - cliui "^4.0.0" - decamelize "^1.1.1" - find-up "^2.1.0" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^8.1.0" - yargs@^4.7.1: version "4.8.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" diff --git a/etc/state-migration-test/Cargo.lock b/etc/state-migration-test/Cargo.lock deleted file mode 100644 index 56b2b9927..000000000 --- a/etc/state-migration-test/Cargo.lock +++ /dev/null @@ -1,1245 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "ahash" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" - -[[package]] -name = "arrayref" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" - -[[package]] -name = "arrayvec" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4dc07131ffa69b8072d35f5007352af944213cde02545e2103680baed38fcd" - -[[package]] -name = "aurora-bn" -version = "0.1.0" -source = "git+https://github.com/aurora-is-near/aurora-bn.git#8f1743884061981cac84388862e2763b2aa09307" -dependencies = [ - "byteorder", - "getrandom", -] - -[[package]] -name = "aurora-engine" -version = "2.6.1" -dependencies = [ - "aurora-bn", - "aurora-engine-precompiles", - "aurora-engine-sdk", - "aurora-engine-transactions", - "aurora-engine-types", - "base64", - "bitflags", - "borsh", - "byte-slice-cast", - "ethabi", - "evm", - "evm-core", - "hex", - "libsecp256k1", - "logos", - "num", - "primitive-types 0.10.1", - "ripemd160", - "rjson", - "rlp", - "sha3 0.9.1", - "wee_alloc", -] - -[[package]] -name = "aurora-engine-precompiles" -version = "1.0.0" -dependencies = [ - "aurora-engine-sdk", - "aurora-engine-types", - "base64", - "borsh", - "ethabi", - "evm", - "evm-core", - "hex", - "libsecp256k1", - "num", - "primitive-types 0.11.1", - "ripemd160", - "sha2", - "sha3 0.9.1", - "zeropool-bn", -] - -[[package]] -name = "aurora-engine-sdk" -version = "1.0.0" -dependencies = [ - "aurora-engine-types", - "borsh", - "sha2", - "sha3 0.9.1", -] - -[[package]] -name = "aurora-engine-state-migration-test" -version = "1.0.0" -dependencies = [ - "aurora-engine", - "aurora-engine-sdk", - "aurora-engine-types", - "borsh", -] - -[[package]] -name = "aurora-engine-transactions" -version = "1.0.0" -dependencies = [ - "aurora-engine-precompiles", - "aurora-engine-sdk", - "aurora-engine-types", - "evm", - "hex", - "rlp", -] - -[[package]] -name = "aurora-engine-types" -version = "1.0.0" -dependencies = [ - "borsh", - "ethabi", - "hex", - "primitive-types 0.11.1", - "sha3 0.9.1", -] - -[[package]] -name = "auto_impl" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7862e21c893d65a1650125d157eaeec691439379a1cee17ee49031b79236ada4" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "base64" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" - -[[package]] -name = "beef" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6736e2428df2ca2848d846c43e88745121a6654696e349ce0054a420815a7409" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "block-padding", - "generic-array", -] - -[[package]] -name = "block-buffer" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-padding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" - -[[package]] -name = "borsh" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a7111f797cc721407885a323fb071636aee57f750b1a4ddc27397eba168a74" -dependencies = [ - "borsh-derive", - "hashbrown", -] - -[[package]] -name = "borsh-derive" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307f3740906bac2c118a8122fe22681232b244f1369273e45f1156b45c43d2dd" -dependencies = [ - "borsh-derive-internal", - "borsh-schema-derive-internal", - "proc-macro-crate 0.1.5", - "proc-macro2", - "syn", -] - -[[package]] -name = "borsh-derive-internal" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2104c73179359431cc98e016998f2f23bc7a05bc53e79741bcba705f30047bc" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae29eb8418fcd46f723f8691a2ac06857d31179d33d2f2d91eb13967de97c728" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "bumpalo" -version = "3.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe" - -[[package]] -name = "byte-slice-cast" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65c1bf4a04a88c54f589125563643d773f3254b5c38571395e2b591c693bbc81" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cpufeatures" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed00c67cb5d0a7d64a44f6ad2668db7e7530311dd53ea79bcd4fb022c64911c8" -dependencies = [ - "libc", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "crypto-mac" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "derive_more" -version = "0.99.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40eebddd2156ce1bb37b20bbe5151340a31828b1f2d22ba4141f3531710e38df" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "digest" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" -dependencies = [ - "block-buffer 0.10.2", - "crypto-common", -] - -[[package]] -name = "ethabi" -version = "17.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f186de076b3e77b8e6d73c99d1b52edc2a229e604f4b5eb6992c06c11d79d537" -dependencies = [ - "ethereum-types", - "hex", - "sha3 0.10.2", -] - -[[package]] -name = "ethbloom" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11da94e443c60508eb62cf256243a64da87304c2802ac2528847f79d750007ef" -dependencies = [ - "crunchy", - "fixed-hash", - "impl-codec", - "impl-rlp", - "scale-info", - "tiny-keccak", -] - -[[package]] -name = "ethereum" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23750149fe8834c0e24bb9adcbacbe06c45b9861f15df53e09f26cb7c4ab91ef" -dependencies = [ - "bytes", - "ethereum-types", - "hash-db", - "hash256-std-hasher", - "rlp", - "rlp-derive", - "sha3 0.10.2", - "triehash", -] - -[[package]] -name = "ethereum-types" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2827b94c556145446fcce834ca86b7abf0c39a805883fe20e72c5bfdb5a0dc6" -dependencies = [ - "ethbloom", - "fixed-hash", - "impl-codec", - "impl-rlp", - "primitive-types 0.11.1", - "scale-info", - "uint", -] - -[[package]] -name = "evm" -version = "0.35.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.36.0-aurora#7dfbeb535e7105a7531a4e6c559f0f5d45f20014" -dependencies = [ - "auto_impl", - "ethereum", - "evm-core", - "evm-gasometer", - "evm-runtime", - "log", - "primitive-types 0.11.1", - "rlp", - "sha3 0.10.2", -] - -[[package]] -name = "evm-core" -version = "0.35.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.36.0-aurora#7dfbeb535e7105a7531a4e6c559f0f5d45f20014" -dependencies = [ - "primitive-types 0.11.1", -] - -[[package]] -name = "evm-gasometer" -version = "0.35.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.36.0-aurora#7dfbeb535e7105a7531a4e6c559f0f5d45f20014" -dependencies = [ - "evm-core", - "evm-runtime", - "primitive-types 0.11.1", -] - -[[package]] -name = "evm-runtime" -version = "0.35.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.36.0-aurora#7dfbeb535e7105a7531a4e6c559f0f5d45f20014" -dependencies = [ - "auto_impl", - "evm-core", - "primitive-types 0.11.1", - "sha3 0.10.2", -] - -[[package]] -name = "fixed-hash" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" -dependencies = [ - "byteorder", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "generic-array" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", -] - -[[package]] -name = "hash-db" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" - -[[package]] -name = "hash256-std-hasher" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" -dependencies = [ - "crunchy", -] - -[[package]] -name = "hashbrown" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" -dependencies = [ - "ahash", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hmac" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" -dependencies = [ - "crypto-mac", - "digest 0.9.0", -] - -[[package]] -name = "hmac-drbg" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" -dependencies = [ - "digest 0.9.0", - "generic-array", - "hmac", -] - -[[package]] -name = "impl-codec" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" -dependencies = [ - "parity-scale-codec 3.1.5", -] - -[[package]] -name = "impl-rlp" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" -dependencies = [ - "rlp", -] - -[[package]] -name = "impl-trait-for-tuples" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5dacb10c5b3bb92d46ba347505a9041e676bb20ad220101326bffb0c93031ee" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "js-sys" -version = "0.3.51" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "keccak" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -dependencies = [ - "spin", -] - -[[package]] -name = "libc" -version = "0.2.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e" - -[[package]] -name = "libsecp256k1" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0452aac8bab02242429380e9b2f94ea20cea2b37e2c1777a1358799bbe97f37" -dependencies = [ - "arrayref", - "base64", - "digest 0.9.0", - "hmac-drbg", - "libsecp256k1-core", - "libsecp256k1-gen-ecmult", - "libsecp256k1-gen-genmult", - "rand", - "serde", - "sha2", - "typenum", -] - -[[package]] -name = "libsecp256k1-core" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" -dependencies = [ - "crunchy", - "digest 0.9.0", - "subtle", -] - -[[package]] -name = "libsecp256k1-gen-ecmult" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" -dependencies = [ - "libsecp256k1-core", -] - -[[package]] -name = "libsecp256k1-gen-genmult" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" -dependencies = [ - "libsecp256k1-core", -] - -[[package]] -name = "log" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "logos" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427e2abca5be13136da9afdbf874e6b34ad9001dd70f2b103b083a85daa7b345" -dependencies = [ - "logos-derive", -] - -[[package]] -name = "logos-derive" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56a7d287fd2ac3f75b11f19a1c8a874a7d55744bd91f7a1b3e7cf87d4343c36d" -dependencies = [ - "beef", - "fnv", - "proc-macro2", - "quote", - "regex-syntax", - "syn", - "utf8-ranges", -] - -[[package]] -name = "memory_units" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" - -[[package]] -name = "num" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d047c1062aa51e256408c560894e5251f08925980e53cf1aa5bd00eec6512" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26873667bbbb7c5182d4a37c1add32cdf09f841af72da53318fdb81543c15085" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" -dependencies = [ - "autocfg", -] - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "parity-scale-codec" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373b1a4c1338d9cd3d1fa53b3a11bdab5ab6bd80a20f7f7becd76953ae2be909" -dependencies = [ - "arrayvec", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive 2.3.1", -] - -[[package]] -name = "parity-scale-codec" -version = "3.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9182e4a71cae089267ab03e67c99368db7cd877baf50f931e5d6d4b71e195ac0" -dependencies = [ - "arrayvec", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive 3.1.3", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" -dependencies = [ - "proc-macro-crate 1.1.0", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "3.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9299338969a3d2f491d65f140b00ddec470858402f888af98e8642fb5e8965cd" -dependencies = [ - "proc-macro-crate 1.1.0", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "primitive-types" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" -dependencies = [ - "fixed-hash", - "impl-rlp", - "uint", -] - -[[package]] -name = "primitive-types" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a" -dependencies = [ - "fixed-hash", - "impl-codec", - "impl-rlp", - "scale-info", - "uint", -] - -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml", -] - -[[package]] -name = "proc-macro-crate" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" -dependencies = [ - "thiserror", - "toml", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" - -[[package]] -name = "regex-syntax" -version = "0.6.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" - -[[package]] -name = "ripemd160" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eca4ecc81b7f313189bf73ce724400a07da2a6dac19588b03c8bd76a2dcc251" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "rjson" -version = "0.3.2" -source = "git+https://github.com/aurora-is-near/rjson?rev=cc3da949#cc3da9495e7e520900d66d2b517539f74fff93cf" - -[[package]] -name = "rlp" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e54369147e3e7796c9b885c7304db87ca3d09a0a98f72843d532868675bbfba8" -dependencies = [ - "bytes", - "rustc-hex", -] - -[[package]] -name = "rlp-derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - -[[package]] -name = "scale-info" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c55b744399c25532d63a0d2789b109df8d46fc93752d46b0782991a931a782f" -dependencies = [ - "cfg-if 1.0.0", - "derive_more", - "parity-scale-codec 2.3.1", - "scale-info-derive", -] - -[[package]] -name = "scale-info-derive" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baeb2780690380592f86205aa4ee49815feb2acad8c2f59e6dd207148c3f1fcd" -dependencies = [ - "proc-macro-crate 1.1.0", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde" -version = "1.0.126" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.126" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "sha2" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362ae5752fd2137731f9fa25fd4d9058af34666ca1966fb969119cc35719f12" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "sha3" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "keccak", - "opaque-debug", -] - -[[package]] -name = "sha3" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a31480366ec990f395a61b7c08122d99bd40544fdb5abcfc1b06bb29994312c" -dependencies = [ - "digest 0.10.3", - "keccak", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "subtle" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" - -[[package]] -name = "syn" -version = "1.0.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "thiserror" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "toml" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" -dependencies = [ - "serde", -] - -[[package]] -name = "triehash" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1631b201eb031b563d2e85ca18ec8092508e262a3196ce9bd10a67ec87b9f5c" -dependencies = [ - "hash-db", - "rlp", -] - -[[package]] -name = "typenum" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" - -[[package]] -name = "uint" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6470ab50f482bde894a037a57064480a246dbfdd5960bd65a44824693f08da5f" -dependencies = [ - "byteorder", - "crunchy", - "hex", - "static_assertions", -] - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "utf8-ranges" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" - -[[package]] -name = "version_check" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[package]] -name = "wasm-bindgen" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd" -dependencies = [ - "cfg-if 1.0.0", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900" -dependencies = [ - "bumpalo", - "lazy_static", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" - -[[package]] -name = "wee_alloc" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "memory_units", - "winapi", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "zeropool-bn" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e61de68ede9ffdd69c01664f65a178c5188b73f78faa21f0936016a888ff7c" -dependencies = [ - "byteorder", - "crunchy", - "lazy_static", - "rand", - "rustc-hex", -] diff --git a/etc/tests/.catalog-info.yaml b/etc/tests/.catalog-info.yaml new file mode 100644 index 000000000..2437b8305 --- /dev/null +++ b/etc/tests/.catalog-info.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: aurora-engine-tests + description: |- + Collection of Engine Tests + tags: + - near + links: [] + annotations: + aurora.dev/security-tier: "-1" +spec: + owner: engine-team + type: contract-tests + lifecycle: production + system: aurora-engine + interactsWith: [] diff --git a/etc/tests/fibonacci/src/lib.rs b/etc/tests/fibonacci/src/lib.rs index 0e4b4a55f..9de166514 100644 --- a/etc/tests/fibonacci/src/lib.rs +++ b/etc/tests/fibonacci/src/lib.rs @@ -57,7 +57,7 @@ impl Fib { p } - /// An alternative version of `accumulate`. Rather then performing the recursion + /// An alternative version of `accumulate`. Rather than performing the recursion /// with a single input which contains the previous two Fibonacci values, this function /// takes the previous two terms as separate inputs. This gives an alternate way to compute /// Fibonacci numbers using this contract: `fib(n - 1).and(fib(n - 2)).then(sum)`. diff --git a/etc/tests/self-contained-5bEgfRQ/Cargo.toml b/etc/tests/self-contained-5bEgfRQ/Cargo.toml index 8a69714e0..a43be94fc 100644 --- a/etc/tests/self-contained-5bEgfRQ/Cargo.toml +++ b/etc/tests/self-contained-5bEgfRQ/Cargo.toml @@ -37,7 +37,7 @@ codegen-units = 1 rpath = false [dependencies] -borsh = { version = "0.9.3", default-features = false } +borsh = { version = "0.10", default-features = false } aurora-engine = { path = "../../../engine", default-features = false } aurora-engine-sdk = { path = "../../../engine-sdk", default-features = false, features = ["contract"] } aurora-engine-types = { path = "../../../engine-types", default-features = false } diff --git a/etc/tests/self-contained-5bEgfRQ/src/lib.rs b/etc/tests/self-contained-5bEgfRQ/src/lib.rs index e146a6487..16bd4a956 100644 --- a/etc/tests/self-contained-5bEgfRQ/src/lib.rs +++ b/etc/tests/self-contained-5bEgfRQ/src/lib.rs @@ -39,7 +39,7 @@ pub extern "C" fn run() { let state = BTreeMap::try_from_slice(STATE).unwrap(); let in_mem_io = InMemIO::new(&state, INPUT); - let engine_state = aurora_engine::engine::get_state(&in_mem_io).unwrap(); + let engine_state = aurora_engine::state::get_state(&in_mem_io).unwrap(); let relayer_address = aurora_engine_sdk::types::near_account_to_evm_address( local_env.predecessor_account_id.as_bytes(), ); diff --git a/etc/tests/state-migration-test/Cargo.toml b/etc/tests/state-migration-test/Cargo.toml index bf645e4b0..a843975d5 100644 --- a/etc/tests/state-migration-test/Cargo.toml +++ b/etc/tests/state-migration-test/Cargo.toml @@ -37,7 +37,7 @@ codegen-units = 1 rpath = false [dependencies] -borsh = { version = "0.9.3", default-features = false } +borsh = { version = "0.10", default-features = false } aurora-engine = { path = "../../../engine", default-features = false } aurora-engine-sdk = { path = "../../../engine-sdk", default-features = false, features = ["contract"] } aurora-engine-types = { path = "../../../engine-types", default-features = false } diff --git a/etc/tests/state-migration-test/src/lib.rs b/etc/tests/state-migration-test/src/lib.rs index 1e7ae6ccf..08b82b09e 100644 --- a/etc/tests/state-migration-test/src/lib.rs +++ b/etc/tests/state-migration-test/src/lib.rs @@ -3,7 +3,7 @@ extern crate alloc; use alloc::vec::Vec; -use aurora_engine::engine::{self, EngineState}; +use aurora_engine::state; use aurora_engine_sdk::near_runtime::Runtime; use aurora_engine_sdk::io::{IO, StorageIntermediate}; use aurora_engine_types::storage; @@ -11,14 +11,14 @@ use borsh::{BorshDeserialize, BorshSerialize}; #[derive(BorshDeserialize, BorshSerialize)] struct NewFancyState { - old_state: EngineState, + old_state: state::EngineState, some_other_numbers: [u32; 7], } #[no_mangle] pub extern "C" fn state_migration() { let mut io = Runtime; - let old_state = match engine::get_state(&io) { + let old_state = match state::get_state(&io) { Ok(state) => state, Err(e) => aurora_engine_sdk::panic_utf8(e.as_ref()), }; diff --git a/etc/xcc-router/.catalog-info.yaml b/etc/xcc-router/.catalog-info.yaml new file mode 100644 index 000000000..b6fa1f3dc --- /dev/null +++ b/etc/xcc-router/.catalog-info.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: aurora-engine-xcc-router + description: |- + Cross-contract call ruter for engine tests + tags: + - near + links: [] + annotations: + aurora.dev/security-tier: "-1" +spec: + owner: engine-team + type: contract-tests + lifecycle: production + system: aurora-engine + interactsWith: [] diff --git a/etc/xcc-router/Cargo.lock b/etc/xcc-router/Cargo.lock index 65de40ccc..a4bd9ebae 100644 --- a/etc/xcc-router/Cargo.lock +++ b/etc/xcc-router/Cargo.lock @@ -41,9 +41,12 @@ checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" name = "aurora-engine-types" version = "1.0.0" dependencies = [ - "borsh", + "borsh 0.10.2", + "borsh 0.9.3", "hex", "primitive-types 0.12.1", + "serde", + "serde_json", ] [[package]] @@ -118,7 +121,17 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" dependencies = [ - "borsh-derive", + "borsh-derive 0.9.3", + "hashbrown", +] + +[[package]] +name = "borsh" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40f9ca3698b2e4cb7c15571db0abc5551dca417a21ae8140460b50309bb2cc62" +dependencies = [ + "borsh-derive 0.10.2", "hashbrown", ] @@ -128,8 +141,21 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" dependencies = [ - "borsh-derive-internal", - "borsh-schema-derive-internal", + "borsh-derive-internal 0.9.3", + "borsh-schema-derive-internal 0.9.3", + "proc-macro-crate 0.1.5", + "proc-macro2", + "syn", +] + +[[package]] +name = "borsh-derive" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598b3eacc6db9c3ee57b22707ad8f6a8d2f6d442bfe24ffeb8cbb70ca59e6a35" +dependencies = [ + "borsh-derive-internal 0.10.2", + "borsh-schema-derive-internal 0.10.2", "proc-macro-crate 0.1.5", "proc-macro2", "syn", @@ -146,6 +172,17 @@ dependencies = [ "syn", ] +[[package]] +name = "borsh-derive-internal" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186b734fa1c9f6743e90c95d7233c9faab6360d1a96d4ffa19d9cfd1e9350f8a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "borsh-schema-derive-internal" version = "0.9.3" @@ -157,6 +194,17 @@ dependencies = [ "syn", ] +[[package]] +name = "borsh-schema-derive-internal" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99b7ff1008316626f485991b960ade129253d4034014616b94f309a15366cc49" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "bs58" version = "0.4.0" @@ -451,6 +499,15 @@ dependencies = [ "rlp", ] +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + [[package]] name = "impl-trait-for-tuples" version = "0.2.2" @@ -492,7 +549,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de83d74a9241be8cc4eb3055216966b58bf8c463e8e285c0dc553925acdd19fa" dependencies = [ - "borsh", + "borsh 0.9.3", "serde", ] @@ -504,7 +561,7 @@ checksum = "b8ecf0b8b31aa7f4e60f629f72213a2617ca4a5f45cd1ae9ed2cf7cecfebdbb7" dependencies = [ "arrayref", "blake2", - "borsh", + "borsh 0.9.3", "bs58", "c2-chacha", "curve25519-dalek", @@ -529,7 +586,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a2ba19282e79a4485a77736b679d276b09870bbf8042a18e0f0ae36347489c5" dependencies = [ - "borsh", + "borsh 0.9.3", "byteorder", "bytesize", "chrono", @@ -559,7 +616,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb561feb392bb8c4f540256073446e6689af087bf6356e8dddcf75fc279f201f" dependencies = [ "base64 0.11.0", - "borsh", + "borsh 0.9.3", "bs58", "derive_more", "near-account-id", @@ -598,7 +655,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bda34e06e28fb9a09ac54efbdc49f0c9308780fc932aaa81c49c493fde974045" dependencies = [ "base64 0.13.0", - "borsh", + "borsh 0.9.3", "bs58", "near-crypto", "near-primitives", @@ -635,7 +692,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e02faf2bc1f6ef82b965cfe44389808fb5594f7aca4b596766117f4ce74df20" dependencies = [ - "borsh", + "borsh 0.9.3", "near-account-id", "near-rpc-error-macro", "serde", @@ -648,7 +705,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f024d90451cd3c24d7a0a5cabf3636b192a60eb8e3ff0456f6c18b91152c346d" dependencies = [ "base64 0.13.0", - "borsh", + "borsh 0.9.3", "bs58", "byteorder", "near-account-id", @@ -780,6 +837,7 @@ checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" dependencies = [ "fixed-hash 0.8.0", "impl-rlp", + "impl-serde", "uint", ] diff --git a/etc/xcc-router/Cargo.toml b/etc/xcc-router/Cargo.toml index faf1e77f7..ce5db7e32 100644 --- a/etc/xcc-router/Cargo.toml +++ b/etc/xcc-router/Cargo.toml @@ -15,7 +15,7 @@ debug = false panic = "abort" [dependencies] -aurora-engine-types = { path = "../../engine-types", default-features = false } +aurora-engine-types = { path = "../../engine-types", default-features = false, features = ["borsh-compat"] } near-sdk = "4.0.0" [features] diff --git a/etc/xcc-router/src/lib.rs b/etc/xcc-router/src/lib.rs index fd604ea3f..c8763bc5f 100644 --- a/etc/xcc-router/src/lib.rs +++ b/etc/xcc-router/src/lib.rs @@ -6,7 +6,9 @@ use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; use near_sdk::collections::{LazyOption, LookupMap}; use near_sdk::json_types::{U128, U64}; use near_sdk::BorshStorageKey; -use near_sdk::{env, near_bindgen, AccountId, Gas, PanicOnDefault, Promise, PromiseIndex}; +use near_sdk::{ + env, near_bindgen, AccountId, Gas, PanicOnDefault, Promise, PromiseIndex, PromiseResult, +}; #[cfg(not(target_arch = "wasm32"))] #[cfg(test)] @@ -194,7 +196,15 @@ impl Router { .get() .unwrap_or_else(|| env::panic_str("ERR_CONTRACT_NOT_INITIALIZED")); if caller != parent { - env::panic_str(ERR_ILLEGAL_CALLER) + env::panic_str(ERR_ILLEGAL_CALLER); + } + // Any method that can only be called by the parent should also only be executed if + // the parent's execution was successful. + let num_promises = env::promise_results_count(); + for index in 0..num_promises { + if let PromiseResult::Failed | PromiseResult::NotReady = env::promise_result(index) { + env::panic_str("ERR_CALLBACK_OF_FAILED_PROMISE"); + } } } diff --git a/rust-toolchain b/rust-toolchain index 067dff55b..e1a2ebf0f 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,3 @@ [toolchain] channel = "nightly-2022-09-29" -components = [] targets = ["wasm32-unknown-unknown"]