From c202942beab85f759b860c803dc56dd5f3eb79e6 Mon Sep 17 00:00:00 2001 From: Web3 Philosopher Date: Tue, 22 Mar 2022 08:43:32 +0100 Subject: [PATCH] polkadot-v0.9.17 (#789) * [CU-200y9ka] Auction: generate a file with weights (#470) * CU-200y9ka - Auction: generate a file with weights * Make clippy happier * Fix tests * Add remark check in CI (#220) * Add remark check in CI * Add a config file for remark * Update config of CI * Make remark happier * Revert crowdloan bench (#485) * refactor crowdloan benchmarking * revert benchmarking integration of crowdloan rewards * CU-1uq4a7x - ValidateUnsigned instead of SignedExtension in Crowdloan (#486) * move crowdloan from SignedExtension to ValidateUnsigned * revert transaction version upgrade as we removed the SignedExtra * Check including wasm build (#489) * Check including wasm build * Add std feature check * remove actions-rs from test step (#490) * CU-1ubvcrq - introduce `Validated` and `Validate` for custom codec validation (#492) * introduce `Validated` and `Validate` for custom codec validation * add missing Deref/AsRef, use WrapperTypeEncode and introduce `And` * devnet (#427) * devnet release * Build everything * Use self hosted runners * use pre-installed cargo Co-authored-by: Karel L. Kubat * Fix devnet deployment (#502) * fix * only on main * CU-1wty9p0 oracle api clarification (#462) * oracle api clarification Signed-off-by: Dzmitry Lahoda * fixing pr comments Signed-off-by: Dzmitry Lahoda * fixed comment Signed-off-by: Dzmitry Lahoda * crazy fmt issue Signed-off-by: Dzmitry Lahoda * just something to tirgget build after fail Signed-off-by: Dzmitry Lahoda * fixed price, added ratio test Signed-off-by: Dzmitry Lahoda * fixed comments Signed-off-by: Dzmitry Lahoda * docs(Updated local devnet run information.): (#505) Removed "--features develop" flag from local build command instructions. Signed-off-by: Dominik Roth * CU-1yykjpw Fix calc_utilization_ratio() and add proptest for it. * CU-1u5ykup - add generated types and refactor, add eth sign to crowdloan tests, bonded finance tests implementation (#487) * add generated types and refactor tests, add eth sign to crowdloan * Pulling bondPrice for bondedFinance Tests from variable * test(bondedFinance TX Tests, Added mocha config file, Cleanup.): (txBondedFinanceTests.ts): bondedFinance Extrinsic test implementation. (BondedFinance Pallet): MinReward now exposed through a constant query. (queryCrowdloanRewardsTests.ts): Updated checks and timeout. Following files have been removed, due to problems with the new type implementation. (queryTokenTests.ts): Removed Query Token Tests (Partial stub and stopped working) (querySystemAccountTests.ts): Removed Query System Account Tests (Stopped working) Added .mocharc.json configuration file. Cleanup Signed-off-by: Dominik Roth * test(bondedFinance TX Tests, bondedFinance pallet, Runtime Tests ReadMe): (txBondedFinanceTests.ts): Moved test handlers into a folder to reduce the file length. Also added additional tests. (BondedFinance Pallet): In cancel function, set keep-alive of second Transfer function to false. Since clears the wallet of the staking account, and wasn't working therefore. (README.md): Changed timeout example to not show an infinite timeout. Added run information for the type generator. Signed-off-by: Dominik Roth Co-authored-by: Dominik Roth <96540347+Dom-Roth@users.noreply.github.com> Co-authored-by: Dominik Roth * Add Makefile.toml (#506) * Adds Benchmarking & Simnode (#497) * check_runtime workflow * check_runtime workflow * Updates weights for picasso-dev * update benchmark script * update benchmark script * support -> frame_support * Updates weights for picasso-dev * Updates weights for dali-dev * fix conflict * Add cargo.lock * fix runtime.sh * replace boldprint with echo * adds set_changes_trie_config to weights * adds set_changes_trie_config to weights * Updates weights for picasso-dev * hotpatch substrate * fmt & clippy * Updates weights for picasso-dev * Update simnode script * Update github workflow * Update github workflow * Updates weights for dali-dev * Update github workflow * Update github workflow * Updates weights for composable-dev * Add condition to ignore check_runtime on draft PR * fmt * adds +nighly to checks * add git pull * Finalizing cleanup * Finalizing cleanup * fmt fixes * clippy fixes * use +nightly-2021-11-29 for fmt * Updates weights for picasso-dev Co-authored-by: Seun Lanlege Co-authored-by: haroldsphinx * CU-1wty1zv fixed lending (#484) * oracle api clarification Signed-off-by: Dzmitry Lahoda * fixing pr comments Signed-off-by: Dzmitry Lahoda * fixed comment Signed-off-by: Dzmitry Lahoda * crazy fmt issue Signed-off-by: Dzmitry Lahoda * just something to tirgget build after fail Signed-off-by: Dzmitry Lahoda * fixed lending Signed-off-by: Dzmitry Lahoda * fixed price, added ratio test Signed-off-by: Dzmitry Lahoda * fixed comments of review Signed-off-by: Dzmitry Lahoda * fixed comments Signed-off-by: Dzmitry Lahoda * Update benchmark workflow (#510) * Update Makefile * Update release * Update * Updating release * Added runtime check * Consolidate all branches into main * Update check_runtime * update benchmark workflow * fix makefile * diff base branch * diff base branch * diff base branch * fix makefile * github.ref * i give up * show-current * use commit sha * fetch main branch * try again Co-authored-by: Seun Lanlege * Add tag for polkadotjs signature in crowdloan (#514) The public polkadotjs api signRaw is wrapping the message in this tag. * [CU-2326a8t] Update benchmarks of pallet-dutch-auction (#512) * Update benchmarks of pallet-dutch-auction * Update benchmarks of pallet-dutch-auction * fix asset count to change an existing asset (#481) * fix asset count to change an existing asset * remove unused slash amount * remove lingering slash amount * handle better then default * remove unwrap or defaults from asset_info * fix benchmarks * Add cleanup step (#515) * Rollout Cleanup to fix max buffer error * fix check runtime for main & releases (#513) * fix check runtime for main & releases * fix diffs * conditionl artifact build * fix syntax * fix syntax * testing * take 2 * take 3 * seun 1 - 0 CI * needs-benchmarks * Update .maintain/client_release.sh * fix release notes * Add bump version (#519) * fix workflow syntax * Add cleanup step * add bump version * bump version and changelog * bump version and changelog * bump version and changelog * bump version and changelog * Release drafter update (#525) * cleanup some CI cruft (#511) * Cleanup CI and add rust-toolchain.toml * remove .yarn * fmt * adds script to update draft release (#528) * added oracle setup script (#503) * Add BoundedSortedVec and SortedVec (#532) * Add BoundedSortedVec and SortedVec * fail on unsorted decodes * adds paritytech/ci-linux:production (#536) * added paritytech * update branch trigger * update run machines * Update .github/workflows/paritytech.yml * Apply suggestions from code review * update cargo nightly * update cargo exec path * Update .github/workflows/check.yml Co-authored-by: Seun Lanlege * update check.yml * use llvm-cov action * prevent rust-toolchain.toml from overriding parity:ci * update workflow file * fix hadolint * update hadolint to action * remove image for unit test * fix syntax error * install cargo-llvm manually * use image * skip hadolint and remark * add llvm-tools-preview * run llvm-cov on runner * update workflow file * update workflow file * force install * llvm-cov in paritytech/ci-linux:production * rustup show * install llvm * remove sudo * one-line install * apt-get install wget * apt-get install wget * apt-get install wget * gnupg2 * run code-cov on runner * path to cargo bin * remove llvm installation * use specific nightly version * please just work * sigh Co-authored-by: Seun Lanlege Co-authored-by: Seun Lanlege Co-authored-by: haroldsphinx * substitute dali & picasso wasm in chainspec with tested wasm (#539) * clean up release pipeline (#541) * Add Acala's tests (#534) * [CU-23t6rux] Add decimals for foreign assets in assets-registry (#552) * Add decimals for foreign assets in assets-registry * Renaming * fixes #535 (#553) * fixes #535 * don't skip integration tests * remove ref: main * get github ref from action * try base_ref * try GITHUB_SHA * GITHUB_REF_NAME * back to GITHUB_SHA * checkout pull request commit * renamee to release-pipeline * back to Co-authored-by: Seun Lanlege * install stable+nightly (#554) * Fix issue with git diff (#557) * Fix issue with git diff * rename git tags * rename git tags * deploy devnet from main (#559) * kill stale jobs when pushing new changes (#562) * kill stale jobs when pushing new changes * test cancel * test: Fixed docstrings and variable naming. (#529) Signed-off-by: Dominik Roth test: Checks added to oracle tx tests, fixed crowdloan tx test. Result checks added to oracle tx tests. Fixed associate() tests for crowdloan rewards. Added oracle tx tests documentation. Fixed Lint configuration Signed-off-by: Dominik Roth test: Fix test.ts calls. Signed-off-by: Dominik Roth test(Oracle Runtime Tests): All oracle success tests implemented. Signed-off-by: Dominik Roth fix(Runtime Tests Interfaces): Fixed faulty interface generation, due to changes to dutchAuction pallet. Signed-off-by: Dominik Roth test(Better error messages.): Signed-off-by: Dominik Roth test(bugfix):Tests erroring if result has no event attribute. Updated polkadot api. Signed-off-by: Dominik Roth test: Oracle Runtime Test Integration, Bugfix in Request function. (txOracleTests.ts): Added addStake Test, fixed a few issues. (polkadotjs.ts): Fixed filter for missing event tag in request result. (.mocharc.json): Set retries per test to 0. This had caused problems, due to multiple Promise returns, if the answer was just delayed. (tsconfig.json): Configured to resolve json modules. Signed-off-by: Dominik Roth test: Oracle Tests Implementation, Configs & Deps, Cleanup (txOracleTests.ts): Implemented first oracle tests. (txCrowdloanRewardsTests.ts): Cleanup. (polkadotjs.ts): Switched from lambda functions to normal ones. (test.ts): Added oracle tests calls and cleanup. (mocharc.json): Added reporter configurations and added .ts files to "watch-files". Dependency update. Signed-off-by: Dominik Roth test: Oracle Tests Implementation, Configs & Deps, Cleanup (txOracleTests.ts): Implemented first oracle tests. (txCrowdloanRewardsTests.ts): Cleanup. (polkadotjs.ts): Switched from lambda functions to normal ones. (test.ts): Added oracle tests calls and cleanup. (mocharc.json): Added reporter configurations and added .ts files to "watch-files". Fixed Mochawesome not exporting results. Dependency update. Signed-off-by: Dominik Roth * pallet mosaic (#547) * initial commit * save * add a couple of tests * add events everywhere * Fix updating of penalty * Add test for linear_decay * remove unused variables * add rescind_timelocked_mit and set_timelock_duration * add tests for transfer_to and accept_transfer * more tests and a fix * enable todo in do_transfer_to * avoid burning the full balance * introduce tuple in scope instead of indexing * fixup * Split account into sub_accounts * Fix do_transfer_to test by checking if the correct Event was emitted * Fix timelocked_mint tests * Fix issue where any user could remove IncomingTransactions belonging to any other account * More mosaic docs * introduce `TransactionType` and `SubAccount` to split incoming/ougoing accounts Users were having their incoming/outgoing funds merged together into a single sub_account within the pallet. Which would allow a bug to impact all the funds. By splitting them, they are isolated. * use tuple deconstruction instead of indexing * format tests * use `AssetId` instead of `CurrencyId` for consistency in tests * implements more tests & fix some types used by mocking (accountId too small) * Group transfer_to tests * Add more test todos * set_relayer tests * rotate_relayer tests * set_network tests * more budget tests * more mosaic tests * mosaic timelocked_mint tests * more mosaic timelocked_mint tests * add a couple of tests * Fix updating of penalty * add tests for transfer_to and accept_transfer * more tests and a fix * Split account into sub_accounts * Fix timelocked_mint tests * More mosaic docs * introduce `TransactionType` and `SubAccount` to split incoming/ougoing accounts Users were having their incoming/outgoing funds merged together into a single sub_account within the pallet. Which would allow a bug to impact all the funds. By splitting them, they are isolated. * format tests * use `AssetId` instead of `CurrencyId` for consistency in tests * implements more tests & fix some types used by mocking (accountId too small) * Group transfer_to tests * Add more test todos * more mosaic tests * mosaic timelocked_mint tests * mosaic test claim_to * convert first mosaic test to proptest * proptest with unique AccountIds * add prop_assert_err and prop_assert_noop * use prop_assert_err and prop_assert_noop in mosaic tests * rename decay types * test decay of budget penalties for mints * cargo fmt * cargo fmt nightly * forbid impossible state by avoiding default instance for RelayerConfig We were using Default + ValueQuery for RelayerConfig. It was fine because RelayerConfig was containing an `Option` but this would allow inconsistent states such as None for RelayerConfig.current & None for RelayerConfig.next. By removing the option within RelayerConfig and using an OptionQuery for the storage, we it's more clear that a Relayer can be Set/Unset. And if set, an AcccountId must be present. * better naming * fmt * update test-helpers edition * remove rust-version from mosaic * refactor for consistency * remove unused newline * better naming * more comments on decayer * reflect the partial/complete nature of a transfer via the event * rebase on main * fiix difffd * bump spec version for simnode * fmt Co-authored-by: kaiserkarel Co-authored-by: Hussein Ait Lahcen Co-authored-by: Seun Lanlege * CU-1ux3e25 CU-1q4x2t6 CU-1pdtjrz finalizing lending features (#546) * make benchmark to work with labels (#563) * make benchmark to work with labels * trigger workflow based on label * Update CODEOWNERS (#565) * Bring mosaic in dali (#564) * add missing constant/getter * fix mosaic bringing std via num-traits default features * add mosaic to dali runtime * Bump node-fetch from 2.6.6 to 2.6.7 in /integration-tests/runtime-tests (#558) Bumps [node-fetch](https://github.com/node-fetch/node-fetch) from 2.6.6 to 2.6.7. - [Release notes](https://github.com/node-fetch/node-fetch/releases) - [Commits](https://github.com/node-fetch/node-fetch/compare/v2.6.6...v2.6.7) --- updated-dependencies: - dependency-name: node-fetch dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * update release drafter template (#566) * Update sequence diagram of assets-registry (#568) * fix for dalishot backup (#569) * fix for dalishot backup * testing backup * testing backup * testing backup * testing backup * cleanup * exclude subxt Co-authored-by: Seun Lanlege * added label trigger (#576) * added label trigger * add if condition based on lable * Simnode trigger (#577) * added label trigger * add if condition based on lable * fix if statement * Introduce ControlOrigin (#574) * Introduce ControlOrigin * import EnsureRoot * CU-24fwjma Add implementation of codec::MaxEncodedLen in pallet-assets-registry (#575) * Add implementation of codec::MaxEncodedLen for all types persisted to storage in assets-registry * Bump spec_version * Added 'std' features to Balances (#548) * Added 'std' features to Balances * Removed Balances from build dep * some clippy and warnings and more checks (#570) * some clippy and warnings and more checks Signed-off-by: Dzmitry Lahoda * fixing build Signed-off-by: Dzmitry Lahoda * fix version again Signed-off-by: Dzmitry Lahoda * tuning deny Signed-off-by: Dzmitry Lahoda * fixing rebase Signed-off-by: Dzmitry Lahoda Co-authored-by: Ewere Diagboya * CU-1nh9erq Implement basic DEX Router pallet. (#446) * Implement basic DEX Router pallet. * [CU-244gudh] Update dex-router (#561) * Use BoundedVec instead of Vec in pallet-dex-router * Add tests in pallet-dex-router * Add TODO comment for minimum expected value as input parameter to `exchange()`. Co-authored-by: andor0 * CU-24fwjma Add MaxEncodedLen implementations in pallets (#580) * Add MaxEncodedLen implementations in pallets * Formatting * all scripts: fail on error (#583) * Inverted Validate trait (#572) * failed to decode wrapped types * inverted validate * inverted existing impl of Validate * Added module doc and examples * cargo +nightly fmt * fixed module doc examples * removed commented out code * restored validation * cargo +nightly fmt * made validate param more generic * cleaned up validate calls * add workflow for label validation (#582) * simplify benchmarking (#585) * disable logs during benchmarking * Use wildcard for pallet selector * re-add log filter * tinker around more * disable runtime change check * add workflow dispatch trigger * properly disable check for runtime changes * Update simnode script (#590) * Update simnode script * Update simnode script * Update simnode path (#592) * Update simnode script * Update simonde script * Update simnode path (#593) * Update simnode script * Update simonde script * github action to upload benchmark commit * github action to upload benchmark commit * github action to upload benchmark commit * github action to upload benchmark commit * github action to upload benchmark commit * github action to upload benchmark commit * Pushing benchmark changes * github action to upload benchmark commit * github action to upload benchmark commit Co-authored-by: haroldsphinx * Update simnode path (#594) * Update simnode script * Update simonde script * github action to upload benchmark commit * github action to upload benchmark commit * github action to upload benchmark commit * github action to upload benchmark commit * github action to upload benchmark commit * github action to upload benchmark commit * Pushing benchmark changes * github action to upload benchmark commit * github action to upload benchmark commit * github action to upload benchmark commit Co-authored-by: haroldsphinx * Upgrade to polkadot-v0.9.16 (#567) * switch deps * add fork patch * upgrade to v0.9.16 * wip parachain utils * upgrade pallet-privilege to 0.9.16 * Add support of polkadot-v0.9.16 in pallet-oracle (#587) * postpone upgrade * missing maxencodedlen for defi struct * style * normalize orml-tokens/orml-traits and upgrade dex-router * update cargolock * derive MaxEncodedLen for Currency * reorder * revert registre MaxEncodedLen as XcmLocation does not implements it yet * upgrade xcm related orml packages and add preimage * format * WIP: upgrade runtime, please CHECK THIS * update cargo.lock * upgrade node/chain_spec * parachain_utils: make upgrade_runtime generic * bump transaction version * fmt * parachain_utils:: minor fix * parachain_utils: minor fixes * Use BoundedVec instead of Vec (#589) * upgrade executive, from AllPallets to AllPalletsReversedWithSystemFirst to preserve previous behavior * upgrade pallet mocks, adding missing MaxConsumers in sys config * remove unused benchmark from composable * fix oracle benchmarking * update cargo.lock * fix parachain-utils * some stuff * format * fix tests/benchmarking * update cargo.lock * style * some stuff * upgrade xcm-emulator * update cargo.lock * ignore integration tests * ignore simnode * fix simnode * benchmarks * adds scheduler migrations * cargo fmt * bump runtime version * cargo fmt * fix benchmark workflow * fix check benchmarks * cargo fmt * fix benchmark.yml * fix runtime benchmark * simnode stuff * only benchmark picasso * Pushing benchmark changes * finalize picasso benchmarks * fix weights * cargo fmt Co-authored-by: Hussein Ait Lahcen Co-authored-by: david Co-authored-by: andor0 Co-authored-by: seunlanlege * update git token for label (#597) * Update an errors handling (#599) * add std features for some missing pallets (#602) * mosaic benchmarks * benchmark set_relayer * benchmark rotate_relayer * benchmark set_network and set_budget (set_budget still wip) * more explicit error when a tx is still locked * implement missing benchmarking * introduce weightinfo for mosaic * introduce weightinfo for mosaic config * fix benchmark and test issues * generate weights for mosaic and use them in dali * style * bump impl version for simnode * Pushing benchmark changes * prefer the usage of arbitrary weights rather than 0 for () Co-authored-by: Hussein Ait Lahcen Co-authored-by: hussein-aitlahcen * Update benchmarking docs (#605) * improving lending docs (#601) Signed-off-by: Dzmitry Lahoda * Karel/currency ranges (#584) * save * migrate pallets to new currency-factory-impl * lint * add CurrencyFactory to list-benchmarks * disable RUNTIME_CHECK * Updates weights for picasso-dev * remove needles reference * Add MaxConsumers to currency-factory Co-authored-by: haroldsphinx * CU-1wty1h0 liquidations test/bench/runtime - required by lending (#608) * liquidation test and runtime Signed-off-by: Dzmitry Lahoda * build fix Signed-off-by: Dzmitry Lahoda * revert chainspec to picasso-1.2.0 (#610) * Karel/assets more tests (#551) * Add proptests for currency implementation * reservable currency tests * updated indentation * updated indentation * updating formatting * multicurrency tests * added lockcable multicurrency tests * updated lockable multicurrency tests * updated lockable multicurrency tests * updated lockable multicurrency tests * repariate_reserve * updated Cargo.lock * removed unused comment * removed empty comments * removed version * returned error * returned to proptest * updated mock user name * updated mock user name * fixed variale dec * removed unused imports * fixed braces * added import * returned error * empty * cargo fmt * updated test * updated test Co-authored-by: kaiserkarel * CI Fixes (#613) * ci fixes * test release pipeline * remove release pipeline * Update benchmarks settings (#617) * CU-256ucnj Update pallet-lending (#609) * Update pallet-lending * Do extrinsic permissionless * bonded-finance benchmarking (#579) * finalize bonded-finance benchmarking * style * more doc and cleanup todo * arbitrary weights for () * bump impl_version * Pushing benchmark changes * devnet upgrade (#622) * Update Simnode Implementation (#624) * simnode update * update simnode api implementation * update simnode deps * remove unused deps * Update integration-tests/simnode/src/chain/picasso.rs * fix diffing on release-pipeline (#626) * Ci upgrade (#627) * Update simnode script * Update simonde script * Cleanup Ansible github actions * Debugging docker release failures * Add Slack Integration for feedback notification * Ad custom channel for reporrting errors * Add cargo build step for docker release * Update makefile for docker * Update makefile for docker * Fix docker release * Fix docker release * Add dali-chachacha client release to docker release * Create release notifier * Update slack token * Update release-pipeline fix * Update release-pipeline fix * add concurrency flow * Update docker releae flow * Update Makefile Co-authored-by: Seun Lanlege * update workflow * add version to realease-pipeline binaru * cleanup workflow Co-authored-by: Seun Lanlege * fix polkadot launch config (#621) * adds chainspec for rococo (#631) * Ben/assets rpc (#493) * Implement basic RPC structure Implement basic RPC structure Implement basic balance_of functionality (untested) Add asset rpc to node Add assets RPC to picasso runtime Remove develop feature gate from rpc Add assets rpc to picasso runtime (WIP) Add assets RPC to dali and composable runtimes Fix WASM build This requird refactoring the assets pallet into 3 separate crates: rpc, runtime-api, and pallet so that there weren't non-wasm compatable dependencies in the runtime. add std feature to composable Move assets pallet back to frame/assets Remove extraneous commented code Update workspace Cargo.toml Formatting Add crowdloan rewards rpc Fix workspace members Update cargo.lock & add crowdloan rewards rcp to runtimes Implement basic crowdloan rewards rpc custom rpc polkadotjs Change signature of crowdloan rewards rpc to use AccountId add interface types Fix integration test structure Add basic assets tests structure WIP push Fix u128 error in rpc definitions with wrapper type Fix errors after rebase & add RPC documentation Fix missed merge conflict marker Improve RPC documentation Reorganize types Re-add types Fix testing with assets rpc Clean up imports Reorganize assets rpc tests Update crowdloan rewards tests Uncomment integration tests Formatting Update Cargo.lock Remove unused imports Attempt to fix wasm build error Remove unnecessary dependencies from assets pallet Remove commented code and dbg! usage in assets pallet Cargo.toml formatting Reorganize dependencies in picasso-runtime Update assets rpc to v0.9.16 Clean up dependencies in assets-runtime-api Clean up dependencies in composable-support Clean up dependencies in composable-traits Clean up rpc.md Review & reorganize dependencies in currency-factory Remove extra newline in workspace Cargo.toml Remove num-traits dependency from assets pallet Review & reorganize dependencies in crowdloan-rewards Review & reorganize dependencies in crowdloan-rewards rpc Review & reorganize dependencies in crowdloan-rewards runtime-api Reorganize composable-support/rpc_helpers Update Cargo.lock * Formatting * Remove assets tests.rs file * Remove commented-out code * Remove specific RPC crate entries in workspace Cargo.toml * Remove std feature from assets-rpc * Update Cargo.lock * Update generated api types * Remove std feature from crowdloan-rewards-rpc * Clean up crowdloan-rewards-rpc * Update Cargo.lock * Update RPC docs * Clean up RPC tests * Remove unused imports in crowdloan-rewards-rpc * Update Cargo.lock * Fix slash for chatops (#629) * test push with labels * test push * test push again * test push #3 * test push 4 * test push 5 Co-authored-by: Seun Lanlege * Refactored Validated Traits (#619) * refactored Validated traits * removed U from new * lending into runtime (#616) * lending into runtime Signed-off-by: Dzmitry Lahoda * added comment on more tests Signed-off-by: Dzmitry Lahoda * fixed review comment Signed-off-by: Dzmitry Lahoda * fixing wasm build Signed-off-by: Dzmitry Lahoda * Pushing benchmark changes Signed-off-by: Dzmitry Lahoda * sing Signed-off-by: Dzmitry Lahoda * rebase main Signed-off-by: Dzmitry Lahoda * Revert "Pushing benchmark changes" This reverts commit 2130ef4ac4237d2d1234474097f0ceb2900f455f. Signed-off-by: Dzmitry Lahoda * fixed comments Signed-off-by: Dzmitry Lahoda * fixed borkne script Signed-off-by: Dzmitry Lahoda Co-authored-by: Seun Lanlege Co-authored-by: dzmitry-lahoda * Bump polkadot-launch version, update polkadot-launch configuration (#639) * test(Runtime Integration Tests): Runtime integration tests parallelization & Mocha v.9 (#560) Updated asset & crowdloan rpc tests with new structure. Fixed types. Updated deps. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Fixed for new bonded finance change & types update. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Updated types & deps. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Types and dependency updates. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Updated polkadotjs dep, and refreshed types. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Removed unnecessary lines of code within oracle tests. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Start Balance Generator added, fixed generators. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Fix: Last commit did contain build failures, due to missing references. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Updated structure, docs & generated types. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Fixed slow setting, fixed docstrings. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Fixed timeout setting for oracle.reclaimStake() test. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Made crowdloan rewards tx tests being able to work multiple times on the same chain. Upped slow time configuration for mocha. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Bonded Finance TX Checks updated & Parallelization. Signed-off-by: Dominik Roth test(Runtime Integration Tests): W.I.P. Parallelization Integration. Signed-off-by: Dominik Roth * Bump node-fetch from 2.6.1 to 2.6.7 in /setup (#542) Bumps [node-fetch](https://github.com/node-fetch/node-fetch) from 2.6.1 to 2.6.7. - [Release notes](https://github.com/node-fetch/node-fetch/releases) - [Changelog](https://github.com/node-fetch/node-fetch/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/node-fetch/node-fetch/compare/v2.6.1...v2.6.7) --- updated-dependencies: - dependency-name: node-fetch dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump node-fetch in /scripts/polkadot-launch/initialization (#544) Bumps [node-fetch](https://github.com/node-fetch/node-fetch) from 2.6.6 to 2.6.7. - [Release notes](https://github.com/node-fetch/node-fetch/releases) - [Changelog](https://github.com/node-fetch/node-fetch/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/node-fetch/node-fetch/compare/v2.6.6...v2.6.7) --- updated-dependencies: - dependency-name: node-fetch dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump simple-get from 2.8.1 to 2.8.2 in /scripts/polkadot-launch (#595) Bumps [simple-get](https://github.com/feross/simple-get) from 2.8.1 to 2.8.2. - [Release notes](https://github.com/feross/simple-get/releases) - [Commits](https://github.com/feross/simple-get/compare/v2.8.1...v2.8.2) --- updated-dependencies: - dependency-name: simple-get dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump simple-get from 2.8.1 to 2.8.2 in /integration-tests/runtime-tests (#586) Bumps [simple-get](https://github.com/feross/simple-get) from 2.8.1 to 2.8.2. - [Release notes](https://github.com/feross/simple-get/releases) - [Commits](https://github.com/feross/simple-get/compare/v2.8.1...v2.8.2) --- updated-dependencies: - dependency-name: simple-get dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Ben/update rpc docs (#643) * Update rpc.md to new integration-tests structure * rename rpc.md to custom-rpcs.md * Add bootnode peerid rococo (#644) * Update simnode script * Update simonde script * Add new bootnode peer ID * xcmp: speed up tests, fixed some tests (#571) * Ben/update rpc docs (#643) * Update rpc.md to new integration-tests structure * rename rpc.md to custom-rpcs.md Signed-off-by: Dzmitry Lahoda * lending into runtime Signed-off-by: Dzmitry Lahoda * improved xcmp support Signed-off-by: Dzmitry Lahoda Co-authored-by: benluelo <57334811+benluelo@users.noreply.github.com> Co-authored-by: Seun Lanlege * add initialize_at (#640) * add initialize_at * add check to ensure claims are only available after start block * add enabled check in ValidateUnsigned * enables collator-sidecar (#648) * Update make version (#646) * Update simnode script * Add new bootnode peer ID * fix docker version (#651) * fix docker version * set proper env * try again * Update dockerfile * Clean up release * Clean up release * Clean up release * Clean up release Co-authored-by: haroldsphinx * Add Dockerfile to build composable-sandbox (#652) * xmcp take weight (#581) Signed-off-by: Dzmitry Lahoda * Fix amount_available_to_claim_for RPC (#642) * Ansible update (#658) * Update notification url * upgrade codecov ci action (#660) * Ansible update (#662) * Update simnode script * Update simonde script * Add new bootnode peer ID * check release update * mute picasso * mute picasso * mute picasso * mute picasso * mute picasso * mute picasso * Update notification url * Update release pipeline * Update release pipeline * Update release pipeline * trigger build * trigger build * trigger build * trigger build * trigger build * trigger build * trigger build * trigger build * trigger build * update local * update local * update local * update local * update make version * update make version * update make version * Ansible update (#664) * collator sidecar (#669) * use jsonrpsee instead * cargo fmt * add std features to dev-dependencies (#668) * [CU-1ux39mq] Validate vault extrinsics (#647) * Added validation to Vault * Added validation for Creation Deposit * Added validation for Max Strategies * Fixed benchmarking * cargo +nightly fmt * lending benchmarking * Removed commented code * Seun fix collator sidecar (#670) * use jsonrpsee instead * cargo fmt * use http client instead * cargo fmt * sigh * sigh * [CU-1vzab3b] Added TryIntoValidated (#666) * Added TryIntoValidated * moved U to fn type param * CI job to build a Docker image of composable-sandbox (#672) * [CU-1ux39qh] Validation/oracle (#655) * updated oracle validation * upstream * removed trait * removed trait * updated oracle validation * cargo lock * updated validation * updated tests * cargo * updated tests * updated benchmark * fmt * fixed error * fixed error * chore(oracle): remove valid_ prefixes * feat(oracle): public impl Deref for Validated * fmt * fix(oracle): fix broken benchmarks * fmt Co-authored-by: cor * lending market creation event is good (#673) * market event is good Signed-off-by: Dzmitry Lahoda * merge Signed-off-by: Dzmitry Lahoda * removed curve out of event Signed-off-by: Dzmitry Lahoda * Extend Simnode RPC Apis (#677) * extend simnode rpc apis * refactor simnode * update simnode workflow files * fixes * bump simnode Co-authored-by: Seun Lanlege * Updated Crowdloan Readme (#678) * Ben/currency docs (#676) * lending into runtime Signed-off-by: Dzmitry Lahoda * Add CreateMarket event test * Update Currency docs * Remove changes brought over from previous branch * Remove changes brought over from previous branch * Remove trait impls and CurrencyId type alias * Re-add CurrencyId type * Fix doctests * Fix doctests * Fix docs (for real this time) * Remove plotter artifacts Co-authored-by: Seun Lanlege * adds simnode docs (#685) * fix(benchmarks): oracle: prefer the usage of the runtime type when benchmarking (#684) * fix(benchmarks): prefer the usage of the runtime type when benchmarking * revert the integration of lending benchmark * Pushing benchmark changes * fix(ci): mandatory single-pass benchmarking (#686) * fix(ci): mandatory single-pass benchmarking against runtimes to avoid breaking changes in configs * fix(benchmarking): normalize bonded-finance/mosaic WeightInfo path * CU-263dx6e - Mosaic assets mapping (#683) * use blake2 for indexing maps * more comments * introduce 2-way mapping for assets, (network_id, remote_asset) -> asset_id, (network_id, asset_id) -> remote_asset * introduce a enum for mosaic remote assets to simplify future upgrade * Pushing benchmark changes * Refactor uniswap, curve & interface, introduce extrinsic + benchmarkings (#618) * Implement get_exchange_value() function in DEXs. Implement `buy()` and `sell()` in DEXs. Refactor `exchange()` and add `update_balance()` function. * Update dex-router pallet to not use PoolTokenIndex. * Implement buy/sell in dex-router pallet. * refactor uniswap pallet * introduce custom partialeq for pair such that pair == swap(pair) * cleanup curve amm * style * fix uniswap * document fee * refactor imports * rename sell `quote_amount` to `base_amount` as we always sell the base * better uniswap maths * better documentation & introduce extrinsics * clean cargo deps * introduce benchmarking * Refactor curve-amm pallet. * Fix uniswap-v2 pallet so test passes. * Fix issues with curve-amm and make test pass. * Add extrinsics for curve-amm pallet. Add dummy weights. Add benchmarks for curve-amm pallet. Add few tests. Charge protocol_fee from lp_fee. * Use BigUint for internal computation in curve-amm. Add extrinsics for curve-amm pallet. Add dummy weights. Add benchmarks for curve-amm pallet. Add few tests. Charge protocol_fee from lp_fee. * Fix dex_ruoter tests. * fix uniswap get_exchange_value * introduce composable-maths * refactor uniswap to use composable-maths * fix dex router * Add test for plot. * extract more uniswap maths to composable-maths * spelling and comment * Remove use of VecDequeue from dex-router pallet. * fix(lending): use runtime weights * add stableswap/constant_product dexes to dali * Add test for curve plot. * fix(curve-amm): mocks + curve graph drawing * Fix benchmark test issues for curver-amm and uniswap-v2 pallet. * Fix fee calculation in add_liquidity() and add simple test for it. * style * fix(dali): add benchmarking for uniswap/curve Co-authored-by: Vivek Pandya * upgrade devnet (#687) * CU-2697dme - Crowdloan funded rewards (#693) * fix(crowdloan-rewards): avoid silent overflow when populating rewards * fix(crowdloan-rewards): fix typo * fix(crowdloan-rewards): make constants const and document signature tag origin * fix(crowdloan-rewards): better comments * feat(crowdloan-rewards): expected pallet account to hold rewards funds instead of minting the reward * fix(style): apply make style * Documentation deployment (#691) * feat(ci): push docs along binaries * feat(devnet): use composable.ninja subdomain * fix(crowdloan-rewards): allow to incrementally populate the rewards (#694) We were removing previous entry whenever we were doing a populate call which would result in an issue when the transaction would exceed a block size. * Set reasonable values (#695) * Set reasonable values * fmt * fix 'liquidation' typos (#689) * fix(ci): remove docs after having compressed to avoid no space left (#696) * feat(runtimes): filter Tokens and unfilter Balance (#700) * feat(runtimes): filter Tokens and unfilter Balance * feat(dali): faster crowdloan vesting for devnet * fix(benchmarking): use asset id != native to avoi existential deposit issues * fix(assets): do not use custom error for `BadOrigin` (#699) * Added explanation of ValidateUnsigned to README.md (#698) * Added explination of ValidateUnsigned to README.md * grammar * ensure we lint tests (#697) * Ensure we have errors checked in proptests * feat(tests): custom precision for proptests to avoid edge cases (#702) * feat(tests): custom precision for proptests to avoid edge cases The issue with proptest is that because of the fact that we generate random values, we might have some issue because of division. The issue rely on the fact that for instane, integer division might result in less/more value than expected (odd number for instance). We can circumvent thoses cases (pretty rare but still making the CI fail) by lowering the precision of the expected value for some tests. * fix(style): apply make style * fix(lint): avoid identity conversion * Composable bootnode peerid (#708) * Setup composable bootnode peer id * Composable bootnode peerid (#710) * update node permission * Update node permission (#712) * feat(ci): full backtrace for benchmarking (#714) * Use compressed wasm instead of compact (#716) * use compressed wasm instead of compact * check for runtime changes before doing single pass benchmarking * CU-1vz89jk - Liquidity bootstrapping pallet (#661) * introduce liquidity bootstrapping pallet * extract math to pure functions * better comment * move images to plots subdirectory, finish benchmarking and add tests * rebase and reuse composable-maths * more test & fix style * add missing benchmarking and more tests * fix(liquidations): bechmarking on dali * add liquidity-bootstrapping pallet in dali * feat(benchmarks): generate weights * fix(liquidity-bootstrapping): format and typos * fix(style): apply make style * Fix clippy warnings for LBP, curve-amm and uniswap-v2. * Fix clippy warnings. (#719) * Add few more test for dex. (#690) * Add few more test for dex. Add extrinsics for add/remove_liquidity(). Update benchmarks. * Check exact value for lp_tokens received after add_liquidity() in tests. Reanme `CurveAmm` trait to `Amm`. * Pushing benchmark changes * Add test for fee in uniswap-v2 pallet. Add comments for add/remove_liquidity() extrinsics. * Use `assert_noop` instead of `assert_err`. Use pallet extrinsics where possible to use. * Rename `CurveAmm` to `Amm` in LBP. * Address minor review comments. Co-authored-by: vivekvpandya * Update node permission (#720) * Update bootnode id * Validation/mosaic (#704) * cargo * cargo * added validation * updated tests * updated error messages * removed unused comments * updated benchmarking * cargo fmt * updated benchmarking * updated benchmarking * updated benchmarking * updated benchmarking * updated benchmarking * updated benchmarking * xcmp: treasury, trap, weights, tests, fees, ed, common (#656) * xcmp Signed-off-by: Dzmitry Lahoda xcmp Signed-off-by: Dzmitry Lahoda * fmt, more robust test Signed-off-by: Dzmitry Lahoda * [cu-1ubuznb] Vesting Benchmarks (#705) * [cu-1ubuznb] Adding Vesting Benchmarks * Final weights * Adjust funding for update_vesting_schedules * fmt * fmt * Minor fixes * Fix style * Try to fix EnsureOrigin * Try to fix EnsureOrigin * dali * Fix error * Pushing benchmark changes * Review comments * Revert liquidation impl change * Style Co-authored-by: Vim Wickramasinghe Co-authored-by: hussein-aitlahcen * [CU-1ux39kw] Validation/bond offer (#623) * moved validation to new file * cargo fmt * updated trait name * updated generic type * updated generic type * removed unused code * updated traits * added Decode trate * removed trait * added trait * updated validation code * updated validation * updated trait implementations * updated tests * removed reduntant / previous validation * fixed merge * fixed type mismatch * valiadation structural change * cargi=o fmt * cargo lock * cargo * cargo * cargo * removed space * updated test * updated bonded_finance.rs * updated validation * updated bond_pricev alidation * updated nb_of_bonds validation * updated validation * removed unused validation code * removed unused validation code * updated bond_offer_validation tests * updated benchmarl * updated benchmark * updated benchmark * cargo fmt * Enable BEEFY in polkadot-launch (#726) * add beefy * add extra flags for beefy * remove duplicate flag * add ferdie to composable-sandbox Co-authored-by: Seun Lanlege * Fix typo (#724) really simple change, removing unneeded spaces inside word 'development'. * Make clippy happier (#728) * Fix clippy warnings (#730) * adds chainspec for composable westend (#731) * adds chainspec for composable wested * cargo fmt * Amp can not be zero (#725) * Fix curve_amm math so that amplification_factor can be 0. Add proptest for curve_amm and uniswap-v2. * Add proptest for curve_amm with amplification_factor is 0. * Better description in expect() message in tests for curve-amm and uniswap. * Report error in create_pool is amplification_coefficient is 0. The math implementation is however able to handle above case. * fix single pass benchmarking CI (#733) * Chnage westend bootnode (#736) * Update simnode script * Update simonde script * Add new bootnode peer ID * Setup composable bootnode peer id * update node permission * Update westend bootnode * updating bootnode (#741) * Use mmr-polkadot instead of polkadot in composable-sandbox (#738) * feat(devnet): auto optimise/gc nix store to avoid no space left (#735) * Refactor/safe arithmentic (#734) * fixed merge conflict * split SafeArithmetic * added SafeArithmetic * added SafeArithmetic * cargo fmt * docker multi-arch (#657) * docker multi-arch * release variable to environment * get tag from previous step * feat(crowdloan-reward): move from `BlockNumber` to `Moment` for vesting (#744) * [cu-1ubuznb] Correct misconfiguration of weights for vesting (#749) * feat(crowdloan-rewards): make dali crowdloan faster and correct `VestingStep` type (#750) * [cu-206y1te, cu-26ezj25] Support time based vesting schedules in Vesting pallet (#748) * [cu-206y1te] Support time based vesting schedules in Vesting pallet * unit tests: frame/composable-traits/src/vesting.rs * Unit test updates * Fix the dependents of Vesting * Fix vesting benchmarking * style * Minor fixes * More coverage * Cleanup `Cargo.toml` files & add taplo step in CI (#752) * chore(style): cleanup `Cargo.toml` files * chore(style): introduce taplo for `.toml` files formatting in Makefile `style` command * chore(style): apply taplo to codebase * feat(ci): introduce taplo check for `.toml` formatting * Update initialization script (#753) * [cu-206y1te, cu-26ezj25] Adjusting documentation for vesting pallet (#756) * [cu-206y1te, cu-26ezj25] Adjust documentation * minor adjustment * minor adjustment * Composable ngihtly snapshot (#762) * multi arch build test * setup mightly backup for composable db * update docker-release Co-authored-by: haroldsphinx * Initial commit for pablo. (#766) - Adds and enum for PoolConfiguration, with this commit it has StableSwap. - Added skeleton of extrinsic for the pallet. * Rework vesting origin & audit fixes (#775) * feat(vesting): do not use origin as source account * fix(runtime): use `u128` for `BondOfferId` and use `RootOrHalfCouncil` instead of `EnsureRoot` * fix(runtime): avoid confusion by removing the non-required `Self` for `unit` in CurrencyId * fix(crowdloan-rewards): meaningful error when `at` time is in the past * fix(bonded-finance): misleading comment + clarify second comment * fix(bonded-finance): prefer the usage of `SafeAdd` over `WrappingNext` * chore(style): apply make style * test(Runtime Integration Tests): Dep. Update, Type Update, Docker Integration & Refactoring. (#757) test(Runtime Integration Tests): Updated README.md for Docker && Better endpoint detection test(Runtime Integration Tests): Deactivated parallel mode for mocha due to the `priority too low` issue. test(Runtime Integration Tests): Added docker-compose run script. test(Runtime Integration Tests): Removed args.ts & refactored testSetup.ts to use `import` instead of `require` (Linter recommendation). Fixed a docstring in setStartBalance.ts. test(Runtime Integration Tests): Dep. update & removed "@types/expect" dependency. test(Runtime Integration Tests): Updated dependencies & README.md. test(Runtime Integration Tests): Updated Dependencies & Types. Added mintingHelper.ts as utility. * CU-23v2xj9 Add code and tests for StableSwap pallet in Pablo. (#767) * Add code and tests for StableSwap pallet in Pablo. Add new PoolInitConfiguration enum in Pablo to be used as input for create() extrinsic. Remove redundant pallet_balances from curve_amm and uniswap_v2 mocks. * Enable more tests for stable_swap. Organize code in stable_swap.rs and stable_swap_test.rs files. * Rename PoolInitOf to PoolInitConfigurationOf. Few other minor nitpicks. * Clarify why we claim while associating & provide the timestamp at which the crowdloan start (#776) * feat(crowdloan-rewards): provide the timestamp at which the crowdloan start * fix(crowdloan-rewards): clarify why we claim when associating * Update Vesting pallet runtime & remove bencharking filter in CI check (#778) * fix(dali): vested transfer origin must be RootOrHalfCouncil * fix(ci): disable broken benchmark filter * [cu-23v2xkb][Pablo] ConstantProductPool Integration (#770) * [Pablo] Minimal ConstantProductPool Integration * Updates with tests * Minor * [cu-23v2xkb] Tests fixed * Linter seems confused * Review and try lint * try lint * try lint * Fortify mosaic & vesting pallets (#779) * feat(mosaic): introduce `min_transfer_size` for networks * feat(vesting): introduce check to avoid `vested_transfer` to caller * chore(style): apply make style * polkadot v0.9.17 (#688) * attempt to bump to polkadot-v0.9.17 * chore(polkadot): upgrade to v0.9.17 * chore(style): apply make style * fix(tests): `storage_root` now expect a `StateVersion` * fix(tests): no more Default for AccountId * bump simnode * chore(polkadot): upgrade to v0.9.17 * chore(style): apply make style * fix(tests): no more Default for AccountId * chore(polkadot): upgrade integration tests * feat(ci): upgrade codecov * cargo fmt * taplo fmt * remove --raw arg from single pass benchmarking * sigh fix run_benchmarks * bump cumulus * Pushing benchmark changes * adds support for simnode to composable-runtime * fix(bench): revert curve benchmarking * fix(bench): revert uni benchmarking * make non-production release buil faster by disabling linking opt * fix(bench): revert curve/uni weights * feat(ci): make git diff visible for taplo check * chore(style): apply make style * fix(lint): unused test attribute in bonded finance * fix permission issue with simnode * ci benchmark changes * chore(cargo): update Cargo.lock * feat(ci): pin codecov nightly * wip * wip * chore(polkadot): upgrade pablo pallet * chore(style): apply make style * chore(ci): duplicate checkout * bump simnode * adds proper rococo chainspec * cargo fmt * fix clippy Co-authored-by: Hussein Ait Lahcen Co-authored-by: seunlanlege Co-authored-by: haroldsphinx * [CU-20185wr] Integration Tests-Constant Product Dex Tests (#761) * Constant Product Tests * test config added * helper added. * Deleted extra file * Move do_compute_swap() to StableSwap module. (#780) Add common_test_functions module and update add_remove_lp() test to use it. Minor refactoring to use references when possible. * CU-25ye81h CU-1yyr5hv CU-1yyr5fv xcmp kusd picasso (#759) * xcmp kusd picasso Signed-off-by: Dzmitry Lahoda * fixed comment, added links Signed-off-by: Dzmitry Lahoda * force proper features Signed-off-by: Dzmitry Lahoda * finally catched condition Signed-off-by: Dzmitry Lahoda * fixes after review Signed-off-by: Dzmitry Lahoda * merge fix Signed-off-by: Dzmitry Lahoda * 9/17 migration fixes Signed-off-by: Dzmitry Lahoda * all version must be exact Signed-off-by: Dzmitry Lahoda * feat(devnet): update polkadot (#784) * [CU-23n7a3r] Integration Testing - Fixing CrowdloanRewards Tests. (#777) * test(Runtime Integration Tests): Fixed crowdloanRewards tests. * test(Runtime Integration Tests): Crowdloan Fix, removed temporary waitForBlocks(n) call. * test(Runtime Integration Tests): Crowdloan Rewards Fix. Removed redundant import in mintingHelper.ts. * test(Runtime Integration Tests): Added toggle flag to claim test. Updated types. * test(Runtime Integration Tests): Crowdloan Rewards Tests added documentation. * [cu-23v2xng][Pablo] Integrate Liquidity Bootstrapping Pool (#781) * [cu-23v2xng][Pablo] Integrate Liquidity Bootstrapping Pool * visualizations * Review * Fix for main * Try fix * Try fix * Create a CI job to build ci-linux docker image (#786) * Create a CI job to build a docker image of composablefi/mmr-polkadot (#758) * Pushing benchmark changes * trigger CI Co-authored-by: andor0 Co-authored-by: Hussein Ait-Lahcen Co-authored-by: Karel L. Kubat Co-authored-by: Dzmitry Lahoda Co-authored-by: Dominik Roth <96540347+Dom-Roth@users.noreply.github.com> Co-authored-by: Vivek Pandya Co-authored-by: Dominik Roth Co-authored-by: Adedayo Akinpelu Co-authored-by: haroldsphinx Co-authored-by: JesseAbram <33698952+JesseAbram@users.noreply.github.com> Co-authored-by: Ewere Diagboya Co-authored-by: cor Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Connor Davis <17688291+PoisonPhang@users.noreply.github.com> Co-authored-by: haroldsphinx Co-authored-by: david Co-authored-by: seunlanlege Co-authored-by: hussein-aitlahcen Co-authored-by: Yusuf Kelo Co-authored-by: David Salami <31099392+Wizdave97@users.noreply.github.com> Co-authored-by: benluelo <57334811+benluelo@users.noreply.github.com> Co-authored-by: dzmitry-lahoda Co-authored-by: Matheus Cardoso <45436839+Cardosaum@users.noreply.github.com> Co-authored-by: vivekvpandya Co-authored-by: Vim Co-authored-by: Vim Wickramasinghe Co-authored-by: Vim Co-authored-by: Yasin <64729564+kollegian@users.noreply.github.com> --- .config/cargo_spellcheck.toml | 2 +- .dockerignore | 1 + .github/workflows/Picasso-release.yml | 44 - .github/workflows/benchmark.yml | 2 +- .github/workflows/check.yml | 45 +- .github/workflows/ci-linux.yml | 49 + .github/workflows/composable-sandbox.yml | 49 + .github/workflows/devnet-release.yml | 10 +- .github/workflows/mmr-polkadot.yml | 49 + .gitignore | 4 +- .maintain/playbooks/delete-db-directory.yml | 21 - .maintain/playbooks/run-integration-tests.yml | 2 +- .maintain/run_benchmarks.sh | 5 +- .maintain/run_simnode.sh | 4 +- .taplo.toml | 30 + ARCHITECTURE.md | 13 +- Cargo.lock | 2719 +++--- Cargo.toml | 308 +- Makefile | 36 +- Makefile.toml | 55 +- clippy.toml | 4 +- deny.toml | 76 +- docker/ci-linux.dockerfile | 7 + docker/composable-sandbox.dockerfile | 53 + docker/mmr-polkadot.dockerfile | 26 + docs/CONTRIBUTING.md | 2 +- docs/benchmarking.md | 10 +- docs/custom-rpcs.md | 383 + docs/glossary.md | 3 + docs/runtime-testing.md | 17 + frame/assets-registry/Cargo.toml | 56 +- frame/assets-registry/local-mapping.plantuml | 9 +- frame/assets-registry/src/lib.rs | 83 +- frame/assets-registry/src/mock.rs | 4 + frame/assets-registry/src/tests.rs | 52 +- frame/assets/Cargo.toml | 83 +- frame/assets/rpc/Cargo.toml | 34 + frame/assets/rpc/src/lib.rs | 73 + frame/assets/runtime-api/Cargo.toml | 21 + frame/assets/runtime-api/src/lib.rs | 20 + frame/assets/src/lib.rs | 6 +- frame/assets/src/mocks.rs | 6 +- frame/assets/src/tests/traits.rs | 55 +- frame/bonded-finance/Cargo.toml | 64 +- .../proptest-regressions/tests.txt | 9 + frame/bonded-finance/src/benchmarks.rs | 57 +- frame/bonded-finance/src/lib.rs | 120 +- frame/bonded-finance/src/mock.rs | 19 +- frame/bonded-finance/src/tests.rs | 406 +- frame/bonded-finance/src/utils.rs | 3 - frame/bonded-finance/src/weights.rs | 24 + frame/call-filter/Cargo.toml | 48 +- frame/composable-maths/Cargo.toml | 34 + .../src/dex/constant_product.rs | 162 + frame/composable-maths/src/dex/mod.rs | 2 + frame/composable-maths/src/dex/stable_swap.rs | 136 + frame/composable-maths/src/lib.rs | 15 + frame/composable-support/Cargo.toml | 54 +- .../src/collections/vec/sorted/mod.rs | 3 +- frame/composable-support/src/lib.rs | 1 + frame/composable-support/src/rpc_helpers.rs | 79 + frame/composable-support/src/validation.rs | 86 +- frame/composable-tests-helpers/Cargo.toml | 28 +- .../src/test/helper.rs | 20 +- .../src/test/proptest.rs | 14 +- frame/composable-traits/Cargo.toml | 48 +- frame/composable-traits/src/bonded_finance.rs | 112 +- frame/composable-traits/src/currency.rs | 27 +- frame/composable-traits/src/defi.rs | 22 +- frame/composable-traits/src/dex.rs | 210 +- frame/composable-traits/src/lending/math.rs | 2 +- frame/composable-traits/src/lending/mod.rs | 4 +- frame/composable-traits/src/math.rs | 32 +- frame/composable-traits/src/oracle.rs | 25 +- frame/composable-traits/src/vesting.rs | 177 +- frame/crowdloan-rewards/Cargo.toml | 88 +- frame/crowdloan-rewards/README.md | 58 +- frame/crowdloan-rewards/rpc/Cargo.toml | 36 + frame/crowdloan-rewards/rpc/src/lib.rs | 67 + .../crowdloan-rewards/runtime-api/Cargo.toml | 23 + .../crowdloan-rewards/runtime-api/src/lib.rs | 18 + frame/crowdloan-rewards/src/lib.rs | 233 +- frame/crowdloan-rewards/src/mocks.rs | 40 +- frame/crowdloan-rewards/src/models.rs | 4 +- frame/crowdloan-rewards/src/tests.rs | 152 +- frame/currency-factory/Cargo.toml | 66 +- frame/curve-amm/Cargo.toml | 68 +- frame/curve-amm/README.md | 3 +- frame/curve-amm/curve_base.png | Bin 0 -> 54802 bytes frame/curve-amm/curve_graph.png | Bin 0 -> 57555 bytes frame/curve-amm/curve_slippage.png | Bin 0 -> 52401 bytes frame/curve-amm/src/benchmarking.rs | 174 + frame/curve-amm/src/lib.rs | 1336 +-- frame/curve-amm/src/maths.rs | 136 + frame/curve-amm/src/mock.rs | 39 +- frame/curve-amm/src/tests.rs | 1180 ++- frame/curve-amm/src/weights.rs | 43 + frame/democracy/Cargo.toml | 74 +- frame/dex-router/Cargo.toml | 51 +- frame/dex-router/src/lib.rs | 120 +- frame/dex-router/src/mock.rs | 20 +- frame/dex-router/src/tests.rs | 143 +- frame/dutch-auction/Cargo.toml | 78 +- frame/dutch-auction/src/math.rs | 2 +- frame/dutch-auction/src/mock/runtime.rs | 24 - frame/governance-registry/Cargo.toml | 38 +- frame/lending/Cargo.toml | 90 +- frame/lending/README.md | 8 +- frame/lending/lending.plantuml | 10 +- frame/lending/proptest-regressions/tests.txt | 1 + frame/lending/src/benchmarking.rs | 484 +- frame/lending/src/currency.rs | 87 + frame/lending/src/lib.rs | 91 +- frame/lending/src/mocks/currency.rs | 7 - frame/lending/src/mocks/mod.rs | 105 +- frame/lending/src/mocks/oracle.rs | 131 - frame/lending/src/models.rs | 3 +- frame/lending/src/setup.rs | 40 + frame/lending/src/tests.rs | 477 +- frame/liquidations/Cargo.toml | 74 +- frame/liquidations/README.md | 7 +- .../external-dex-liqudation.sequence.plantuml | 6 +- frame/liquidations/src/benchmarking.rs | 2 +- frame/liquidations/src/lib.rs | 9 +- frame/liquidations/src/mock/runtime.rs | 24 - frame/liquidations/src/tests.rs | 2 +- frame/liquidations/src/weights.rs | 6 +- frame/liquidity-bootstrapping/Cargo.toml | 68 + frame/liquidity-bootstrapping/README.md | 1 + .../plots/lbp_buy_project.png | Bin 0 -> 47829 bytes .../plots/lbp_sell_project.png | Bin 0 -> 46174 bytes .../plots/lbp_spot_price.png | Bin 0 -> 36925 bytes .../plots/lbp_weights.png | Bin 0 -> 40114 bytes .../src/benchmarking.rs | 230 + frame/liquidity-bootstrapping/src/lib.rs | 736 ++ frame/liquidity-bootstrapping/src/mock.rs | 135 + frame/liquidity-bootstrapping/src/tests.rs | 633 ++ frame/liquidity-bootstrapping/src/weights.rs | 43 + frame/mosaic/Cargo.toml | 67 +- frame/mosaic/src/benchmarking.rs | 68 +- frame/mosaic/src/lib.rs | 268 +- frame/mosaic/src/mock.rs | 2 + frame/mosaic/src/tests.rs | 768 +- frame/mosaic/src/validation.rs | 54 + frame/mosaic/src/weights.rs | 71 +- frame/oracle/Cargo.toml | 61 +- frame/oracle/src/benchmarking.rs | 18 +- frame/oracle/src/lib.rs | 59 +- frame/oracle/src/mock.rs | 4 + frame/oracle/src/tests.rs | 301 +- frame/oracle/src/validation.rs | 103 + frame/pablo/Cargo.toml | 68 + frame/pablo/plots/lbp/lbp_buy_project.png | Bin 0 -> 47978 bytes frame/pablo/plots/lbp/lbp_sell_project.png | Bin 0 -> 46521 bytes frame/pablo/plots/lbp/lbp_spot_price.png | Bin 0 -> 36823 bytes frame/pablo/plots/lbp/lbp_weights.png | Bin 0 -> 40290 bytes frame/pablo/plots/stable_swap/curve_base.png | Bin 0 -> 54926 bytes frame/pablo/plots/stable_swap/curve_graph.png | Bin 0 -> 58012 bytes .../plots/stable_swap/curve_slippage.png | Bin 0 -> 52539 bytes frame/pablo/src/common_test_functions.rs | 68 + frame/pablo/src/lib.rs | 866 ++ frame/pablo/src/liquidity_bootstrapping.rs | 209 + .../src/liquidity_bootstrapping_tests.rs | 673 ++ frame/pablo/src/mock.rs | 142 + frame/pablo/src/stable_swap.rs | 266 + frame/pablo/src/stable_swap_tests.rs | 883 ++ frame/pablo/src/uniswap.rs | 195 + frame/pablo/src/uniswap_tests.rs | 408 + frame/ping/Cargo.toml | 40 +- frame/privilege/Cargo.toml | 48 +- frame/transaction-fee/Cargo.lock | 2655 ++++++ frame/transaction-fee/Cargo.toml | 50 +- frame/uniswap-v2/Cargo.toml | 77 +- frame/uniswap-v2/src/benchmarking.rs | 177 + frame/uniswap-v2/src/lib.rs | 1087 +-- frame/uniswap-v2/src/mock.rs | 57 +- frame/uniswap-v2/src/tests.rs | 515 +- frame/uniswap-v2/src/weights.rs | 43 + frame/vault/Cargo.toml | 69 +- frame/vault/src/benchmarking.rs | 19 +- frame/vault/src/lib.rs | 21 +- frame/vault/src/tests.rs | 30 +- frame/vault/src/validation.rs | 39 + frame/vesting/Cargo.toml | 61 +- frame/vesting/README.md | 8 +- frame/vesting/src/benchmarks.rs | 144 + frame/vesting/src/default_weight.rs | 27 - frame/vesting/src/lib.rs | 136 +- frame/vesting/src/mock.rs | 53 +- frame/vesting/src/tests.rs | 443 +- frame/vesting/src/weights.rs | 7 + integration-tests/Cargo.toml | 205 - integration-tests/README.md | 109 - .../local-integration-tests/Cargo.toml | 219 + .../local-integration-tests/README.md | 32 + .../local-integration-tests/awesome-xcmp.md | 50 + .../sibling-asset-transfer.sequence.plantuml | 32 + .../src/cross_chain_transfer.rs | 1101 +++ .../local-integration-tests/src/helpers.rs | 59 + .../src/kusama_test_net.rs | 57 +- .../local-integration-tests/src/lib.rs | 58 + .../local-integration-tests/src/prelude.rs | 26 + .../local-integration-tests/src/relaychain.rs | 100 + .../src/runtime_tests.rs | 17 +- .../src/transact_calls.rs | 6 + .../src/xcm_tests.rs | 84 +- .../xcmp.sequence.plantuml | 11 + integration-tests/runtime-tests/.mocharc.json | 12 +- integration-tests/runtime-tests/DockerRun.sh | 3 + integration-tests/runtime-tests/README.md | 26 +- .../runtime-tests/docker-compose.yml | 17 + .../runtime-tests/package-lock.json | 7591 ++++++++++++----- integration-tests/runtime-tests/package.json | 74 +- .../testTransactionGenerator.ts | 15 +- .../generators/setBalance/setStartBalance.ts | 46 + .../src/{initializeState.ts => main.ts} | 9 +- integration-tests/runtime-tests/src/test.ts | 52 - .../tests/examples/querySystemAccountTests.ts | 29 - .../tests/query/council/queryCouncilTests.ts | 9 - .../queryCrowdloanRewardsTests.ts | 58 - .../rpcCrowdloanRewardsTests.ts | 28 - .../tx/bondedFinance/txBondedFinanceTests.ts | 178 - .../txCrowdloanRewardsTests.ts | 130 - .../src/tests/tx/oracle/txOracleTests.ts | 204 - .../types/interfaces/assets/definitions.ts | 27 + .../interfaces/{default => assets}/index.ts | 0 .../src/types/interfaces/assets/types.ts | 12 + .../types/interfaces/augment-api-consts.ts | 141 +- .../types/interfaces/augment-api-errors.ts | 207 +- .../types/interfaces/augment-api-events.ts | 303 +- .../src/types/interfaces/augment-api-query.ts | 245 +- .../src/types/interfaces/augment-api-rpc.ts | 29 +- .../src/types/interfaces/augment-api-tx.ts | 527 +- .../src/types/interfaces/augment-types.ts | 58 +- .../crowdloanRewards/definitions.ts | 151 + .../interfaces/crowdloanRewards/index.ts | 4 + .../{default => crowdloanRewards}/types.ts | 131 +- .../src/types/interfaces/definitions.ts | 73 +- .../src/types/interfaces/types.ts | 3 +- .../runtime-tests/src/utils/args.ts | 6 - .../runtime-tests/src/utils/mintingHelper.ts | 27 + .../runtime-tests/src/utils/polkadotjs.ts | 47 +- .../runtime-tests/src/utils/testSetup.ts | 61 +- .../runtime-tests/{src => test}/globals.ts | 1 + .../test/tests/assets/rpcAssetsTests.ts | 23 + .../test/tests/assets/test_configuration.json | 8 + .../bondedFinance/testHandlers/bondTests.ts | 4 +- .../bondedFinance/testHandlers/cancelTests.ts | 0 .../bondedFinance/testHandlers/offerTests.ts | 4 +- .../bondedFinance/test_configuration.json | 26 + .../bondedFinance/txBondedFinanceTests.ts | 204 + .../queryCrowdloanRewardsTests.ts | 54 + .../rpcCrowdloanRewardsTests.ts | 22 + .../crowdloanRewards/test_configuration.json | 57 + .../txCrowdloanRewardsTests.ts | 292 + .../constantProductTests.ts | 167 + .../testHandlers/constantProductDexHelper.ts | 152 + .../test_configuration.json | 33 + .../tests/examples/querySystemAccountTests.ts | 41 + .../tests/examples/test_configuration.json | 11 + .../testHandlers/addAssetAndInfoTests.ts | 2 +- .../oracle/testHandlers/addStakeTests.ts | 4 +- .../oracle/testHandlers/reclaimStakeTests.ts | 7 +- .../oracle/testHandlers/removeStakeTests.ts | 7 +- .../oracle/testHandlers/setSignerTests.ts | 2 +- .../oracle/testHandlers/submitPriceTests.ts | 8 +- .../test/tests/oracle/test_configuration.json | 29 + .../test/tests/oracle/txOracleTests.ts | 207 + .../test/tests/xcmp/transfers.ts | 6 + integration-tests/runtime-tests/tsconfig.json | 21 +- integration-tests/src/cross_chain_transfer.rs | 413 - integration-tests/src/lib.rs | 17 - nix/.gitignore | 1 + nix/README.md | 28 +- nix/devnet-gce.nix | 68 +- nix/devnet.json | 14 +- nix/devnet.nix | 32 +- nix/flake.lock | 16 +- nix/flake.nix | 61 +- nix/latest.sh | 10 + node/Cargo.toml | 144 +- node/src/chain_spec.rs | 9 +- node/src/chain_spec/composable.rs | 9 +- node/src/chain_spec/dali.rs | 9 +- node/src/chain_spec/picasso.rs | 9 +- node/src/cli.rs | 45 +- node/src/rpc.rs | 11 +- node/src/runtime.rs | 5 + runtime/common/Cargo.toml | 92 +- runtime/common/src/impls.rs | 13 +- runtime/common/src/lib.rs | 88 +- runtime/common/src/xcmp/mod.rs | 350 + runtime/composable/Cargo.toml | 348 +- runtime/composable/src/lib.rs | 152 +- runtime/composable/src/weights/balances.rs | 23 +- .../src/weights/collator_selection.rs | 43 +- runtime/composable/src/weights/collective.rs | 97 +- runtime/composable/src/weights/democracy.rs | 121 +- .../composable/src/weights/frame_system.rs | 29 +- runtime/composable/src/weights/indices.rs | 19 +- runtime/composable/src/weights/membership.rs | 49 +- runtime/composable/src/weights/scheduler.rs | 144 +- runtime/composable/src/weights/session.rs | 33 +- runtime/composable/src/weights/timestamp.rs | 13 +- runtime/composable/src/weights/treasury.rs | 25 +- runtime/composable/src/weights/utility.rs | 25 +- runtime/composable/src/xcmp.rs | 35 +- runtime/dali/Cargo.toml | 405 +- runtime/dali/build.rs | 23 +- runtime/dali/src/README.md | 27 + runtime/dali/src/lib.rs | 276 +- runtime/dali/src/weights/balances.rs | 23 +- runtime/dali/src/weights/bonded_finance.rs | 58 + .../dali/src/weights/collator_selection.rs | 43 +- runtime/dali/src/weights/collective.rs | 103 +- runtime/dali/src/weights/currency_factory.rs | 39 +- runtime/dali/src/weights/curve_amm.rs | 82 + runtime/dali/src/weights/democracy.rs | 125 +- runtime/dali/src/weights/dutch_auction.rs | 21 +- runtime/dali/src/weights/frame_system.rs | 25 +- runtime/dali/src/weights/identity.rs | 145 +- runtime/dali/src/weights/indices.rs | 19 +- runtime/dali/src/weights/lending.rs | 69 + runtime/dali/src/weights/liqudations.rs | 15 - runtime/dali/src/weights/liquidations.rs | 38 + .../src/weights/liquidity_bootstrapping.rs | 79 + runtime/dali/src/weights/membership.rs | 51 +- runtime/dali/src/weights/mod.rs | 7 + runtime/dali/src/weights/mosaic.rs | 59 +- runtime/dali/src/weights/multisig.rs | 89 +- runtime/dali/src/weights/oracle.rs | 100 +- runtime/dali/src/weights/scheduler.rs | 142 +- runtime/dali/src/weights/session.rs | 33 +- runtime/dali/src/weights/timestamp.rs | 13 +- runtime/dali/src/weights/treasury.rs | 25 +- runtime/dali/src/weights/uniswap_v2.rs | 82 + runtime/dali/src/weights/utility.rs | 25 +- runtime/dali/src/weights/vault.rs | 39 +- runtime/dali/src/weights/vesting.rs | 70 + runtime/dali/src/xcmp.rs | 354 +- runtime/picasso/Cargo.toml | 366 +- runtime/picasso/build.rs | 15 +- runtime/picasso/src/lib.rs | 228 +- runtime/picasso/src/weights/balances.rs | 17 +- runtime/picasso/src/weights/bonded_finance.rs | 58 + .../picasso/src/weights/collator_selection.rs | 35 +- runtime/picasso/src/weights/collective.rs | 83 +- .../picasso/src/weights/currency_factory.rs | 7 +- runtime/picasso/src/weights/democracy.rs | 103 +- runtime/picasso/src/weights/frame_system.rs | 15 +- runtime/picasso/src/weights/identity.rs | 125 +- runtime/picasso/src/weights/indices.rs | 13 +- runtime/picasso/src/weights/membership.rs | 35 +- runtime/picasso/src/weights/mod.rs | 2 + runtime/picasso/src/weights/multisig.rs | 55 +- runtime/picasso/src/weights/scheduler.rs | 85 +- runtime/picasso/src/weights/session.rs | 7 +- runtime/picasso/src/weights/timestamp.rs | 7 +- runtime/picasso/src/weights/treasury.rs | 19 +- runtime/picasso/src/weights/utility.rs | 17 +- runtime/picasso/src/weights/vesting.rs | 75 + runtime/picasso/src/xcmp.rs | 385 +- runtime/primitives/Cargo.toml | 34 +- runtime/primitives/src/currency.rs | 49 +- rustfmt.toml | 8 +- scripts/polkadot-launch/README.md | 63 +- scripts/polkadot-launch/composable.json | 16 +- .../composable_and_basilisk.json | 27 +- .../initialization/config/config.json | 6 +- .../initialization/src/index.ts | 13 +- .../polkadot-launch/initialization/yarn.lock | 6 +- scripts/polkadot-launch/package.json | 4 +- scripts/polkadot-launch/yarn.lock | 18 +- scripts/{benchmarks.sh => run_benchmarks.sh} | 4 +- setup/yarn.lock | 26 +- .../simnode => simnode}/common/Cargo.toml | 42 +- .../simnode => simnode}/common/src/chains.rs | 2 + simnode/common/src/chains/composable.rs | 68 + .../common/src/chains/dali.rs | 25 +- .../common/src/chains/picasso.rs | 25 +- .../simnode => simnode}/common/src/cli.rs | 0 .../simnode => simnode}/common/src/events.rs | 2 + .../simnode => simnode}/common/src/lib.rs | 0 .../simnode-node/Cargo.toml | 10 +- simnode/simnode-node/README.md | 45 + .../simnode-node/src/main.rs | 8 + .../simnode-tests/Cargo.toml | 47 +- .../simnode-tests/src/chains.rs | 2 + .../simnode-tests/src/chains/composable.rs | 20 + .../simnode-tests/src/chains/dali.rs | 0 .../simnode-tests/src/chains/picasso.rs | 0 .../simnode-tests/src/main.rs | 1 + .../simnode-tests/src/tests.rs | 0 .../src/tests/runtime_upgrade.rs | 0 utils/collator-sidecar/Cargo.toml | 19 +- utils/collator-sidecar/src/main.rs | 35 +- utils/faucet-server/Cargo.toml | 28 +- utils/parachain-utils/Cargo.toml | 32 +- utils/price-feed/Cargo.toml | 28 +- 399 files changed, 34611 insertions(+), 13075 deletions(-) create mode 100644 .dockerignore delete mode 100644 .github/workflows/Picasso-release.yml create mode 100644 .github/workflows/ci-linux.yml create mode 100644 .github/workflows/composable-sandbox.yml create mode 100644 .github/workflows/mmr-polkadot.yml delete mode 100644 .maintain/playbooks/delete-db-directory.yml create mode 100644 .taplo.toml create mode 100644 docker/ci-linux.dockerfile create mode 100644 docker/composable-sandbox.dockerfile create mode 100644 docker/mmr-polkadot.dockerfile create mode 100644 docs/custom-rpcs.md create mode 100644 docs/glossary.md create mode 100644 docs/runtime-testing.md create mode 100644 frame/assets/rpc/Cargo.toml create mode 100644 frame/assets/rpc/src/lib.rs create mode 100644 frame/assets/runtime-api/Cargo.toml create mode 100644 frame/assets/runtime-api/src/lib.rs create mode 100644 frame/bonded-finance/proptest-regressions/tests.txt delete mode 100644 frame/bonded-finance/src/utils.rs create mode 100644 frame/bonded-finance/src/weights.rs create mode 100644 frame/composable-maths/Cargo.toml create mode 100644 frame/composable-maths/src/dex/constant_product.rs create mode 100644 frame/composable-maths/src/dex/mod.rs create mode 100644 frame/composable-maths/src/dex/stable_swap.rs create mode 100644 frame/composable-maths/src/lib.rs create mode 100644 frame/composable-support/src/rpc_helpers.rs create mode 100644 frame/crowdloan-rewards/rpc/Cargo.toml create mode 100644 frame/crowdloan-rewards/rpc/src/lib.rs create mode 100644 frame/crowdloan-rewards/runtime-api/Cargo.toml create mode 100644 frame/crowdloan-rewards/runtime-api/src/lib.rs create mode 100644 frame/curve-amm/curve_base.png create mode 100644 frame/curve-amm/curve_graph.png create mode 100644 frame/curve-amm/curve_slippage.png create mode 100644 frame/curve-amm/src/benchmarking.rs create mode 100644 frame/curve-amm/src/maths.rs create mode 100644 frame/curve-amm/src/weights.rs create mode 100644 frame/lending/src/currency.rs delete mode 100644 frame/lending/src/mocks/currency.rs delete mode 100644 frame/lending/src/mocks/oracle.rs create mode 100644 frame/lending/src/setup.rs rename integration-tests/dex-messages.plantuml => frame/liquidations/external-dex-liqudation.sequence.plantuml (80%) create mode 100644 frame/liquidity-bootstrapping/Cargo.toml create mode 100644 frame/liquidity-bootstrapping/README.md create mode 100644 frame/liquidity-bootstrapping/plots/lbp_buy_project.png create mode 100644 frame/liquidity-bootstrapping/plots/lbp_sell_project.png create mode 100644 frame/liquidity-bootstrapping/plots/lbp_spot_price.png create mode 100644 frame/liquidity-bootstrapping/plots/lbp_weights.png create mode 100644 frame/liquidity-bootstrapping/src/benchmarking.rs create mode 100644 frame/liquidity-bootstrapping/src/lib.rs create mode 100644 frame/liquidity-bootstrapping/src/mock.rs create mode 100644 frame/liquidity-bootstrapping/src/tests.rs create mode 100644 frame/liquidity-bootstrapping/src/weights.rs create mode 100644 frame/mosaic/src/validation.rs create mode 100644 frame/oracle/src/validation.rs create mode 100644 frame/pablo/Cargo.toml create mode 100644 frame/pablo/plots/lbp/lbp_buy_project.png create mode 100644 frame/pablo/plots/lbp/lbp_sell_project.png create mode 100644 frame/pablo/plots/lbp/lbp_spot_price.png create mode 100644 frame/pablo/plots/lbp/lbp_weights.png create mode 100644 frame/pablo/plots/stable_swap/curve_base.png create mode 100644 frame/pablo/plots/stable_swap/curve_graph.png create mode 100644 frame/pablo/plots/stable_swap/curve_slippage.png create mode 100644 frame/pablo/src/common_test_functions.rs create mode 100644 frame/pablo/src/lib.rs create mode 100644 frame/pablo/src/liquidity_bootstrapping.rs create mode 100644 frame/pablo/src/liquidity_bootstrapping_tests.rs create mode 100644 frame/pablo/src/mock.rs create mode 100644 frame/pablo/src/stable_swap.rs create mode 100644 frame/pablo/src/stable_swap_tests.rs create mode 100644 frame/pablo/src/uniswap.rs create mode 100644 frame/pablo/src/uniswap_tests.rs create mode 100644 frame/transaction-fee/Cargo.lock create mode 100644 frame/uniswap-v2/src/benchmarking.rs create mode 100644 frame/uniswap-v2/src/weights.rs create mode 100644 frame/vault/src/validation.rs create mode 100644 frame/vesting/src/benchmarks.rs delete mode 100644 frame/vesting/src/default_weight.rs delete mode 100644 integration-tests/Cargo.toml delete mode 100644 integration-tests/README.md create mode 100644 integration-tests/local-integration-tests/Cargo.toml create mode 100644 integration-tests/local-integration-tests/README.md create mode 100644 integration-tests/local-integration-tests/awesome-xcmp.md create mode 100644 integration-tests/local-integration-tests/sibling-asset-transfer.sequence.plantuml create mode 100644 integration-tests/local-integration-tests/src/cross_chain_transfer.rs create mode 100644 integration-tests/local-integration-tests/src/helpers.rs rename integration-tests/{ => local-integration-tests}/src/kusama_test_net.rs (76%) create mode 100644 integration-tests/local-integration-tests/src/lib.rs create mode 100644 integration-tests/local-integration-tests/src/prelude.rs create mode 100644 integration-tests/local-integration-tests/src/relaychain.rs rename integration-tests/{ => local-integration-tests}/src/runtime_tests.rs (73%) create mode 100644 integration-tests/local-integration-tests/src/transact_calls.rs rename integration-tests/{ => local-integration-tests}/src/xcm_tests.rs (59%) create mode 100644 integration-tests/local-integration-tests/xcmp.sequence.plantuml create mode 100755 integration-tests/runtime-tests/DockerRun.sh create mode 100644 integration-tests/runtime-tests/docker-compose.yml create mode 100644 integration-tests/runtime-tests/src/generators/setBalance/setStartBalance.ts rename integration-tests/runtime-tests/src/{initializeState.ts => main.ts} (86%) delete mode 100644 integration-tests/runtime-tests/src/test.ts delete mode 100644 integration-tests/runtime-tests/src/tests/examples/querySystemAccountTests.ts delete mode 100644 integration-tests/runtime-tests/src/tests/query/council/queryCouncilTests.ts delete mode 100644 integration-tests/runtime-tests/src/tests/query/crowdloanRewards/queryCrowdloanRewardsTests.ts delete mode 100644 integration-tests/runtime-tests/src/tests/rpc/crowdloanRewards/rpcCrowdloanRewardsTests.ts delete mode 100644 integration-tests/runtime-tests/src/tests/tx/bondedFinance/txBondedFinanceTests.ts delete mode 100644 integration-tests/runtime-tests/src/tests/tx/crowdloanRewards/txCrowdloanRewardsTests.ts delete mode 100644 integration-tests/runtime-tests/src/tests/tx/oracle/txOracleTests.ts create mode 100644 integration-tests/runtime-tests/src/types/interfaces/assets/definitions.ts rename integration-tests/runtime-tests/src/types/interfaces/{default => assets}/index.ts (100%) create mode 100644 integration-tests/runtime-tests/src/types/interfaces/assets/types.ts create mode 100644 integration-tests/runtime-tests/src/types/interfaces/crowdloanRewards/definitions.ts create mode 100644 integration-tests/runtime-tests/src/types/interfaces/crowdloanRewards/index.ts rename integration-tests/runtime-tests/src/types/interfaces/{default => crowdloanRewards}/types.ts (60%) delete mode 100644 integration-tests/runtime-tests/src/utils/args.ts create mode 100644 integration-tests/runtime-tests/src/utils/mintingHelper.ts rename integration-tests/runtime-tests/{src => test}/globals.ts (94%) create mode 100644 integration-tests/runtime-tests/test/tests/assets/rpcAssetsTests.ts create mode 100644 integration-tests/runtime-tests/test/tests/assets/test_configuration.json rename integration-tests/runtime-tests/{src/tests/tx => test/tests}/bondedFinance/testHandlers/bondTests.ts (88%) rename integration-tests/runtime-tests/{src/tests/tx => test/tests}/bondedFinance/testHandlers/cancelTests.ts (100%) rename integration-tests/runtime-tests/{src/tests/tx => test/tests}/bondedFinance/testHandlers/offerTests.ts (88%) create mode 100644 integration-tests/runtime-tests/test/tests/bondedFinance/test_configuration.json create mode 100644 integration-tests/runtime-tests/test/tests/bondedFinance/txBondedFinanceTests.ts create mode 100644 integration-tests/runtime-tests/test/tests/crowdloanRewards/queryCrowdloanRewardsTests.ts create mode 100644 integration-tests/runtime-tests/test/tests/crowdloanRewards/rpcCrowdloanRewardsTests.ts create mode 100644 integration-tests/runtime-tests/test/tests/crowdloanRewards/test_configuration.json create mode 100644 integration-tests/runtime-tests/test/tests/crowdloanRewards/txCrowdloanRewardsTests.ts create mode 100644 integration-tests/runtime-tests/test/tests/dexTests/constantProductDex/constantProductTests.ts create mode 100644 integration-tests/runtime-tests/test/tests/dexTests/constantProductDex/testHandlers/constantProductDexHelper.ts create mode 100644 integration-tests/runtime-tests/test/tests/dexTests/constantProductDex/test_configuration.json create mode 100644 integration-tests/runtime-tests/test/tests/examples/querySystemAccountTests.ts create mode 100644 integration-tests/runtime-tests/test/tests/examples/test_configuration.json rename integration-tests/runtime-tests/{src/tests/tx => test/tests}/oracle/testHandlers/addAssetAndInfoTests.ts (99%) rename integration-tests/runtime-tests/{src/tests/tx => test/tests}/oracle/testHandlers/addStakeTests.ts (99%) rename integration-tests/runtime-tests/{src/tests/tx => test/tests}/oracle/testHandlers/reclaimStakeTests.ts (99%) rename integration-tests/runtime-tests/{src/tests/tx => test/tests}/oracle/testHandlers/removeStakeTests.ts (99%) rename integration-tests/runtime-tests/{src/tests/tx => test/tests}/oracle/testHandlers/setSignerTests.ts (99%) rename integration-tests/runtime-tests/{src/tests/tx => test/tests}/oracle/testHandlers/submitPriceTests.ts (99%) create mode 100644 integration-tests/runtime-tests/test/tests/oracle/test_configuration.json create mode 100644 integration-tests/runtime-tests/test/tests/oracle/txOracleTests.ts create mode 100644 integration-tests/runtime-tests/test/tests/xcmp/transfers.ts delete mode 100644 integration-tests/src/cross_chain_transfer.rs delete mode 100644 integration-tests/src/lib.rs create mode 100755 nix/latest.sh create mode 100644 runtime/common/src/xcmp/mod.rs create mode 100644 runtime/dali/src/README.md create mode 100644 runtime/dali/src/weights/bonded_finance.rs create mode 100644 runtime/dali/src/weights/curve_amm.rs create mode 100644 runtime/dali/src/weights/lending.rs delete mode 100644 runtime/dali/src/weights/liqudations.rs create mode 100644 runtime/dali/src/weights/liquidations.rs create mode 100644 runtime/dali/src/weights/liquidity_bootstrapping.rs create mode 100644 runtime/dali/src/weights/uniswap_v2.rs create mode 100644 runtime/dali/src/weights/vesting.rs create mode 100644 runtime/picasso/src/weights/bonded_finance.rs create mode 100644 runtime/picasso/src/weights/vesting.rs rename scripts/{benchmarks.sh => run_benchmarks.sh} (100%) rename {integration-tests/simnode => simnode}/common/Cargo.toml (54%) rename {integration-tests/simnode => simnode}/common/src/chains.rs (63%) create mode 100644 simnode/common/src/chains/composable.rs rename {integration-tests/simnode => simnode}/common/src/chains/dali.rs (68%) rename {integration-tests/simnode => simnode}/common/src/chains/picasso.rs (68%) rename {integration-tests/simnode => simnode}/common/src/cli.rs (100%) rename {integration-tests/simnode => simnode}/common/src/events.rs (89%) rename {integration-tests/simnode => simnode}/common/src/lib.rs (100%) rename {integration-tests/simnode => simnode}/simnode-node/Cargo.toml (68%) create mode 100644 simnode/simnode-node/README.md rename {integration-tests/simnode => simnode}/simnode-node/src/main.rs (75%) rename {integration-tests/simnode => simnode}/simnode-tests/Cargo.toml (65%) rename {integration-tests/simnode => simnode}/simnode-tests/src/chains.rs (63%) create mode 100644 simnode/simnode-tests/src/chains/composable.rs rename {integration-tests/simnode => simnode}/simnode-tests/src/chains/dali.rs (100%) rename {integration-tests/simnode => simnode}/simnode-tests/src/chains/picasso.rs (100%) rename {integration-tests/simnode => simnode}/simnode-tests/src/main.rs (87%) rename {integration-tests/simnode => simnode}/simnode-tests/src/tests.rs (100%) rename {integration-tests/simnode => simnode}/simnode-tests/src/tests/runtime_upgrade.rs (100%) diff --git a/.config/cargo_spellcheck.toml b/.config/cargo_spellcheck.toml index 2fee7330572..c57328b4352 100644 --- a/.config/cargo_spellcheck.toml +++ b/.config/cargo_spellcheck.toml @@ -66,4 +66,4 @@ allow_dashed = false [Reflow] # Reflows doc comments to adhere to adhere to a given maximum line width limit. -max_line_length = 80 \ No newline at end of file +max_line_length = 80 diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000000..eb5a316cbd1 --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +target diff --git a/.github/workflows/Picasso-release.yml b/.github/workflows/Picasso-release.yml deleted file mode 100644 index 49ba6616eba..00000000000 --- a/.github/workflows/Picasso-release.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: "Picasso Community Release" - -on: - push: - tags: - - 'picasso-*' -env: - CHAIN: "picasso" - -jobs: - build-and-publish: - runs-on: - - self-hosted - - linux - - x64 - - sre - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - ref: picasso - - - name: Set env - run: | - echo "RELEASE_VERSION=$(git tag --sort=committerdate | grep -E '^picasso-[0-9]' | tail -1 )" >> $GITHUB_ENV - make version - - - name: Build and Push Artifacts to gcloud - run: | - /home/runner/.cargo/bin/cargo build --release --bins - tar -czvf composable-${{ env.RELEASE_VERSION }}.tar.gz target/release/composable - tar -czvf picasso_runtime.compact.wasm-${RELEASE_VERSION}.tar.gz target/release/wbuild/picasso-runtime/picasso_runtime.compact.wasm - tar -czvf parachain-utils-${RELEASE_VERSION}.tar.gz target/release/parachain - gsutil mv *.tar.gz gs://composable-binaries/community-releases/${RELEASE_VERSION} - - name: Login to DockerHub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} - - - name: Build Docker image - run: make containerize-release - - name: Docker push - run: make push-release diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 114b1112abb..9a0e0cd60ea 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -50,7 +50,7 @@ jobs: GITHUB_BRANCH_NAME: ${{ steps.branch-name.outputs.current_branch }} if: env.RUNTIME_CHECK == 1 id: run_benchmarks - run: .maintain/run_benchmarks.sh + run: .maintain/run_benchmarks.sh 50 20 - uses: EndBug/add-and-commit@v8 with: diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 31dc82e6511..9e27f80b68d 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -3,6 +3,9 @@ name: CI Check # please update docker, toolchain toml and github action with toolchain at same time on: + push: + branches: + - main pull_request: branches: - main @@ -63,16 +66,13 @@ jobs: - name: Rustup show run: | /home/runner/.cargo/bin/rustup show - - uses: actions/checkout@v2 - name: Run Test (with coverage) run: | - # integration tests can't be compiled with --feature=runtime-benchmarks - # TODO: https://github.com/ComposableFi/composable/issues/535 - /home/runner/.cargo/bin/cargo install -f cargo-llvm-cov + /home/runner/.cargo/bin/cargo +nightly-2021-11-08 install -f cargo-llvm-cov /home/runner/.cargo/bin/rustup component add llvm-tools-preview --toolchain=nightly-2021-11-08 SKIP_WASM_BUILD=1 /home/runner/.cargo/bin/cargo +nightly-2021-11-08 llvm-cov --workspace --locked --release --verbose --features=runtime-benchmarks --lcov --output-path lcov.info - name: Upload coverage to Codecov - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v2 with: token: ${{ secrets.CODECOV_TOKEN }} files: lcov.info @@ -101,16 +101,21 @@ jobs: docker system prune --force --all --volumes - uses: actions/checkout@v2 - - name: Check for runtime changes - env: - BASE_BRANCH: ${{ github.event.pull_request.base.ref }} - GITHUB_BRANCH_NAME: ${{ steps.branch-name.outputs.current_branch }} - id: check_runtime - run: .maintain/check_runtime.sh + - name: Get branch name + id: branch-name + uses: tj-actions/branch-names@v5.1 + + # FIXME: actually broken: https://github.com/ComposableFi/composable/runs/5570301249?check_suite_focus=true + # - name: Check for runtime changes + # env: + # BASE_BRANCH: ${{ github.event.pull_request.base.ref }} + # GITHUB_BRANCH_NAME: ${{ steps.branch-name.outputs.current_branch }} + # id: check_runtime + # run: .maintain/check_runtime.sh - name: Run single pass benchmarking # only run this step if there are runtime changes - if: env.RUNTIME_CHECK == 1 + # if: env.RUNTIME_CHECK == 1 env: RUST_BACKTRACE: full run: | @@ -123,7 +128,6 @@ jobs: --extrinsic='*' \ --steps=1 \ --repeat=1 \ - --raw \ --log error @@ -177,9 +181,20 @@ jobs: with: node-version: 14.x - - name: Cargo fmt + - name: Cargo format (Rust) run: | cargo +nightly fmt --all -- --check + + - name: Taplo format (Toml) + run: | + cargo install taplo-cli + taplo lint --warn-as-error + taplo fmt --warn-as-error + if ! git diff-index HEAD; then + exit 1 + else + echo "Everything is fine!" + fi - name: Hadolint env: @@ -215,7 +230,7 @@ jobs: - name: Cargo clippy run: | - SKIP_WASM_BUILD=1 env -u RUSTFLAGS cargo +nightly clippy --all-targets + SKIP_WASM_BUILD=1 env -u RUSTFLAGS cargo +nightly clippy --all-targets --tests -- -D warnings - name: Cargo Single Depedency # description: Speed up builds and reduced security check surface diff --git a/.github/workflows/ci-linux.yml b/.github/workflows/ci-linux.yml new file mode 100644 index 00000000000..3e440635dda --- /dev/null +++ b/.github/workflows/ci-linux.yml @@ -0,0 +1,49 @@ +name: "ci-linux Docker image" + +on: + workflow_dispatch: + push: + branches: + - ci-linux + +env: + DOCKER_USER_OPTION: '$UID:$GID' + SCCACHE_GCS_BUCKET: 'composable-build-artefacts' + RUSTC_WRAPPER: "/home/runner/.cargo/bin/sccache" + SCCACHE_GCS_RW_MODE: "READ_WRITE" + +jobs: + build-and-publish: + runs-on: + - self-hosted + - linux + - x64 + - sre + concurrency: + group: docker-${{ github.ref }} + cancel-in-progress: true + strategy: + fail-fast: true + + steps: + - name: Clean up + continue-on-error: true + run: | + sudo chown -R $USER:$USER $GITHUB_WORKSPACE + docker system prune --force --all --volumes + + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} + + - name: Build Docker image + run: make containerize-ci-linux + + - name: Docker push + run: make push-ci-linux diff --git a/.github/workflows/composable-sandbox.yml b/.github/workflows/composable-sandbox.yml new file mode 100644 index 00000000000..a242cbbb69e --- /dev/null +++ b/.github/workflows/composable-sandbox.yml @@ -0,0 +1,49 @@ +name: "composable-sandbox Docker image" + +on: + workflow_dispatch: + push: + branches: + - composable-sandbox + +env: + DOCKER_USER_OPTION: '$UID:$GID' + SCCACHE_GCS_BUCKET: 'composable-build-artefacts' + RUSTC_WRAPPER: "/home/runner/.cargo/bin/sccache" + SCCACHE_GCS_RW_MODE: "READ_WRITE" + +jobs: + build-and-publish: + runs-on: + - self-hosted + - linux + - x64 + - sre + concurrency: + group: docker-${{ github.ref }} + cancel-in-progress: true + strategy: + fail-fast: true + + steps: + - name: Clean up + continue-on-error: true + run: | + sudo chown -R $USER:$USER $GITHUB_WORKSPACE + docker system prune --force --all --volumes + + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} + + - name: Build Docker image + run: make containerize-composable-sandbox + + - name: Docker push + run: make push-composable-sandbox diff --git a/.github/workflows/devnet-release.yml b/.github/workflows/devnet-release.yml index 6f47088b2a2..0f6d7d9d038 100644 --- a/.github/workflows/devnet-release.yml +++ b/.github/workflows/devnet-release.yml @@ -22,8 +22,6 @@ jobs: - uses: actions/setup-python@v2 - uses: cachix/install-nix-action@v16 - with: - nix_path: nixpkgs=channel:nixos-unstable - uses: cachix/cachix-action@v10 with: @@ -43,14 +41,18 @@ jobs: - name: Install latest Nightly uses: actions-rs/toolchain@v1 with: - toolchain: nightly + toolchain: nightly-2022-02-01 target: wasm32-unknown-unknown + - uses: Swatinem/rust-cache@v1 + - name: Push artifact run: | cargo build --release - tar -czvf composable-picasso-${{ env.RELEASE_VERSION }}.tar.gz target/release/composable + cargo doc --release + tar -czvf composable-picasso-${{ env.RELEASE_VERSION }}.tar.gz target/release/composable target/doc gsutil mv *.tar.gz gs://composable-binaries/community-releases/picasso/ + rm -rf target - name: Load state run: | diff --git a/.github/workflows/mmr-polkadot.yml b/.github/workflows/mmr-polkadot.yml new file mode 100644 index 00000000000..70cfefbaf11 --- /dev/null +++ b/.github/workflows/mmr-polkadot.yml @@ -0,0 +1,49 @@ +name: "mmr-polkadot Docker image" + +on: + workflow_dispatch: + push: + branches: + - mmr-polkadot + +env: + DOCKER_USER_OPTION: '$UID:$GID' + SCCACHE_GCS_BUCKET: 'composable-build-artefacts' + RUSTC_WRAPPER: "/home/runner/.cargo/bin/sccache" + SCCACHE_GCS_RW_MODE: "READ_WRITE" + +jobs: + build-and-publish: + runs-on: + - self-hosted + - linux + - x64 + - sre + concurrency: + group: docker-${{ github.ref }} + cancel-in-progress: true + strategy: + fail-fast: true + + steps: + - name: Clean up + continue-on-error: true + run: | + sudo chown -R $USER:$USER $GITHUB_WORKSPACE + docker system prune --force --all --volumes + + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} + + - name: Build Docker image + run: make containerize-mmr-polkadot + + - name: Docker push + run: make push-mmr-polkadot diff --git a/.gitignore b/.gitignore index 31e4914a423..e2f5eb34100 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,6 @@ target node_modules/ **/yarn-error.log **/.yarn/ -rust-toolchain.toml \ No newline at end of file +rust-toolchain.toml + +.benchmarkRun \ No newline at end of file diff --git a/.maintain/playbooks/delete-db-directory.yml b/.maintain/playbooks/delete-db-directory.yml deleted file mode 100644 index 1a2f29a6680..00000000000 --- a/.maintain/playbooks/delete-db-directory.yml +++ /dev/null @@ -1,21 +0,0 @@ ---- -- name: Delete DB Directory for Dali - hosts: all - become: runner - tasks: - - name: Run Backup Script - become: true - shell: | - #!/bin/bash - sudo supervisorctl stop composable - sudo rm -rf /var/lib/composable-data - args: - executable: /bin/bash - register: stdout - - - name: Copy runner config Script - copy: - src: composable-rococo.conf - dest: /etc/supervisor/conf.d/composable.conf - owner: composable - group: 0755 \ No newline at end of file diff --git a/.maintain/playbooks/run-integration-tests.yml b/.maintain/playbooks/run-integration-tests.yml index e75431d6796..5d9aefedb33 100644 --- a/.maintain/playbooks/run-integration-tests.yml +++ b/.maintain/playbooks/run-integration-tests.yml @@ -130,7 +130,7 @@ dest: "/home/{{ user }}/basilisk" - url: https://storage.googleapis.com/composable-binaries/testnet-releases/picasso/composable-latest.tar.gz dest: "/home/{{ user }}/composable-latest.tar.gz" - - url: https://github.com/paritytech/polkadot/releases/download/v0.9.16/polkadot + - url: https://github.com/paritytech/polkadot/releases/download/v0.9.17/polkadot dest: "/home/{{ user }}/polkadot" - name: Clone composable repo diff --git a/.maintain/run_benchmarks.sh b/.maintain/run_benchmarks.sh index a6b792b5165..65c53b0f2ed 100755 --- a/.maintain/run_benchmarks.sh +++ b/.maintain/run_benchmarks.sh @@ -13,8 +13,8 @@ VERSIONS_FILES=( "runtime/composable/src/weights,composable-dev,composable" ) -steps=50 -repeat=20 +steps=$1 +repeat=$2 /home/runner/.cargo/bin/rustup install nightly /home/runner/.cargo/bin/rustup target add wasm32-unknown-unknown --toolchain nightly @@ -35,7 +35,6 @@ run_benchmarks() { --extrinsic='*' \ --steps=$steps \ --repeat=$repeat \ - --raw \ --output="$OUTPUT" \ --log error # ToDO: Setup gpg signing and create a bot account for pushing diff --git a/.maintain/run_simnode.sh b/.maintain/run_simnode.sh index a5d124d3c13..81d7824f6ec 100755 --- a/.maintain/run_simnode.sh +++ b/.maintain/run_simnode.sh @@ -11,7 +11,7 @@ set -e # fail on any error VERSIONS_FILES=( "picasso,picasso" "dali-rococo,dali" - # "composable,composable" # TODO: add simnode suppport for composable + "composable,composable" ) /home/runner/.cargo/bin/rustup update nightly @@ -28,7 +28,7 @@ run_simnode() { GS_BUCKET="$CHAIN-data-store" sudo gsutil cp gs://$GS_BUCKET/"$FILENAME" . sudo unzip -o "$FILENAME" -d /tmp/db - ./target/release/simnode-tests --chain="$CHAIN" --base-path=/tmp/db/var/lib/composable-data/ --pruning=archive --execution=wasm + sudo ./target/release/simnode-tests --chain="$CHAIN" --base-path=/tmp/db/var/lib/composable-data/ --pruning=archive --execution=wasm } # shellcheck disable=SC2039 diff --git a/.taplo.toml b/.taplo.toml new file mode 100644 index 00000000000..7c65b90cb24 --- /dev/null +++ b/.taplo.toml @@ -0,0 +1,30 @@ +include = ["Cargo.toml", "**/*.toml"] + +[formatting] +# Align consecutive entries vertically. +align_entries = false +# Append trailing commas for multi-line arrays. +array_trailing_comma = true +# Expand arrays to multiple lines that exceed the maximum column width. +array_auto_expand = true +# Collapse arrays that don't exceed the maximum column width and don't contain comments. +array_auto_collapse = true +# Omit white space padding from single-line arrays +compact_arrays = true +# Omit white space padding from the start and end of inline tables. +compact_inline_tables = false +# Maximum column width in characters, affects array expansion and collapse, this doesn't take whitespace into account. +# Note that this is not set in stone, and works on a best-effort basis. +column_width = 80 +# Indent based on tables and arrays of tables and their subtables, subtables out of order are not indented. +indent_tables = false +# The substring that is used for indentation, should be tabs or spaces (but technically can be anything). +indent_string = ' ' +# Add trailing newline at the end of the file if not present. +trailing_newline = true +# Alphabetically reorder keys that are not separated by empty lines. +reorder_keys = true +# Maximum amount of allowed consecutive blank lines. This does not affect the whitespace at the end of the document, as it is always stripped. +allowed_blank_lines = 2 +# Use CRLF for line endings. +crlf = false diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index e9dad145c8d..b4374fb83b6 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -9,9 +9,16 @@ The Composable project consists of a blockchain, various utility applications, d # Runtimes When building the chain, we use different names to target different [relay chain](https://wiki.polkadot.network/docs/learn-architecture): -- the **Dali** chain is deployed for **Westend/Rococo/Chachacha** -- the **Picasso** chain is deployed for **Kusama** -- the **Composable** chain is deployed for **Polkadot** + +| Chain and Runtime | Deployed to | Relayer Native Currency | Link | Docs | +| ----------------- | ----------------- | ----------------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------- | +| Dali | Devnet(own Relay) | KSM | https://polkadot.js.org/apps/?rpc=wss://dali.devnets.composablefinance.ninja/parachain/alice#/explorer | https://dali.devnets.composablefinance.ninja/ | +| Picasso | Devnet(own Relay) | KSM | https://polkadot.js.org/apps/?rpc=wss://picasso.devnets.composablefinance.ninja/parachain/alice#/explorer | +| Dali | Westend | WND(DOT) | +| Dali | Rococo | | https://polkadot.js.org/apps/?rpc=wss://rpc.composablefinance.ninja | +| Dali | Chachacha | | +| Picasso | Kusama | KSM | https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fpicasso-rpc.composable.finance#/explorer | +| Composable | Polkadot | DOT | The runtimes can be found under the `runtime` directory. The chain specs are located in `node/src/chain_spec`. diff --git a/Cargo.lock b/Cargo.lock index e2afc1f8073..50d49f29d80 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -128,7 +128,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.4", + "getrandom 0.2.5", "once_cell", "version_check 0.9.4", ] @@ -159,9 +159,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.53" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0" +checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" [[package]] name = "approx" @@ -211,6 +211,32 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" +[[package]] +name = "assets-rpc" +version = "0.0.1" +dependencies = [ + "assets-runtime-api", + "composable-support", + "jsonrpc-core", + "jsonrpc-core-client", + "jsonrpc-derive", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-blockchain", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "assets-runtime-api" +version = "0.0.1" +dependencies = [ + "composable-support", + "parity-scale-codec", + "sp-api", +] + [[package]] name = "async-attributes" version = "1.1.2" @@ -218,7 +244,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" dependencies = [ "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -258,9 +284,9 @@ dependencies = [ [[package]] name = "async-global-executor" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9586ec52317f36de58453159d48351bc244bc24ced3effc1fce22f3d48664af6" +checksum = "c026b7e44f1316b567ee750fea85103f87fcb80792b860e979f221259796ca0a" dependencies = [ "async-channel", "async-executor", @@ -310,9 +336,9 @@ dependencies = [ [[package]] name = "async-lock" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6a8ea61bf9947a1007c5cada31e647dbc77b103c679858150003ba697ea798b" +checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" dependencies = [ "event-listener", ] @@ -390,7 +416,7 @@ dependencies = [ "async-io", "async-lock", "async-process", - "crossbeam-utils 0.8.6", + "crossbeam-utils 0.8.8", "futures-channel", "futures-core", "futures-io", @@ -423,9 +449,9 @@ dependencies = [ [[package]] name = "async-task" -version = "4.1.0" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d306121baf53310a3fd342d88dc0824f6bbeace68347593658525565abee8" +checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9" [[package]] name = "async-trait" @@ -435,7 +461,7 @@ checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -470,7 +496,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b88d82667eca772c4aa12f0f1348b3ae643424c8876448f3f7bd5787032e234c" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", ] [[package]] @@ -492,15 +518,18 @@ dependencies = [ [[package]] name = "autocfg" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" +dependencies = [ + "autocfg 1.1.0", +] [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" @@ -572,11 +601,11 @@ dependencies = [ [[package]] name = "beefy-gadget" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "beefy-primitives", "fnv", - "futures 0.3.19", + "futures 0.3.21", "log 0.4.14", "parity-scale-codec", "parking_lot 0.11.2", @@ -601,12 +630,11 @@ dependencies = [ [[package]] name = "beefy-gadget-rpc" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "beefy-gadget", "beefy-primitives", - "derive_more", - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -625,12 +653,12 @@ dependencies = [ [[package]] name = "beefy-merkle-tree" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" [[package]] name = "beefy-primitives" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "parity-scale-codec", "scale-info", @@ -807,9 +835,9 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95" +checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" dependencies = [ "generic-array 0.14.5", ] @@ -831,9 +859,9 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "blocking" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046e47d4b2d391b1f6f8b407b1deb8dee56c1852ccd868becf2710f601b5f427" +checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc" dependencies = [ "async-channel", "async-task", @@ -855,7 +883,7 @@ dependencies = [ [[package]] name = "bp-header-chain" version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "finality-grandpa", "frame-support", @@ -871,7 +899,7 @@ dependencies = [ [[package]] name = "bp-message-dispatch" version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "bp-runtime", "frame-support", @@ -883,7 +911,7 @@ dependencies = [ [[package]] name = "bp-messages" version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "bitvec", "bp-runtime", @@ -899,7 +927,7 @@ dependencies = [ [[package]] name = "bp-polkadot-core" version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "bp-messages", "bp-runtime", @@ -917,7 +945,7 @@ dependencies = [ [[package]] name = "bp-rococo" version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "bp-messages", "bp-polkadot-core", @@ -934,7 +962,7 @@ dependencies = [ [[package]] name = "bp-runtime" version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "frame-support", "hash-db", @@ -952,7 +980,7 @@ dependencies = [ [[package]] name = "bp-test-utils" version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "bp-header-chain", "ed25519-dalek", @@ -967,7 +995,7 @@ dependencies = [ [[package]] name = "bp-wococo" version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "bp-messages", "bp-polkadot-core", @@ -982,7 +1010,7 @@ dependencies = [ [[package]] name = "bridge-runtime-common" version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "bp-message-dispatch", "bp-messages", @@ -1044,9 +1072,9 @@ checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" [[package]] name = "byte-slice-cast" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d30c751592b77c499e7bce34d99d67c2c11bdc0574e9a488ddade14150a4698" +checksum = "87c5fdd0166095e1d463fc6cc01aa8ce547ad77a4e84d42eb6762b084e28067e" [[package]] name = "byte-tools" @@ -1056,9 +1084,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytemuck" -version = "1.7.3" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439989e6b8c38d1b6570a384ef1e49c8848128f5a97f3914baef02920842712f" +checksum = "0e851ca7c24871e7336801608a4797d7376545b6928a10d32d75685687141ead" [[package]] name = "byteorder" @@ -1108,22 +1136,22 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba2ae6de944143141f6155a473a6b02f66c7c3f9f47316f802f80204ebfe6e12" +checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" dependencies = [ "camino", "cargo-platform", - "semver 1.0.4", + "semver 1.0.6", "serde", "serde_json", ] [[package]] name = "cc" -version = "1.0.72" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" dependencies = [ "jobserver", ] @@ -1260,9 +1288,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.0.14" +version = "3.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63edc3f163b3c71ec8aa23f9bd6070f77edbf3d1d198b164afa90ff00e4ec62" +checksum = "d8c93436c21e4698bacadf42917db28b23017027a4deccb35dbe47a7e7840123" dependencies = [ "atty", "bitflags", @@ -1272,20 +1300,20 @@ dependencies = [ "os_str_bytes", "strsim 0.10.0", "termcolor", - "textwrap 0.14.2", + "textwrap 0.15.0", ] [[package]] name = "clap_derive" -version = "3.0.14" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1132dc3944b31c20dd8b906b3a9f0a5d0243e092d59171414969657ac6aa85" +checksum = "da95d038ede1a964ce99f49cbe27a7fb538d1da595e4b4f70b8c8f338d17bf16" dependencies = [ "heck 0.4.0", "proc-macro-error", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -1311,11 +1339,8 @@ name = "collator-sidecar" version = "0.1.0" dependencies = [ "async-std", - "common", "env_logger 0.8.4", - "jsonrpc-core-client", - "picasso-runtime", - "sc-rpc", + "jsonrpsee 0.9.0", "serde", "structopt", "tide", @@ -1368,22 +1393,45 @@ dependencies = [ "sp-io", "sp-runtime", "sp-std", + "xcm", + "xcm-builder", + "xcm-executor", ] [[package]] name = "composable" -version = "1.0.9" +version = "1.0.0" dependencies = [ "color-eyre", "composable-node", ] +[[package]] +name = "composable-maths" +version = "0.0.1" +dependencies = [ + "composable-traits", + "frame-support", + "frame-system", + "parity-scale-codec", + "rust_decimal", + "scale-info", + "sp-arithmetic", + "sp-runtime", + "sp-std", +] + [[package]] name = "composable-node" -version = "1.0.9" +version = "1.0.0" dependencies = [ + "assets-rpc", + "assets-runtime-api", + "clap 3.1.6", "common", "composable-runtime", + "crowdloan-rewards-rpc", + "crowdloan-rewards-runtime-api", "cumulus-client-cli", "cumulus-client-collator", "cumulus-client-consensus-aura", @@ -1400,6 +1448,8 @@ dependencies = [ "hex", "jsonrpc-core", "log 0.4.14", + "pallet-assets", + "pallet-crowdloan-rewards", "pallet-transaction-payment-rpc", "pallet-transaction-payment-rpc-runtime-api", "parity-scale-codec", @@ -1408,6 +1458,7 @@ dependencies = [ "polkadot-parachain", "polkadot-primitives", "polkadot-service", + "primitives", "sc-basic-authorship", "sc-chain-spec", "sc-cli", @@ -1442,7 +1493,6 @@ dependencies = [ "sp-timestamp", "sp-transaction-pool", "sp-trie", - "structopt", "substrate-build-script-utils", "substrate-frame-rpc-system", "substrate-prometheus-endpoint", @@ -1452,8 +1502,11 @@ dependencies = [ name = "composable-runtime" version = "0.1.0" dependencies = [ + "assets-runtime-api", "common", + "composable-support", "composable-traits", + "crowdloan-rewards-runtime-api", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -1483,6 +1536,7 @@ dependencies = [ "pallet-call-filter", "pallet-collator-selection", "pallet-collective", + "pallet-crowdloan-rewards", "pallet-currency-factory", "pallet-democracy 4.0.0-dev", "pallet-governance-registry", @@ -1506,6 +1560,7 @@ dependencies = [ "polkadot-parachain", "primitives", "scale-info", + "simnode-runtime-apis", "smallvec 1.8.0", "sp-api", "sp-block-builder", @@ -1532,7 +1587,7 @@ dependencies = [ "frame-system", "is_sorted", "parity-scale-codec", - "proptest 1.0.0", + "proptest", "scale-info", "serde", "serde_json", @@ -1563,10 +1618,9 @@ dependencies = [ "composable-support", "frame-support", "frame-system", - "orml-traits", "parity-scale-codec", "plotters", - "proptest 1.0.0", + "proptest", "scale-info", "serde", "sp-arithmetic", @@ -1613,7 +1667,7 @@ dependencies = [ "hkdf", "hmac 0.10.1", "percent-encoding 2.1.0", - "rand 0.8.4", + "rand 0.8.5", "sha2 0.9.9", "time 0.2.27", "version_check 0.9.4", @@ -1621,9 +1675,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ "core-foundation-sys", "libc", @@ -1707,18 +1761,18 @@ checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" [[package]] name = "cranelift-bforest" -version = "0.80.0" +version = "0.80.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9516ba6b2ba47b4cbf63b713f75b432fafa0a0e0464ec8381ec76e6efe931ab3" +checksum = "62fc68cdb867b7d27b5f33cd65eb11376dfb41a2d09568a1a2c2bc1dc204f4ef" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.80.0" +version = "0.80.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489e5d0081f7edff6be12d71282a8bf387b5df64d5592454b75d662397f2d642" +checksum = "31253a44ab62588f8235a996cc9b0636d98a299190069ced9628b8547329b47a" dependencies = [ "cranelift-bforest", "cranelift-codegen-meta", @@ -1733,33 +1787,33 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.80.0" +version = "0.80.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d36ee1140371bb0f69100e734b30400157a4adf7b86148dee8b0a438763ead48" +checksum = "7a20ab4627d30b702fb1b8a399882726d216b8164d3b3fa6189e3bf901506afe" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.80.0" +version = "0.80.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "981da52d8f746af1feb96290c83977ff8d41071a7499e991d8abae0d4869f564" +checksum = "6687d9668dacfed4468361f7578d86bded8ca4db978f734d9b631494bebbb5b8" [[package]] name = "cranelift-entity" -version = "0.80.0" +version = "0.80.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2906740053dd3bcf95ce53df0fd9b5649c68ae4bd9adada92b406f059eae461" +checksum = "c77c5d72db97ba2cb36f69037a709edbae0d29cb25503775891e7151c5c874bf" dependencies = [ "serde", ] [[package]] name = "cranelift-frontend" -version = "0.80.0" +version = "0.80.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cb156de1097f567d46bf57a0cd720a72c3e15e1a2bd8b1041ba2fc894471b7" +checksum = "426dca83f63c7c64ea459eb569aadc5e0c66536c0042ed5d693f91830e8750d0" dependencies = [ "cranelift-codegen", "log 0.4.14", @@ -1769,9 +1823,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.80.0" +version = "0.80.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "166028ca0343a6ee7bddac0e70084e142b23f99c701bd6f6ea9123afac1a7a46" +checksum = "8007864b5d0c49b026c861a15761785a2871124e401630c03ef1426e6d0d559e" dependencies = [ "cranelift-codegen", "libc", @@ -1780,9 +1834,9 @@ dependencies = [ [[package]] name = "cranelift-wasm" -version = "0.80.0" +version = "0.80.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5012a1cde0c8b3898770b711490d803018ae9bec2d60674ba0e5b2058a874f80" +checksum = "94cf12c071415ba261d897387ae5350c4d83c238376c8c5a96514ecfa2ea66a3" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -1796,21 +1850,21 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2209c310e29876f7f0b2721e7e26b84aff178aa3da5d091f9bfbf47669e60e3" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "crossbeam-channel" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa" +checksum = "fdbfe11fe19ff083c48923cf179540e8cd0535903dc35e178a1fdeeb59aef51f" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.6", + "crossbeam-utils 0.8.8", ] [[package]] @@ -1821,17 +1875,18 @@ checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ "cfg-if 1.0.0", "crossbeam-epoch", - "crossbeam-utils 0.8.6", + "crossbeam-utils 0.8.8", ] [[package]] name = "crossbeam-epoch" -version = "0.9.6" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97242a70df9b89a65d0b6df3c4bf5b9ce03c5b7309019777fbde37e7537f8762" +checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" dependencies = [ + "autocfg 1.1.0", "cfg-if 1.0.0", - "crossbeam-utils 0.8.6", + "crossbeam-utils 0.8.8", "lazy_static", "memoffset", "scopeguard", @@ -1843,21 +1898,49 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "cfg-if 0.1.10", "lazy_static", ] [[package]] name = "crossbeam-utils" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcae03edb34f947e64acdb1c33ec169824e20657e9ecb61cef6c8c74dcb8120" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" dependencies = [ "cfg-if 1.0.0", "lazy_static", ] +[[package]] +name = "crowdloan-rewards-rpc" +version = "0.0.1" +dependencies = [ + "composable-support", + "composable-traits", + "crowdloan-rewards-runtime-api", + "frame-support", + "jsonrpc-core", + "jsonrpc-core-client", + "jsonrpc-derive", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-blockchain", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "crowdloan-rewards-runtime-api" +version = "0.0.1" +dependencies = [ + "composable-support", + "parity-scale-codec", + "sp-api", +] + [[package]] name = "crunchy" version = "0.2.2" @@ -1866,11 +1949,12 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-common" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d6b536309245c849479fba3da410962a43ed8e51c26b729208ec0ac2798d0" +checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" dependencies = [ "generic-array 0.14.5", + "typenum", ] [[package]] @@ -1909,7 +1993,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1a816186fa68d9e426e3cb4ae4dff1fcd8e4a2c34b781bf7a822574a0d0aac8" dependencies = [ - "sct", + "sct 0.6.1", ] [[package]] @@ -1919,7 +2003,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" dependencies = [ "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -1954,23 +2038,23 @@ dependencies = [ [[package]] name = "cumulus-client-cli" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ + "clap 3.1.6", "sc-cli", "sc-service", - "structopt", ] [[package]] name = "cumulus-client-collator" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "cumulus-client-consensus-common", "cumulus-client-network", "cumulus-primitives-core", "cumulus-relay-chain-interface", - "futures 0.3.19", + "futures 0.3.21", "parity-scale-codec", "parking_lot 0.10.2", "polkadot-node-primitives", @@ -1988,12 +2072,12 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-aura" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "async-trait", "cumulus-client-consensus-common", "cumulus-primitives-core", - "futures 0.3.19", + "futures 0.3.21", "parity-scale-codec", "sc-client-api", "sc-consensus", @@ -2017,12 +2101,12 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-common" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "async-trait", "cumulus-relay-chain-interface", "dyn-clone", - "futures 0.3.19", + "futures 0.3.21", "parity-scale-codec", "polkadot-primitives", "sc-client-api", @@ -2038,15 +2122,15 @@ dependencies = [ [[package]] name = "cumulus-client-network" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "async-trait", "cumulus-relay-chain-interface", "derive_more", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "polkadot-node-primitives", "polkadot-parachain", "polkadot-primitives", @@ -2063,18 +2147,18 @@ dependencies = [ [[package]] name = "cumulus-client-pov-recovery" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "cumulus-primitives-core", "cumulus-relay-chain-interface", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "parity-scale-codec", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-overseer", "polkadot-primitives", - "rand 0.8.4", + "rand 0.8.5", "sc-client-api", "sc-consensus", "sp-api", @@ -2087,7 +2171,7 @@ dependencies = [ [[package]] name = "cumulus-client-service" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "cumulus-client-collator", "cumulus-client-consensus-common", @@ -2095,7 +2179,7 @@ dependencies = [ "cumulus-primitives-core", "cumulus-relay-chain-interface", "parity-scale-codec", - "parking_lot 0.10.2", + "parking_lot 0.12.0", "polkadot-overseer", "polkadot-primitives", "sc-chain-spec", @@ -2116,7 +2200,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-aura-ext" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "frame-executive", "frame-support", @@ -2134,7 +2218,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-dmp-queue" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -2152,7 +2236,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-parachain-system" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "cumulus-pallet-parachain-system-proc-macro", "cumulus-primitives-core", @@ -2182,18 +2266,18 @@ dependencies = [ [[package]] name = "cumulus-pallet-parachain-system-proc-macro" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] name = "cumulus-pallet-session-benchmarking" version = "3.0.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "frame-benchmarking", "frame-support", @@ -2207,7 +2291,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcm" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -2224,7 +2308,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcmp-queue" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -2242,7 +2326,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-core" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "frame-support", "parity-scale-codec", @@ -2258,7 +2342,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-parachain-inherent" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -2281,7 +2365,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-timestamp" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "cumulus-primitives-core", "sp-inherents", @@ -2292,7 +2376,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-utility" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -2309,13 +2393,13 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-interface" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "async-trait", "cumulus-primitives-core", "derive_more", - "futures 0.3.19", - "parking_lot 0.11.2", + "futures 0.3.21", + "parking_lot 0.12.0", "polkadot-overseer", "sc-client-api", "sc-service", @@ -2330,14 +2414,14 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-local" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "async-trait", "cumulus-primitives-core", "cumulus-relay-chain-interface", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "polkadot-client", "polkadot-service", "sc-client-api", @@ -2358,7 +2442,7 @@ dependencies = [ [[package]] name = "cumulus-test-relay-sproof-builder" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "cumulus-primitives-core", "parity-scale-codec", @@ -2404,8 +2488,11 @@ checksum = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9" name = "dali-runtime" version = "0.1.0" dependencies = [ + "assets-runtime-api", "common", + "composable-support", "composable-traits", + "crowdloan-rewards-runtime-api", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -2438,12 +2525,15 @@ dependencies = [ "pallet-collective", "pallet-crowdloan-rewards", "pallet-currency-factory", + "pallet-curve-amm", "pallet-democracy 4.0.0-dev", "pallet-dutch-auction", "pallet-governance-registry", "pallet-identity", "pallet-indices", + "pallet-lending", "pallet-liquidations", + "pallet-liquidity-bootstrapping", "pallet-membership", "pallet-mosaic", "pallet-multisig", @@ -2457,6 +2547,7 @@ dependencies = [ "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", "pallet-treasury", + "pallet-uniswap-v2", "pallet-utility", "pallet-vault", "pallet-vesting 0.0.1", @@ -2518,7 +2609,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5bbed42daaa95e780b60a50546aa345b8413a1e46f9a40a12907d3598f038db" dependencies = [ "data-encoding", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -2539,7 +2630,7 @@ checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -2552,7 +2643,7 @@ dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", "rustc_version 0.4.0", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -2575,13 +2666,12 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b697d66081d42af4fba142d56918a3cb21dc8eb63372c6b85d14f44fb9c5979b" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" dependencies = [ - "block-buffer 0.10.0", + "block-buffer 0.10.2", "crypto-common", - "generic-array 0.14.5", ] [[package]] @@ -2693,7 +2783,7 @@ checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -2704,9 +2794,9 @@ checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf" [[package]] name = "ed25519" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74e1069e39f1454367eb2de793ed062fac4c35c2934b76a81d90dd9abcd28816" +checksum = "eed12bbf7b5312f8da1c2722bc06d8c6b12c2d86a7fb35a194c7f3e6fc2bbe39" dependencies = [ "signature", ] @@ -2742,14 +2832,14 @@ dependencies = [ [[package]] name = "enum-as-inner" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595" +checksum = "570d109b813e904becc80d8d5da38376818a143348413f7149f1340fe04754d4" dependencies = [ - "heck 0.3.3", + "heck 0.4.0", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -2775,7 +2865,7 @@ checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -2786,20 +2876,7 @@ checksum = "4e58b112d5099aa0857c5d05f0eacab86406dd8c0f85fe5d320a13256d29ecf4" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", -] - -[[package]] -name = "env_logger" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" -dependencies = [ - "atty", - "humantime 1.3.0", - "log 0.4.14", - "regex", - "termcolor", + "syn 1.0.88", ] [[package]] @@ -2809,7 +2886,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" dependencies = [ "atty", - "humantime 2.1.0", + "humantime", "log 0.4.14", "regex", "termcolor", @@ -2822,7 +2899,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" dependencies = [ "atty", - "humantime 2.1.0", + "humantime", "log 0.4.14", "regex", "termcolor", @@ -2834,6 +2911,15 @@ version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68b91989ae21441195d7d9b9993a2f9295c7e1a8c96255d8b729accddc124797" +[[package]] +name = "envy" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f47e0157f2cb54f5ae1bd371b30a2ae4311e1c028f575cd4e81de7353215965" +dependencies = [ + "serde", +] + [[package]] name = "errno" version = "0.2.8" @@ -2864,33 +2950,6 @@ dependencies = [ "version_check 0.9.4", ] -[[package]] -name = "ethbloom" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb684ac8fa8f6c5759f788862bb22ec6fe3cb392f6bfd08e3c64b603661e3f8" -dependencies = [ - "crunchy", - "fixed-hash", - "impl-rlp", - "impl-serde", - "tiny-keccak", -] - -[[package]] -name = "ethereum-types" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05136f7057fe789f06e6d41d07b34e6f70d8c86e5693b60f97aaa6553553bdaf" -dependencies = [ - "ethbloom", - "fixed-hash", - "impl-rlp", - "impl-serde", - "primitive-types", - "uint", -] - [[package]] name = "event-listener" version = "2.5.2" @@ -2903,7 +2962,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e43f2f1833d64e33f15592464d6fdd70f349dda7b1a53088eb83cd94014008c5" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", ] [[package]] @@ -2918,9 +2977,9 @@ dependencies = [ [[package]] name = "eyre" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc225d8f637923fe585089fcf03e705c222131232d2c1fb622e84ecf725d0eb8" +checksum = "9289ed2c0440a6536e65119725cf91fc2c6b5e513bfd2e36e1134d7cca6ca12f" dependencies = [ "indenter", "once_cell", @@ -2974,11 +3033,11 @@ dependencies = [ [[package]] name = "file-per-thread-logger" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fdbe0d94371f9ce939b555dd342d0686cc4c0cadbcd4b61d70af5ff97eb4126" +checksum = "21e16290574b39ee41c71aeb90ae960c504ebaf1e2a1c87bd52aa56ed6e1a02f" dependencies = [ - "env_logger 0.7.1", + "env_logger 0.9.0", "log 0.4.14", ] @@ -2989,7 +3048,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8ac3ff5224ef91f3c97e03eb1de2db82743427e91aaa5ac635f454f0b164f5a" dependencies = [ "either", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "log 0.4.14", "num-traits", @@ -3005,7 +3064,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" dependencies = [ "byteorder", - "rand 0.8.4", + "rand 0.8.5", "rustc-hex", "static_assertions", ] @@ -3084,7 +3143,7 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "fork-tree" version = "3.0.0" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "parity-scale-codec", ] @@ -3102,7 +3161,7 @@ dependencies = [ [[package]] name = "frame-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-support", "frame-system", @@ -3111,6 +3170,7 @@ dependencies = [ "parity-scale-codec", "paste 1.0.6", "scale-info", + "serde", "sp-api", "sp-application-crypto", "sp-io", @@ -3123,10 +3183,11 @@ dependencies = [ [[package]] name = "frame-benchmarking-cli" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "Inflector", "chrono", + "clap 3.1.6", "frame-benchmarking", "frame-support", "handlebars", @@ -3138,18 +3199,18 @@ dependencies = [ "sc-executor", "sc-service", "serde", + "serde_json", "sp-core", "sp-externalities", "sp-keystore", "sp-runtime", "sp-state-machine", - "structopt", ] [[package]] name = "frame-election-provider-support" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-support", "frame-system", @@ -3163,7 +3224,7 @@ dependencies = [ [[package]] name = "frame-executive" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-support", "frame-system", @@ -3191,7 +3252,7 @@ dependencies = [ [[package]] name = "frame-support" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "bitflags", "frame-metadata", @@ -3220,41 +3281,41 @@ dependencies = [ [[package]] name = "frame-support-procedural" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "Inflector", "frame-support-procedural-tools", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] name = "frame-support-procedural-tools" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-support-procedural-tools-derive", - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] name = "frame-support-procedural-tools-derive" version = "3.0.0" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] name = "frame-system" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-support", "log 0.4.14", @@ -3271,7 +3332,7 @@ dependencies = [ [[package]] name = "frame-system-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -3286,7 +3347,7 @@ dependencies = [ [[package]] name = "frame-system-rpc-runtime-api" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "parity-scale-codec", "sp-api", @@ -3295,7 +3356,7 @@ dependencies = [ [[package]] name = "frame-try-runtime" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-support", "sp-api", @@ -3326,9 +3387,9 @@ dependencies = [ [[package]] name = "fs-err" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ebd3504ad6116843b8375ad70df74e7bfe83cac77a1f3fe73200c844d43bfe0" +checksum = "5bd79fa345a495d3ae89fb7165fec01c0e72f41821d642dda363a1e97975652e" [[package]] name = "fs-swap" @@ -3388,9 +3449,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" dependencies = [ "futures-channel", "futures-core", @@ -3403,9 +3464,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" dependencies = [ "futures-core", "futures-sink", @@ -3413,15 +3474,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" [[package]] name = "futures-executor" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" dependencies = [ "futures-core", "futures-task", @@ -3431,9 +3492,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" [[package]] name = "futures-lite" @@ -3452,13 +3513,13 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -3468,21 +3529,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a1387e07917c711fb4ee4f48ea0adb04a3c9739e53ef85bf43ae1edc2937a8b" dependencies = [ "futures-io", - "rustls", - "webpki", + "rustls 0.19.1", + "webpki 0.21.4", ] [[package]] name = "futures-sink" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" [[package]] name = "futures-task" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" [[package]] name = "futures-timer" @@ -3492,9 +3553,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" dependencies = [ "futures 0.1.31", "futures-channel", @@ -3543,9 +3604,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" +checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" dependencies = [ "cfg-if 1.0.0", "libc", @@ -3626,9 +3687,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e" +checksum = "62eeb471aa3e3c9197aa4bfeabfe02982f6dc96f750486c0bb0009ac58b26d2b" dependencies = [ "bytes 1.1.0", "fnv", @@ -3645,9 +3706,9 @@ dependencies = [ [[package]] name = "handlebars" -version = "4.2.1" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25546a65e5cf1f471f3438796fc634650b31d7fcde01d444c309aeb28b92e3a8" +checksum = "99d6a30320f094710245150395bc763ad23128d6a1ebbad7594dc4164b62c56b" dependencies = [ "log 0.4.14", "pest", @@ -3692,9 +3753,9 @@ dependencies = [ [[package]] name = "headers" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c84c647447a07ca16f5fbd05b633e535cc41a08d2d74ab1e08648df53be9cb89" +checksum = "4cff78e5788be1e0ab65b04d306b2ed5092c815ec97ec70f4ebd5aee158aa55d" dependencies = [ "base64 0.13.0", "bitflags", @@ -3703,7 +3764,7 @@ dependencies = [ "http", "httpdate", "mime 0.3.16", - "sha-1 0.9.8", + "sha-1 0.10.0", ] [[package]] @@ -3878,9 +3939,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" +checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" [[package]] name = "httpdate" @@ -3888,15 +3949,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" -[[package]] -name = "humantime" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -dependencies = [ - "quick-error 1.2.3", -] - [[package]] name = "humantime" version = "2.1.0" @@ -3924,9 +3976,9 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.16" +version = "0.14.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" +checksum = "043f0e083e9901b6cc658a77d1eb86f4fc650bbb977a4337dd63192826aa85dd" dependencies = [ "bytes 1.1.0", "futures-channel", @@ -3937,7 +3989,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 0.4.8", + "itoa 1.0.1", "pin-project-lite 0.2.8", "socket2 0.4.4", "tokio", @@ -3954,13 +4006,29 @@ checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64" dependencies = [ "ct-logs", "futures-util", - "hyper 0.14.16", + "hyper 0.14.17", "log 0.4.14", - "rustls", - "rustls-native-certs", + "rustls 0.19.1", + "rustls-native-certs 0.5.0", "tokio", - "tokio-rustls", - "webpki", + "tokio-rustls 0.22.0", + "webpki 0.21.4", +] + +[[package]] +name = "hyper-rustls" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" +dependencies = [ + "http", + "hyper 0.14.17", + "log 0.4.14", + "rustls 0.20.4", + "rustls-native-certs 0.6.1", + "tokio", + "tokio-rustls 0.23.2", + "webpki-roots 0.22.2", ] [[package]] @@ -3970,7 +4038,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes 1.1.0", - "hyper 0.14.16", + "hyper 0.14.17", "native-tls", "tokio", "tokio-native-tls", @@ -4026,7 +4094,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae8ab7f67bad3240049cb24fb9cb0b4c2c6af4c245840917fbbdededeee91179" dependencies = [ "async-io", - "futures 0.3.19", + "futures 0.3.21", "futures-lite", "if-addrs", "ipnet", @@ -4060,15 +4128,6 @@ dependencies = [ "parity-scale-codec", ] -[[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-serde" version = "0.3.2" @@ -4080,13 +4139,13 @@ dependencies = [ [[package]] name = "impl-trait-for-tuples" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5dacb10c5b3bb92d46ba347505a9041e676bb20ad220101326bffb0c93031ee" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -4101,7 +4160,7 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "hashbrown 0.11.2", "serde", ] @@ -4123,9 +4182,9 @@ dependencies = [ [[package]] name = "integer-encoding" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90c11140ffea82edce8dcd74137ce9324ec24b3cf0175fc9d7e29164da9915b8" +checksum = "0e85a1509a128c855368e135cffcde7eac17d8e1083f41e2b98c58bc1a5074be" [[package]] name = "integer-sqrt" @@ -4174,9 +4233,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" +checksum = "35e70ee094dc02fd9c13fdad4940090f22dbd6ac7c9e7094a46cf0232a50bc7c" [[package]] name = "is_sorted" @@ -4236,8 +4295,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a" dependencies = [ "derive_more", - "futures 0.3.19", - "hyper 0.14.16", + "futures 0.3.21", + "hyper 0.14.17", "hyper-tls", "jsonrpc-core", "jsonrpc-pubsub", @@ -4255,7 +4314,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "futures-executor", "futures-util", "log 0.4.14", @@ -4270,7 +4329,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b51da17abecbdab3e3d4f26b01c5ec075e88d3abe3ab3b05dc9aa69392764ec0" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-client-transports", ] @@ -4283,7 +4342,7 @@ dependencies = [ "proc-macro-crate 0.1.5", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -4292,8 +4351,8 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff" dependencies = [ - "futures 0.3.19", - "hyper 0.14.16", + "futures 0.3.21", + "hyper 0.14.17", "jsonrpc-core", "jsonrpc-server-utils", "log 0.4.14", @@ -4308,7 +4367,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "382bb0206323ca7cda3dcd7e245cea86d37d02457a02a975e3378fb149a48845" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-server-utils", "log 0.4.14", @@ -4323,7 +4382,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240f87695e6c6f62fb37f05c02c04953cf68d6408b8c1c89de85c7a0125b1011" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "lazy_static", "log 0.4.14", @@ -4339,7 +4398,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" dependencies = [ "bytes 1.1.0", - "futures 0.3.19", + "futures 0.3.21", "globset", "jsonrpc-core", "lazy_static", @@ -4356,7 +4415,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f892c7d766369475ab7b0669f417906302d7c0fb521285c0a0c92e52e7c8e946" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-server-utils", "log 0.4.14", @@ -4371,23 +4430,140 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6373a33d987866ccfe1af4bc11b089dce941764313f9fd8b7cf13fcb51b72dc5" dependencies = [ - "jsonrpsee-proc-macros", - "jsonrpsee-types", + "jsonrpsee-types 0.4.1", "jsonrpsee-utils", - "jsonrpsee-ws-client", + "jsonrpsee-ws-client 0.4.1", +] + +[[package]] +name = "jsonrpsee" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05fd8cd6c6b1bbd06881d2cf88f1fc83cc36c98f2219090f839115fb4a956cb9" +dependencies = [ + "jsonrpsee-core 0.8.0", + "jsonrpsee-proc-macros 0.8.0", + "jsonrpsee-types 0.8.0", + "jsonrpsee-ws-client 0.8.0", +] + +[[package]] +name = "jsonrpsee" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d0b8cc1959f8c05256ace093b2317482da9127f1d9227564f47e7e6bf9bda8" +dependencies = [ + "jsonrpsee-core 0.9.0", + "jsonrpsee-http-client", + "jsonrpsee-proc-macros 0.9.0", + "jsonrpsee-types 0.9.0", +] + +[[package]] +name = "jsonrpsee-client-transport" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3303cdf246e6ab76e2866fb3d9acb6c76a068b1b28bd923a1b7a8122257ad7b5" +dependencies = [ + "futures 0.3.21", + "http", + "jsonrpsee-core 0.8.0", + "jsonrpsee-types 0.8.0", + "pin-project 1.0.10", + "rustls-native-certs 0.6.1", + "soketto", + "thiserror", + "tokio", + "tokio-rustls 0.23.2", + "tokio-util", + "tracing", + "webpki-roots 0.22.2", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f220b5a238dc7992b90f1144fbf6eaa585872c9376afe6fe6863ffead6191bf3" +dependencies = [ + "anyhow", + "arrayvec 0.7.2", + "async-trait", + "beef", + "futures-channel", + "futures-util", + "hyper 0.14.17", + "jsonrpsee-types 0.8.0", + "rustc-hash", + "serde", + "serde_json", + "soketto", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22abc3274b265dcefe2e26c4beecf9fda4fffa48cf94930443a6c73678f020d5" +dependencies = [ + "anyhow", + "arrayvec 0.7.2", + "async-trait", + "beef", + "futures-channel", + "futures-util", + "hyper 0.14.17", + "jsonrpsee-types 0.9.0", + "serde", + "serde_json", + "soketto", + "thiserror", +] + +[[package]] +name = "jsonrpsee-http-client" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d31b837273d09dd80051eefa57d337769dff6c3266108c43a3544ac7ffed9d68" +dependencies = [ + "async-trait", + "hyper 0.14.17", + "hyper-rustls 0.23.0", + "jsonrpsee-core 0.9.0", + "jsonrpsee-types 0.9.0", + "rustc-hash", + "serde", + "serde_json", + "thiserror", + "tokio", + "tracing", ] [[package]] name = "jsonrpsee-proc-macros" -version = "0.4.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d802063f7a3c867456955f9d2f15eb3ee0edb5ec9ec2b5526324756759221c0f" +checksum = "4299ebf790ea9de1cb72e73ff2ae44c723ef264299e5e2d5ef46a371eb3ac3d8" dependencies = [ - "log 0.4.14", - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", +] + +[[package]] +name = "jsonrpsee-proc-macros" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e171d8071079c8ccdce1b4ab34411c5afa6158d57db7963311ad3c6d073cb1" +dependencies = [ + "proc-macro-crate 1.1.3", + "proc-macro2 1.0.36", + "quote 1.0.15", + "syn 1.0.88", ] [[package]] @@ -4399,14 +4575,42 @@ dependencies = [ "anyhow", "async-trait", "beef", - "futures-channel", - "futures-util", - "hyper 0.14.16", - "log 0.4.14", + "futures-channel", + "futures-util", + "hyper 0.14.17", + "log 0.4.14", + "serde", + "serde_json", + "soketto", + "thiserror", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b3f601bbbe45cd63f5407b6f7d7950e08a7d4f82aa699ff41a4a5e9e54df58" +dependencies = [ + "anyhow", + "beef", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f4c45d2e2aa1db4c7d7d7dbaabc10a5b5258d99cd9d42fbfd5260b76f80c324" +dependencies = [ + "anyhow", + "beef", "serde", "serde_json", - "soketto", "thiserror", + "tracing", ] [[package]] @@ -4417,7 +4621,7 @@ checksum = "0109c4f972058f3b1925b73a17210aff7b63b65967264d0045d15ee88fe84f0c" dependencies = [ "arrayvec 0.7.2", "beef", - "jsonrpsee-types", + "jsonrpsee-types 0.4.1", ] [[package]] @@ -4429,21 +4633,32 @@ dependencies = [ "arrayvec 0.7.2", "async-trait", "fnv", - "futures 0.3.19", + "futures 0.3.21", "http", - "jsonrpsee-types", + "jsonrpsee-types 0.4.1", "log 0.4.14", "pin-project 1.0.10", - "rustls-native-certs", + "rustls-native-certs 0.5.0", "serde", "serde_json", "soketto", "thiserror", "tokio", - "tokio-rustls", + "tokio-rustls 0.22.0", "tokio-util", ] +[[package]] +name = "jsonrpsee-ws-client" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aff425cee7c779e33920913bc695447416078ee6d119f443f3060feffa4e86b5" +dependencies = [ + "jsonrpsee-client-transport", + "jsonrpsee-core 0.8.0", + "jsonrpsee-types 0.8.0", +] + [[package]] name = "keccak" version = "0.1.0" @@ -4462,8 +4677,8 @@ dependencies = [ [[package]] name = "kusama-runtime" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "beefy-primitives", "bitvec", @@ -4550,8 +4765,8 @@ dependencies = [ [[package]] name = "kusama-runtime-constants" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "frame-support", "polkadot-primitives", @@ -4628,9 +4843,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.117" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c" +checksum = "ad5c14e80759d0939d013e6ca49930e59fc53dd8e5009132f76240c179380c09" [[package]] name = "libloading" @@ -4654,9 +4869,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" +checksum = "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db" [[package]] name = "libp2p" @@ -4666,7 +4881,7 @@ checksum = "3bec54343492ba5940a6c555e512c6721139835d28c59bc22febece72dfd0d9d" dependencies = [ "atomic", "bytes 1.1.0", - "futures 0.3.19", + "futures 0.3.21", "lazy_static", "libp2p-core", "libp2p-deflate", @@ -4701,17 +4916,18 @@ dependencies = [ [[package]] name = "libp2p-core" -version = "0.30.0" +version = "0.30.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef22d9bba1e8bcb7ec300073e6802943fe8abb8190431842262b5f1c30abba1" +checksum = "86aad7d54df283db817becded03e611137698a6509d4237a96881976a162340c" dependencies = [ "asn1_der", "bs58", "ed25519-dalek", "either", "fnv", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", + "instant", "lazy_static", "libsecp256k1", "log 0.4.14", @@ -4722,7 +4938,7 @@ dependencies = [ "pin-project 1.0.10", "prost", "prost-build", - "rand 0.8.4", + "rand 0.8.5", "ring", "rw-stream-sink", "sha2 0.9.9", @@ -4740,7 +4956,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51a800adb195f33de63f4b17b63fe64cfc23bf2c6a0d3d0d5321328664e65197" dependencies = [ "flate2", - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", ] @@ -4751,7 +4967,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb8f89d15cb6e3c5bc22afff7513b11bab7856f2872d3cfba86f7f63a06bc498" dependencies = [ "async-std-resolver", - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "log 0.4.14", "smallvec 1.8.0", @@ -4766,7 +4982,7 @@ checksum = "aab3d7210901ea51b7bae2b581aa34521797af8c4ec738c980bda4a06434067f" dependencies = [ "cuckoofilter", "fnv", - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log 0.4.14", @@ -4787,7 +5003,7 @@ dependencies = [ "byteorder", "bytes 1.1.0", "fnv", - "futures 0.3.19", + "futures 0.3.21", "hex_fmt", "libp2p-core", "libp2p-swarm", @@ -4808,7 +5024,7 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cca1275574183f288ff8b72d535d5ffa5ea9292ef7829af8b47dcb197c7b0dcd" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log 0.4.14", @@ -4830,7 +5046,7 @@ dependencies = [ "bytes 1.1.0", "either", "fnv", - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log 0.4.14", @@ -4854,13 +5070,13 @@ dependencies = [ "async-io", "data-encoding", "dns-parser", - "futures 0.3.19", + "futures 0.3.21", "if-watch", "lazy_static", "libp2p-core", "libp2p-swarm", "log 0.4.14", - "rand 0.8.4", + "rand 0.8.5", "smallvec 1.8.0", "socket2 0.4.4", "void", @@ -4888,7 +5104,7 @@ checksum = "7f2cd64ef597f40e14bfce0497f50ecb63dd6d201c61796daeb4227078834fbf" dependencies = [ "asynchronous-codec 0.6.0", "bytes 1.1.0", - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "log 0.4.14", "nohash-hasher", @@ -4906,13 +5122,13 @@ checksum = "a8772c7a99088221bb7ca9c5c0574bf55046a7ab4c319f3619b275f28c8fb87a" dependencies = [ "bytes 1.1.0", "curve25519-dalek 3.2.0", - "futures 0.3.19", + "futures 0.3.21", "lazy_static", "libp2p-core", "log 0.4.14", "prost", "prost-build", - "rand 0.8.4", + "rand 0.8.5", "sha2 0.9.9", "snow", "static_assertions", @@ -4926,7 +5142,7 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80ef7b0ec5cf06530d9eb6cf59ae49d46a2c45663bde31c25a12f682664adbcf" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log 0.4.14", @@ -4943,7 +5159,7 @@ checksum = "5fba1a6ff33e4a274c89a3b1d78b9f34f32af13265cc5c46c16938262d4e945a" dependencies = [ "asynchronous-codec 0.6.0", "bytes 1.1.0", - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "log 0.4.14", "prost", @@ -4958,7 +5174,7 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f1a458bbda880107b5b36fcb9b5a1ef0c329685da0e203ed692a8ebe64cc92c" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "log 0.4.14", "pin-project 1.0.10", "rand 0.7.3", @@ -4974,7 +5190,7 @@ checksum = "2852b61c90fa8ce3c8fcc2aba76e6cefc20d648f9df29157d6b3a916278ef3e3" dependencies = [ "asynchronous-codec 0.6.0", "bytes 1.1.0", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "libp2p-core", "libp2p-swarm", @@ -4997,13 +5213,13 @@ checksum = "14a6d2b9e7677eff61dc3d2854876aaf3976d84a01ef6664b610c77a0c9407c5" dependencies = [ "asynchronous-codec 0.6.0", "bimap", - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log 0.4.14", "prost", "prost-build", - "rand 0.8.4", + "rand 0.8.5", "sha2 0.9.9", "thiserror", "unsigned-varint 0.7.1", @@ -5019,11 +5235,11 @@ checksum = "a877a4ced6d46bf84677e1974e8cf61fb434af73b2e96fb48d6cb6223a4634d8" dependencies = [ "async-trait", "bytes 1.1.0", - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log 0.4.14", - "lru 0.7.2", + "lru 0.7.3", "rand 0.7.3", "smallvec 1.8.0", "unsigned-varint 0.7.1", @@ -5037,7 +5253,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f5184a508f223bc100a12665517773fb8730e9f36fc09eefb670bf01b107ae9" dependencies = [ "either", - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "log 0.4.14", "rand 0.7.3", @@ -5053,7 +5269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "072c290f727d39bdc4e9d6d1c847978693d25a673bd757813681e33e5f6c00c2" dependencies = [ "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -5063,7 +5279,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7399c5b6361ef525d41c11fcf51635724f832baf5819b30d3d873eabb4fbae4b" dependencies = [ "async-io", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "if-watch", "ipnet", @@ -5080,7 +5296,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8b7563e46218165dfd60f64b96f7ce84590d75f53ecbdc74a7dd01450dc5973" dependencies = [ "async-std", - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "log 0.4.14", ] @@ -5091,7 +5307,7 @@ version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1008a302b73c5020251f9708c653f5ed08368e530e247cc9cd2f109ff30042cf" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "js-sys", "libp2p-core", "parity-send-wrapper", @@ -5106,7 +5322,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22e12df82d1ed64969371a9e65ea92b91064658604cc2576c2757f18ead9a1cf" dependencies = [ "either", - "futures 0.3.19", + "futures 0.3.21", "futures-rustls", "libp2p-core", "log 0.4.14", @@ -5114,7 +5330,7 @@ dependencies = [ "rw-stream-sink", "soketto", "url 2.2.2", - "webpki-roots", + "webpki-roots 0.21.1", ] [[package]] @@ -5123,7 +5339,7 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e7362abb8867d7187e7e93df17f460d554c997fc5c8ac57dc1259057f6889af" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "libp2p-core", "parking_lot 0.11.2", "thiserror", @@ -5155,7 +5371,7 @@ dependencies = [ "libsecp256k1-core", "libsecp256k1-gen-ecmult", "libsecp256k1-gen-genmult", - "rand 0.8.4", + "rand 0.8.5", "serde", "sha2 0.9.9", "typenum", @@ -5192,9 +5408,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66" +checksum = "6f35facd4a5673cb5a48822be2be1d4236c1c99cb4113cab7061ac720d5bf859" dependencies = [ "cc", "pkg-config", @@ -5250,6 +5466,89 @@ dependencies = [ "paste 0.1.18", ] +[[package]] +name = "local-integration-tests" +version = "0.1.0" +dependencies = [ + "common", + "composable-traits", + "cumulus-pallet-aura-ext", + "cumulus-pallet-dmp-queue", + "cumulus-pallet-parachain-system", + "cumulus-pallet-session-benchmarking", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-core", + "cumulus-primitives-timestamp", + "cumulus-primitives-utility", + "dali-runtime", + "env_logger 0.9.0", + "frame-benchmarking", + "frame-executive", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "hex-literal", + "kusama-runtime", + "num-traits", + "orml-tokens", + "orml-traits", + "orml-xtokens", + "pallet-assets", + "pallet-assets-registry", + "pallet-aura", + "pallet-authorship", + "pallet-balances", + "pallet-call-filter", + "pallet-collator-selection", + "pallet-collective", + "pallet-currency-factory", + "pallet-democracy 4.0.0-dev", + "pallet-governance-registry", + "pallet-indices", + "pallet-membership", + "pallet-oracle", + "pallet-randomness-collective-flip", + "pallet-scheduler", + "pallet-session", + "pallet-sudo", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-treasury", + "pallet-utility", + "pallet-vault", + "pallet-xcm", + "parachain-info", + "parity-scale-codec", + "paste 1.0.6", + "picasso-runtime", + "polkadot-core-primitives", + "polkadot-parachain", + "polkadot-primitives", + "polkadot-runtime-parachains", + "primitives", + "scale-info", + "smallvec 1.8.0", + "sp-api", + "sp-block-builder", + "sp-consensus-aura", + "sp-core", + "sp-inherents", + "sp-io", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-std", + "sp-transaction-pool", + "sp-version", + "xcm", + "xcm-builder", + "xcm-emulator", + "xcm-executor", +] + [[package]] name = "lock_api" version = "0.3.4" @@ -5298,9 +5597,9 @@ dependencies = [ [[package]] name = "lru" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "274353858935c992b13c0ca408752e2121da852d07dec7ce5f108c77dfa14d1f" +checksum = "fcb87f3080f6d1d69e8c564c0fcfde1d7aa8cc451ce40cae89479111f03bc0eb" dependencies = [ "hashbrown 0.11.2", ] @@ -5316,9 +5615,9 @@ dependencies = [ [[package]] name = "lz4" -version = "1.23.2" +version = "1.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac20ed6991e01bf6a2e68cc73df2b389707403662a8ba89f68511fb340f724c" +checksum = "4edcb94251b1c375c459e5abe9fb0168c1c826c3370172684844f8f3f8d1a885" dependencies = [ "libc", "lz4-sys", @@ -5326,9 +5625,9 @@ dependencies = [ [[package]] name = "lz4-sys" -version = "1.9.2" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca79aa95d8b3226213ad454d328369853be3a1382d89532a854f4d69640acae" +checksum = "d7be8908e2ed6f31c02db8a9fa962f03e36c53fbfde437363eae3306b85d7e17" dependencies = [ "cc", "libc", @@ -5402,9 +5701,9 @@ dependencies = [ [[package]] name = "memmap2" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe3179b85e1fd8b14447cbebadb75e45a1002f541b925f0bfec366d56a81c56d" +checksum = "057a3db23999c867821a7a59feb06a578fcb03685e983dff90daf9e7d24ac08f" dependencies = [ "libc", ] @@ -5415,7 +5714,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", ] [[package]] @@ -5458,11 +5757,11 @@ dependencies = [ [[package]] name = "metered-channel" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "derive_more", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "thiserror", "tracing", @@ -5470,12 +5769,12 @@ dependencies = [ [[package]] name = "mick-jaeger" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd2c2cc134e57461f0898b0e921f0a7819b5e3f3a4335b9aa390ce81a5f36fb9" +checksum = "69672161530e8aeca1d1400fbf3f1a1747ff60ea604265a4e906c2442df20532" dependencies = [ - "futures 0.3.19", - "rand 0.8.4", + "futures 0.3.21", + "rand 0.8.5", "thrift", ] @@ -5496,9 +5795,9 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "mime_guess" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" dependencies = [ "mime 0.3.16", "unicase 2.6.0", @@ -5526,7 +5825,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" dependencies = [ "adler", - "autocfg 1.0.1", + "autocfg 1.1.0", ] [[package]] @@ -5550,14 +5849,15 @@ dependencies = [ [[package]] name = "mio" -version = "0.7.14" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +checksum = "7ba42135c6a5917b9db9cd7b293e5409e1c6b041e6f9825e92e55a894c63b6f8" dependencies = [ "libc", "log 0.4.14", "miow 0.3.7", "ntapi", + "wasi 0.11.0+wasi-snapshot-preview1", "winapi 0.3.9", ] @@ -5665,11 +5965,11 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "424f6e86263cd5294cbd7f1e95746b95aca0e0d66bff31e5a40d6baa87b4aa99" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro-error", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", "synstructure", ] @@ -5691,7 +5991,7 @@ dependencies = [ "mime 0.3.16", "mime_guess", "quick-error 1.2.3", - "rand 0.8.4", + "rand 0.8.5", "safemem", "tempfile", "twoway", @@ -5704,7 +6004,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56a336acba8bc87c8876f6425407dbbe6c417bf478b22015f8fb0994ef3bc0ab" dependencies = [ "bytes 1.1.0", - "futures 0.3.19", + "futures 0.3.21", "log 0.4.14", "pin-project 1.0.10", "smallvec 1.8.0", @@ -5723,7 +6023,7 @@ dependencies = [ "num-complex", "num-rational 0.4.0", "num-traits", - "rand 0.8.4", + "rand 0.8.5", "rand_distr", "simba", "typenum", @@ -5737,7 +6037,7 @@ checksum = "01fcc0b8149b4632adc89ac3b7b31a12fb6099a0317a4eb2ebff574ef7de7218" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -5746,7 +6046,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10a8690bf09abf659851e58cd666c3d37ac6af07c2bd7a9e332cfba471715775" dependencies = [ - "rand 0.8.4", + "rand 0.8.5", ] [[package]] @@ -5792,20 +6092,19 @@ checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" [[package]] name = "nom" -version = "7.1.0" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" dependencies = [ "memchr", "minimal-lexical", - "version_check 0.9.4", ] [[package]] name = "ntapi" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" dependencies = [ "winapi 0.3.9", ] @@ -5816,7 +6115,7 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "num-integer", "num-traits", ] @@ -5836,7 +6135,7 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "num-traits", ] @@ -5846,7 +6145,7 @@ version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "num-integer", "num-traits", ] @@ -5857,7 +6156,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "num-bigint", "num-integer", "num-traits", @@ -5869,7 +6168,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "num-integer", "num-traits", ] @@ -5880,7 +6179,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "num-integer", "num-traits", ] @@ -5891,7 +6190,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "libm", ] @@ -5918,9 +6217,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" +checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" [[package]] name = "opaque-debug" @@ -5954,7 +6253,7 @@ checksum = "a15c83b586f00268c619c1cb3340ec1a6f59dd9ba1d9833a273a68e6d5cd8ffc" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -5983,7 +6282,7 @@ version = "0.9.72" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "cc", "libc", "pkg-config", @@ -6002,7 +6301,7 @@ dependencies = [ [[package]] name = "orml-tokens" version = "0.4.1-dev" -source = "git+https://github.com/open-web3-stack/open-runtime-module-library?rev=2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6#2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?rev=9e041dc9d213f843b18b3008f32f3acabb287dcb#9e041dc9d213f843b18b3008f32f3acabb287dcb" dependencies = [ "frame-support", "frame-system", @@ -6017,7 +6316,7 @@ dependencies = [ [[package]] name = "orml-traits" version = "0.4.1-dev" -source = "git+https://github.com/open-web3-stack/open-runtime-module-library?rev=2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6#2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?rev=9e041dc9d213f843b18b3008f32f3acabb287dcb#9e041dc9d213f843b18b3008f32f3acabb287dcb" dependencies = [ "frame-support", "impl-trait-for-tuples", @@ -6035,7 +6334,7 @@ dependencies = [ [[package]] name = "orml-unknown-tokens" version = "0.4.1-dev" -source = "git+https://github.com/open-web3-stack/open-runtime-module-library?rev=2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6#2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?rev=9e041dc9d213f843b18b3008f32f3acabb287dcb#9e041dc9d213f843b18b3008f32f3acabb287dcb" dependencies = [ "frame-support", "frame-system", @@ -6050,7 +6349,7 @@ dependencies = [ [[package]] name = "orml-utilities" version = "0.4.1-dev" -source = "git+https://github.com/open-web3-stack/open-runtime-module-library?rev=2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6#2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?rev=9e041dc9d213f843b18b3008f32f3acabb287dcb#9e041dc9d213f843b18b3008f32f3acabb287dcb" dependencies = [ "frame-support", "parity-scale-codec", @@ -6064,7 +6363,7 @@ dependencies = [ [[package]] name = "orml-xcm-support" version = "0.4.1-dev" -source = "git+https://github.com/open-web3-stack/open-runtime-module-library?rev=2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6#2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?rev=9e041dc9d213f843b18b3008f32f3acabb287dcb#9e041dc9d213f843b18b3008f32f3acabb287dcb" dependencies = [ "frame-support", "orml-traits", @@ -6078,7 +6377,7 @@ dependencies = [ [[package]] name = "orml-xtokens" version = "0.4.1-dev" -source = "git+https://github.com/open-web3-stack/open-runtime-module-library?rev=2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6#2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?rev=9e041dc9d213f843b18b3008f32f3acabb287dcb#9e041dc9d213f843b18b3008f32f3acabb287dcb" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -6134,8 +6433,9 @@ dependencies = [ "pallet-balances", "pallet-governance-registry", "parity-scale-codec", - "proptest 0.9.6", + "proptest", "scale-info", + "sp-api", "sp-arithmetic", "sp-core", "sp-io", @@ -6165,7 +6465,7 @@ dependencies = [ [[package]] name = "pallet-aura" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-support", "frame-system", @@ -6181,7 +6481,7 @@ dependencies = [ [[package]] name = "pallet-authority-discovery" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-support", "frame-system", @@ -6197,7 +6497,7 @@ dependencies = [ [[package]] name = "pallet-authorship" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-support", "frame-system", @@ -6212,7 +6512,7 @@ dependencies = [ [[package]] name = "pallet-babe" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -6236,7 +6536,7 @@ dependencies = [ [[package]] name = "pallet-bags-list" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -6256,7 +6556,7 @@ dependencies = [ [[package]] name = "pallet-balances" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -6271,7 +6571,7 @@ dependencies = [ [[package]] name = "pallet-beefy" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "beefy-primitives", "frame-support", @@ -6287,7 +6587,7 @@ dependencies = [ [[package]] name = "pallet-beefy-mmr" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "beefy-merkle-tree", "beefy-primitives", @@ -6313,6 +6613,7 @@ dependencies = [ name = "pallet-bonded-finance" version = "0.0.1" dependencies = [ + "composable-support", "composable-tests-helpers", "composable-traits", "frame-benchmarking", @@ -6320,9 +6621,10 @@ dependencies = [ "frame-system", "orml-tokens", "orml-traits", + "pallet-timestamp", "pallet-vesting 0.0.1", "parity-scale-codec", - "proptest 1.0.0", + "proptest", "proptest-derive", "scale-info", "serde", @@ -6336,7 +6638,7 @@ dependencies = [ [[package]] name = "pallet-bounties" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -6354,7 +6656,7 @@ dependencies = [ [[package]] name = "pallet-bridge-dispatch" version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "bp-message-dispatch", "bp-runtime", @@ -6371,7 +6673,7 @@ dependencies = [ [[package]] name = "pallet-bridge-grandpa" version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "bp-header-chain", "bp-runtime", @@ -6393,7 +6695,7 @@ dependencies = [ [[package]] name = "pallet-bridge-messages" version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "bitvec", "bp-message-dispatch", @@ -6432,7 +6734,7 @@ dependencies = [ [[package]] name = "pallet-collator-selection" version = "3.0.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "frame-benchmarking", "frame-support", @@ -6441,7 +6743,7 @@ dependencies = [ "pallet-authorship", "pallet-session", "parity-scale-codec", - "rand 0.7.3", + "rand 0.8.5", "scale-info", "serde", "sp-runtime", @@ -6452,7 +6754,7 @@ dependencies = [ [[package]] name = "pallet-collective" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -6470,6 +6772,7 @@ dependencies = [ name = "pallet-crowdloan-rewards" version = "0.0.1" dependencies = [ + "composable-traits", "frame-benchmarking", "frame-support", "frame-system", @@ -6477,6 +6780,7 @@ dependencies = [ "hex-literal", "libsecp256k1", "pallet-balances", + "pallet-timestamp", "parity-scale-codec", "rustc-hex", "scale-info", @@ -6501,7 +6805,7 @@ dependencies = [ "frame-system", "pallet-balances", "parity-scale-codec", - "proptest 0.9.6", + "proptest", "scale-info", "sp-arithmetic", "sp-core", @@ -6514,6 +6818,7 @@ dependencies = [ name = "pallet-curve-amm" version = "0.0.1" dependencies = [ + "composable-tests-helpers", "composable-traits", "frame-benchmarking", "frame-support", @@ -6522,13 +6827,12 @@ dependencies = [ "num-traits", "orml-tokens", "orml-traits", - "pallet-balances", "pallet-currency-factory", "pallet-oracle", "pallet-vault", "parity-scale-codec", "plotters", - "proptest 0.9.6", + "proptest", "scale-info", "serde", "sp-arithmetic", @@ -6564,7 +6868,7 @@ dependencies = [ [[package]] name = "pallet-democracy" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -6581,6 +6885,7 @@ dependencies = [ name = "pallet-dex-router" version = "0.0.1" dependencies = [ + "composable-tests-helpers", "composable-traits", "frame-support", "frame-system", @@ -6618,7 +6923,7 @@ dependencies = [ "pallet-currency-factory", "pallet-timestamp", "parity-scale-codec", - "proptest 1.0.0", + "proptest", "scale-info", "serde", "smallvec 1.8.0", @@ -6632,7 +6937,7 @@ dependencies = [ [[package]] name = "pallet-election-provider-multi-phase" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -6649,14 +6954,13 @@ dependencies = [ "sp-runtime", "sp-std", "static_assertions", - "strum 0.22.0", - "strum_macros 0.23.1", + "strum", ] [[package]] name = "pallet-elections-phragmen" version = "5.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.16#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -6674,7 +6978,7 @@ dependencies = [ [[package]] name = "pallet-gilt" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -6707,7 +7011,7 @@ dependencies = [ [[package]] name = "pallet-grandpa" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -6730,7 +7034,7 @@ dependencies = [ [[package]] name = "pallet-identity" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "enumflags2", "frame-benchmarking", @@ -6746,7 +7050,7 @@ dependencies = [ [[package]] name = "pallet-im-online" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -6766,7 +7070,7 @@ dependencies = [ [[package]] name = "pallet-indices" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -6806,7 +7110,7 @@ dependencies = [ "pallet-vault", "parity-scale-codec", "plotters", - "proptest 0.9.6", + "proptest", "scale-info", "serde", "smallvec 1.8.0", @@ -6836,7 +7140,7 @@ dependencies = [ "pallet-dutch-auction", "pallet-timestamp", "parity-scale-codec", - "proptest 1.0.0", + "proptest", "scale-info", "smallvec 1.8.0", "sp-arithmetic", @@ -6846,10 +7150,36 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-liquidity-bootstrapping" +version = "0.0.1" +dependencies = [ + "composable-maths", + "composable-support", + "composable-tests-helpers", + "composable-traits", + "frame-benchmarking", + "frame-support", + "frame-system", + "orml-tokens", + "orml-traits", + "pallet-currency-factory", + "parity-scale-codec", + "plotters", + "proptest", + "rust_decimal", + "scale-info", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-membership" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -6866,7 +7196,7 @@ dependencies = [ [[package]] name = "pallet-mmr" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "ckb-merkle-mountain-range", "frame-benchmarking", @@ -6884,7 +7214,7 @@ dependencies = [ [[package]] name = "pallet-mmr-primitives" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-support", "frame-system", @@ -6900,7 +7230,7 @@ dependencies = [ [[package]] name = "pallet-mmr-rpc" version = "3.0.0" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "jsonrpc-core", "jsonrpc-core-client", @@ -6918,6 +7248,7 @@ dependencies = [ name = "pallet-mosaic" version = "0.1.0" dependencies = [ + "composable-support", "composable-tests-helpers", "composable-traits", "frame-benchmarking", @@ -6929,7 +7260,7 @@ dependencies = [ "orml-traits", "parity-scale-codec", "plotters", - "proptest 0.9.6", + "proptest", "scale-info", "sp-core", "sp-io", @@ -6941,7 +7272,7 @@ dependencies = [ [[package]] name = "pallet-multisig" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -6956,7 +7287,7 @@ dependencies = [ [[package]] name = "pallet-nicks" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-support", "frame-system", @@ -6970,7 +7301,7 @@ dependencies = [ [[package]] name = "pallet-offences" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-support", "frame-system", @@ -6987,7 +7318,7 @@ dependencies = [ [[package]] name = "pallet-offences-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -7011,6 +7342,7 @@ dependencies = [ name = "pallet-oracle" version = "1.0.0" dependencies = [ + "composable-support", "composable-traits", "frame-benchmarking", "frame-support", @@ -7030,6 +7362,32 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-pablo" +version = "0.0.1" +dependencies = [ + "composable-maths", + "composable-support", + "composable-tests-helpers", + "composable-traits", + "frame-benchmarking", + "frame-support", + "frame-system", + "orml-tokens", + "orml-traits", + "pallet-currency-factory", + "parity-scale-codec", + "plotters", + "proptest", + "rust_decimal", + "scale-info", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-ping" version = "0.1.0" @@ -7049,7 +7407,7 @@ dependencies = [ [[package]] name = "pallet-preimage" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -7082,7 +7440,7 @@ dependencies = [ [[package]] name = "pallet-proxy" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -7097,7 +7455,7 @@ dependencies = [ [[package]] name = "pallet-randomness-collective-flip" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-support", "frame-system", @@ -7111,7 +7469,7 @@ dependencies = [ [[package]] name = "pallet-recovery" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-support", "frame-system", @@ -7125,7 +7483,7 @@ dependencies = [ [[package]] name = "pallet-scheduler" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -7141,7 +7499,7 @@ dependencies = [ [[package]] name = "pallet-session" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-support", "frame-system", @@ -7162,7 +7520,7 @@ dependencies = [ [[package]] name = "pallet-session-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -7178,7 +7536,7 @@ dependencies = [ [[package]] name = "pallet-society" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-support", "frame-system", @@ -7192,7 +7550,7 @@ dependencies = [ [[package]] name = "pallet-staking" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -7215,18 +7573,18 @@ dependencies = [ [[package]] name = "pallet-staking-reward-curve" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] name = "pallet-staking-reward-fn" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "log 0.4.14", "sp-arithmetic", @@ -7235,7 +7593,7 @@ dependencies = [ [[package]] name = "pallet-sudo" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-support", "frame-system", @@ -7249,7 +7607,7 @@ dependencies = [ [[package]] name = "pallet-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -7267,7 +7625,7 @@ dependencies = [ [[package]] name = "pallet-tips" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -7286,7 +7644,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-support", "frame-system", @@ -7303,7 +7661,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "jsonrpc-core", "jsonrpc-core-client", @@ -7320,7 +7678,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc-runtime-api" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "pallet-transaction-payment", "parity-scale-codec", @@ -7331,7 +7689,7 @@ dependencies = [ [[package]] name = "pallet-treasury" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -7349,6 +7707,8 @@ dependencies = [ name = "pallet-uniswap-v2" version = "0.0.1" dependencies = [ + "composable-maths", + "composable-tests-helpers", "composable-traits", "frame-benchmarking", "frame-support", @@ -7357,12 +7717,10 @@ dependencies = [ "num-traits", "orml-tokens", "orml-traits", - "pallet-balances", "pallet-currency-factory", - "pallet-oracle", - "pallet-vault", "parity-scale-codec", "plotters", + "proptest", "scale-info", "serde", "sp-arithmetic", @@ -7375,7 +7733,7 @@ dependencies = [ [[package]] name = "pallet-utility" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -7393,6 +7751,7 @@ name = "pallet-vault" version = "0.0.1" dependencies = [ "bitflags", + "composable-support", "composable-tests-helpers", "composable-traits", "frame-benchmarking", @@ -7405,7 +7764,7 @@ dependencies = [ "orml-traits", "pallet-balances", "parity-scale-codec", - "proptest 0.9.6", + "proptest", "scale-info", "serde", "sp-arithmetic", @@ -7420,10 +7779,12 @@ name = "pallet-vesting" version = "0.0.1" dependencies = [ "composable-traits", + "frame-benchmarking", "frame-support", "frame-system", "orml-tokens", "orml-traits", + "pallet-timestamp", "parity-scale-codec", "scale-info", "serde", @@ -7436,7 +7797,7 @@ dependencies = [ [[package]] name = "pallet-vesting" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-benchmarking", "frame-support", @@ -7450,8 +7811,8 @@ dependencies = [ [[package]] name = "pallet-xcm" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "frame-support", "frame-system", @@ -7468,8 +7829,8 @@ dependencies = [ [[package]] name = "pallet-xcm-benchmarks" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "frame-benchmarking", "frame-support", @@ -7486,7 +7847,7 @@ dependencies = [ [[package]] name = "parachain-info" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.16#86f76c5619c64d1300315612695ad4b4fcd0f562" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.17#db11baacc325537be74ad34517fcb28ed9ded6c6" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -7496,11 +7857,39 @@ dependencies = [ "serde", ] +[[package]] +name = "parachain-utils" +version = "0.1.0" +dependencies = [ + "common", + "cumulus-pallet-parachain-system", + "dali-runtime", + "derive_more", + "env_logger 0.8.4", + "envy", + "frame-system", + "hex", + "jsonrpc-core-client", + "log 0.4.14", + "pallet-transaction-payment", + "parity-scale-codec", + "picasso-runtime", + "sc-rpc", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "structopt", + "substrate-xt", + "tokio", + "url 1.7.2", +] + [[package]] name = "parity-db" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68de01cff53da5574397233383dd7f5c15ee958c348245765ea8cb09f2571e6b" +checksum = "865edee5b792f537356d9e55cbc138e7f4718dc881a7ea45a18b37bf61c21e3d" dependencies = [ "blake2-rfc", "crc32fast", @@ -7511,7 +7900,7 @@ dependencies = [ "lz4", "memmap2 0.2.3", "parking_lot 0.11.2", - "rand 0.8.4", + "rand 0.8.5", "snap", ] @@ -7535,10 +7924,10 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -7553,7 +7942,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9981e32fb75e004cc148f5fb70342f393830e0a4aa62e3cc93b50976218d42b6" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "libc", "log 0.4.14", "rand 0.7.3", @@ -7568,10 +7957,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f4cb4e169446179cbc6b8b6320cc9fca49bd2e94e8db25f25f200a8ea774770" dependencies = [ "cfg-if 1.0.0", - "ethereum-types", "hashbrown 0.11.2", "impl-trait-for-tuples", - "lru 0.6.6", "parity-util-mem-derive", "parking_lot 0.11.2", "primitive-types", @@ -7586,7 +7973,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" dependencies = [ "proc-macro2 1.0.36", - "syn 1.0.86", + "syn 1.0.88", "synstructure", ] @@ -7661,6 +8048,16 @@ dependencies = [ "parking_lot_core 0.8.5", ] +[[package]] +name = "parking_lot" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api 0.4.6", + "parking_lot_core 0.9.1", +] + [[package]] name = "parking_lot_core" version = "0.6.2" @@ -7699,11 +8096,24 @@ dependencies = [ "cfg-if 1.0.0", "instant", "libc", - "redox_syscall 0.2.10", + "redox_syscall 0.2.11", "smallvec 1.8.0", "winapi 0.3.9", ] +[[package]] +name = "parking_lot_core" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall 0.2.11", + "smallvec 1.8.0", + "windows-sys", +] + [[package]] name = "paste" version = "0.1.18" @@ -7813,7 +8223,7 @@ dependencies = [ "pest_meta", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -7841,8 +8251,11 @@ dependencies = [ name = "picasso-runtime" version = "0.1.0" dependencies = [ + "assets-runtime-api", "common", + "composable-support", "composable-traits", + "crowdloan-rewards-runtime-api", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -7865,6 +8278,7 @@ dependencies = [ "orml-xcm-support", "orml-xtokens", "pallet-assets", + "pallet-assets-registry", "pallet-aura", "pallet-authorship", "pallet-balances", @@ -7942,7 +8356,7 @@ checksum = "044964427019eed9d49d9d5bbce6047ef18f37100ea400912a9fa4a3523ab12a" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -7953,7 +8367,7 @@ checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -8046,10 +8460,10 @@ dependencies = [ [[package]] name = "polkadot-approval-distribution" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "polkadot-node-network-protocol", "polkadot-node-primitives", "polkadot-node-subsystem", @@ -8060,10 +8474,10 @@ dependencies = [ [[package]] name = "polkadot-availability-bitfield-distribution" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "polkadot-node-network-protocol", "polkadot-node-subsystem", "polkadot-node-subsystem-util", @@ -8073,12 +8487,12 @@ dependencies = [ [[package]] name = "polkadot-availability-distribution" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "derive_more", - "futures 0.3.19", - "lru 0.7.2", + "futures 0.3.21", + "lru 0.7.3", "parity-scale-codec", "polkadot-erasure-coding", "polkadot-node-network-protocol", @@ -8086,7 +8500,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand 0.8.4", + "rand 0.8.5", "sp-core", "sp-keystore", "thiserror", @@ -8095,11 +8509,11 @@ dependencies = [ [[package]] name = "polkadot-availability-recovery" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ - "futures 0.3.19", - "lru 0.7.2", + "futures 0.3.21", + "lru 0.7.3", "parity-scale-codec", "polkadot-erasure-coding", "polkadot-node-network-protocol", @@ -8107,7 +8521,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand 0.8.4", + "rand 0.8.5", "sc-network", "thiserror", "tracing", @@ -8115,11 +8529,12 @@ dependencies = [ [[package]] name = "polkadot-cli" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ + "clap 3.1.6", "frame-benchmarking-cli", - "futures 0.3.19", + "futures 0.3.21", "log 0.4.14", "polkadot-node-core-pvf", "polkadot-node-metrics", @@ -8130,7 +8545,6 @@ dependencies = [ "sc-tracing", "sp-core", "sp-trie", - "structopt", "substrate-build-script-utils", "thiserror", "try-runtime-cli", @@ -8138,8 +8552,8 @@ dependencies = [ [[package]] name = "polkadot-client" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "beefy-primitives", "frame-benchmarking", @@ -8169,12 +8583,12 @@ dependencies = [ [[package]] name = "polkadot-collator-protocol" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "always-assert", "derive_more", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "polkadot-node-network-protocol", "polkadot-node-primitives", @@ -8190,8 +8604,8 @@ dependencies = [ [[package]] name = "polkadot-core-primitives" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "parity-scale-codec", "parity-util-mem", @@ -8203,12 +8617,12 @@ dependencies = [ [[package]] name = "polkadot-dispute-distribution" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "derive_more", - "futures 0.3.19", - "lru 0.7.2", + "futures 0.3.21", + "lru 0.7.3", "parity-scale-codec", "polkadot-erasure-coding", "polkadot-node-network-protocol", @@ -8225,8 +8639,8 @@ dependencies = [ [[package]] name = "polkadot-erasure-coding" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "parity-scale-codec", "polkadot-node-primitives", @@ -8239,16 +8653,16 @@ dependencies = [ [[package]] name = "polkadot-gossip-support" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "polkadot-node-network-protocol", "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand 0.8.4", + "rand 0.8.5", "rand_chacha 0.3.1", "sc-network", "sp-application-crypto", @@ -8259,11 +8673,11 @@ dependencies = [ [[package]] name = "polkadot-network-bridge" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "async-trait", - "futures 0.3.19", + "futures 0.3.21", "parity-scale-codec", "parking_lot 0.11.2", "polkadot-node-network-protocol", @@ -8278,10 +8692,10 @@ dependencies = [ [[package]] name = "polkadot-node-collation-generation" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "parity-scale-codec", "polkadot-erasure-coding", "polkadot-node-primitives", @@ -8296,15 +8710,15 @@ dependencies = [ [[package]] name = "polkadot-node-core-approval-voting" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "bitvec", "derive_more", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "kvdb", - "lru 0.7.2", + "lru 0.7.3", "merlin", "parity-scale-codec", "polkadot-node-jaeger", @@ -8324,11 +8738,11 @@ dependencies = [ [[package]] name = "polkadot-node-core-av-store" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "bitvec", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "kvdb", "parity-scale-codec", @@ -8344,11 +8758,11 @@ dependencies = [ [[package]] name = "polkadot-node-core-backing" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "bitvec", - "futures 0.3.19", + "futures 0.3.21", "polkadot-erasure-coding", "polkadot-node-primitives", "polkadot-node-subsystem", @@ -8362,10 +8776,10 @@ dependencies = [ [[package]] name = "polkadot-node-core-bitfield-signing" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", @@ -8377,11 +8791,11 @@ dependencies = [ [[package]] name = "polkadot-node-core-candidate-validation" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "async-trait", - "futures 0.3.19", + "futures 0.3.21", "parity-scale-codec", "polkadot-node-core-pvf", "polkadot-node-primitives", @@ -8395,10 +8809,10 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-api" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", @@ -8410,10 +8824,10 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-selection" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "kvdb", "parity-scale-codec", @@ -8427,12 +8841,12 @@ dependencies = [ [[package]] name = "polkadot-node-core-dispute-coordinator" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "kvdb", - "lru 0.7.2", + "lru 0.7.3", "parity-scale-codec", "polkadot-node-primitives", "polkadot-node-subsystem", @@ -8445,11 +8859,11 @@ dependencies = [ [[package]] name = "polkadot-node-core-parachains-inherent" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "async-trait", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "polkadot-node-subsystem", "polkadot-primitives", @@ -8462,38 +8876,38 @@ dependencies = [ [[package]] name = "polkadot-node-core-provisioner" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "bitvec", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand 0.8.4", + "rand 0.8.5", "thiserror", "tracing", ] [[package]] name = "polkadot-node-core-pvf" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "always-assert", "assert_matches", "async-process", "async-std", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "parity-scale-codec", "pin-project 1.0.10", "polkadot-core-primitives", "polkadot-node-subsystem-util", "polkadot-parachain", - "rand 0.8.4", + "rand 0.8.5", "sc-executor", "sc-executor-common", "sc-executor-wasmtime", @@ -8509,10 +8923,10 @@ dependencies = [ [[package]] name = "polkadot-node-core-pvf-checker" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-node-subsystem-util", @@ -8525,10 +8939,10 @@ dependencies = [ [[package]] name = "polkadot-node-core-runtime-api" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "memory-lru", "parity-util-mem", "polkadot-node-subsystem", @@ -8543,8 +8957,8 @@ dependencies = [ [[package]] name = "polkadot-node-jaeger" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "async-std", "lazy_static", @@ -8561,11 +8975,11 @@ dependencies = [ [[package]] name = "polkadot-node-metrics" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "bs58", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "log 0.4.14", "metered-channel", @@ -8580,29 +8994,29 @@ dependencies = [ [[package]] name = "polkadot-node-network-protocol" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "async-trait", "derive_more", - "futures 0.3.19", + "futures 0.3.21", "parity-scale-codec", "polkadot-node-jaeger", "polkadot-node-primitives", "polkadot-primitives", "sc-authority-discovery", "sc-network", - "strum 0.23.0", + "strum", "thiserror", ] [[package]] name = "polkadot-node-primitives" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "bounded-vec", - "futures 0.3.19", + "futures 0.3.21", "parity-scale-codec", "polkadot-parachain", "polkadot-primitives", @@ -8620,8 +9034,8 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "polkadot-node-jaeger", "polkadot-node-subsystem-types", @@ -8630,11 +9044,11 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-types" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "derive_more", - "futures 0.3.19", + "futures 0.3.21", "polkadot-node-jaeger", "polkadot-node-network-protocol", "polkadot-node-primitives", @@ -8649,14 +9063,14 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-util" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "async-trait", "derive_more", - "futures 0.3.19", + "futures 0.3.21", "itertools", - "lru 0.7.2", + "lru 0.7.3", "metered-channel", "parity-scale-codec", "pin-project 1.0.10", @@ -8667,7 +9081,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-overseer", "polkadot-primitives", - "rand 0.8.4", + "rand 0.8.5", "sp-application-crypto", "sp-core", "sp-keystore", @@ -8677,12 +9091,12 @@ dependencies = [ [[package]] name = "polkadot-overseer" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "futures-timer", - "lru 0.7.2", + "lru 0.7.3", "parity-util-mem", "parking_lot 0.11.2", "polkadot-node-metrics", @@ -8698,11 +9112,11 @@ dependencies = [ [[package]] name = "polkadot-overseer-gen" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "async-trait", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "metered-channel", "pin-project 1.0.10", @@ -8715,19 +9129,19 @@ dependencies = [ [[package]] name = "polkadot-overseer-gen-proc-macro" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] name = "polkadot-parachain" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "derive_more", "frame-support", @@ -8743,8 +9157,8 @@ dependencies = [ [[package]] name = "polkadot-performance-test" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "env_logger 0.9.0", "kusama-runtime", @@ -8758,8 +9172,8 @@ dependencies = [ [[package]] name = "polkadot-primitives" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "bitvec", "frame-system", @@ -8788,8 +9202,8 @@ dependencies = [ [[package]] name = "polkadot-rpc" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "beefy-gadget", "beefy-gadget-rpc", @@ -8819,8 +9233,8 @@ dependencies = [ [[package]] name = "polkadot-runtime" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "beefy-primitives", "bitvec", @@ -8903,8 +9317,8 @@ dependencies = [ [[package]] name = "polkadot-runtime-common" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "beefy-primitives", "bitvec", @@ -8950,8 +9364,8 @@ dependencies = [ [[package]] name = "polkadot-runtime-constants" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "frame-support", "polkadot-primitives", @@ -8962,8 +9376,8 @@ dependencies = [ [[package]] name = "polkadot-runtime-metrics" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "bs58", "parity-scale-codec", @@ -8974,8 +9388,8 @@ dependencies = [ [[package]] name = "polkadot-runtime-parachains" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "bitflags", "bitvec", @@ -8995,7 +9409,7 @@ dependencies = [ "parity-scale-codec", "polkadot-primitives", "polkadot-runtime-metrics", - "rand 0.8.4", + "rand 0.8.5", "rand_chacha 0.3.1", "rustc-hex", "scale-info", @@ -9009,25 +9423,26 @@ dependencies = [ "sp-session", "sp-staking", "sp-std", + "static_assertions", "xcm", "xcm-executor", ] [[package]] name = "polkadot-service" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "async-trait", "beefy-gadget", "beefy-primitives", "frame-system-rpc-runtime-api", - "futures 0.3.19", + "futures 0.3.21", "hex-literal", "kusama-runtime", "kvdb", "kvdb-rocksdb", - "lru 0.7.2", + "lru 0.7.3", "pallet-babe", "pallet-im-online", "pallet-mmr-primitives", @@ -9116,12 +9531,12 @@ dependencies = [ [[package]] name = "polkadot-statement-distribution" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "arrayvec 0.5.2", "derive_more", - "futures 0.3.19", + "futures 0.3.21", "indexmap", "parity-scale-codec", "polkadot-node-network-protocol", @@ -9137,8 +9552,8 @@ dependencies = [ [[package]] name = "polkadot-statement-table" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "parity-scale-codec", "polkadot-primitives", @@ -9204,11 +9619,11 @@ version = "0.1.0" dependencies = [ "binance", "chrono", - "clap 3.0.14", + "clap 3.1.6", "custom_derive", "enum_derive", "env_logger 0.9.0", - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-client-transports", "jsonrpc-core", "lazy_static", @@ -9231,7 +9646,6 @@ checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" dependencies = [ "fixed-hash", "impl-codec", - "impl-rlp", "impl-serde", "scale-info", "uint", @@ -9241,6 +9655,7 @@ dependencies = [ name = "primitives" version = "0.1.0" dependencies = [ + "composable-support", "composable-traits", "parity-scale-codec", "scale-info", @@ -9260,9 +9675,9 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.1.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" +checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" dependencies = [ "thiserror", "toml", @@ -9277,7 +9692,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", "version_check 0.9.4", ] @@ -9330,26 +9745,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "proptest" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01c477819b845fe023d33583ebf10c9f62518c8d79a0960ba5c36d6ac8a55a5b" -dependencies = [ - "bit-set", - "bitflags", - "byteorder", - "lazy_static", - "num-traits", - "quick-error 1.2.3", - "rand 0.6.5", - "rand_chacha 0.1.1", - "rand_xorshift 0.1.1", - "regex-syntax", - "rusty-fork 0.2.2", - "tempfile", -] - [[package]] name = "proptest" version = "1.0.0" @@ -9362,11 +9757,11 @@ dependencies = [ "lazy_static", "num-traits", "quick-error 2.0.1", - "rand 0.8.4", + "rand 0.8.5", "rand_chacha 0.3.1", "rand_xorshift 0.3.0", "regex-syntax", - "rusty-fork 0.3.0", + "rusty-fork", "tempfile", ] @@ -9421,7 +9816,7 @@ dependencies = [ "itertools", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -9436,9 +9831,9 @@ dependencies = [ [[package]] name = "psm" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd136ff4382c4753fc061cb9e4712ab2af263376b95bbd5bd8cd50c020b78e69" +checksum = "6eca0fa5dd7c4c96e184cec588f0b1db1ee3165e678db21c09793105acb17e6f" dependencies = [ "cc", ] @@ -9496,7 +9891,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" dependencies = [ - "autocfg 0.1.7", + "autocfg 0.1.8", "libc", "rand_chacha 0.1.1", "rand_core 0.4.2", @@ -9525,14 +9920,13 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.3", - "rand_hc 0.3.1", ] [[package]] @@ -9541,7 +9935,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" dependencies = [ - "autocfg 0.1.7", + "autocfg 0.1.8", "rand_core 0.3.1", ] @@ -9595,7 +9989,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.2.4", + "getrandom 0.2.5", ] [[package]] @@ -9605,7 +9999,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ "num-traits", - "rand 0.8.4", + "rand 0.8.5", ] [[package]] @@ -9623,16 +10017,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core 0.6.3", + "rand_core 0.5.1", ] [[package]] @@ -9675,7 +10060,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" dependencies = [ - "autocfg 0.1.7", + "autocfg 0.1.8", "rand_core 0.4.2", ] @@ -9718,7 +10103,7 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "crossbeam-deque", "either", "rayon-core", @@ -9732,7 +10117,7 @@ checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" dependencies = [ "crossbeam-channel", "crossbeam-deque", - "crossbeam-utils 0.8.6", + "crossbeam-utils 0.8.8", "lazy_static", "num_cpus", ] @@ -9754,9 +10139,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c" dependencies = [ "bitflags", ] @@ -9767,8 +10152,8 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ - "getrandom 0.2.4", - "redox_syscall 0.2.10", + "getrandom 0.2.5", + "redox_syscall 0.2.11", ] [[package]] @@ -9801,7 +10186,7 @@ checksum = "4c38e3aecd2b21cb3959637b883bb3714bc7e43f0268b9a29d3743ee3e55cdd2" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -9817,9 +10202,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" dependencies = [ "aho-corasick", "memchr", @@ -9856,10 +10241,10 @@ dependencies = [ [[package]] name = "remote-externalities" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "env_logger 0.9.0", - "jsonrpsee", + "jsonrpsee 0.8.0", "log 0.4.14", "parity-scale-codec", "serde", @@ -9881,9 +10266,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.9" +version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f242f1488a539a79bac6dbe7c8609ae43b7914b7736210f239a37cccb32525" +checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb" dependencies = [ "base64 0.13.0", "bytes 1.1.0", @@ -9893,7 +10278,7 @@ dependencies = [ "h2", "http", "http-body", - "hyper 0.14.16", + "hyper 0.14.17", "hyper-tls", "ipnet", "js-sys", @@ -9912,7 +10297,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg 0.7.0", + "winreg 0.10.1", ] [[package]] @@ -9927,9 +10312,9 @@ dependencies = [ [[package]] name = "retain_mut" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51dd4445360338dab5116712bee1388dc727991d51969558a8882ab552e6db30" +checksum = "8c31b5c4033f8fdde8700e4657be2c497e7288f01515be52168c631e2e4d4086" [[package]] name = "ring" @@ -9946,16 +10331,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "rlp" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "999508abb0ae792aabed2460c45b89106d97fe4adac593bdaef433c2605847b5" -dependencies = [ - "bytes 1.1.0", - "rustc-hex", -] - [[package]] name = "rocksdb" version = "0.17.0" @@ -9968,8 +10343,8 @@ dependencies = [ [[package]] name = "rococo-runtime" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "beefy-primitives", "bp-messages", @@ -10043,8 +10418,8 @@ dependencies = [ [[package]] name = "rococo-runtime-constants" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "frame-support", "polkadot-primitives", @@ -10069,6 +10444,16 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "rust_decimal" +version = "1.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d37baa70cf8662d2ba1c1868c5983dda16ef32b105cce41fb5c47e72936a90b3" +dependencies = [ + "arrayvec 0.7.2", + "num-traits", +] + [[package]] name = "rustc-demangle" version = "0.1.21" @@ -10111,7 +10496,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.4", + "semver 1.0.6", ] [[package]] @@ -10137,8 +10522,20 @@ dependencies = [ "base64 0.13.0", "log 0.4.14", "ring", - "sct", - "webpki", + "sct 0.6.1", + "webpki 0.21.4", +] + +[[package]] +name = "rustls" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921" +dependencies = [ + "log 0.4.14", + "ring", + "sct 0.7.0", + "webpki 0.22.0", ] [[package]] @@ -10148,29 +10545,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092" dependencies = [ "openssl-probe", - "rustls", + "rustls 0.19.1", "schannel", "security-framework", ] [[package]] -name = "rustversion" -version = "1.0.6" +name = "rustls-native-certs" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" +checksum = "5ca9ebdfa27d3fc180e42879037b5338ab1c040c06affd00d8338598e7800943" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] [[package]] -name = "rusty-fork" -version = "0.2.2" +name = "rustls-pemfile" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dd93264e10c577503e926bd1430193eeb5d21b059148910082245309b424fae" +checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" dependencies = [ - "fnv", - "quick-error 1.2.3", - "tempfile", - "wait-timeout", + "base64 0.13.0", ] +[[package]] +name = "rustversion" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" + [[package]] name = "rusty-fork" version = "0.3.0" @@ -10189,7 +10595,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4da5fcb054c46f5a5dff833b129285a93d3f0179531735e6c866e8cc307d2020" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "pin-project 0.4.29", "static_assertions", ] @@ -10236,7 +10642,7 @@ dependencies = [ [[package]] name = "sc-allocator" version = "4.1.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "log 0.4.14", "sp-core", @@ -10247,11 +10653,10 @@ dependencies = [ [[package]] name = "sc-authority-discovery" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "async-trait", - "derive_more", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "ip_network", "libp2p", @@ -10269,14 +10674,15 @@ dependencies = [ "sp-keystore", "sp-runtime", "substrate-prometheus-endpoint", + "thiserror", ] [[package]] name = "sc-basic-authorship" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "log 0.4.14", "parity-scale-codec", @@ -10297,7 +10703,7 @@ dependencies = [ [[package]] name = "sc-block-builder" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "parity-scale-codec", "sc-client-api", @@ -10313,10 +10719,10 @@ dependencies = [ [[package]] name = "sc-chain-spec" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "impl-trait-for-tuples", - "memmap2 0.5.2", + "memmap2 0.5.3", "parity-scale-codec", "sc-chain-spec-derive", "sc-network", @@ -10330,22 +10736,23 @@ dependencies = [ [[package]] name = "sc-chain-spec-derive" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] name = "sc-cli" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "chrono", + "clap 3.1.6", "fdlimit", - "futures 0.3.19", + "futures 0.3.21", "hex", "libp2p", "log 0.4.14", @@ -10370,7 +10777,6 @@ dependencies = [ "sp-panic-handler", "sp-runtime", "sp-version", - "structopt", "thiserror", "tiny-bip39", "tokio", @@ -10379,10 +10785,10 @@ dependencies = [ [[package]] name = "sc-client-api" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "fnv", - "futures 0.3.19", + "futures 0.3.21", "hash-db", "log 0.4.14", "parity-scale-codec", @@ -10407,7 +10813,7 @@ dependencies = [ [[package]] name = "sc-client-db" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "hash-db", "kvdb", @@ -10432,10 +10838,10 @@ dependencies = [ [[package]] name = "sc-consensus" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "async-trait", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "libp2p", "log 0.4.14", @@ -10456,11 +10862,10 @@ dependencies = [ [[package]] name = "sc-consensus-aura" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "async-trait", - "derive_more", - "futures 0.3.19", + "futures 0.3.21", "log 0.4.14", "parity-scale-codec", "sc-block-builder", @@ -10480,17 +10885,17 @@ dependencies = [ "sp-keystore", "sp-runtime", "substrate-prometheus-endpoint", + "thiserror", ] [[package]] name = "sc-consensus-babe" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "async-trait", - "derive_more", "fork-tree", - "futures 0.3.19", + "futures 0.3.21", "log 0.4.14", "merlin", "num-bigint", @@ -10523,15 +10928,15 @@ dependencies = [ "sp-runtime", "sp-version", "substrate-prometheus-endpoint", + "thiserror", ] [[package]] name = "sc-consensus-babe-rpc" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ - "derive_more", - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -10547,12 +10952,13 @@ dependencies = [ "sp-core", "sp-keystore", "sp-runtime", + "thiserror", ] [[package]] name = "sc-consensus-epochs" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "fork-tree", "parity-scale-codec", @@ -10565,12 +10971,11 @@ dependencies = [ [[package]] name = "sc-consensus-manual-seal" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "assert_matches", "async-trait", - "derive_more", - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -10596,15 +11001,16 @@ dependencies = [ "sp-runtime", "sp-timestamp", "substrate-prometheus-endpoint", + "thiserror", ] [[package]] name = "sc-consensus-slots" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "async-trait", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "log 0.4.14", "parity-scale-codec", @@ -10626,7 +11032,7 @@ dependencies = [ [[package]] name = "sc-consensus-uncles" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "sc-client-api", "sp-authorship", @@ -10637,7 +11043,7 @@ dependencies = [ [[package]] name = "sc-executor" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "lazy_static", "libsecp256k1", @@ -10665,9 +11071,8 @@ dependencies = [ [[package]] name = "sc-executor-common" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ - "derive_more", "environmental", "parity-scale-codec", "sc-allocator", @@ -10683,7 +11088,7 @@ dependencies = [ [[package]] name = "sc-executor-wasmi" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "log 0.4.14", "parity-scale-codec", @@ -10699,7 +11104,7 @@ dependencies = [ [[package]] name = "sc-executor-wasmtime" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "cfg-if 1.0.0", "libc", @@ -10717,19 +11122,18 @@ dependencies = [ [[package]] name = "sc-finality-grandpa" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "async-trait", - "derive_more", "dyn-clone", "finality-grandpa", "fork-tree", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "log 0.4.14", "parity-scale-codec", "parking_lot 0.11.2", - "rand 0.8.4", + "rand 0.8.5", "sc-block-builder", "sc-chain-spec", "sc-client-api", @@ -10750,16 +11154,16 @@ dependencies = [ "sp-keystore", "sp-runtime", "substrate-prometheus-endpoint", + "thiserror", ] [[package]] name = "sc-finality-grandpa-rpc" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ - "derive_more", "finality-grandpa", - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -10774,15 +11178,16 @@ dependencies = [ "sp-blockchain", "sp-core", "sp-runtime", + "thiserror", ] [[package]] name = "sc-informant" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "ansi_term", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "log 0.4.14", "parity-util-mem", @@ -10796,22 +11201,22 @@ dependencies = [ [[package]] name = "sc-keystore" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "async-trait", - "derive_more", "hex", "parking_lot 0.11.2", "serde_json", "sp-application-crypto", "sp-core", "sp-keystore", + "thiserror", ] [[package]] name = "sc-network" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "async-std", "async-trait", @@ -10819,11 +11224,10 @@ dependencies = [ "bitflags", "bytes 1.1.0", "cid", - "derive_more", "either", "fnv", "fork-tree", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "hex", "ip_network", @@ -10831,7 +11235,7 @@ dependencies = [ "linked-hash-map", "linked_hash_set", "log 0.4.14", - "lru 0.7.2", + "lru 0.7.3", "parity-scale-codec", "parking_lot 0.11.2", "pin-project 1.0.10", @@ -10862,13 +11266,13 @@ dependencies = [ [[package]] name = "sc-network-gossip" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "libp2p", "log 0.4.14", - "lru 0.7.2", + "lru 0.7.3", "sc-network", "sp-runtime", "substrate-prometheus-endpoint", @@ -10878,15 +11282,15 @@ dependencies = [ [[package]] name = "sc-offchain" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "bytes 1.1.0", "fnv", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "hex", - "hyper 0.14.16", - "hyper-rustls", + "hyper 0.14.17", + "hyper-rustls 0.22.1", "num_cpus", "once_cell", "parity-scale-codec", @@ -10906,9 +11310,9 @@ dependencies = [ [[package]] name = "sc-peerset" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "libp2p", "log 0.4.14", "sc-utils", @@ -10919,7 +11323,7 @@ dependencies = [ [[package]] name = "sc-proposer-metrics" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "log 0.4.14", "substrate-prometheus-endpoint", @@ -10928,9 +11332,9 @@ dependencies = [ [[package]] name = "sc-rpc" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "hash-db", "jsonrpc-core", "jsonrpc-pubsub", @@ -10959,9 +11363,9 @@ dependencies = [ [[package]] name = "sc-rpc-api" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -10984,9 +11388,9 @@ dependencies = [ [[package]] name = "sc-rpc-server" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-http-server", "jsonrpc-ipc-server", @@ -11001,12 +11405,12 @@ dependencies = [ [[package]] name = "sc-service" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "async-trait", "directories", "exit-future", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "hash-db", "jsonrpc-core", @@ -11065,7 +11469,7 @@ dependencies = [ [[package]] name = "sc-state-db" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "log 0.4.14", "parity-scale-codec", @@ -11079,7 +11483,7 @@ dependencies = [ [[package]] name = "sc-sync-state-rpc" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "jsonrpc-core", "jsonrpc-core-client", @@ -11101,10 +11505,10 @@ dependencies = [ [[package]] name = "sc-telemetry" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "chrono", - "futures 0.3.19", + "futures 0.3.21", "libp2p", "log 0.4.14", "parking_lot 0.11.2", @@ -11119,7 +11523,7 @@ dependencies = [ [[package]] name = "sc-tracing" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "ansi_term", "atty", @@ -11150,20 +11554,20 @@ dependencies = [ [[package]] name = "sc-tracing-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] name = "sc-transaction-pool" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "linked-hash-map", "log 0.4.14", @@ -11188,10 +11592,9 @@ dependencies = [ [[package]] name = "sc-transaction-pool-api" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ - "derive_more", - "futures 0.3.19", + "futures 0.3.21", "log 0.4.14", "serde", "sp-blockchain", @@ -11202,9 +11605,9 @@ dependencies = [ [[package]] name = "sc-utils" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "lazy_static", "parking_lot 0.11.2", @@ -11231,10 +11634,10 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baeb2780690380592f86205aa4ee49815feb2acad8c2f59e6dd207148c3f1fcd" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -11287,6 +11690,16 @@ dependencies = [ "untrusted", ] +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "secrecy" version = "0.8.0" @@ -11298,9 +11711,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.6.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fed7948b6c68acbb6e20c334f55ad635dc0f75506963de4464289fbd3b051ac" +checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" dependencies = [ "bitflags", "core-foundation", @@ -11311,9 +11724,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.6.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a57321bf8bc2362081b2599912d2961fe899c0efadf1b4b2f8d48b3e253bb96c" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" dependencies = [ "core-foundation-sys", "libc", @@ -11348,9 +11761,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012" +checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d" dependencies = [ "serde", ] @@ -11387,14 +11800,14 @@ checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] name = "serde_json" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d23c1ba4cf0efd44be32017709280b32d1cea5c3f1275c3b6d9e8bc54f758085" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" dependencies = [ "itoa 1.0.1", "ryu", @@ -11470,6 +11883,17 @@ dependencies = [ "opaque-debug 0.3.0", ] +[[package]] +name = "sha-1" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures 0.2.1", + "digest 0.10.3", +] + [[package]] name = "sha1" version = "0.6.1" @@ -11512,13 +11936,13 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec" +checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" dependencies = [ "cfg-if 1.0.0", "cpufeatures 0.2.1", - "digest 0.10.1", + "digest 0.10.3", ] [[package]] @@ -11603,11 +12027,14 @@ version = "0.1.0" dependencies = [ "common", "composable-node", + "composable-runtime", "cumulus-primitives-parachain-inherent", "dali-runtime", "derive_more", "frame-benchmarking", + "frame-system", "jsonrpc-core", + "pallet-transaction-payment", "picasso-runtime", "sc-cli", "sc-consensus", @@ -11637,7 +12064,7 @@ dependencies = [ [[package]] name = "simnode-runtime-apis" version = "0.1.0" -source = "git+https://github.com/polytope-labs/substrate-simnode?branch=master#7e2453df89dac7ae6800186a121d2d0c335728f6" +source = "git+https://github.com/polytope-labs/substrate-simnode?branch=master#a5bc46c664884bac71ab13aa1669693e62fd99fd" dependencies = [ "parity-scale-codec", "sp-api", @@ -11650,6 +12077,7 @@ version = "0.1.0" dependencies = [ "common", "composable-node", + "composable-runtime", "cumulus-pallet-parachain-system", "dali-runtime", "frame-benchmarking", @@ -11693,8 +12121,8 @@ checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" [[package]] name = "slot-range-helper" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "enumn", "parity-scale-codec", @@ -11742,7 +12170,7 @@ dependencies = [ "aes-gcm 0.9.4", "blake2", "chacha20poly1305", - "rand 0.8.4", + "rand 0.8.5", "rand_core 0.6.3", "ring", "rustc_version 0.3.3", @@ -11781,10 +12209,10 @@ dependencies = [ "base64 0.13.0", "bytes 1.1.0", "flate2", - "futures 0.3.19", + "futures 0.3.21", "httparse", "log 0.4.14", - "rand 0.8.4", + "rand 0.8.5", "sha-1 0.9.8", ] @@ -11797,7 +12225,7 @@ checksum = "4210e1a17d165a0c1d4a233af1e3b36fb21b1359042767a4d2c73554f5f8c2aa" [[package]] name = "sp-api" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "hash-db", "log 0.4.14", @@ -11814,19 +12242,19 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "blake2-rfc", - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] name = "sp-application-crypto" -version = "4.0.0" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "parity-scale-codec", "scale-info", @@ -11839,7 +12267,7 @@ dependencies = [ [[package]] name = "sp-arithmetic" version = "4.0.0" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "integer-sqrt", "num-traits", @@ -11854,7 +12282,7 @@ dependencies = [ [[package]] name = "sp-authority-discovery" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "parity-scale-codec", "scale-info", @@ -11867,7 +12295,7 @@ dependencies = [ [[package]] name = "sp-authorship" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "async-trait", "parity-scale-codec", @@ -11879,7 +12307,7 @@ dependencies = [ [[package]] name = "sp-block-builder" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "parity-scale-codec", "sp-api", @@ -11891,11 +12319,11 @@ dependencies = [ [[package]] name = "sp-blockchain" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "log 0.4.14", - "lru 0.7.2", + "lru 0.7.3", "parity-scale-codec", "parking_lot 0.11.2", "sp-api", @@ -11909,10 +12337,10 @@ dependencies = [ [[package]] name = "sp-consensus" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "async-trait", - "futures 0.3.19", + "futures 0.3.21", "futures-timer", "log 0.4.14", "parity-scale-codec", @@ -11928,7 +12356,7 @@ dependencies = [ [[package]] name = "sp-consensus-aura" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "async-trait", "parity-scale-codec", @@ -11946,7 +12374,7 @@ dependencies = [ [[package]] name = "sp-consensus-babe" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "async-trait", "merlin", @@ -11969,7 +12397,7 @@ dependencies = [ [[package]] name = "sp-consensus-slots" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "parity-scale-codec", "scale-info", @@ -11981,7 +12409,7 @@ dependencies = [ [[package]] name = "sp-consensus-vrf" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "parity-scale-codec", "schnorrkel", @@ -11992,8 +12420,8 @@ dependencies = [ [[package]] name = "sp-core" -version = "4.1.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "base58", "bitflags", @@ -12001,7 +12429,7 @@ dependencies = [ "byteorder", "dyn-clonable", "ed25519-dalek", - "futures 0.3.19", + "futures 0.3.21", "hash-db", "hash256-std-hasher", "hex", @@ -12021,7 +12449,7 @@ dependencies = [ "schnorrkel", "secrecy", "serde", - "sha2 0.10.1", + "sha2 0.10.2", "sp-core-hashing", "sp-debug-derive", "sp-externalities", @@ -12041,11 +12469,11 @@ dependencies = [ [[package]] name = "sp-core-hashing" version = "4.0.0" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "blake2-rfc", "byteorder", - "sha2 0.10.1", + "sha2 0.10.2", "sp-std", "tiny-keccak", "twox-hash", @@ -12054,18 +12482,18 @@ dependencies = [ [[package]] name = "sp-core-hashing-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", "sp-core-hashing", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] name = "sp-database" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "kvdb", "parking_lot 0.11.2", @@ -12074,17 +12502,17 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "4.0.0" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] name = "sp-externalities" -version = "0.10.0" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +version = "0.11.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "environmental", "parity-scale-codec", @@ -12095,7 +12523,7 @@ dependencies = [ [[package]] name = "sp-finality-grandpa" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "finality-grandpa", "log 0.4.14", @@ -12113,7 +12541,7 @@ dependencies = [ [[package]] name = "sp-inherents" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "async-trait", "impl-trait-for-tuples", @@ -12126,10 +12554,10 @@ dependencies = [ [[package]] name = "sp-io" -version = "4.0.0" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "hash-db", "libsecp256k1", "log 0.4.14", @@ -12150,23 +12578,22 @@ dependencies = [ [[package]] name = "sp-keyring" -version = "4.1.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "lazy_static", "sp-core", "sp-runtime", - "strum 0.22.0", + "strum", ] [[package]] name = "sp-keystore" -version = "0.10.0" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +version = "0.11.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "async-trait", - "derive_more", - "futures 0.3.19", + "futures 0.3.21", "merlin", "parity-scale-codec", "parking_lot 0.11.2", @@ -12174,20 +12601,22 @@ dependencies = [ "serde", "sp-core", "sp-externalities", + "thiserror", ] [[package]] name = "sp-maybe-compressed-blob" version = "4.1.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ + "thiserror", "zstd", ] [[package]] name = "sp-npos-elections" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "parity-scale-codec", "scale-info", @@ -12202,18 +12631,18 @@ dependencies = [ [[package]] name = "sp-npos-elections-solution-type" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] name = "sp-offchain" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "sp-api", "sp-core", @@ -12223,7 +12652,7 @@ dependencies = [ [[package]] name = "sp-panic-handler" version = "4.0.0" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "backtrace", "lazy_static", @@ -12232,8 +12661,8 @@ dependencies = [ [[package]] name = "sp-rpc" -version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "rustc-hash", "serde", @@ -12242,8 +12671,8 @@ dependencies = [ [[package]] name = "sp-runtime" -version = "4.1.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "either", "hash256-std-hasher", @@ -12264,8 +12693,8 @@ dependencies = [ [[package]] name = "sp-runtime-interface" -version = "4.1.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -12282,19 +12711,19 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "4.0.0" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "Inflector", - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] name = "sp-serializer" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "serde", "serde_json", @@ -12303,7 +12732,7 @@ dependencies = [ [[package]] name = "sp-session" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "parity-scale-codec", "scale-info", @@ -12317,7 +12746,7 @@ dependencies = [ [[package]] name = "sp-staking" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "parity-scale-codec", "scale-info", @@ -12327,8 +12756,8 @@ dependencies = [ [[package]] name = "sp-state-machine" -version = "0.10.0" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +version = "0.11.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "hash-db", "log 0.4.14", @@ -12351,12 +12780,12 @@ dependencies = [ [[package]] name = "sp-std" version = "4.0.0" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" [[package]] name = "sp-storage" -version = "4.0.0" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "impl-serde", "parity-scale-codec", @@ -12369,7 +12798,7 @@ dependencies = [ [[package]] name = "sp-tasks" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "log 0.4.14", "sp-core", @@ -12382,7 +12811,7 @@ dependencies = [ [[package]] name = "sp-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "async-trait", "futures-timer", @@ -12398,7 +12827,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "4.0.0" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "parity-scale-codec", "sp-std", @@ -12410,7 +12839,7 @@ dependencies = [ [[package]] name = "sp-transaction-pool" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "sp-api", "sp-runtime", @@ -12419,7 +12848,7 @@ dependencies = [ [[package]] name = "sp-transaction-storage-proof" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "async-trait", "log 0.4.14", @@ -12434,8 +12863,8 @@ dependencies = [ [[package]] name = "sp-trie" -version = "4.0.0" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "hash-db", "memory-db", @@ -12450,7 +12879,7 @@ dependencies = [ [[package]] name = "sp-version" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "impl-serde", "parity-scale-codec", @@ -12467,18 +12896,18 @@ dependencies = [ [[package]] name = "sp-version-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "parity-scale-codec", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] name = "sp-wasm-interface" -version = "4.1.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "impl-trait-for-tuples", "log 0.4.14", @@ -12496,9 +12925,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "ss58-registry" -version = "1.12.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8319f44e20b42e5c11b88b1ad4130c35fe2974665a007b08b02322070177136a" +checksum = "2f9799e6d412271cb2414597581128b03f3285f260ea49f5363d07df6a332b3e" dependencies = [ "Inflector", "proc-macro2 1.0.36", @@ -12551,7 +12980,7 @@ dependencies = [ "memchr", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -12564,7 +12993,7 @@ dependencies = [ "lazy_static", "nalgebra", "num-traits", - "rand 0.8.4", + "rand 0.8.5", ] [[package]] @@ -12591,7 +13020,7 @@ dependencies = [ "quote 1.0.15", "serde", "serde_derive", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -12607,7 +13036,7 @@ dependencies = [ "serde_derive", "serde_json", "sha1", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -12649,16 +13078,7 @@ dependencies = [ "proc-macro-error", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", -] - -[[package]] -name = "strum" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7ac893c7d471c8a21f31cfe213ec4f6d9afeed25537c772e08ef3f005f8729e" -dependencies = [ - "strum_macros 0.22.0", + "syn 1.0.88", ] [[package]] @@ -12667,19 +13087,7 @@ version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb" dependencies = [ - "strum_macros 0.23.1", -] - -[[package]] -name = "strum_macros" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "339f799d8b549e3744c7ac7feb216383e4005d94bdb22561b3ab8f3b808ae9fb" -dependencies = [ - "heck 0.3.3", - "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", + "strum_macros", ] [[package]] @@ -12692,7 +13100,7 @@ dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", "rustversion", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -12711,7 +13119,7 @@ dependencies = [ [[package]] name = "substrate-build-script-utils" version = "3.0.0" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "platforms", ] @@ -12719,10 +13127,10 @@ dependencies = [ [[package]] name = "substrate-frame-rpc-system" version = "4.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "frame-system-rpc-runtime-api", - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -12741,27 +13149,28 @@ dependencies = [ [[package]] name = "substrate-prometheus-endpoint" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "async-std", - "derive_more", "futures-util", - "hyper 0.14.16", + "hyper 0.14.17", "log 0.4.14", "prometheus", + "thiserror", "tokio", ] [[package]] name = "substrate-simnode" version = "0.1.0" -source = "git+https://github.com/polytope-labs/substrate-simnode?branch=master#7e2453df89dac7ae6800186a121d2d0c335728f6" +source = "git+https://github.com/polytope-labs/substrate-simnode?branch=master#a5bc46c664884bac71ab13aa1669693e62fd99fd" dependencies = [ + "clap 3.1.6", "cumulus-pallet-parachain-system", "cumulus-primitives-parachain-inherent", "cumulus-test-relay-sproof-builder", "frame-system", - "futures 0.3.19", + "futures 0.3.21", "jsonrpc-core", "log 0.4.14", "num-traits", @@ -12809,18 +13218,40 @@ dependencies = [ [[package]] name = "substrate-wasm-builder" version = "5.0.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ "ansi_term", "build-helper", "cargo_metadata", "sp-maybe-compressed-blob", + "strum", "tempfile", "toml", "walkdir", "wasm-gc-api", ] +[[package]] +name = "substrate-xt" +version = "0.1.0" +source = "git+https://github.com/polytope-labs/substrate-xt?branch=master#0f174b36742c22431ee673dbdc4cc4aea8c9de77" +dependencies = [ + "frame-system", + "futures 0.3.21", + "jsonrpsee 0.8.0", + "parity-scale-codec", + "sc-client-api", + "sc-rpc-api", + "sc-transaction-pool-api", + "sp-core", + "sp-externalities", + "sp-io", + "sp-runtime", + "sp-storage", + "thiserror", + "tokio", +] + [[package]] name = "subtle" version = "2.4.1" @@ -12846,9 +13277,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.86" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +checksum = "ebd69e719f31e88618baa1eaa6ee2de5c9a1c004f1e9ecdb58e8352a13f20a01" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", @@ -12863,7 +13294,7 @@ checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", "unicode-xid 0.2.2", ] @@ -12888,16 +13319,16 @@ dependencies = [ "cfg-if 1.0.0", "fastrand", "libc", - "redox_syscall 0.2.10", + "redox_syscall 0.2.11", "remove_dir_all", "winapi 0.3.9", ] [[package]] name = "termcolor" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] @@ -12913,9 +13344,9 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.14.2" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "thiserror" @@ -12934,7 +13365,7 @@ checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -13037,7 +13468,7 @@ dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", "standback", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -13085,19 +13516,20 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.16.1" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c27a64b625de6d309e8c57716ba93021dccf1b3b5c97edd6d3dd2d2135afc0a" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" dependencies = [ "bytes 1.1.0", "libc", "memchr", - "mio 0.7.14", + "mio 0.8.1", "num_cpus", "once_cell", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "pin-project-lite 0.2.8", "signal-hook-registry", + "socket2 0.4.4", "tokio-macros", "winapi 0.3.9", ] @@ -13142,7 +13574,7 @@ checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -13180,9 +13612,20 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" dependencies = [ - "rustls", + "rustls 0.19.1", + "tokio", + "webpki 0.21.4", +] + +[[package]] +name = "tokio-rustls" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a27d5f2b839802bd8267fa19b0530f5a08b9c08cd417976be2a65d130fe1c11b" +dependencies = [ + "rustls 0.20.4", "tokio", - "webpki", + "webpki 0.22.0", ] [[package]] @@ -13276,9 +13719,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.30" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d8d93354fe2a8e50d5953f5ae2e47a3fc2ef03292e7ea46e3cc38f549525fb9" +checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f" dependencies = [ "cfg-if 1.0.0", "log 0.4.14", @@ -13289,20 +13732,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8276d9a4a3a558d7b7ad5303ad50b53d58264641b82914b7ada36bd762e7a716" +checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] name = "tracing-core" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23" +checksum = "aa31669fa42c09c34d94d8165dd2012e8ff3c66aca50f3bb226b68f216f2706c" dependencies = [ "lazy_static", "valuable", @@ -13331,9 +13774,9 @@ dependencies = [ [[package]] name = "tracing-serde" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" dependencies = [ "serde", "tracing-core", @@ -13349,7 +13792,7 @@ dependencies = [ "chrono", "lazy_static", "matchers", - "parking_lot 0.10.2", + "parking_lot 0.11.2", "regex", "serde", "serde_json", @@ -13407,7 +13850,7 @@ dependencies = [ "ipnet", "lazy_static", "log 0.4.14", - "rand 0.8.4", + "rand 0.8.5", "smallvec 1.8.0", "thiserror", "tinyvec", @@ -13442,9 +13885,10 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "try-runtime-cli" version = "0.10.0-dev" -source = "git+https://github.com/composableFi/substrate?branch=polkadot-v0.9.16#d78e92de5aeaea1b4df48c639eb88d5b93cf19ef" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#22d40c761a985482f93bbbea5ba4199bdba74f8e" dependencies = [ - "jsonrpsee", + "clap 3.1.6", + "jsonrpsee 0.4.1", "log 0.4.14", "parity-scale-codec", "remote-externalities", @@ -13460,7 +13904,6 @@ dependencies = [ "sp-runtime", "sp-state-machine", "sp-version", - "structopt", "zstd", ] @@ -13488,7 +13931,7 @@ dependencies = [ "http", "httparse", "log 0.4.14", - "rand 0.8.4", + "rand 0.8.5", "sha-1 0.9.8", "thiserror", "url 2.2.2", @@ -13508,7 +13951,7 @@ dependencies = [ "httparse", "log 0.4.14", "native-tls", - "rand 0.8.4", + "rand 0.8.5", "sha-1 0.9.8", "thiserror", "url 2.2.2", @@ -13531,7 +13974,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee73e6e4924fe940354b8d4d98cad5231175d615cd855b758adc658c0aac6a0" dependencies = [ "cfg-if 1.0.0", - "rand 0.8.4", + "rand 0.8.5", "static_assertions", ] @@ -13600,9 +14043,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" +checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" [[package]] name = "unicode-width" @@ -13792,7 +14235,7 @@ dependencies = [ "futures-util", "headers", "http", - "hyper 0.14.16", + "hyper 0.14.17", "log 0.4.14", "mime 0.3.16", "mime_guess", @@ -13823,6 +14266,12 @@ version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "wasm-bindgen" version = "0.2.79" @@ -13846,7 +14295,7 @@ dependencies = [ "log 0.4.14", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", "wasm-bindgen-shared", ] @@ -13880,7 +14329,7 @@ checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -13917,7 +14366,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "js-sys", "parking_lot 0.11.2", "pin-utils", @@ -13958,9 +14407,9 @@ checksum = "98930446519f63d00a836efdc22f67766ceae8dbcc1571379f2bcabc6b2b9abc" [[package]] name = "wasmtime" -version = "0.33.0" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414be1bc5ca12e755ffd3ff7acc3a6d1979922f8237fc34068b2156cebcc3270" +checksum = "4c9c724da92e39a85d2231d4c2a942c8be295211441dbca581c6c3f3f45a9f00" dependencies = [ "anyhow", "backtrace", @@ -13990,9 +14439,9 @@ dependencies = [ [[package]] name = "wasmtime-cache" -version = "0.33.0" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9b4cd1949206fda9241faf8c460a7d797aa1692594d3dd6bc1cbfa57ee20d0" +checksum = "da4439d99100298344567c0eb6916ad5864e99e54760b8177c427e529077fb30" dependencies = [ "anyhow", "base64 0.13.0", @@ -14010,9 +14459,9 @@ dependencies = [ [[package]] name = "wasmtime-cranelift" -version = "0.33.0" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4693d33725773615a4c9957e4aa731af57b27dca579702d1d8ed5750760f1a9" +checksum = "1762765dd69245f00e5d9783b695039e449a7be0f9c5383e4c78465dd6131aeb" dependencies = [ "anyhow", "cranelift-codegen", @@ -14032,9 +14481,9 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "0.33.0" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b17e47116a078b9770e6fb86cff8b9a660826623cebcfff251b047c8d8993ef" +checksum = "c4468301d95ec71710bb6261382efe27d1296447711645e3dbabaea6e4de3504" dependencies = [ "anyhow", "cranelift-entity", @@ -14052,9 +14501,9 @@ dependencies = [ [[package]] name = "wasmtime-jit" -version = "0.33.0" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60ea5b380bdf92e32911400375aeefb900ac9d3f8e350bb6ba555a39315f2ee7" +checksum = "ab0ae6e581ff014b470ec35847ea3c0b4c3ace89a55df5a04c802a11f4574e7d" dependencies = [ "addr2line", "anyhow", @@ -14074,9 +14523,9 @@ dependencies = [ [[package]] name = "wasmtime-runtime" -version = "0.33.0" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abc7cd79937edd6e238b337608ebbcaf9c086a8457f01dfd598324f7fa56d81a" +checksum = "6d9c28877ae37a367cda7b52b8887589816152e95dde9b7c80cc686f52761961" dependencies = [ "anyhow", "backtrace", @@ -14089,7 +14538,7 @@ dependencies = [ "mach", "memoffset", "more-asserts", - "rand 0.8.4", + "rand 0.8.5", "region", "rustix", "thiserror", @@ -14099,9 +14548,9 @@ dependencies = [ [[package]] name = "wasmtime-types" -version = "0.33.0" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9e5e51a461a2cf2b69e1fc48f325b17d78a8582816e18479e8ead58844b23f8" +checksum = "395726e8f5dd8c57cb0db445627b842343f7e29ed7489467fdf7953ed9d3cd4f" dependencies = [ "cranelift-entity", "serde", @@ -14129,13 +14578,32 @@ dependencies = [ "untrusted", ] +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "webpki-roots" version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" dependencies = [ - "webpki", + "webpki 0.21.4", +] + +[[package]] +name = "webpki-roots" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552ceb903e957524388c4d3475725ff2c8b7960922063af6ce53c9a43da07449" +dependencies = [ + "webpki 0.22.0", ] [[package]] @@ -14196,8 +14664,8 @@ dependencies = [ [[package]] name = "westend-runtime" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "beefy-primitives", "bitvec", @@ -14282,8 +14750,8 @@ dependencies = [ [[package]] name = "westend-runtime-constants" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "frame-support", "polkadot-primitives", @@ -14352,6 +14820,49 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" + +[[package]] +name = "windows_i686_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" + +[[package]] +name = "windows_i686_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" + [[package]] name = "winreg" version = "0.6.2" @@ -14363,9 +14874,9 @@ dependencies = [ [[package]] name = "winreg" -version = "0.7.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ "winapi 0.3.9", ] @@ -14408,8 +14919,8 @@ dependencies = [ [[package]] name = "xcm" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "derivative", "impl-trait-for-tuples", @@ -14421,8 +14932,8 @@ dependencies = [ [[package]] name = "xcm-builder" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "frame-support", "frame-system", @@ -14439,10 +14950,34 @@ dependencies = [ "xcm-executor", ] +[[package]] +name = "xcm-emulator" +version = "0.1.0" +source = "git+https://github.com/shaunxw/xcm-simulator?rev=24ccbce563d1f99019b4cdfa2f3af4e99bac0dfc#24ccbce563d1f99019b4cdfa2f3af4e99bac0dfc" +dependencies = [ + "cumulus-pallet-dmp-queue", + "cumulus-pallet-parachain-system", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-core", + "cumulus-primitives-parachain-inherent", + "cumulus-test-relay-sproof-builder", + "frame-support", + "frame-system", + "parachain-info", + "parity-scale-codec", + "paste 1.0.6", + "polkadot-primitives", + "polkadot-runtime-parachains", + "sp-io", + "sp-std", + "xcm", + "xcm-executor", +] + [[package]] name = "xcm-executor" -version = "0.9.16" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "frame-benchmarking", "frame-support", @@ -14460,12 +14995,12 @@ dependencies = [ [[package]] name = "xcm-procedural" version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.16#41ab002d7451766324a9f314fee11c9c53314350" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" dependencies = [ "Inflector", "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", ] [[package]] @@ -14474,32 +15009,32 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7d9028f208dd5e63c614be69f115c1b53cacc1111437d4c765185856666c107" dependencies = [ - "futures 0.3.19", + "futures 0.3.21", "log 0.4.14", "nohash-hasher", "parking_lot 0.11.2", - "rand 0.8.4", + "rand 0.8.5", "static_assertions", ] [[package]] name = "zeroize" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c88870063c39ee00ec285a2f8d6a966e5b6fb2becc4e8dac77ed0d370ed6006" +checksum = "50344758e2f40e3a1fcfc8f6f91aa57b5f8ebd8d27919fe6451f15aaaf9ee608" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81e8f13fef10b63c06356d65d416b070798ddabcadc10d3ece0c5be9b3c7eddb" +checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ "proc-macro2 1.0.36", "quote 1.0.15", - "syn 1.0.86", + "syn 1.0.88", "synstructure", ] @@ -14531,3 +15066,103 @@ dependencies = [ "cc", "libc", ] + +[[patch.unused]] +name = "polkadot" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" + +[[patch.unused]] +name = "polkadot-node-subsystem-test-helpers" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" + +[[patch.unused]] +name = "polkadot-primitives-test-helpers" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" + +[[patch.unused]] +name = "polkadot-test-client" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" + +[[patch.unused]] +name = "polkadot-test-malus" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" + +[[patch.unused]] +name = "polkadot-test-runtime" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" + +[[patch.unused]] +name = "polkadot-test-service" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" + +[[patch.unused]] +name = "polkadot-voter-bags" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" + +[[patch.unused]] +name = "remote-ext-tests-bags-list" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" + +[[patch.unused]] +name = "staking-miner" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" + +[[patch.unused]] +name = "test-parachain-adder" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" + +[[patch.unused]] +name = "test-parachain-adder-collator" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" + +[[patch.unused]] +name = "test-parachain-halt" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" + +[[patch.unused]] +name = "test-parachains" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" + +[[patch.unused]] +name = "test-runtime-constants" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" + +[[patch.unused]] +name = "xcm-executor-integration-tests" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" + +[[patch.unused]] +name = "xcm-simulator" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" + +[[patch.unused]] +name = "xcm-simulator-example" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" + +[[patch.unused]] +name = "xcm-simulator-fuzzer" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" + +[[patch.unused]] +name = "zombienet-backchannel" +version = "0.9.17" +source = "git+https://github.com/composableFi/polkadot?branch=release-v0.9.17#1db48fed44a2b28648b464e6c3696fb40604dba0" diff --git a/Cargo.toml b/Cargo.toml index a15d7819a2a..2ff38226d79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,208 +1,150 @@ -[[bin]] -name = "composable" -path = "src/main.rs" - [package] -name = "composable" -version = "1.0.9" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2018" +homepage = "https://composable.finance" +name = "composable" +version = "1.0.0" + +[[bin]] +name = "composable" +path = "src/main.rs" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [dependencies] -composable-node = { path = "node", features = [ "composable", "dali" ] } color-eyre = { version = "0.5.11", default-features = false } +composable-node = { path = "node", features = ["composable", "dali"] } [features] -runtime-benchmarks = [ "composable-node/runtime-benchmarks" ] -std = [ "composable-node/std" ] - - +dali = [] +local-integration-tests = [] +picasso = [] +runtime-benchmarks = ["composable-node/runtime-benchmarks"] +std = ["composable-node/std"] [workspace] exclude = ["frame/transaction-fee"] members = [ - "runtime/common", - "runtime/primitives", - "frame/*", - "node", - "runtime/picasso", - "runtime/dali", - "runtime/composable", - "utils/price-feed", - "utils/collator-sidecar", - "integration-tests/simnode/simnode-node", - "integration-tests/simnode/simnode-tests", - "integration-tests/simnode/common", + "frame/*", + "integration-tests/local-integration-tests", + "node", + + "runtime/common", + "runtime/primitives", + "runtime/picasso", + "runtime/dali", + "runtime/composable", + + "utils/parachain-utils", + "utils/price-feed", + "utils/collator-sidecar", + "simnode/simnode-node", + "simnode/simnode-tests", + "simnode/common", ] [profile.release] # Polkadot runtime requires unwinding. +lto = false panic = "unwind" [profile.production] inherits = "release" lto = true -[patch."https://github.com/paritytech/substrate"] -frame-benchmarking ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -frame-support ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -frame-support-procedural ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -frame-support-procedural-tools ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -frame-support-procedural-tools-derive ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-arithmetic ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-debug-derive ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-std ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-core ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-core-hashing ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-externalities ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-storage ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-runtime-interface ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-runtime-interface-proc-macro ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-tracing ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-wasm-interface ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-io ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-keystore ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-state-machine ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-panic-handler ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-trie ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-runtime ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-application-crypto ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-api ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-api-proc-macro ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-version ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-version-proc-macro ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-block-builder ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-client-api ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -substrate-prometheus-endpoint ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-executor ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-executor-common ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-allocator ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-maybe-compressed-blob ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-serializer ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-executor-wasmi ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-executor-wasmtime ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-tasks ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -substrate-wasm-builder ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-core-hashing-proc-macro ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-tracing ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-rpc-server ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-tracing-proc-macro ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-blockchain ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-consensus ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-inherents ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-database ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-rpc ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -frame-system ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -frame-system-rpc-runtime-api ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-babe ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-authorship ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-authorship ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-session ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-timestamp ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-timestamp ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-session ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-staking ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-consensus-babe ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-consensus-slots ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-consensus-vrf ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -frame-election-provider-support ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-npos-elections ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-npos-elections-solution-type ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-service ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-chain-spec ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-chain-spec-derive ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-network ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -fork-tree ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-consensus ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-utils ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-peerset ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-finality-grandpa ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-telemetry ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-client-db ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-state-db ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-informant ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-transaction-pool-api ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-keystore ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-offchain ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-offchain ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-transaction-pool ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-transaction-pool ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-rpc ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-rpc-api ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-block-builder ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-transaction-storage-proof ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-balances ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-transaction-payment ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-offences ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-staking ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-bags-list ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-staking-reward-curve ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-consensus-aura ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-keyring ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -frame-benchmarking-cli ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-cli ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -frame-executive ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -frame-system-benchmarking ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-aura ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-grandpa ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-randomness-collective-flip ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-sudo ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-transaction-payment-rpc-runtime-api ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-transaction-payment-rpc ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-basic-authorship ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-proposer-metrics ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-consensus-aura ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-consensus-slots ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-finality-grandpa ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-network-gossip ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -substrate-frame-rpc-system ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -substrate-build-script-utils ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -frame-try-runtime ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-authority-discovery ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sp-authority-discovery ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-bounties ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-treasury ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-collective ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-utility ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-democracy ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-scheduler ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-election-provider-multi-phase ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-gilt ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-identity ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-im-online ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-indices ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-membership ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-mmr ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-preimage ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-mmr-primitives ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-multisig ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-offences-benchmarking ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-proxy ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-recovery ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-session-benchmarking ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-society ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-tips ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-vesting ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-mmr-rpc ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-consensus-babe ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-consensus-epochs ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-consensus-babe-rpc ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-finality-grandpa-rpc ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-sync-state-rpc ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-authority-discovery ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-consensus-uncles ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -try-runtime-cli ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -remote-externalities ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -beefy-gadget ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -beefy-primitives ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -beefy-gadget-rpc ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -sc-consensus-manual-seal ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-beefy ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-beefy-mmr ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -beefy-merkle-tree ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-nicks ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } -pallet-staking-reward-fn ={git = "https://github.com/composableFi/substrate" ,branch = "polkadot-v0.9.16" } +[patch."https://github.com/paritytech/polkadot"] +bp-header-chain = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +bp-message-dispatch = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +bp-messages = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +bp-polkadot-core = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +bp-rococo = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +bp-runtime = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +bp-test-utils = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +bp-wococo = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +bridge-runtime-common = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +kusama-runtime = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +kusama-runtime-constants = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +metered-channel = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +pallet-bridge-dispatch = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +pallet-bridge-grandpa = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +pallet-bridge-messages = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +pallet-xcm = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +pallet-xcm-benchmarks = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-approval-distribution = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-availability-bitfield-distribution = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-availability-distribution = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-availability-recovery = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-cli = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-client = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-collator-protocol = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-core-primitives = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-dispute-distribution = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-erasure-coding = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-gossip-support = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-network-bridge = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-collation-generation = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-core-approval-voting = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-core-av-store = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-core-backing = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-core-bitfield-signing = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-core-candidate-validation = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-core-chain-api = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-core-chain-selection = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-core-dispute-coordinator = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-core-parachains-inherent = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-core-provisioner = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-core-pvf = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-core-pvf-checker = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-core-runtime-api = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-jaeger = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-metrics = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-network-protocol = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-primitives = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-subsystem = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-subsystem-test-helpers = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-subsystem-types = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-node-subsystem-util = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-overseer = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-overseer-gen = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-overseer-gen-proc-macro = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-parachain = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-performance-test = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-primitives = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-primitives-test-helpers = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-rpc = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-runtime = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-runtime-common = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-runtime-constants = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-runtime-metrics = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-runtime-parachains = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-service = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-statement-distribution = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-statement-table = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-test-client = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-test-malus = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-test-runtime = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-test-service = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +polkadot-voter-bags = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +remote-ext-tests-bags-list = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +rococo-runtime = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +rococo-runtime-constants = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +slot-range-helper = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +staking-miner = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +test-parachain-adder = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +test-parachain-adder-collator = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +test-parachain-halt = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +test-parachains = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +test-runtime-constants = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +westend-runtime = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +westend-runtime-constants = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +xcm = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +xcm-builder = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +xcm-executor = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +xcm-executor-integration-tests = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +xcm-procedural = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +xcm-simulator = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +xcm-simulator-example = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +xcm-simulator-fuzzer = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } +zombienet-backchannel = { git = "https://github.com/composableFi/polkadot", branch = "release-v0.9.17" } diff --git a/Makefile b/Makefile index a77219d3452..c065192ae5e 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,8 @@ style-check: style: @rustup component add rustfmt 2> /dev/null - cargo +nightly fmt --all + cargo install taplo-cli 2> /dev/null + cargo +nightly fmt --all && taplo fmt lint: @rustup component add clippy 2> /dev/null @@ -56,10 +57,10 @@ version: .PHONY: containerize-release containerize-release: version containerize -containerize: +containerize: @docker build \ --build-arg SERVICE_DIR=${INSTALL_DIR} --build-arg VERSION=${RELEASE_VERSION} \ - -f ${INSTALL_DIR}/Dockerfile \ + -f ${INSTALL_DIR}/Dockerfile \ -t ${IMAGE_WITH_COMMIT} \ -t ${IMAGE_WITH_RELEASE_VERSION} \ -t ${IMAGE_WITH_BRANCH} \ @@ -75,6 +76,32 @@ push: push-release: @docker push ${IMAGE_WITH_RELEASE_VERSION} +containerize-composable-sandbox: + @docker build -f docker/composable-sandbox.dockerfile \ + -t ${REPO}/composable-sandbox:${COMMIT_SHA} \ + -t ${REPO}/composable-sandbox:latest \ + . + +push-composable-sandbox: + @docker push ${REPO}/composable-sandbox:${COMMIT_SHA} + @docker push ${REPO}/composable-sandbox:latest + +containerize-mmr-polkadot: + @docker build -f docker/mmr-polkadot.dockerfile \ + -t ${REPO}/mmr-polkadot:latest \ + . + +push-mmr-polkadot: + @docker push ${REPO}/mmr-polkadot:latest + +containerize-ci-linux: + @docker build -f docker/ci-linux.dockerfile \ + -t ${REPO}/ci-linux:production \ + . + +push-ci-linux: + @docker push ${REPO}/ci-linux:production + stop: @docker-compose down @@ -88,7 +115,8 @@ endif .PHONY: build test docs style-check lint udeps containerize dev push install stop containerize-release push-release - +.PHONY: containerize-composable-sandbox push-composable-sandbox containerize-mmr-polkadot push-mmr-polkadot +.PHONY: containerize-ci-linux push-ci-linux #---------------------------------------------------------------------- # UTILITY FUNCTIONS TO remove diff --git a/Makefile.toml b/Makefile.toml index aaa1f7870ef..4633dfb3917 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -3,29 +3,68 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true [tasks.fmt] -workspace = false script = ''' cargo +nightly fmt ''' +workspace = false [tasks.build] -workspace = false args = ["build", "--release"] +workspace = false [tasks.polkadot] -workspace = false script = ''' if [ ! -d "../polkadot" ] ; then - git clone -b v0.9.16 https://github.com/paritytech/polkadot ../polkadot + git clone -b v0.9.17 https://github.com/paritytech/polkadot ../polkadot fi cd ../polkadot && cargo build --release ''' - -[tasks.devnet] workspace = false -dependencies = ["build", "polkadot"] + +[tasks.start-devnet] +dependencies = ["build", "git-polkadot"] script = ''' cargo run --release -- --version cd ../polkadot && cargo run --release -- --version && pwd && cd ../composable cd scripts/polkadot-launch && yarn && yarn composable -''' \ No newline at end of file +''' +workspace = false + +[tasks.start-devnet-docker] +dependencies = [] +script = ''' +docker run --rm -ti -u$(id -u):$(id -g) -p9944:9944 -p9988:9988 -p9998:9998 composablefi/composable-sandbox:latest +''' +workspace = false + +[tasks.remove-composable-sandbox-image] +dependencies = [] +script = ''' +docker rmi composablefi/composable-sandbox:latest +''' +workspace = false + +[tasks.run-local-integration-tests] +script = ''' +# we cannot use toolchain setting as different parts of codebase require different compiler +cargo +stable test --package local-integration-tests --features local-integration-tests --no-default-features +''' +workspace = false + +[tasks.run-local-integration-tests-debug] +script = ''' +RUST_BACKTRACE=full RUST_LOG=trace,parity-db=warn,trie=warn,runtime=trace,substrate-relay=trace,bridge=trace,xcmp=trace cargo +stable test --package local-integration-tests --features local-integration-tests --features picasso --no-default-features -- --nocapture --test-threads=1 +''' +workspace = false + +[tasks.check-ci] +script = ''' +SKIP_WASM_BUILD=1 cargo +nightly check --benches --all # checks all rust crates with default-features, tests, benchmarks +''' +workspace = false + +[tasks.build-benchmarks] +script = ''' +cargo build --release --features runtime-benchmarks +''' +workspace = false diff --git a/clippy.toml b/clippy.toml index 09c4e1c8419..afb52b4117b 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1,6 +1,6 @@ disallowed-methods = [ - "core::result::Result::unwrap", # { path = "core::result::Result::unwrap", reason = "Errors should be handled properly. If panicking is valid in this context, make sure to write a comment explaining why." }, - "core::option::Option::unwrap", # { path = "core::option::Option::unwrap", reason = "Errors should be handled properly. If panicking is valid in this context, make sure to write a comment explaining why." }, + "core::result::Result::unwrap", # { path = "core::result::Result::unwrap", reason = "Errors should be handled properly. If panicking is valid in this context, make sure to write a comment explaining why." }, + "core::option::Option::unwrap", # { path = "core::option::Option::unwrap", reason = "Errors should be handled properly. If panicking is valid in this context, make sure to write a comment explaining why." }, ] disallowed-types = ["frame_support::storage::types::ValueQuery"] diff --git a/deny.toml b/deny.toml index 02e7f9a52c0..9a4fbe081e7 100644 --- a/deny.toml +++ b/deny.toml @@ -22,13 +22,13 @@ # dependencies not shared by any other crates, would be ignored, as the target # list here is effectively saying which targets you are building for. targets = [ - # The triple can be any string, but only the target triples built in to - # rustc (as of 1.40) can be checked against actual config expressions - #{ triple = "x86_64-unknown-linux-musl" }, - # You can also specify which target_features you promise are enabled for a - # particular target. target_features are currently not validated against - # the actual valid features supported by the target architecture. - #{ triple = "wasm32-unknown-unknown", features = ["atomics"] }, + # The triple can be any string, but only the target triples built in to + # rustc (as of 1.40) can be checked against actual config expressions + #{ triple = "x86_64-unknown-linux-musl" }, + # You can also specify which target_features you promise are enabled for a + # particular target. target_features are currently not validated against + # the actual valid features supported by the target architecture. + #{ triple = "wasm32-unknown-unknown", features = ["atomics"] }, ] # This section is considered when running `cargo deny check advisories` @@ -52,7 +52,7 @@ notice = "warn" # A list of advisory IDs to ignore. Note that ignored advisories will still # output a note when they are encountered. ignore = [ - #"RUSTSEC-0000-0000", + #"RUSTSEC-0000-0000", ] # Threshold for security vulnerabilities, any vulnerability with a CVSS score # lower than the range specified will be ignored. Note that ignored advisories @@ -74,15 +74,15 @@ unlicensed = "deny" # See https://spdx.org/licenses/ for list of possible licenses # [possible values: any SPDX 3.11 short identifier (+ optional exception)]. allow = [ - #"MIT", - #"Apache-2.0", - #"Apache-2.0 WITH LLVM-exception", + #"MIT", + #"Apache-2.0", + #"Apache-2.0 WITH LLVM-exception", ] # List of explicitly disallowed licenses # See https://spdx.org/licenses/ for list of possible licenses # [possible values: any SPDX 3.11 short identifier (+ optional exception)]. deny = [ - #"Nokia", + #"Nokia", ] # Lint level for licenses considered copyleft copyleft = "warn" @@ -106,9 +106,9 @@ confidence-threshold = 0.8 # Allow 1 or more licenses on a per-crate basis, so that particular licenses # aren't accepted for every possible crate as with the normal allow list exceptions = [ - # Each entry is the crate and version constraint, and its specific allow - # list - #{ allow = ["Zlib"], name = "adler32", version = "*" }, + # Each entry is the crate and version constraint, and its specific allow + # list + #{ allow = ["Zlib"], name = "adler32", version = "*" }, ] # Some crates don't have (easily) machine readable licensing information, @@ -127,8 +127,8 @@ exceptions = [ # and the crate will be checked normally, which may produce warnings or errors # depending on the rest of your configuration #license-files = [ - # Each entry is a crate relative path, and the (opaque) hash of its contents - #{ path = "LICENSE", hash = 0xbd0eed23 } +# Each entry is a crate relative path, and the (opaque) hash of its contents +#{ path = "LICENSE", hash = 0xbd0eed23 } #] [licenses.private] @@ -141,7 +141,7 @@ ignore = false # is only published to private registries, and ignore is true, the crate will # not have its license(s) checked registries = [ - #"https://sekretz.com/registry + #"https://sekretz.com/registry ] # This section is considered when running `cargo deny check bans`. @@ -161,38 +161,38 @@ wildcards = "allow" highlight = "lowest-version" # List of crates that are allowed. Use with care! allow = [ - #{ name = "ansi_term", version = "=0.11.0" }, + #{ name = "ansi_term", version = "=0.11.0" }, ] # List of crates to deny deny = [ - # Each entry the name of a crate and a version range. If version is - # not specified, all versions will be matched. - #{ name = "ansi_term", version = "=0.11.0" }, - # - # Wrapper crates can optionally be specified to allow the crate when it - # is a direct dependency of the otherwise banned crate - #{ name = "ansi_term", version = "=0.11.0", wrappers = [] }, + # Each entry the name of a crate and a version range. If version is + # not specified, all versions will be matched. + #{ name = "ansi_term", version = "=0.11.0" }, + # + # Wrapper crates can optionally be specified to allow the crate when it + # is a direct dependency of the otherwise banned crate + #{ name = "ansi_term", version = "=0.11.0", wrappers = [] }, ] # Certain crates/versions that will be skipped when doing duplicate detection. skip = [ - # unfortunately substrate itself depends on several versions, to allow for it - { name = "wasi", version = "=0.10.0+wasi-snapshot-preview1" }, - { name = "smallvec", version = "=0.6.14" }, - { name = "sha2", version = "=0.9.9" }, - { name = "semver", version = "=1.0.4" }, - { name = "rustc_version", version = "=0.4.0" }, - { name = "redox_syscall", version = "=0.2.10" }, - { name = "pbkdf2", version = "=0.8.0" }, - { name = "rand_xorshift", version = "=0.3.0" }, - { name = "rand_pcg", version = "=0.2.1" }, - { name = "opaque-debug", version = "=0.3.0" }, + # unfortunately substrate itself depends on several versions, to allow for it + { name = "wasi", version = "=0.10.0+wasi-snapshot-preview1" }, + { name = "smallvec", version = "=0.6.14" }, + { name = "sha2", version = "=0.9.9" }, + { name = "semver", version = "=1.0.4" }, + { name = "rustc_version", version = "=0.4.0" }, + { name = "redox_syscall", version = "=0.2.10" }, + { name = "pbkdf2", version = "=0.8.0" }, + { name = "rand_xorshift", version = "=0.3.0" }, + { name = "rand_pcg", version = "=0.2.1" }, + { name = "opaque-debug", version = "=0.3.0" }, ] # Similarly to `skip` allows you to skip certain crates during duplicate # detection. Unlike skip, it also includes the entire tree of transitive # dependencies starting at the specified crate, up to a certain depth, which is # by default infinite skip-tree = [ - #{ name = "ansi_term", version = "=0.11.0", depth = 20 }, + #{ name = "ansi_term", version = "=0.11.0", depth = 20 }, ] # This section is considered when running `cargo deny check sources`. diff --git a/docker/ci-linux.dockerfile b/docker/ci-linux.dockerfile new file mode 100644 index 00000000000..32034a0c56c --- /dev/null +++ b/docker/ci-linux.dockerfile @@ -0,0 +1,7 @@ +FROM paritytech/ci-linux:production + +RUN rustup toolchain uninstall nightly-2021-11-08 && \ + rustup toolchain uninstall nightly && \ + rustup toolchain install nightly-2021-11-29 && \ + rustup target install wasm32-unknown-unknown --toolchain nightly-2021-11-29 && \ + ln -s "${RUSTUP_HOME}/toolchains/nightly-2021-11-29-x86_64-unknown-linux-gnu" "${RUSTUP_HOME}/toolchains/nightly-x86_64-unknown-linux-gnu" diff --git a/docker/composable-sandbox.dockerfile b/docker/composable-sandbox.dockerfile new file mode 100644 index 00000000000..cde2f3439c4 --- /dev/null +++ b/docker/composable-sandbox.dockerfile @@ -0,0 +1,53 @@ +FROM debian:11-slim as builder +LABEL description="Docker image with Composable" + +ARG NIGHTLY_VERSION=nightly + +ENV DEBIAN_FRONTEND=noninteractive + +COPY . /build +WORKDIR /build + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +RUN apt-get update && apt-get install -y --no-install-recommends apt-utils ca-certificates clang curl git libssl-dev llvm libudev-dev && \ + curl https://sh.rustup.rs -sSf | sh -s -- -y && \ + export PATH="$PATH:$HOME/.cargo/bin" && \ + rustup default stable && \ + rustup update && \ + rustup update ${NIGHTLY_VERSION} && \ + rustup target add wasm32-unknown-unknown --toolchain ${NIGHTLY_VERSION} && \ + cargo build --release + +# ===== SECOND STAGE ====== + +FROM composablefi/mmr-polkadot:latest as mmr-polkadot + +FROM debian:11-slim + +ENV DEBIAN_FRONTEND=noninteractive + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +RUN groupadd -g 1000 service && useradd -m -s /bin/sh -g 1000 -G service service && \ + mkdir -p /apps/composable/scripts /apps/composable/target/release /apps/Basilisk-node/target/release /apps/polkadot/target/release && \ + apt-get update && apt-get install -y --no-install-recommends apt-utils ca-certificates curl git && \ + curl -fsSL https://deb.nodesource.com/setup_17.x | bash - && \ + apt-get update && apt-get install -y --no-install-recommends nodejs && \ + npm install --global npm yarn && \ + curl https://github.com/galacticcouncil/Basilisk-node/releases/download/v7.0.0/basilisk -Lo /apps/Basilisk-node/target/release/basilisk && \ + chmod +x /apps/Basilisk-node/target/release/basilisk && \ + apt-get clean && \ + find /var/lib/apt/lists/ -type f -not -name lock -delete; + +COPY --from=builder /build/target/release/composable /apps/composable/target/release/ +COPY --from=mmr-polkadot /polkadot /apps/polkadot/target/release/ +COPY ./scripts/polkadot-launch /apps/composable/scripts/polkadot-launch + +WORKDIR /apps/composable/scripts/polkadot-launch + +RUN chown -R service /apps/composable/scripts/polkadot-launch && \ + yarn && \ + sed -i 's/"--rpc-cors=all"/"--rpc-cors=all", "--ws-external", "--unsafe-rpc-external", "--rpc-methods=unsafe"/' composable_and_basilisk.json + +USER service +EXPOSE 9945 9988 9998 +ENTRYPOINT ["yarn", "composable_and_basilisk"] diff --git a/docker/mmr-polkadot.dockerfile b/docker/mmr-polkadot.dockerfile new file mode 100644 index 00000000000..cf49fc6df71 --- /dev/null +++ b/docker/mmr-polkadot.dockerfile @@ -0,0 +1,26 @@ +FROM debian:11-slim as builder + +ARG NIGHTLY_VERSION=nightly + +ENV DEBIAN_FRONTEND=noninteractive + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +RUN apt-get update && apt-get install -y --no-install-recommends apt-utils build-essential ca-certificates clang curl git libclang-dev libudev-dev llvm pkg-config && \ + curl https://sh.rustup.rs -sSf | sh -s -- -y && \ + export PATH="$PATH:$HOME/.cargo/bin" && \ + rustup default stable && \ + rustup update && \ + rustup update ${NIGHTLY_VERSION} && \ + rustup target add wasm32-unknown-unknown --toolchain ${NIGHTLY_VERSION} && \ + git clone -b mmr-polkadot-v0.9.17 https://github.com/composableFi/polkadot + +WORKDIR /polkadot + +RUN export PATH="$PATH:$HOME/.cargo/bin" && \ + cargo build --release + +# ===== SECOND STAGE ====== + +FROM debian:11-slim + +COPY --from=builder /polkadot/target/release/polkadot / diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index a514bb30fa7..e0ee003074f 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -4,7 +4,7 @@ We have a few guidelines and requirements to ensure correct workflows are follow ## First Things First Before contributing, go through the documentation found in `~/docs/`. Specifically: -* [rust-setup.md](./rust-setup.md) ― A walkthrough for installing and configuring Rust and other tools in your develop ment environment +* [rust-setup.md](./rust-setup.md) ― A walkthrough for installing and configuring Rust and other tools in your development environment * [proptest.md](./proptest.md) ― A guide to our approach and philosophy for automated testing * [benchmarking.md](./benchmarking.md) ― A guide for benchmarking pallet changes diff --git a/docs/benchmarking.md b/docs/benchmarking.md index e9ab9e34d0e..a58f7f1d6f2 100644 --- a/docs/benchmarking.md +++ b/docs/benchmarking.md @@ -170,7 +170,7 @@ add_benchmark!(params, batches, balances, Balances); // ... ``` -or [define_benchmarks](https://github.com/paritytech/substrate/blob/master/frame/benchmarking/src/lib.rs#L1834-L1869) macro (it's available starting with `polkadot-v0.9.16` branch): +or [define_benchmarks](https://github.com/paritytech/substrate/blob/master/frame/benchmarking/src/lib.rs#L1834-L1869) macro (it's available starting with `polkadot-v0.9.17` branch): ```rust define_benchmarks!( @@ -185,15 +185,14 @@ https://github.com/paritytech/substrate/blob/master/frame/benchmarking/src/lib.r https://crates.io/crates/frame-benchmarking Extra: -If we are running the latest version of the frame-benchmarking dependency we can also add our pallet to the [benchmark_metadata](https://github.com/paritytech/substrate/blob/polkadot-v0.9.16/frame/benchmarking/src/utils.rs#L150) function. +If we are running the latest version of the frame-benchmarking dependency we can also add our pallet to the [benchmark_metadata](https://github.com/paritytech/substrate/blob/polkadot-v0.9.17/frame/benchmarking/src/utils.rs#L150) function. ## Compile and run -Now when we have everything we need, we want to build it and enable -the runtime-benchmarks features, which are optional. +Now when we have everything we need, we want to build it: ```shell -$ cargo build --release --features runtime-benchmarks +cargo make build-benchmarks ``` ## Run the benchmarks @@ -216,4 +215,3 @@ https://www.shawntabrizi.com/substrate-graph-benchmarks/docs/#/ https://substrate.dev/docs/en/knowledgebase/runtime/benchmarking https://crates.io/crates/frame-benchmarking https://github.com/paritytech/substrate/tree/polkadot-v0.9.8/frame/benchmarking - diff --git a/docs/custom-rpcs.md b/docs/custom-rpcs.md new file mode 100644 index 00000000000..5db30c00f42 --- /dev/null +++ b/docs/custom-rpcs.md @@ -0,0 +1,383 @@ +# Adding an RPC interface to a pallet + +Create 2 new crates beside the `src/` folder of the pallet you want to add the RPC to: + +```plaintext +frame + pallet + src + Cargo.toml + rpc + src + Cargo.toml + runtime-api + src + Cargo.toml +``` + +## Runtime API Crate + +### In `Cargo.toml` + +```toml +[package] +name = "pallet-name-runtime-api" +version = "0.0.1" +authors = ["Composable Developers"] +homepage = "https://composable.finance" +edition = "2021" +rust-version = "1.56" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +codec = { default-features = false, features = ["derive"], package = "parity-scale-codec", version = "2.0.0" } + +# ...any other dependencies, as per usual + +[features] +default = ["std"] +std = ["sp-api/std"] + +``` + +### In `lib.rs` + +```rust +#![cfg_attr(not(feature = "std"), no_std)] +#![allow(clippy::too_many_arguments)] // REVIEW: I'm not sure if these are actually necessary +#![allow(clippy::unnecessary_mut_passed)] // REVIEW: I'm not sure if these are actually necessary + +sp_api::decl_runtime_apis! { + pub trait PalletNameRuntimeApi + where + GENERIC_PARAMETER: codec::Codec, // all parameters must implement `Codec` + { + fn rpc_function_name(/* ...parameters... */) -> ReturnType; + + // as many rpcs as are needed for the pallet can all be defined here in the same trait + } +} +``` + +## RPC Crate + +### In `Cargo.toml` + +```toml +[package] +name = "PALLET-NAME-rpc" +version = "0.0.1" +authors = ["Composable Developers"] +homepage = "https://composable.finance" +edition = "2021" +rust-version = "1.56" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +# substrate primitives +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } + +# SCALE +scale-info = { version = "1.0", features = ["derive"] } +codec = { version = "2.0.0", package = "parity-scale-codec", features = ["derive"] } + +# local +pallet-name-runtime-api = { path = "../runtime-api" } + +# rpc +jsonrpc-core = "18.0.0" +jsonrpc-core-client = "18.0.0" +jsonrpc-derive = "18.0.0" +``` + +Note that this crate will only be included in the node and not the runtime, so there is no need for a `std` feature. + +### In `lib.rs` + +Required imports: + +```rust +use pallet_name_runtime_api::PalletNameRuntimeApi; +use codec::Codec; +use jsonrpc_core::{Error as RpcError, ErrorCode, Result as RpcResult}; +use jsonrpc_derive::rpc; +use sp_api::ProvideRuntimeApi; +use sp_blockchain::HeaderBackend; +use sp_runtime::{generic::BlockId, traits::Block as BlockT}; +use sp_std::{sync::Arc, marker::PhantomData}; +``` + +This defines the RPC itself. The name of the RPC needs to follow the pattern of `moduleName_functionName`. + +**Note**: Any types that either are or are a wrapper type around `u128/i128` will need to be wrapped in `composable_support::rpc_helpers::SafeRpcWrapper`. + +```rust +#[rpc] +pub trait PalletNameApi +where + GENERIC_PARAMETER: Codec, // if the type is a u128/i128, this should be SafeRpcWrapperType instead of Codec (Codec is a supertrait of SafeRpcWrapperType) +{ + // the name of the rpc must be moduleName_functionName, where both module + // and function are camelCase and are seperated by an underscore. + #[rpc(name = "palletName_rpcFunctionName")] + fn rpc_function_name( + &self, + // any additional parameters here + // if the type is or wraps a 128 bit integer, it should be declared as follows: + u128_ish: SafeRpcWrapper + at: Option, // `at` should be last + ) -> RpcResult; +} +``` + +This is a struct that will implement the above API. It contains the client to make the RPC calls. + +If there are more generics, instead of adding more parameters (`PalletName`), just use a tuple instead: `PalletName { + client: Arc, + _marker: PhantomData, +} + +impl PalletName { + pub fn new(client: Arc) -> Self { + Self { client, _marker: Default::default() } + } +} +``` + +```rust +impl + PalletNameApi<::Hash, /* ...any generic parameters... */> + for PalletName +where + Block: BlockT, + // all generic parameters must have at least these bounds + // if the type is a u128/i128, this should be SafeRpcWrapperType instead of Codec (Codec is a supertrait of SafeRpcWrapperType) + GENERIC_PARAMETER: Codec + Send + Sync + 'static, + C: Send + Sync + 'static, + C: ProvideRuntimeApi, + C: HeaderBackend, + C::Api: PalletNameRuntimeApi, +{ + fn rpc_function_name( + &self, + // any additional parameters here + // if the type is or wraps a 128 bit integer, it should be declared as follows: + u128_ish: SafeRpcWrapper + at: Option<::Hash>, // `at` should be last + ) -> RpcResult { + let api = self.client.runtime_api(); + let at = BlockId::hash(at.unwrap_or_else(|| { + // If the block hash is not supplied assume the best block. + self.client.info().best_hash + })); + + let runtime_api_result = api.rpc_function_name(&at, asset_id, account_id); + // TODO(benluelo): Review what error message & code to use + runtime_api_result.map_err(|e| { + RpcError { + code: ErrorCode::ServerError(9876), // No real reason for this value + message: "Something wrong".into(), + data: Some(format!("{:?}", e).into()), + } + }) + } +} +``` + +## In `node/` + +The RPC needs to be added to the node in order to be called. First, add both the above crates to `node/Cargo.toml`: + +```toml +[dependencies] +# ...stub... +pallet-name-rpc = { path = "../frame/pallet-name/rpc" } +pallet-name-runtime-api = { path = "../frame/pallet-name/runtime-api" } +``` + +Then, in `node/src/runtime.rs`, add a bound in both the definition and blanket impl for `HostRuntimeApis`: + +```rust +pub trait HostRuntimeApis: + // ...stub... + + pallet_name_runtime_api::PalletNameRuntimeApi, + // ...stub... + +impl HostRuntimeApis for Api +where + Api: // ...stub... + + pallet_name_runtime_api::PalletNameRuntimeApi, + // ...stub... +``` + +Then, in `node/src/rpc.rs`, in `fn create(...)`, add a bound to `C::Api`, and then within the function, add the RPC to the runtime: + +```rust +pub fn create(deps: FullDeps) -> jsonrpc_core::IoHandler +where + // ...stub... + C::Api: pallet_name_runtime_api::PalletNameRuntimeApi, + // ...stub... +{ + // ...stub... + io.extend_with(CrowdloanRewardsApi::to_delegate(CrowdloanRewards::new(client))); + + io +} +``` + +## Add to runtimes + +Within each runtime's `Cargo.toml`, add the runtime-api dependency: + +```toml +# ...stub... +[dependencies] +pallet-name-runtime-api = { path = '../../frame/pallet-name/runtime-api', default-features = false } +# ...stub... +``` + +And then in each runtime's `lib.rs`, in the `impl_runtime_apis!` macro, implement the API: + +```rust +impl_runtime_apis! { + impl pallet_name_runtime_api::PalletNameRuntimeApi for Runtime { + fn rpc_function_name(/* ...rpc parameters... */) -> ReturnType { + // actual implementation here + } + } + // ...stub... +} +``` + +Note that this assumes that the pallet has already been added to the runtime and the pallet's `Config` already implemented. + +## Integration Tests + +/home/ben/codeprojects/composable/integration-tests/runtime-tests/src/types/interfaces/definitions.ts + +### Type Definitions + +Create a folder here: `integration-tests/runtime-tests/src/types/interfaces/pallet-name` + +And then within that folder, create a file `defintions.ts` with the following structure: + +```typescript +export default { + rpc: { + // the functionName part of the RPC call as defined in the `#[rpc(name="")]` annotation on the rust definition + rpcFunctionName: { + description: "Provide a short description of the RPC here.", + params: [ + // define the paramaters in the same order as defined in the rust RPC + { + name: "parameter_name", + type: "ParameterType" + }, + // see note below + { + name: "at", + type: "Hash", + isOptional: true, + }, + ], + type: "ReturnType" + }, + // if there are multiple RPCs, they can all be defined here + }, + types: { + // define any custom types for the pallet here + // see the note below for more information + }, +}; +``` + +Then, in `integration-tests/runtime-tests/src/types/interfaces/definitions.ts`, add the following line: + +```typescript +export { default as palletName } from "./palletName/definitions"; +``` + +Notes: + +* `at` is mandatory, and is defined as the last parameter in the rust RPC definition for a reason: + Most of the time when calling an RPC the block hash can be omitted, and the best hash will be assumed if one is not provided. + + Having it as the last parameter makes calling the RPC simpler: + + ```typescript + palletName.rpcFunctionName(param1, param2) + ``` + + Instead of: + + ```typescript + palletName.rpcFunctionName(null, param1, param2) + ``` + + If `at` were defined first. + + Technically, it is possible to define `at` anywhere in the RPC definition, but putting it last for all of them makes the RPCs simpler and more consistent. + +* If this is a preexisting pallet, the types for it are most likely already defined in the type definitions for `crowdloanRewards` (for reasons that don't need to be covered in this document) and can just be moved over to this file. + + Even if there are no types to declare, still define an empty object or else everything will explode. + +### Tests + +Create a folder here (if it doesn't already exist): `integration-tests/runtime-tests/test/tests/pallet-name` + +And then within that folder, create a file `rpcPalletNameTests.ts` with the following structure: + +```typescript +/* eslint-disable no-trailing-spaces */ +import { /* any custom defined types that are needed for the RPC */ } from '@composable/types/interfaces'; +import { expect } from 'chai'; + + +describe('query.palletName.account Tests', function() { + // Set timeout to 1 minute. + this.timeout(60*1000); // <- increaase this if tests are timing out + + // repeat this block as needed for every test case defined in the class below. + it('rpc.palletName.functionName Tests', async function() { + await RpcPalletNameTests.rpcPalletNameFunctionNameTest(); + }); +}); + + +export class RpcPalletNameTests { + /** + * + */ + public static async rpcPalletNameFunctionNameTest() { + // api is a global variable + const result = await api.rpc.palletName.functionName(/* parameters */); + + // see note below about bignumbers + // (this is just an example assertion) + expect(result).to.be.a["bignumber"].that.equals('0'); + } +} +``` + +Notes: + +* If the type being compared against is a `u128`/`i128` on the rust side and has been wrapped in `SafeRpcWrapper`, it will be a bn.js `BN` (big number) here. `chai-bn` is used for asssertions with `BN`s but typescript can't quite figure out that it's being used; using `["bignumber"]` instead of `.bignumber` circumvents the typechecker a bit and allows it to pass without a `@ts-ignore` comment. + + Thanks Dominik for figuring this one out! + +## Additional Resources + +For a good overview of how custom RPCs work, see . diff --git a/docs/glossary.md b/docs/glossary.md new file mode 100644 index 00000000000..d5255ef8e89 --- /dev/null +++ b/docs/glossary.md @@ -0,0 +1,3 @@ + + +ED - existential deposit \ No newline at end of file diff --git a/docs/runtime-testing.md b/docs/runtime-testing.md new file mode 100644 index 00000000000..682215e44c5 --- /dev/null +++ b/docs/runtime-testing.md @@ -0,0 +1,17 @@ +# Overview + +Runtime testing involves running parachain code to ensure quality. +Unlike type system or static analysis (unluding basic linting). +Here is hierarchy of testing you may find in this parachain + +| Name | Runtime | Warp | Start from real state | Serde | +| ------------- | --------- | ---- | --------------------- | ----- | +| Unit | no | yes | no | no | +| Runtime Unit | mock | yes | yes | +| Property test | mock | yes | +| Benchmark | mock/real | yes | +| Visualization | no/mock | yes | +| Simulation | real | yes | yes | +| Simnode | real | yes | yes | +| Local Relay | real | no | | +| Deployment | real | no | | \ No newline at end of file diff --git a/frame/assets-registry/Cargo.toml b/frame/assets-registry/Cargo.toml index cfe68c5ab31..cd7b3246a23 100644 --- a/frame/assets-registry/Cargo.toml +++ b/frame/assets-registry/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "pallet-assets-registry" -version = "0.1.0" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" +homepage = "https://composable.finance" +name = "pallet-assets-registry" +version = "0.1.0" [package.metadata.docs.rs] @@ -21,40 +21,42 @@ version = "2.0.0" [dependencies] composable-traits = { path = "../composable-traits", default-features = false } -frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.16" } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -xcm = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +xcm = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17" } log = { version = "0.4.14", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } [dev-dependencies] -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } [features] default = ["std"] std = [ - "codec/std", - "log/std", - "composable-traits/std", - "scale-info/std", - "frame-support/std", - "frame-system/std", - "sp-runtime/std", - "sp-io/std", - "sp-core/std", - "sp-std/std", - "xcm/std", + "codec/std", + "log/std", + "composable-traits/std", + "scale-info/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-io/std", + "sp-core/std", + "sp-std/std", + "xcm/std", ] runtime-benchmarks = [ - 'frame-benchmarking', - 'frame-support/runtime-benchmarks', - 'frame-system/runtime-benchmarks', + 'frame-benchmarking', + 'frame-support/runtime-benchmarks', + 'frame-system/runtime-benchmarks', ] diff --git a/frame/assets-registry/local-mapping.plantuml b/frame/assets-registry/local-mapping.plantuml index 7da062033fd..c76f0acb418 100644 --- a/frame/assets-registry/local-mapping.plantuml +++ b/frame/assets-registry/local-mapping.plantuml @@ -21,14 +21,15 @@ note across: Bob can approve an asset mapping candidate ... -alice -> assets_registry_pallet: Approve an asset mapping candidate with local_asset_id = x and foreign_asset_id = y +alice -> assets_registry_pallet: Approve an asset mapping candidate with local_asset_id = x, foreign_asset_id = y and decimals = z ... -bob -> assets_registry_pallet: Approve an asset mapping candidate with local_asset_id = x and foreign_asset_id = y +bob -> assets_registry_pallet: Approve an asset mapping candidate with local_asset_id = x, foreign_asset_id = y and decimals = z note over assets_registry_pallet -asset mapping for local_asset_id = x -and foreign_asset_id = y stored +asset mapping for local_asset_id = x, +foreign_asset_id = y and decimals = z +stored end note note across: Alice and Bob can set metadata of asset mapping for local_asset_id = x and foreign_asset_id = y diff --git a/frame/assets-registry/src/lib.rs b/frame/assets-registry/src/lib.rs index 1be8ad00380..f15a2168f25 100644 --- a/frame/assets-registry/src/lib.rs +++ b/frame/assets-registry/src/lib.rs @@ -54,6 +54,16 @@ pub mod pallet { + Default + TypeInfo; type ForeignAssetId: FullCodec + + Eq + + PartialEq + + Copy + + MaybeSerializeDeserialize + + From + + Into + + Debug + + Default + + TypeInfo; + type Location: FullCodec + Eq + PartialEq // we wrap non serde type, so until written custom serde, cannot handle that @@ -116,6 +126,18 @@ pub mod pallet { OptionQuery, >; + #[pallet::storage] + #[pallet::getter(fn foreign_asset_location)] + /// Mapping foreign asset to foreign location. + pub type ForeignAssetLocation = + StorageMap<_, Blake2_128Concat, T::LocalAssetId, T::Location, OptionQuery>; + + #[pallet::storage] + #[pallet::getter(fn from_foreign_asset_location)] + /// Mapping foreign location to foreign asset. + pub type FromForeignAssetLocation = + StorageMap<_, Blake2_128Concat, T::Location, T::LocalAssetId, OptionQuery>; + #[pallet::storage] #[pallet::getter(fn foreign_asset_metadata)] /// Mapping local asset to foreign asset metadata. @@ -126,6 +148,11 @@ pub mod pallet { pub struct GenesisConfig { local_admin: Option, foreign_admin: Option, + // TODO: split this into 2 pairs + // 1. (xcm location -> local asset id as used in our tuntime), so that when others send our + // id to our chain we can trust them 2. (local qasset id - > remote location -> remote + // asset id) so then when we send our local asset to remote chain we know what id we should + // envode. asset_pairs: Vec<(T::LocalAssetId, XcmAssetLocation)>, } @@ -177,10 +204,12 @@ pub mod pallet { LocalAssetIdAlreadyUsed, ForeignAssetIdAlreadyUsed, LocalAssetIdNotFound, + ForeignAssetIdNotFound, } #[pallet::call] impl Pallet { + // TODO: bench this #[pallet::weight(10_000)] pub fn set_local_admin( origin: OriginFor, @@ -208,6 +237,8 @@ pub mod pallet { origin: OriginFor, local_asset_id: T::LocalAssetId, foreign_asset_id: T::ForeignAssetId, + location: T::Location, + decimals: u8, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin.clone())?; Self::ensure_admins_only(origin)?; @@ -216,10 +247,10 @@ pub mod pallet { Error::::LocalAssetIdAlreadyUsed ); ensure!( - !>::contains_key(foreign_asset_id.clone()), + !>::contains_key(foreign_asset_id), Error::::ForeignAssetIdAlreadyUsed ); - Self::approve_candidate(who, local_asset_id, foreign_asset_id.clone())?; + Self::approve_candidate(who, local_asset_id, foreign_asset_id, location, decimals)?; Self::deposit_event(Event::AssetsMappingCandidateUpdated { local_asset_id, foreign_asset_id, @@ -249,23 +280,23 @@ pub mod pallet { impl RemoteAssetRegistry for Pallet { type AssetId = T::LocalAssetId; - type AssetNativeLocation = T::ForeignAssetId; + type AssetNativeLocation = T::Location; fn set_location( local_asset_id: Self::AssetId, - foreign_asset_id: Self::AssetNativeLocation, + location: Self::AssetNativeLocation, ) -> DispatchResult { - >::insert(local_asset_id, foreign_asset_id.clone()); - >::insert(foreign_asset_id, local_asset_id); + >::insert(local_asset_id, location.clone()); + >::insert(location, local_asset_id); Ok(()) } fn asset_to_location(local_asset_id: Self::AssetId) -> Option { - >::get(local_asset_id) + >::get(local_asset_id) } - fn location_to_asset(foreign_asset_id: Self::AssetNativeLocation) -> Option { - >::get(foreign_asset_id) + fn location_to_asset(location: Self::AssetNativeLocation) -> Option { + >::get(location) } } @@ -285,9 +316,11 @@ pub mod pallet { who: T::AccountId, local_asset_id: T::LocalAssetId, foreign_asset_id: T::ForeignAssetId, + location: T::Location, + decimals: u8, ) -> DispatchResultWithPostInfo { let current_candidate_status = - >::get((local_asset_id, foreign_asset_id.clone())); + >::get((local_asset_id, foreign_asset_id)); let local_admin = >::get(); let foreign_admin = >::get(); match current_candidate_status { @@ -305,17 +338,39 @@ pub mod pallet { }, Some(CandidateStatus::LocalAdminApproved) => if Some(who) == foreign_admin { - Self::set_location(local_asset_id, foreign_asset_id.clone())?; - >::remove((local_asset_id, foreign_asset_id)); + Self::promote_candidate( + local_asset_id, + foreign_asset_id, + location, + decimals, + )?; }, Some(CandidateStatus::ForeignAdminApproved) => if Some(who) == local_admin { - Self::set_location(local_asset_id, foreign_asset_id.clone())?; - >::remove((local_asset_id, foreign_asset_id)); + Self::promote_candidate( + local_asset_id, + foreign_asset_id, + location, + decimals, + )?; }, }; Ok(().into()) } + + fn promote_candidate( + local_asset_id: T::LocalAssetId, + foreign_asset_id: T::ForeignAssetId, + location: T::Location, + decimals: u8, + ) -> DispatchResult { + Self::set_location(local_asset_id, location)?; + >::insert(local_asset_id, foreign_asset_id); + >::insert(foreign_asset_id, local_asset_id); + >::insert(local_asset_id, ForeignMetadata { decimals }); + >::remove((local_asset_id, foreign_asset_id)); + Ok(()) + } } pub struct EnsureLocalAdmin(PhantomData); diff --git a/frame/assets-registry/src/mock.rs b/frame/assets-registry/src/mock.rs index 9b606b0cbc1..19fe0195907 100644 --- a/frame/assets-registry/src/mock.rs +++ b/frame/assets-registry/src/mock.rs @@ -1,4 +1,5 @@ use crate as pallet_assets_registry; +pub use composable_traits::assets::XcmAssetLocation; use frame_support::{ord_parameter_types, parameter_types, traits::Everything}; use frame_system as system; use frame_system::EnsureSignedBy; @@ -17,6 +18,8 @@ pub const ALICE: AccountId = 1_u32; pub const BOB: AccountId = 2_u32; pub const CHARLIE: AccountId = 3_u32; +pub const DECIMALS: u8 = 12; + // Configure a mock runtime to test the pallet. frame_support::construct_runtime!( pub enum Test where @@ -69,6 +72,7 @@ impl pallet_assets_registry::Config for Test { type Event = Event; type LocalAssetId = u128; type ForeignAssetId = u128; + type Location = XcmAssetLocation; type UpdateAdminOrigin = EnsureSignedBy; type LocalAdminOrigin = pallet_assets_registry::EnsureLocalAdmin; type ForeignAdminOrigin = pallet_assets_registry::EnsureForeignAdmin; diff --git a/frame/assets-registry/src/tests.rs b/frame/assets-registry/src/tests.rs index 60e97941e2b..1dac29ebf17 100644 --- a/frame/assets-registry/src/tests.rs +++ b/frame/assets-registry/src/tests.rs @@ -28,6 +28,7 @@ fn set_foreign_admin_tests() { fn approve_assets_mapping_candidate_tests() { new_test_ext().execute_with(|| { let (local_asset_id, foreign_asset_id) = (0, 100); + let location = XcmAssetLocation::LOCAL_NATIVE; assert_eq!(AssetsRegistry::from_local_asset(local_asset_id), None); assert_eq!(AssetsRegistry::from_local_asset(foreign_asset_id), None); assert_ok!(AssetsRegistry::set_local_admin(Origin::signed(ROOT), ALICE)); @@ -35,7 +36,9 @@ fn approve_assets_mapping_candidate_tests() { assert_ok!(AssetsRegistry::approve_assets_mapping_candidate( Origin::signed(ALICE), local_asset_id, - foreign_asset_id + foreign_asset_id, + location.clone(), + DECIMALS, )); assert_eq!( >::get((local_asset_id, foreign_asset_id)), @@ -44,17 +47,25 @@ fn approve_assets_mapping_candidate_tests() { assert_ok!(AssetsRegistry::approve_assets_mapping_candidate( Origin::signed(BOB), local_asset_id, - foreign_asset_id + foreign_asset_id, + location.clone(), + DECIMALS, )); assert_eq!(AssetsRegistry::from_local_asset(local_asset_id), Some(foreign_asset_id)); assert_eq!(AssetsRegistry::from_foreign_asset(foreign_asset_id), Some(local_asset_id)); + assert_eq!( + AssetsRegistry::foreign_asset_metadata(local_asset_id).unwrap(), + ForeignMetadata { decimals: DECIMALS } + ); let (other_local_asset_id, other_foreign_asset_id) = (1, 101); assert_noop!( AssetsRegistry::approve_assets_mapping_candidate( Origin::signed(ALICE), other_local_asset_id, - foreign_asset_id + foreign_asset_id, + location.clone(), + DECIMALS, ), Error::::ForeignAssetIdAlreadyUsed, ); @@ -62,7 +73,9 @@ fn approve_assets_mapping_candidate_tests() { AssetsRegistry::approve_assets_mapping_candidate( Origin::signed(ALICE), local_asset_id, - other_foreign_asset_id + other_foreign_asset_id, + location.clone(), + DECIMALS, ), Error::::LocalAssetIdAlreadyUsed, ); @@ -71,7 +84,9 @@ fn approve_assets_mapping_candidate_tests() { AssetsRegistry::approve_assets_mapping_candidate( Origin::signed(CHARLIE), other_local_asset_id, - other_foreign_asset_id + other_foreign_asset_id, + location.clone(), + DECIMALS, ), Error::::OnlyAllowedForAdmins, ); @@ -81,7 +96,9 @@ fn approve_assets_mapping_candidate_tests() { assert_ok!(AssetsRegistry::approve_assets_mapping_candidate( Origin::signed(BOB), other_local_asset_id, - other_foreign_asset_id + other_foreign_asset_id, + location.clone(), + DECIMALS, )); assert_eq!( >::get((other_local_asset_id, other_foreign_asset_id)), @@ -90,7 +107,9 @@ fn approve_assets_mapping_candidate_tests() { assert_ok!(AssetsRegistry::approve_assets_mapping_candidate( Origin::signed(ALICE), other_local_asset_id, - other_foreign_asset_id + other_foreign_asset_id, + location, + DECIMALS, )); assert_eq!( AssetsRegistry::from_local_asset(other_local_asset_id), @@ -100,6 +119,10 @@ fn approve_assets_mapping_candidate_tests() { AssetsRegistry::from_foreign_asset(other_foreign_asset_id), Some(other_local_asset_id) ); + assert_eq!( + AssetsRegistry::foreign_asset_metadata(local_asset_id).unwrap(), + ForeignMetadata { decimals: DECIMALS } + ) }) } @@ -107,6 +130,7 @@ fn approve_assets_mapping_candidate_tests() { fn set_metadata_tests() { new_test_ext().execute_with(|| { let (local_asset_id, foreign_asset_id) = (0, 100); + let location = XcmAssetLocation::LOCAL_NATIVE; assert_ok!(AssetsRegistry::set_local_admin(Origin::signed(ROOT), ALICE)); assert_ok!(AssetsRegistry::set_foreign_admin(Origin::signed(ROOT), BOB)); @@ -122,17 +146,25 @@ fn set_metadata_tests() { assert_ok!(AssetsRegistry::approve_assets_mapping_candidate( Origin::signed(ALICE), local_asset_id, - foreign_asset_id + foreign_asset_id, + location.clone(), + DECIMALS, )); assert_ok!(AssetsRegistry::approve_assets_mapping_candidate( Origin::signed(BOB), local_asset_id, - foreign_asset_id + foreign_asset_id, + location, + DECIMALS, )); assert_ok!(AssetsRegistry::set_metadata( Origin::signed(ALICE), local_asset_id, - ForeignMetadata { decimals: 12 } + ForeignMetadata { decimals: DECIMALS } )); + assert_eq!( + AssetsRegistry::foreign_asset_metadata(local_asset_id).unwrap(), + ForeignMetadata { decimals: DECIMALS } + ) }) } diff --git a/frame/assets/Cargo.toml b/frame/assets/Cargo.toml index bc5256bf813..203d1d44861 100644 --- a/frame/assets/Cargo.toml +++ b/frame/assets/Cargo.toml @@ -1,59 +1,62 @@ [package] -name = "pallet-assets" -version = "0.0.1" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" - +homepage = "https://composable.finance" +name = "pallet-assets" +version = "0.0.1" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [dependencies] -frame-benchmarking = { default-features = false, optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.16' } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } - -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } - -composable-traits = { path = "../composable-traits", default-features = false } - -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } + +sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } + +# local +composable-traits = { path = "../composable-traits", default-features = false } + +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } + +# misc +codec = { default-features = false, features = [ + "derive", +], package = "parity-scale-codec", version = "2.0.0" } num-traits = { version = "0.2.14", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } - -[dependencies.codec] -default-features = false -features = ["derive"] -package = "parity-scale-codec" -version = "2.0.0" [dev-dependencies] -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -governance-registry = { package = "pallet-governance-registry", path = "../governance-registry", default-features = false } -proptest = "0.9.6" -composable-tests-helpers = { path = "../composable-tests-helpers", default-features = false } +composable-tests-helpers = { path = "../composable-tests-helpers" } +governance-registry = { package = "pallet-governance-registry", path = "../governance-registry" } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +proptest = "1.0" [package.metadata.cargo-udeps.ignore] development = ["governance-registry"] [features] default = ["std"] -std = [ - "composable-traits/std", - "codec/std", - "frame-support/std", - "sp-runtime/std", - "orml-traits/std", - "num-traits/std", -] runtime-benchmarks = [ - "frame-benchmarking", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", +] +std = [ + "composable-traits/std", + "codec/std", + "frame-support/std", + "sp-runtime/std", + "sp-api/std", + "orml-traits/std", + "num-traits/std", ] diff --git a/frame/assets/rpc/Cargo.toml b/frame/assets/rpc/Cargo.toml new file mode 100644 index 00000000000..d0618f8130c --- /dev/null +++ b/frame/assets/rpc/Cargo.toml @@ -0,0 +1,34 @@ +[package] +authors = ["Composable Developers"] +edition = "2021" +homepage = "https://composable.finance" +name = "assets-rpc" +rust-version = "1.56" +version = "0.0.1" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +# substrate primitives +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } + +# local +assets-runtime-api = { path = "../runtime-api" } +composable-support = { path = "../../composable-support" } + +# SCALE +codec = { default-features = false, features = [ + "derive", +], package = "parity-scale-codec", version = "2.0.0" } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } + +# rpc +jsonrpc-core = "18.0.0" +jsonrpc-core-client = "18.0.0" +jsonrpc-derive = "18.0.0" diff --git a/frame/assets/rpc/src/lib.rs b/frame/assets/rpc/src/lib.rs new file mode 100644 index 00000000000..f18f9fc7bfb --- /dev/null +++ b/frame/assets/rpc/src/lib.rs @@ -0,0 +1,73 @@ +use assets_runtime_api::AssetsRuntimeApi; +use codec::Codec; +use composable_support::rpc_helpers::{SafeRpcWrapper, SafeRpcWrapperType}; +use jsonrpc_core::{Error as RpcError, ErrorCode, Result as RpcResult}; +use jsonrpc_derive::rpc; +use sp_api::ProvideRuntimeApi; +use sp_blockchain::HeaderBackend; +use sp_runtime::{generic::BlockId, traits::Block as BlockT}; +use sp_std::sync::Arc; + +#[rpc] +pub trait AssetsApi +where + AssetId: SafeRpcWrapperType, + Balance: SafeRpcWrapperType, +{ + #[rpc(name = "assets_balanceOf")] + fn balance_of( + &self, + currency: SafeRpcWrapper, + account: AccountId, + at: Option, + ) -> RpcResult>; +} + +pub struct Assets { + client: Arc, + _marker: sp_std::marker::PhantomData, +} + +impl Assets { + pub fn new(client: Arc) -> Self { + Self { client, _marker: Default::default() } + } +} + +impl + AssetsApi<::Hash, AssetId, AccountId, Balance> + for Assets +where + Block: BlockT, + AssetId: Codec + Send + Sync + 'static + SafeRpcWrapperType, + AccountId: Codec + Send + Sync + 'static, + Balance: Send + Sync + 'static + SafeRpcWrapperType, + C: Send + Sync + 'static, + C: ProvideRuntimeApi, + C: HeaderBackend, + C::Api: AssetsRuntimeApi, +{ + fn balance_of( + &self, + asset_id: SafeRpcWrapper, + account_id: AccountId, + at: Option<::Hash>, + ) -> RpcResult> { + let api = self.client.runtime_api(); + + let at = BlockId::hash(at.unwrap_or_else(|| { + // If the block hash is not supplied assume the best block. + self.client.info().best_hash + })); + + let runtime_api_result = api.balance_of(&at, asset_id, account_id); + // TODO(benluelo): Review what error message & code to use + runtime_api_result.map_err(|e| { + RpcError { + code: ErrorCode::ServerError(9876), // No real reason for this value + message: "Something wrong".into(), + data: Some(format!("{:?}", e).into()), + } + }) + } +} diff --git a/frame/assets/runtime-api/Cargo.toml b/frame/assets/runtime-api/Cargo.toml new file mode 100644 index 00000000000..26a28fabd30 --- /dev/null +++ b/frame/assets/runtime-api/Cargo.toml @@ -0,0 +1,21 @@ +[package] +authors = ["Composable Developers"] +edition = "2021" +homepage = "https://composable.finance" +name = "assets-runtime-api" +rust-version = "1.56" +version = "0.0.1" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { default-features = false, features = [ + "derive", +], package = "parity-scale-codec", version = "2.0.0" } +composable-support = { path = "../../composable-support", default-features = false } +sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } + +[features] +default = ["std"] +std = ["sp-api/std", "codec/std", "composable-support/std"] diff --git a/frame/assets/runtime-api/src/lib.rs b/frame/assets/runtime-api/src/lib.rs new file mode 100644 index 00000000000..8229caec12e --- /dev/null +++ b/frame/assets/runtime-api/src/lib.rs @@ -0,0 +1,20 @@ +#![cfg_attr(not(feature = "std"), no_std)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::unnecessary_mut_passed)] + +use codec::Codec; +use composable_support::rpc_helpers::{SafeRpcWrapper, SafeRpcWrapperType}; + +// Here we declare the runtime API. It is implemented it the `impl` block in +// runtime amalgamator file (the `runtime/src/lib.rs`) +sp_api::decl_runtime_apis! { + // REVIEW(benluelo): Should the AssetId type parameter be removed and then just use CurencyId directly? + pub trait AssetsRuntimeApi + where + AssetId: SafeRpcWrapperType, + AccountId: Codec, + Balance: SafeRpcWrapperType, + { + fn balance_of(asset_id: SafeRpcWrapper, account_id: AccountId) -> SafeRpcWrapper /* Balance */; + } +} diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index cf9f2f396c5..4c7943158f6 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -105,6 +105,7 @@ pub mod pallet { /// currency id type AssetId: AssetIdLike; type Balance: BalanceLike; + #[pallet::constant] type NativeAssetId: Get; type GenerateCurrencyId: CurrencyFactory; type NativeCurrency; @@ -122,7 +123,6 @@ pub mod pallet { #[pallet::error] pub enum Error { - BadOrigin, CannotSetNewCurrencyToRegistry, } @@ -351,11 +351,11 @@ pub mod pallet { match T::GovernanceRegistry::get(asset_id) { Ok(SignedRawOrigin::Root) => Ok(()), Ok(SignedRawOrigin::Signed(acc)) if acc == account => Ok(()), - _ => Err(Error::::BadOrigin.into()), + _ => Err(DispatchError::BadOrigin), } }, Ok(frame_system::RawOrigin::Root) => Ok(()), - _ => Err(Error::::BadOrigin.into()), + _ => Err(DispatchError::BadOrigin), } } diff --git a/frame/assets/src/mocks.rs b/frame/assets/src/mocks.rs index e5ddcf330fc..a5d1a2c0ce3 100644 --- a/frame/assets/src/mocks.rs +++ b/frame/assets/src/mocks.rs @@ -80,6 +80,10 @@ impl Config for Test { type AdminOrigin = EnsureRoot; } +parameter_types! { + pub const MaxLocks: u32 = 256; +} + impl orml_tokens::Config for Test { type Event = Event; type Balance = Balance; @@ -88,7 +92,7 @@ impl orml_tokens::Config for Test { type WeightInfo = (); type ExistentialDeposits = ExistentialDeposits; type OnDust = (); - type MaxLocks = (); + type MaxLocks = MaxLocks; type DustRemovalWhitelist = Everything; } diff --git a/frame/assets/src/tests/traits.rs b/frame/assets/src/tests/traits.rs index 63827889dc5..eead2235e48 100644 --- a/frame/assets/src/tests/traits.rs +++ b/frame/assets/src/tests/traits.rs @@ -399,21 +399,20 @@ mod multicurrency { prop_assert_ok!( as MultiReservableCurrency>::reserve(asset_id, &account, third)); prop_assert_eq!( as MultiCurrency>::free_balance(asset_id,&account), 0); - // - let mut remaining = as MultiReservableCurrency>::unreserve(asset_id, &account, first); + + let remaining = as MultiReservableCurrency>::unreserve(asset_id, &account, first); prop_assert_eq!( as MultiCurrency>::free_balance(asset_id,&account), first - remaining); - let mut free_balance = as MultiCurrency>::free_balance(asset_id,&account); - remaining = as MultiReservableCurrency>::unreserve(asset_id, &account, second); + let free_balance = as MultiCurrency>::free_balance(asset_id,&account); + let remaining = as MultiReservableCurrency>::unreserve(asset_id, &account, second); prop_assert_eq!( as MultiCurrency>::free_balance(asset_id,&account), free_balance + ( second - remaining)); - let mut free_balance = as MultiCurrency>::free_balance(asset_id,&account); - remaining = as MultiReservableCurrency>::unreserve(asset_id, &account, third); + let free_balance = as MultiCurrency>::free_balance(asset_id,&account); + let remaining = as MultiReservableCurrency>::unreserve(asset_id, &account, third); prop_assert_eq!( as MultiCurrency>::free_balance(asset_id,&account), free_balance + ( third - remaining)); - //lock - free_balance = as MultiCurrency>::free_balance(asset_id,&account); - as MultiLockableCurrency>::set_lock(*b"prelocks", asset_id, &account, first); - prop_assert_eq!( as MultiCurrency>::free_balance(asset_id,&account), first + second + third); + + prop_assert_ok!( as MultiLockableCurrency>::set_lock(*b"prelocks", asset_id, &account, first)); + prop_assert_eq!( as MultiCurrency>::free_balance(asset_id, &account), first + second + third); Ok(()) })?; @@ -439,17 +438,17 @@ mod lockable_multicurrency { prop_assert_eq!( as MultiCurrency>::free_balance(asset_id,&account),0); prop_assert_ok!( as MultiCurrency>::deposit(asset_id, &account,first + second + third)); - as MultiLockableCurrency>::set_lock(*b"prelocks", asset_id, &account, first); + prop_assert_ok!( as MultiLockableCurrency>::set_lock(*b"prelocks", asset_id, &account, first)); prop_assert_ok!( as MultiCurrency>::ensure_can_withdraw(asset_id, &account, second + third )); prop_assert!( as MultiCurrency>::ensure_can_withdraw(asset_id, &account, first + second + third).is_err()); // ensure set_lock updates lock with same id - as MultiLockableCurrency>::set_lock(*b"prelocks", asset_id, &account, second); + prop_assert_ok!( as MultiLockableCurrency>::set_lock(*b"prelocks", asset_id, &account, second)); prop_assert_ok!( as MultiCurrency>::ensure_can_withdraw(asset_id, &account, first + third )); prop_assert!( as MultiCurrency>::ensure_can_withdraw(asset_id, &account, first + second + third).is_err()); // ensure set_lock updates lock with same id - as MultiLockableCurrency>::set_lock(*b"prelocks", asset_id, &account, third); + prop_assert_ok!( as MultiLockableCurrency>::set_lock(*b"prelocks", asset_id, &account, third)); prop_assert_ok!( as MultiCurrency>::ensure_can_withdraw(asset_id, &account, first + second )); prop_assert!( as MultiCurrency>::ensure_can_withdraw(asset_id, &account, first + second + third).is_err()); @@ -468,15 +467,15 @@ mod lockable_multicurrency { prop_assert_eq!( as MultiCurrency>::free_balance(asset_id,&account),0); prop_assert_ok!( as MultiCurrency>::deposit(asset_id, &account,first + second + third)); - as MultiLockableCurrency>::set_lock(*b"prelocks", asset_id, &account, first); + prop_assert_ok!( as MultiLockableCurrency>::set_lock(*b"prelocks", asset_id, &account, first)); prop_assert_ok!( as MultiCurrency>::ensure_can_withdraw(asset_id, &account, second + third )); prop_assert!( as MultiCurrency>::ensure_can_withdraw(asset_id, &account, first + second + third).is_err()); - as MultiLockableCurrency>::extend_lock(*b"prelocks", asset_id, &account, second); + prop_assert_ok!( as MultiLockableCurrency>::extend_lock(*b"prelocks", asset_id, &account, second)); prop_assert_ok!( as MultiCurrency>::ensure_can_withdraw(asset_id, &account, third )); prop_assert!( as MultiCurrency>::ensure_can_withdraw(asset_id, &account, first + second + third).is_err()); - as MultiLockableCurrency>::extend_lock(*b"prelocks", asset_id, &account, third); + prop_assert_ok!( as MultiLockableCurrency>::set_lock(*b"prelocks", asset_id, &account, third)); prop_assert_ok!( as MultiCurrency>::ensure_can_withdraw(asset_id, &account, first + second)); prop_assert!( as MultiCurrency>::ensure_can_withdraw(asset_id, &account, first + second + third).is_err()); Ok(()) @@ -490,19 +489,15 @@ mod lockable_multicurrency { (first, second, _) in valid_amounts_without_overflow_3()) { new_test_ext_multi_currency().execute_with(|| { - - prop_assert_eq!( as MultiCurrency>::free_balance(asset_id,&account),0); - prop_assert_ok!( as MultiCurrency>::deposit(asset_id, &account,first + second)); - - as MultiLockableCurrency>::set_lock(*b"prelocks", asset_id, &account, first + second); - prop_assert!( as MultiCurrency>::ensure_can_withdraw(asset_id, &account, first + second).is_err()); - prop_assert!( as MultiCurrency>::ensure_can_withdraw(asset_id, &account, first ).is_err()); - prop_assert!( as MultiCurrency>::ensure_can_withdraw(asset_id, &account, second ).is_err()); - - prop_assert_ok!( as MultiLockableCurrency>::remove_lock(*b"prelocks", asset_id, &account)); - prop_assert_ok!( as MultiCurrency>::ensure_can_withdraw(asset_id, &account, first + second)); - - Ok(()) + prop_assert_eq!( as MultiCurrency>::free_balance(asset_id,&account),0); + prop_assert_ok!( as MultiCurrency>::deposit(asset_id, &account, first + second)); + prop_assert_ok!( as MultiLockableCurrency>::set_lock(*b"prelocks", asset_id, &account, first + second)); + prop_assert!( as MultiCurrency>::ensure_can_withdraw(asset_id, &account, first + second).is_err()); + prop_assert!( as MultiCurrency>::ensure_can_withdraw(asset_id, &account, first ).is_err()); + prop_assert!( as MultiCurrency>::ensure_can_withdraw(asset_id, &account, second ).is_err()); + prop_assert_ok!( as MultiLockableCurrency>::remove_lock(*b"prelocks", asset_id, &account)); + prop_assert_ok!( as MultiCurrency>::ensure_can_withdraw(asset_id, &account, first + second)); + Ok(()) })?; } @@ -596,7 +591,7 @@ mod reservable_multicurrency { fn test_repariate_reserve_implementation( (account_1, account_2) in accounts_2(), asset_id in asset(), - (first, second, third) in valid_amounts_without_overflow_3() + (first, second, _) in valid_amounts_without_overflow_3() ) { new_test_ext_multi_currency().execute_with(|| { diff --git a/frame/bonded-finance/Cargo.toml b/frame/bonded-finance/Cargo.toml index 06eced116ba..dc1b9f536e5 100644 --- a/frame/bonded-finance/Cargo.toml +++ b/frame/bonded-finance/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "pallet-bonded-finance" -version = "0.0.1" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" +homepage = "https://composable.finance" +name = "pallet-bonded-finance" +version = "0.0.1" [package.metadata.docs.rs] @@ -16,48 +16,52 @@ package = "parity-scale-codec" version = "2.0.0" [dependencies] -frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } +sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +composable-support = { default-features = false, path = "../composable-support" } composable-traits = { path = "../../frame/composable-traits", default-features = false } -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } [dev-dependencies] +composable-tests-helpers = { path = "../composable-tests-helpers" } composable-traits = { path = "../../frame/composable-traits" } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +pallet-vesting = { path = "../../frame/vesting" } proptest = "1.0" proptest-derive = "0.3" serde = { version = "1.0.130" } -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -pallet-vesting = { path = "../../frame/vesting" } -composable-tests-helpers = { path = "../composable-tests-helpers", default-features = false } [features] default = ["std"] std = [ - "codec/std", - "frame-support/std", - "frame-system/std", - "sp-runtime/std", - "sp-io/std", - "sp-core/std", - "sp-std/std", - "sp-arithmetic/std", - "composable-traits/std", - "scale-info/std", + "codec/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-io/std", + "sp-core/std", + "sp-std/std", + "sp-arithmetic/std", + "composable-traits/std", + "scale-info/std", ] runtime-benchmarks = [ - "frame-benchmarking", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks" + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", ] [package.metadata.cargo-udeps.ignore] -normal = ["orml-traits"] \ No newline at end of file +normal = ["orml-traits"] diff --git a/frame/bonded-finance/proptest-regressions/tests.txt b/frame/bonded-finance/proptest-regressions/tests.txt new file mode 100644 index 00000000000..17e8802a547 --- /dev/null +++ b/frame/bonded-finance/proptest-regressions/tests.txt @@ -0,0 +1,9 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc 35820e14563de841f5eda240ea61961e3c4d920b9aceda728dac1e0fa94677e1 # shrinks to offer = BondOffer { beneficiary: 1, asset: BTC, bond_price: 1000000, nb_of_bonds: 1, maturity: BondDuration::Infinite, reward: BondOfferReward { asset: ETH, amount: 1000000, maturity: 1 } } +cc 101ee1a90f927af96e09f0ba0009aab288692d1d15941e07f6ee521371c3c59d # shrinks to offer = BondOffer { beneficiary: 1, asset: BTC, bond_price: 1000000, nb_of_bonds: 2, maturity: BondDuration::Infinite, reward: BondOfferReward { asset: ETH, amount: 2000000, maturity: 1 } } +cc 7b071ed45fc65b0f4a10540fe45e768cbc7861a0ff586bb86192d4bee4f2bb85 # shrinks to offer = BondOffer { beneficiary: 1, asset: BTC, bond_price: 1000000, nb_of_bonds: 2, maturity: BondDuration::Infinite, reward: BondOfferReward { asset: ETH, amount: 2000000, maturity: 1 } } diff --git a/frame/bonded-finance/src/benchmarks.rs b/frame/bonded-finance/src/benchmarks.rs index ad66a26cebd..09b991481ad 100644 --- a/frame/bonded-finance/src/benchmarks.rs +++ b/frame/bonded-finance/src/benchmarks.rs @@ -2,23 +2,21 @@ #[cfg(test)] use crate::Pallet as BondedFinance; -use crate::{ - utils::MIN_VESTED_TRANSFER, AssetIdOf, BalanceOf, BlockNumberOf, BondOfferOf, Call, Config, - Pallet, -}; +use crate::{AssetIdOf, BalanceOf, BlockNumberOf, BondOfferOf, Call, Config, Pallet}; use codec::Decode; -use composable_traits::{ - bonded_finance::{BondDuration, BondOffer, BondOfferReward}, - math::WrappingNext, -}; -use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller, Zero}; +use composable_support::validation::Validated; +use composable_traits::bonded_finance::{BondDuration, BondOffer, BondOfferReward}; +use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller}; use frame_support::{ dispatch::UnfilteredDispatchable, traits::{fungible::Mutate as _, fungibles::Mutate as _}, }; use frame_system::RawOrigin; +use sp_runtime::traits::One; + +const MIN_VESTED_TRANSFER: u128 = 1000 * 1_000_000_000_000; +const BALANCE: u128 = 1_000_000 * 1_000_000_000_000; -const BALANCE: u64 = 10 * 1_000_000_000_000; fn assets() -> [AssetIdOf; 2] where T: Config, @@ -31,13 +29,14 @@ where fn bond_offer(bond_asset: AssetIdOf, reward_asset: AssetIdOf) -> BondOfferOf where T: Config, + BalanceOf: From, { BondOffer { beneficiary: whitelisted_caller(), asset: bond_asset, bond_price: BalanceOf::::from(MIN_VESTED_TRANSFER), maturity: BondDuration::Finite { return_in: BlockNumberOf::::from(1u32) }, - nb_of_bonds: BalanceOf::::from(1u32), + nb_of_bonds: BalanceOf::::from(1u128), reward: BondOfferReward { amount: BalanceOf::::from(MIN_VESTED_TRANSFER), asset: reward_asset, @@ -51,9 +50,10 @@ where T: Config, { let offer_account_id = Pallet::::account_id(offer_id); + let keep_alive = false; T::NativeCurrency::mint_into(&offer_account_id, <_>::try_from(BALANCE).unwrap_or_default()) .unwrap(); - Call::::bond { nb_of_bonds, offer_id } + Call::::bond { nb_of_bonds, offer_id, keep_alive } .dispatch_bypass_filter(RawOrigin::Signed(caller.clone()).into()) .unwrap(); } @@ -62,7 +62,9 @@ fn call_offer(bond_offer: BondOfferOf, caller: &T::AccountId) where T: Config, { - Call::::offer { offer: bond_offer } + let keep_alive = false; + let validated_bond_offer = Validated::new(bond_offer).unwrap(); + Call::::offer { offer: validated_bond_offer, keep_alive } .dispatch_bypass_filter(RawOrigin::Signed(caller.clone()).into()) .unwrap(); } @@ -78,33 +80,38 @@ where } benchmarks! { + where_clause { + where BalanceOf: From + } + + offer { + let [bond_asset, reward_asset] = assets::(); + let caller: T::AccountId = account("caller", 0, 0xCAFEBABE); + initial_mint::(bond_asset, &caller, reward_asset); + let bond_offer = bond_offer::(bond_asset, reward_asset); + let validated_bond_offer = Validated::new(bond_offer).unwrap(); + }: _(RawOrigin::Signed(caller), validated_bond_offer, false) + bond { let [bond_asset, reward_asset] = assets::(); - let caller: T::AccountId = whitelisted_caller(); + let caller: T::AccountId = account("caller", 0, 0xCAFEBABE); initial_mint::(bond_asset, &caller, reward_asset); let bond_offer = bond_offer::(bond_asset, reward_asset); let nb_of_bonds = bond_offer.nb_of_bonds; call_offer::(bond_offer, &caller); - let offer_id = T::BondOfferId::zero().next(); - }: _(RawOrigin::Signed(caller), offer_id, nb_of_bonds) + let offer_id = T::BondOfferId::one(); + }: _(RawOrigin::Signed(caller), offer_id, nb_of_bonds, false) cancel { let [bond_asset, reward_asset] = assets::(); - let caller: T::AccountId = whitelisted_caller(); + let caller: T::AccountId = account("caller", 0, 0xCAFEBABE); initial_mint::(bond_asset, &caller, reward_asset); let bond_offer = bond_offer::(bond_asset, reward_asset); let nb_of_bonds = bond_offer.nb_of_bonds; call_offer::(bond_offer, &caller); - let offer_id = T::BondOfferId::zero().next(); + let offer_id = T::BondOfferId::one(); call_bond::(&caller, nb_of_bonds, offer_id); }: _(RawOrigin::Signed(caller), offer_id) - - offer { - let [bond_asset, reward_asset] = assets::(); - let caller: T::AccountId = whitelisted_caller(); - initial_mint::(bond_asset, &caller, reward_asset); - let bond_offer = bond_offer::(bond_asset, reward_asset); - }: _(RawOrigin::Signed(caller), bond_offer) } impl_benchmark_test_suite!(BondedFinance, crate::mock::ExtBuilder::build(), crate::mock::Runtime); diff --git a/frame/bonded-finance/src/lib.rs b/frame/bonded-finance/src/lib.rs index a974311ec61..b49c0393620 100644 --- a/frame/bonded-finance/src/lib.rs +++ b/frame/bonded-finance/src/lib.rs @@ -46,7 +46,7 @@ //! Bob bonds parts of shares from offer by transfer some asset amount desired by Alice. //! Bob will be vested part of reward amount during maturity period from that moment. //! It the end of some period Bob may or may be not be return with amount he provided to Alice - -//! depends on how offer was setup. +//! depends on how offer was setup. //! //! Alice may cancel offer and prevent new bonds on offer, she gets her native tokens back. //! All existing vesting periods continue to be executed. @@ -55,20 +55,25 @@ //! //! This pallet implements the `composable_traits::bonded_finance::BondedFinance`. +#[cfg(feature = "runtime-benchmarks")] mod benchmarks; + mod mock; mod tests; -mod utils; +pub mod weights; + +pub use crate::weights::WeightInfo; pub use pallet::*; #[frame_support::pallet] pub mod pallet { use codec::FullCodec; + use composable_support::validation::Validated; use composable_traits::{ - bonded_finance::{BondDuration, BondOffer, BondedFinance}, - math::WrappingNext, - vesting::{VestedTransfer, VestingSchedule}, + bonded_finance::{BondDuration, BondOffer, BondedFinance, ValidBondOffer}, + math::SafeAdd, + vesting::{VestedTransfer, VestingSchedule, VestingWindow::BlockNumberBased}, }; use frame_support::{ pallet_prelude::*, @@ -82,11 +87,13 @@ pub mod pallet { use scale_info::TypeInfo; use sp_runtime::{ helpers_128bit::multiply_by_rational, - traits::{AccountIdConversion, BlockNumberProvider, Convert, Zero}, + traits::{AccountIdConversion, BlockNumberProvider, Convert, One, Zero}, ArithmeticError, }; use sp_std::fmt::Debug; + use crate::weights::WeightInfo; + pub(crate) type BlockNumberOf = ::BlockNumber; pub(crate) type AccountIdOf = ::AccountId; pub(crate) type AssetIdOf = @@ -149,7 +156,8 @@ pub mod pallet { + Eq + Debug + Zero - + WrappingNext + + SafeAdd + + One + FullCodec + MaxEncodedLen + TypeInfo; @@ -173,10 +181,14 @@ pub mod pallet { /// The origin that is allowed to cancel bond offers. type AdminOrigin: EnsureOrigin; + + /// Weights + type WeightInfo: WeightInfo; } #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::type_value] @@ -210,15 +222,24 @@ pub mod pallet { /// /// The dispatch origin for this call must be _Signed_ and the sender must have the /// appropriate funds. + /// Allow the issuer to ask for his account to be kept alive using the `keep_alive` + /// parameter. /// /// Emits a `NewOffer`. - #[pallet::weight(10_000)] - pub fn offer(origin: OriginFor, offer: BondOfferOf) -> DispatchResult { + #[pallet::weight(T::WeightInfo::offer())] + pub fn offer( + origin: OriginFor, + offer: Validated< + BondOfferOf, + ValidBondOffer::MinVestedTransfer>, + >, + keep_alive: bool, + ) -> DispatchResult { let from = ensure_signed(origin)?; - Self::do_offer(&from, offer)?; + let value = offer.value(); + Self::do_offer(&from, value, keep_alive)?; Ok(()) } - /// Bond to an offer. /// And user should provide the number of contracts she is willing to buy. /// On offer completion (a.k.a. no more contract on the offer), the `stake` put by the @@ -227,16 +248,20 @@ pub mod pallet { /// The dispatch origin for this call must be _Signed_ and the sender must have the /// appropriate funds. /// + /// Allow the bonder to ask for his account to be kept alive using the `keep_alive` + /// parameter. + /// /// Emits a `NewBond`. /// Possibily Emits a `OfferCompleted`. - #[pallet::weight(10_000)] + #[pallet::weight(T::WeightInfo::bond())] pub fn bond( origin: OriginFor, offer_id: T::BondOfferId, nb_of_bonds: BalanceOf, + keep_alive: bool, ) -> DispatchResult { let from = ensure_signed(origin)?; - Self::do_bond(offer_id, &from, nb_of_bonds)?; + Self::do_bond(offer_id, &from, nb_of_bonds, keep_alive)?; Ok(()) } @@ -245,7 +270,7 @@ pub mod pallet { /// The dispatch origin for this call must be _Signed_ and the sender must be `AdminOrigin` /// /// Emits a `OfferCancelled`. - #[pallet::weight(10_000)] // TODO: add weights + #[pallet::weight(T::WeightInfo::cancel())] #[transactional] pub fn cancel(origin: OriginFor, offer_id: T::BondOfferId) -> DispatchResult { let (issuer, offer) = Self::get_offer(offer_id)?; @@ -260,7 +285,8 @@ pub mod pallet { _ => return Err(DispatchError::BadOrigin), }; let offer_account = Self::account_id(offer_id); - T::NativeCurrency::transfer(&offer_account, &issuer, T::Stake::get(), true)?; + // NOTE(hussein-aitlahcen): no need to keep the offer account alive + T::NativeCurrency::transfer(&offer_account, &issuer, T::Stake::get(), false)?; T::Currency::transfer( offer.reward.asset, &offer_account, @@ -285,26 +311,22 @@ pub mod pallet { pub fn do_offer( from: &AccountIdOf, offer: BondOfferOf, + keep_alive: bool, ) -> Result { - ensure!( - offer.valid( - ::MinVestedTransfer::get(), - T::MinReward::get() - ), - Error::::InvalidBondOffer - ); - let offer_id = BondOfferCount::::mutate(|offer_id| { - *offer_id = offer_id.next(); - *offer_id - }); + let offer_id = BondOfferCount::::try_mutate( + |offer_id| -> Result { + *offer_id = offer_id.safe_add(&T::BondOfferId::one())?; + Ok(*offer_id) + }, + )?; let offer_account = Self::account_id(offer_id); - T::NativeCurrency::transfer(from, &offer_account, T::Stake::get(), true)?; + T::NativeCurrency::transfer(from, &offer_account, T::Stake::get(), keep_alive)?; T::Currency::transfer( offer.reward.asset, from, &offer_account, offer.reward.amount, - true, + keep_alive, )?; BondOffers::::insert(offer_id, (from.clone(), offer)); Self::deposit_event(Event::::NewOffer { offer_id }); @@ -316,6 +338,7 @@ pub mod pallet { offer_id: T::BondOfferId, from: &AccountIdOf, nb_of_bonds: BalanceOf, + keep_alive: bool, ) -> Result, DispatchError> { BondOffers::::try_mutate(offer_id, |offer| { match offer.as_mut() { @@ -342,15 +365,23 @@ pub mod pallet { .map_err(|_| ArithmeticError::Overflow)?, ); let offer_account = Self::account_id(offer_id); - T::Currency::transfer(offer.asset, from, &offer.beneficiary, value, true)?; + T::Currency::transfer( + offer.asset, + from, + &offer.beneficiary, + value, + keep_alive, + )?; let current_block = frame_system::Pallet::::current_block_number(); T::Vesting::vested_transfer( offer.reward.asset, &offer_account, from, VestingSchedule { - start: current_block, - period: offer.reward.maturity, + window: BlockNumberBased { + start: current_block, + period: offer.reward.maturity, + }, period_count: 1, per_period: reward_share, }, @@ -362,8 +393,10 @@ pub mod pallet { &offer.beneficiary, from, VestingSchedule { - start: current_block, - period: return_in, + window: BlockNumberBased { + start: current_block, + period: return_in, + }, period_count: 1, per_period: value, }, @@ -374,9 +407,10 @@ pub mod pallet { // that the protocol is now owning the funds. }, } - // NOTE(hussein-aitlahcen): can't overflow as checked to be < + // NOTE(hussein-aitlahcen): can't overflow as checked to be <= // offer.nb_of_bonds prior to this - // Same goes for reward_share as nb_of_bonds * bond_price <= total_price + // Same goes for reward_share as nb_of_bonds * bond_price <= total_price is + // checked by the `Validate` instance of `BondOffer` (*offer).nb_of_bonds -= nb_of_bonds; (*offer).reward.amount -= reward_share; let new_bond_event = || { @@ -391,7 +425,8 @@ pub mod pallet { &offer_account, issuer, T::Stake::get(), - true, + // NOTE(hussein-aitlahcen): no need to keep the offer account alive + false, )?; new_bond_event(); Self::deposit_event(Event::::OfferCompleted { offer_id }); @@ -415,20 +450,27 @@ pub mod pallet { type Balance = BalanceOf; type BlockNumber = BlockNumberOf; type BondOfferId = T::BondOfferId; + type MinReward = T::MinReward; + type MinVestedTransfer = ::MinVestedTransfer; fn offer( from: &Self::AccountId, - offer: BondOfferOf, + offer: Validated< + BondOfferOf, + ValidBondOffer, + >, + keep_alive: bool, ) -> Result { - Self::do_offer(from, offer) + Self::do_offer(from, offer.value(), keep_alive) } fn bond( offer: Self::BondOfferId, from: &Self::AccountId, nb_of_bonds: Self::Balance, + keep_alive: bool, ) -> Result { - Self::do_bond(offer, from, nb_of_bonds) + Self::do_bond(offer, from, nb_of_bonds, keep_alive) } } } diff --git a/frame/bonded-finance/src/mock.rs b/frame/bonded-finance/src/mock.rs index 86aced0946b..ee9f3a194cf 100644 --- a/frame/bonded-finance/src/mock.rs +++ b/frame/bonded-finance/src/mock.rs @@ -3,7 +3,6 @@ #![cfg(test)] use super::*; -use crate::utils::MIN_VESTED_TRANSFER; use frame_support::{ construct_runtime, pallet_prelude::*, @@ -22,12 +21,15 @@ use sp_runtime::{ }; pub type BlockNumber = u64; +pub type Moment = u64; pub type Balance = u128; pub type Amount = i128; pub type AccountId = u128; +pub const MIN_VESTED_TRANSFER: u128 = 100; pub const NATIVE_CURRENCY_ID: MockCurrencyId = MockCurrencyId::PICA; pub const MIN_REWARD: u128 = 1_000_000; +pub const MILLISECS_PER_BLOCK: u64 = 6000; pub const ALICE: AccountId = 1; pub const BOB: AccountId = 2; @@ -127,6 +129,17 @@ impl orml_tokens::Config for Runtime { type DustRemovalWhitelist = Everything; } +parameter_types! { + pub const MinimumPeriod: u64 = MILLISECS_PER_BLOCK / 2; +} + +impl pallet_timestamp::Config for Runtime { + type Moment = Moment; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + parameter_types! { pub const MaxVestingSchedule: u32 = 2; pub const MinVestedTransfer: u64 = MIN_VESTED_TRANSFER as _; @@ -139,6 +152,8 @@ impl pallet_vesting::Config for Runtime { type VestedTransferOrigin = EnsureAliceOrBob; type WeightInfo = (); type MaxVestingSchedules = MaxVestingSchedule; + type Moment = Moment; + type Time = Timestamp; } parameter_types! { @@ -159,6 +174,7 @@ impl pallet::Config for Runtime { type MinReward = MinReward; type AdminOrigin = EnsureRoot; type Convert = ConvertInto; + type WeightInfo = (); } type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; @@ -174,6 +190,7 @@ construct_runtime!( Vesting: pallet_vesting::{Pallet, Storage, Call, Event, Config}, Tokens: orml_tokens::{Pallet, Call, Storage, Config, Event}, BondedFinance: pallet::{Pallet, Call, Storage, Event}, + Timestamp: pallet_timestamp::{Pallet, Call, Storage}, } ); diff --git a/frame/bonded-finance/src/tests.rs b/frame/bonded-finance/src/tests.rs index 7e6b9a81d21..060cbc067eb 100644 --- a/frame/bonded-finance/src/tests.rs +++ b/frame/bonded-finance/src/tests.rs @@ -3,7 +3,6 @@ #![cfg(test)] use super::*; -use crate::utils::MIN_VESTED_TRANSFER; use composable_tests_helpers::{prop_assert_acceptable_computation_error, prop_assert_ok}; use composable_traits::bonded_finance::{BondDuration, BondOffer, BondOfferReward}; use frame_support::{ @@ -16,138 +15,6 @@ use frame_support::{ use mock::{Event, *}; use proptest::prelude::*; -#[test] -fn valid_offer() { - assert!(BondOffer { - beneficiary: ALICE, - asset: MockCurrencyId::BTC, - bond_price: MIN_VESTED_TRANSFER as _, - nb_of_bonds: 100_000_u128, - maturity: BondDuration::Infinite, - reward: BondOfferReward { - asset: MockCurrencyId::PICA, - amount: 1_000_000_u128 * 100_000_u128, - maturity: 96_u128, - } - } - .valid(MinVestedTransfer::get() as _, MinReward::get())); - assert!(BondOffer { - beneficiary: ALICE, - asset: MockCurrencyId::BTC, - bond_price: MIN_VESTED_TRANSFER as _, - nb_of_bonds: 1_u128, - maturity: BondDuration::Finite { return_in: 1 }, - reward: BondOfferReward { - asset: MockCurrencyId::BTC, - amount: 1_000_000_u128, - maturity: 96_u128, - } - } - .valid(MinVestedTransfer::get() as _, MinReward::get())); - assert!(BondOffer { - beneficiary: ALICE, - asset: MockCurrencyId::BTC, - bond_price: 1_000_000 + MIN_VESTED_TRANSFER as u128, - nb_of_bonds: 100_000_u128, - maturity: BondDuration::Finite { return_in: 1_000_000 }, - reward: BondOfferReward { - asset: MockCurrencyId::BTC, - amount: 1_000_000_u128 * 100_000_u128, - maturity: 96_u128, - } - } - .valid(MinVestedTransfer::get() as _, MinReward::get())); -} - -#[test] -fn invalid_offer() { - // invalid bond_price - assert!(!BondOffer { - beneficiary: ALICE, - asset: MockCurrencyId::BTC, - bond_price: MIN_VESTED_TRANSFER as u128 - 1, - nb_of_bonds: 100_000_u128, - maturity: BondDuration::Infinite, - reward: BondOfferReward { - asset: MockCurrencyId::PICA, - amount: 1_000_000_u128, - maturity: 96_u128 - } - } - .valid(MinVestedTransfer::get() as _, MinReward::get())); - - // invalid nb_of_bonds - assert!(!BondOffer { - beneficiary: ALICE, - asset: MockCurrencyId::BTC, - bond_price: MIN_VESTED_TRANSFER as _, - nb_of_bonds: 0, - maturity: BondDuration::Finite { return_in: 1 }, - reward: BondOfferReward { - asset: MockCurrencyId::BTC, - amount: 1_000_000_u128, - maturity: 96_u128, - } - } - .valid(MinVestedTransfer::get() as _, MinReward::get())); - - // invalid maturity - assert!(!BondOffer { - beneficiary: ALICE, - asset: MockCurrencyId::BTC, - bond_price: 1_000_000 + MIN_VESTED_TRANSFER as u128, - nb_of_bonds: 100_000_u128, - maturity: BondDuration::Finite { return_in: 0 }, - reward: BondOfferReward { - asset: MockCurrencyId::BTC, - amount: 1_000_000_u128, - maturity: 96_u128, - } - } - .valid(MinVestedTransfer::get() as _, MinReward::get())); - - // invalid reward - assert!(!BondOffer { - beneficiary: ALICE, - asset: MockCurrencyId::BTC, - bond_price: 1_000_000 + MIN_VESTED_TRANSFER as u128, - nb_of_bonds: 100_000_u128, - maturity: BondDuration::Finite { return_in: 1_000_000 }, - reward: BondOfferReward { asset: MockCurrencyId::BTC, amount: 0, maturity: 96_u128 } - } - .valid(MinVestedTransfer::get() as _, MinReward::get())); - - // invalid reward: < MinVested - assert!(!BondOffer { - beneficiary: ALICE, - asset: MockCurrencyId::BTC, - bond_price: 1_000_000 + MIN_VESTED_TRANSFER as u128, - nb_of_bonds: 100_000_u128, - maturity: BondDuration::Finite { return_in: 1_000_000 }, - reward: BondOfferReward { - asset: MockCurrencyId::BTC, - amount: 1_000_000_u128 * 100_000_u128 - 1, - maturity: 96_u128 - } - } - .valid(MinVestedTransfer::get() as _, MinReward::get())); - - // invalid reward maturity - assert!(!BondOffer { - beneficiary: ALICE, - asset: MockCurrencyId::BTC, - bond_price: 1_000_000 + MIN_VESTED_TRANSFER as u128, - nb_of_bonds: 100_000_u128, - maturity: BondDuration::Finite { return_in: 1_000_000 }, - reward: BondOfferReward { - asset: MockCurrencyId::BTC, - amount: 1_000_000_u128, - maturity: 0_u128 - } - } - .valid(MinVestedTransfer::get() as _, MinReward::get())); -} - prop_compose! { // NOTE(hussein-aitlahcen): we use u32 before casting to avoid overflows /// Pseudo random valid simple offer @@ -188,7 +55,7 @@ proptest! { System::set_block_number(1); prop_assert_ok!(Tokens::mint_into(NATIVE_CURRENCY_ID, &ALICE, Stake::get())); prop_assert_ok!(Tokens::mint_into(offer.reward.asset, &ALICE, offer.reward.amount)); - let offer_id = BondedFinance::do_offer(&ALICE, offer); + let offer_id = BondedFinance::do_offer(&ALICE, offer, false); prop_assert_ok!(offer_id); let offer_id = offer_id.expect("impossible; qed"); @@ -204,7 +71,7 @@ proptest! { prop_assert_ok!(Tokens::mint_into(offer.reward.asset, &ALICE, offer.reward.amount)); prop_assert_eq!(Tokens::balance(NATIVE_CURRENCY_ID, &ALICE), Stake::get()); - prop_assert_ok!(BondedFinance::do_offer(&ALICE, offer)); + prop_assert_ok!(BondedFinance::do_offer(&ALICE, offer, false)); prop_assert_eq!(Tokens::balance(NATIVE_CURRENCY_ID, &ALICE), 0); Ok(()) })?; @@ -217,7 +84,7 @@ proptest! { prop_assert_ok!(Tokens::mint_into(offer.reward.asset, &ALICE, offer.reward.amount)); prop_assert_eq!(Tokens::balance(offer.reward.asset, &ALICE), offer.reward.amount); - prop_assert_ok!(BondedFinance::do_offer(&ALICE, offer.clone())); + prop_assert_ok!(BondedFinance::do_offer(&ALICE, offer.clone(), false)); prop_assert_eq!(Tokens::balance(offer.reward.asset, &ALICE), 0); Ok(()) })?; @@ -230,7 +97,7 @@ proptest! { prop_assert_ok!(Tokens::mint_into(offer.reward.asset, &ALICE, offer.reward.amount)); prop_assert_eq!(Tokens::balance(offer.reward.asset, &ALICE), offer.reward.amount); - let offer_id = BondedFinance::do_offer(&ALICE, offer.clone()); + let offer_id = BondedFinance::do_offer(&ALICE, offer.clone(), false); prop_assert_ok!(offer_id); let offer_id = offer_id.expect("impossible; qed"); @@ -238,13 +105,15 @@ proptest! { let half_nb_of_bonds = offer.nb_of_bonds / 2; let half_reward = offer.reward.amount / 2; prop_assert_ok!(Tokens::mint_into(offer.asset, &BOB, half_nb_of_bonds * offer.bond_price)); - prop_assert_ok!(BondedFinance::do_bond(offer_id, &BOB, half_nb_of_bonds)); + prop_assert_ok!(BondedFinance::do_bond(offer_id, &BOB, half_nb_of_bonds, false)); // Alice cancel the offer prop_assert_ok!(BondedFinance::cancel(Origin::signed(ALICE), offer_id)); - // The remaining half is refunded to alice - prop_assert_acceptable_computation_error!(Tokens::balance(offer.reward.asset, &ALICE), half_reward); + // The remaining half is refunded to alice + let precision = 100; + let epsilon = 5; + prop_assert_acceptable_computation_error!(Tokens::balance(offer.reward.asset, &ALICE), half_reward, precision, epsilon); Ok(()) })?; @@ -257,7 +126,7 @@ proptest! { prop_assert_ok!(Tokens::mint_into(offer.reward.asset, &ALICE, offer.reward.amount)); prop_assert_eq!(Tokens::balance(offer.reward.asset, &ALICE), offer.reward.amount); - let offer_id = BondedFinance::do_offer(&ALICE, offer.clone()); + let offer_id = BondedFinance::do_offer(&ALICE, offer.clone(), false); prop_assert_ok!(offer_id); let offer_id = offer_id.expect("impossible; qed"); @@ -276,14 +145,14 @@ proptest! { ExtBuilder::build().execute_with(|| { prop_assert_ok!(Tokens::mint_into(NATIVE_CURRENCY_ID, &ALICE, Stake::get())); prop_assert_ok!(Tokens::mint_into(offer.reward.asset, &ALICE, offer.reward.amount)); - let offer_id = BondedFinance::do_offer(&ALICE, offer.clone()); + let offer_id = BondedFinance::do_offer(&ALICE, offer.clone(), false); prop_assert_ok!(offer_id); let offer_id = offer_id.expect("impossible; qed"); prop_assert_ok!(Tokens::mint_into(offer.asset, &BOB, offer.total_price().expect("impossible; qed;"))); - prop_assert_ok!(BondedFinance::bond(Origin::signed(BOB), offer_id, offer.nb_of_bonds)); + prop_assert_ok!(BondedFinance::bond(Origin::signed(BOB), offer_id, offer.nb_of_bonds, false)); prop_assert_eq!( - BondedFinance::bond(Origin::signed(BOB), offer_id, offer.nb_of_bonds), + BondedFinance::bond(Origin::signed(BOB), offer_id, offer.nb_of_bonds, false), Err(Error::::OfferCompleted.into()) ); @@ -320,13 +189,13 @@ proptest! { prop_assert_ok!(Tokens::mint_into(NATIVE_CURRENCY_ID, &ALICE, Stake::get())); prop_assert_ok!(Tokens::mint_into(offer_a.reward.asset, &ALICE, offer_a.reward.amount)); - let offer_a_id = BondedFinance::do_offer(&ALICE, offer_a.clone()); + let offer_a_id = BondedFinance::do_offer(&ALICE, offer_a.clone(), false); prop_assert_ok!(offer_a_id); let offer_a_id = offer_a_id.expect("impossible; qed"); prop_assert_ok!(Tokens::mint_into(NATIVE_CURRENCY_ID, &BOB, Stake::get())); prop_assert_ok!(Tokens::mint_into(offer_b.reward.asset, &BOB, offer_b.reward.amount)); - let offer_b_id = BondedFinance::do_offer(&BOB, offer_b.clone()); + let offer_b_id = BondedFinance::do_offer(&BOB, offer_b.clone(), false); prop_assert_ok!(offer_b_id); let offer_b_id = offer_b_id.expect("impossible; qed"); @@ -351,12 +220,12 @@ proptest! { prop_assert_ok!(Tokens::mint_into(NATIVE_CURRENCY_ID, &ALICE, Stake::get())); prop_assert_ok!(Tokens::mint_into(offer.reward.asset, &ALICE, offer.reward.amount)); - let offer_id = BondedFinance::do_offer(&ALICE, offer.clone()); + let offer_id = BondedFinance::do_offer(&ALICE, offer.clone(), false); prop_assert_ok!(offer_id); let offer_id = offer_id.expect("impossible; qed"); prop_assert_ok!(Tokens::mint_into(offer.asset, &BOB, offer.total_price().expect("impossible; qed;"))); - prop_assert_ok!(BondedFinance::bond(Origin::signed(BOB), offer_id, offer.nb_of_bonds - 1)); + prop_assert_ok!(BondedFinance::bond(Origin::signed(BOB), offer_id, offer.nb_of_bonds - 1, false)); System::assert_last_event(Event::BondedFinance(crate::Event::NewBond { offer_id, @@ -364,7 +233,7 @@ proptest! { nb_of_bonds: offer.nb_of_bonds - 1 })); - prop_assert_ok!(BondedFinance::bond(Origin::signed(BOB), offer_id, 1)); + prop_assert_ok!(BondedFinance::bond(Origin::signed(BOB), offer_id, 1, false)); System::assert_has_event(Event::BondedFinance(crate::Event::NewBond { offer_id, @@ -381,10 +250,10 @@ proptest! { #[test] fn multiple_bonds(offer in simple_offer(2)) { ExtBuilder::build().execute_with(|| { - prop_assert_ok!(Tokens::mint_into(NATIVE_CURRENCY_ID, &ALICE, Stake::get())); - prop_assert_ok!(Tokens::mint_into(offer.reward.asset, &ALICE, offer.reward.amount)); + prop_assert_ok!(Tokens::mint_into(NATIVE_CURRENCY_ID, &ALICE, Stake::get())); + prop_assert_ok!(Tokens::mint_into(offer.reward.asset, &ALICE, offer.reward.amount)); - let offer_id = BondedFinance::do_offer(&ALICE, offer.clone()); + let offer_id = BondedFinance::do_offer(&ALICE, offer.clone(),false); prop_assert_ok!(offer_id); let offer_id = offer_id.expect("impossible; qed"); @@ -392,17 +261,19 @@ proptest! { let half_reward = offer.reward.amount / 2; prop_assert_ok!(Tokens::mint_into(offer.asset, &BOB, half_nb_of_bonds * offer.bond_price)); - let bob_reward = BondedFinance::do_bond(offer_id, &BOB, half_nb_of_bonds); + let bob_reward = BondedFinance::do_bond(offer_id, &BOB, half_nb_of_bonds,false); prop_assert_ok!(bob_reward); let bob_reward = bob_reward.expect("impossible; qed;"); prop_assert_ok!(Tokens::mint_into(offer.asset, &CHARLIE, half_nb_of_bonds * offer.bond_price)); - let charlie_reward = BondedFinance::do_bond(offer_id, &CHARLIE, half_nb_of_bonds); + let charlie_reward = BondedFinance::do_bond(offer_id, &CHARLIE, half_nb_of_bonds,false); prop_assert_ok!(charlie_reward); let charlie_reward = charlie_reward.expect("impossible; qed;"); - prop_assert_acceptable_computation_error!(bob_reward, half_reward, 3); - prop_assert_acceptable_computation_error!(charlie_reward, half_reward, 3); + let precision = 100; + let epsilon = 5; + prop_assert_acceptable_computation_error!(bob_reward, half_reward, precision, epsilon); + prop_assert_acceptable_computation_error!(charlie_reward, half_reward, precision, epsilon); prop_assert!(Tokens::can_withdraw(offer.reward.asset, &BOB, bob_reward) == WithdrawConsequence::Frozen); prop_assert!(Tokens::can_withdraw(offer.reward.asset, &CHARLIE, charlie_reward) == WithdrawConsequence::Frozen); @@ -424,13 +295,13 @@ proptest! { ExtBuilder::build().execute_with(|| { prop_assert_ok!(Tokens::mint_into(NATIVE_CURRENCY_ID, &ALICE, Stake::get())); prop_assert_ok!(Tokens::mint_into(offer.reward.asset, &ALICE, offer.reward.amount)); - let offer_id = BondedFinance::do_offer(&ALICE, offer.clone()); + let offer_id = BondedFinance::do_offer(&ALICE, offer.clone(),false); prop_assert_ok!(offer_id); let offer_id = offer_id.expect("impossible; qed"); prop_assert_ok!(Tokens::mint_into(offer.asset, &BOB, offer.total_price().expect("impossible; qed;"))); prop_assert_eq!( - BondedFinance::bond(Origin::signed(BOB), offer_id + 1, offer.nb_of_bonds), + BondedFinance::bond(Origin::signed(BOB), offer_id + 1, offer.nb_of_bonds,false), Err(Error::::BondOfferNotFound.into()) ); @@ -443,17 +314,17 @@ proptest! { ExtBuilder::build().execute_with(|| { prop_assert_ok!(Tokens::mint_into(NATIVE_CURRENCY_ID, &ALICE, Stake::get())); prop_assert_ok!(Tokens::mint_into(offer.reward.asset, &ALICE, offer.reward.amount)); - let offer_id = BondedFinance::do_offer(&ALICE, offer.clone()); + let offer_id = BondedFinance::do_offer(&ALICE, offer.clone(),false); prop_assert_ok!(offer_id); let offer_id = offer_id.expect("impossible; qed"); prop_assert_ok!(Tokens::mint_into(offer.asset, &BOB, offer.total_price().expect("impossible; qed;"))); prop_assert_eq!( - BondedFinance::bond(Origin::signed(BOB), offer_id, offer.nb_of_bonds + 1), + BondedFinance::bond(Origin::signed(BOB), offer_id, offer.nb_of_bonds + 1,false), Err(Error::::InvalidNumberOfBonds.into()) ); prop_assert_eq!( - BondedFinance::bond(Origin::signed(BOB), offer_id, 0), + BondedFinance::bond(Origin::signed(BOB), offer_id, 0,false), Err(Error::::InvalidNumberOfBonds.into()) ); @@ -466,14 +337,14 @@ proptest! { ExtBuilder::build().execute_with(|| { prop_assert_ok!(Tokens::mint_into(NATIVE_CURRENCY_ID, &ALICE, Stake::get())); prop_assert_ok!(Tokens::mint_into(offer.reward.asset, &ALICE, offer.reward.amount)); - let offer_id = BondedFinance::do_offer(&ALICE, offer.clone()); + let offer_id = BondedFinance::do_offer(&ALICE, offer.clone(),false); prop_assert_ok!(offer_id); let offer_id = offer_id.expect("impossible; qed"); prop_assert_ok!(Tokens::mint_into(offer.asset, &BOB, offer.total_price().expect("impossible; qed;"))); - prop_assert_ok!(BondedFinance::bond(Origin::signed(BOB), offer_id, offer.nb_of_bonds)); + prop_assert_ok!(BondedFinance::bond(Origin::signed(BOB), offer_id, offer.nb_of_bonds,false)); prop_assert_eq!( - BondedFinance::bond(Origin::signed(BOB), offer_id, offer.nb_of_bonds), + BondedFinance::bond(Origin::signed(BOB), offer_id, offer.nb_of_bonds,false), Err(Error::::OfferCompleted.into()) ); @@ -490,7 +361,7 @@ proptest! { prop_assert_ok!(Tokens::mint_into(NATIVE_CURRENCY_ID, &ALICE, Stake::get())); prop_assert_ok!(Tokens::mint_into(offer.reward.asset, &ALICE, offer.reward.amount)); - let offer_id = BondedFinance::do_offer(&ALICE, offer.clone()); + let offer_id = BondedFinance::do_offer(&ALICE, offer.clone(),false); prop_assert_ok!(offer_id); let offer_id = offer_id.expect("impossible; qed"); @@ -504,7 +375,7 @@ proptest! { prop_assert_eq!(Tokens::balance(offer.reward.asset, &ALICE), offer.reward.amount); prop_assert_eq!( - BondedFinance::bond(Origin::signed(BOB), offer_id, offer.nb_of_bonds), + BondedFinance::bond(Origin::signed(BOB), offer_id, offer.nb_of_bonds,false), Err(Error::::BondOfferNotFound.into()) ); @@ -521,7 +392,7 @@ proptest! { prop_assert_ok!(Tokens::mint_into(NATIVE_CURRENCY_ID, &ALICE, Stake::get())); prop_assert_ok!(Tokens::mint_into(offer.reward.asset, &ALICE, offer.reward.amount)); - let offer_id = BondedFinance::do_offer(&ALICE, offer.clone()); + let offer_id = BondedFinance::do_offer(&ALICE, offer.clone(),false); prop_assert_ok!(offer_id); let offer_id = offer_id.expect("impossible; qed"); @@ -535,7 +406,7 @@ proptest! { prop_assert_eq!(Tokens::balance(offer.reward.asset, &ALICE), offer.reward.amount); prop_assert_eq!( - BondedFinance::bond(Origin::signed(BOB), offer_id, offer.nb_of_bonds), + BondedFinance::bond(Origin::signed(BOB), offer_id, offer.nb_of_bonds,false), Err(Error::::BondOfferNotFound.into()) ); @@ -545,3 +416,202 @@ proptest! { })?; } } + +#[cfg(test)] +mod test_bond_offer { + use super::*; + use crate::BondOfferOf; + use composable_support::validation::Validate; + use composable_traits::bonded_finance::{BondDuration, ValidBondOffer}; + use frame_support::assert_ok; + use mock::Runtime; + + #[test] + fn test_valid_offer() { + let valid_bond_offer = BondOfferOf:: { + beneficiary: ALICE, + asset: mock::MockCurrencyId::BTC, + bond_price: 1_000_000 + MIN_VESTED_TRANSFER as u128, + nb_of_bonds: 100_000_u128, + maturity: BondDuration::Infinite, + reward: BondOfferReward { + asset: mock::MockCurrencyId::PICA, + amount: 1_000_000_u128 * 100_000_u128, + maturity: 96_u64, + }, + }; + + assert_ok!( as Validate< + BondOfferOf, + ValidBondOffer, + >>::validate(valid_bond_offer)); + + let valid_bond_offer2 = BondOfferOf:: { + beneficiary: ALICE, + asset: mock::MockCurrencyId::BTC, + bond_price: 1_000_000 + MIN_VESTED_TRANSFER as u128, + nb_of_bonds: 1_u128, + maturity: BondDuration::Finite { return_in: 1 }, + reward: BondOfferReward { + asset: mock::MockCurrencyId::BTC, + amount: 1_000_000_u128, + maturity: 96_u64, + }, + }; + + assert_ok!( as Validate< + BondOfferOf, + ValidBondOffer, + >>::validate(valid_bond_offer2)); + + let valid_bond_offer3 = BondOfferOf:: { + beneficiary: ALICE, + asset: mock::MockCurrencyId::BTC, + bond_price: 1_000_000 + MIN_VESTED_TRANSFER as u128, + nb_of_bonds: 100_000_u128, + maturity: BondDuration::Finite { return_in: 1_000_000 }, + reward: BondOfferReward { + asset: mock::MockCurrencyId::BTC, + amount: 1_000_000_u128 * 100_000_u128, + maturity: 96_u64, + }, + }; + + assert_ok!( as Validate< + BondOfferOf, + ValidBondOffer, + >>::validate(valid_bond_offer3)); + } + + #[test] + fn invalid_bond_price() { + let invalid = BondOfferOf:: { + beneficiary: ALICE, + asset: mock::MockCurrencyId::PICA, + bond_price: MIN_VESTED_TRANSFER as u128 - 1, + nb_of_bonds: 100_000_u128, + maturity: BondDuration::Infinite, + reward: BondOfferReward { + asset: mock::MockCurrencyId::PICA, + amount: 1_000_000_u128, + maturity: 96_u64, + }, + }; + + assert!( as Validate< + BondOfferOf, + ValidBondOffer, + >>::validate(invalid) + .is_err()); + } + + #[test] + fn test_invalid_nb_of_bonds() { + let invalid = BondOfferOf:: { + beneficiary: ALICE, + asset: mock::MockCurrencyId::BTC, + bond_price: MIN_VESTED_TRANSFER as _, + nb_of_bonds: 0, + maturity: BondDuration::Finite { return_in: 1 }, + reward: BondOfferReward { + asset: mock::MockCurrencyId::BTC, + amount: 1_000_000_u128, + maturity: 96_u64, + }, + }; + + assert!( as Validate< + BondOfferOf, + ValidBondOffer, + >>::validate(invalid) + .is_err()); + } + + #[test] + fn test_invalid_maturity() { + let invalid = BondOfferOf:: { + beneficiary: ALICE, + asset: mock::MockCurrencyId::BTC, + bond_price: 1_000_000 + MIN_VESTED_TRANSFER as u128, + nb_of_bonds: 100_000_u128, + maturity: BondDuration::Finite { return_in: 0 }, + reward: BondOfferReward { + asset: mock::MockCurrencyId::BTC, + amount: 1_000_000_u128, + maturity: 96_u64, + }, + }; + + assert!( as Validate< + BondOfferOf, + ValidBondOffer, + >>::validate(invalid) + .is_err()); + } + + #[test] + fn test_invalid_reward() { + let invalid = BondOfferOf:: { + beneficiary: ALICE, + asset: mock::MockCurrencyId::BTC, + bond_price: 1_000_000 + MIN_VESTED_TRANSFER as u128, + nb_of_bonds: 100_000_u128, + maturity: BondDuration::Finite { return_in: 1_000_000 }, + reward: BondOfferReward { + asset: mock::MockCurrencyId::BTC, + amount: 0, + maturity: 96_u64, + }, + }; + + assert!( as Validate< + BondOfferOf, + ValidBondOffer, + >>::validate(invalid) + .is_err()); + } + + #[test] + fn test_invalid_reward_less_than_minvested() { + let invalid = BondOfferOf:: { + beneficiary: ALICE, + asset: mock::MockCurrencyId::BTC, + bond_price: 1_000_000 + MIN_VESTED_TRANSFER as u128, + nb_of_bonds: 100_000_u128, + maturity: BondDuration::Finite { return_in: 1_000_000 }, + reward: BondOfferReward { + asset: mock::MockCurrencyId::BTC, + amount: MIN_VESTED_TRANSFER * 1_000_u128 - 1, + maturity: 96_u64, + }, + }; + + assert!( as Validate< + BondOfferOf, + ValidBondOffer, + >>::validate(invalid) + .is_err()); + } + + #[test] + fn test_invalid_reward_maturity() { + let invalid = BondOfferOf:: { + beneficiary: ALICE, + asset: mock::MockCurrencyId::BTC, + bond_price: 1_000_000 + MIN_VESTED_TRANSFER as u128, + nb_of_bonds: 100_000_u128, + maturity: BondDuration::Finite { return_in: 1_000_000 }, + reward: BondOfferReward { + asset: mock::MockCurrencyId::BTC, + amount: MIN_VESTED_TRANSFER * 1_000_u128 - 1, + maturity: 0_u64, + }, + }; + + assert!( as Validate< + BondOfferOf, + ValidBondOffer, + >>::validate(invalid) + .is_err()); + } +} diff --git a/frame/bonded-finance/src/utils.rs b/frame/bonded-finance/src/utils.rs deleted file mode 100644 index 4c9c9f418db..00000000000 --- a/frame/bonded-finance/src/utils.rs +++ /dev/null @@ -1,3 +0,0 @@ -#[cfg(any(feature = "runtime-benchmarks", test))] - -pub const MIN_VESTED_TRANSFER: u32 = 1_000_000; diff --git a/frame/bonded-finance/src/weights.rs b/frame/bonded-finance/src/weights.rs new file mode 100644 index 00000000000..19636b4d353 --- /dev/null +++ b/frame/bonded-finance/src/weights.rs @@ -0,0 +1,24 @@ +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(clippy::unnecessary_cast)] + +use frame_support::weights::Weight; + +pub trait WeightInfo { + fn offer() -> Weight; + fn bond() -> Weight; + fn cancel() -> Weight; +} + +impl WeightInfo for () { + fn offer() -> Weight { + 10_000 as Weight + } + fn bond() -> Weight { + 10_000 as Weight + } + fn cancel() -> Weight { + 10_000 as Weight + } +} diff --git a/frame/call-filter/Cargo.toml b/frame/call-filter/Cargo.toml index 0915f87a7c2..f6fc932a6b1 100644 --- a/frame/call-filter/Cargo.toml +++ b/frame/call-filter/Cargo.toml @@ -1,38 +1,40 @@ [package] -name = "pallet-call-filter" -version = "0.1.0" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" +homepage = "https://composable.finance" +name = "pallet-call-filter" +version = "0.1.0" [dependencies] -serde = { version = "1.0.130", optional = true } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -support = { package = "frame-support", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -system = { package = "frame-system", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-io= { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -scale-info = { version = "1.0.0", features = ["derive"], default-features = false } -composable-traits = { path = "../../frame/composable-traits" , default-features = false} +composable-traits = { path = "../../frame/composable-traits", default-features = false } +scale-info = { version = "1.0.0", features = [ + "derive", +], default-features = false } +serde = { version = "1.0.130", optional = true } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +support = { package = "frame-support", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +system = { package = "frame-system", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } [dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } smallvec = "1.4.1" +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } [features] default = ["std"] std = [ - "serde", - "codec/std", - "sp-runtime/std", - "support/std", - "system/std", - "sp-io/std", - "sp-std/std", - "support/std", - "scale-info/std", + "serde", + "codec/std", + "sp-runtime/std", + "support/std", + "system/std", + "sp-io/std", + "sp-std/std", + "support/std", + "scale-info/std", ] diff --git a/frame/composable-maths/Cargo.toml b/frame/composable-maths/Cargo.toml new file mode 100644 index 00000000000..83cf896b5b0 --- /dev/null +++ b/frame/composable-maths/Cargo.toml @@ -0,0 +1,34 @@ +[package] +authors = ["Composable Developers"] +edition = "2021" +homepage = "https://composable.finance" +name = "composable-maths" +version = "0.0.1" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } + +sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } + +codec = { version = "2.0.0", package = "parity-scale-codec", default-features = false, features = [ + "derive", +] } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } + +composable-traits = { path = "../composable-traits", default-features = false } + +rust_decimal = { version = "1.2", default-features = false, features = [ + "maths", +] } + +[features] +default = ["std"] +std = ["codec/std", "frame-support/std", "sp-std/std", "scale-info/std"] diff --git a/frame/composable-maths/src/dex/constant_product.rs b/frame/composable-maths/src/dex/constant_product.rs new file mode 100644 index 00000000000..4e76419c958 --- /dev/null +++ b/frame/composable-maths/src/dex/constant_product.rs @@ -0,0 +1,162 @@ +use composable_traits::math::{safe_multiply_by_rational, SafeAdd, SafeDiv, SafeMul, SafeSub}; +use frame_support::ensure; +use rust_decimal::{ + prelude::{FromPrimitive, ToPrimitive}, + Decimal, MathematicalOps, +}; +use sp_runtime::{ + traits::{IntegerSquareRoot, One, Zero}, + ArithmeticError, PerThing, +}; + +/// From https://balancer.fi/whitepaper.pdf, equation (2) +/// Compute the spot price of an asset pair. +/// - `wi` the weight on the quote asset +/// - `wo` the weight of the base asset +/// - `bi` the pool quote balance +/// - `bo` the pool base balance +/// - `base_unit` the unit normalized to the base asset decimal +pub fn compute_spot_price( + wi: T, + wo: T, + bi: u128, + bo: u128, + base_unit: u128, +) -> Result +where + T::Inner: Into, +{ + let wi: u32 = wi.deconstruct().into(); + let wo: u32 = wo.deconstruct().into(); + let weight_sum = wi.safe_add(&wo)?; + let expected_weight_sum: u32 = T::one().deconstruct().into(); + ensure!(weight_sum == expected_weight_sum, ArithmeticError::Overflow); + + let base_unit = Decimal::from_u128(base_unit).ok_or(ArithmeticError::Overflow)?; + let bi = Decimal::from_u128(bi).ok_or(ArithmeticError::Overflow)?; + let bo = Decimal::from_u128(bo).ok_or(ArithmeticError::Overflow)?; + let full_perthing = + Decimal::from_u32(T::one().deconstruct().into()).ok_or(ArithmeticError::Overflow)?; + let wi_numer = Decimal::from_u32(wi).ok_or(ArithmeticError::Overflow)?; + let wi = wi_numer.safe_div(&full_perthing)?; + let wo_numer = Decimal::from_u32(wo).ok_or(ArithmeticError::Overflow)?; + let wo = wo_numer.safe_div(&full_perthing)?; + let bi_div_wi = bi.safe_div(&wi)?; + let bo_div_wo = bo.safe_div(&wo)?; + let spot_price = bi_div_wi.safe_div(&bo_div_wo)?; + spot_price.safe_mul(&base_unit)?.to_u128().ok_or(ArithmeticError::Overflow) +} + +/// From https://balancer.fi/whitepaper.pdf, equation (15) +/// Compute the amount of base asset (out) given the quote asset (in). +/// - `wi` the weight on the quote asset +/// - `wo` the weight of the base asset +/// - `bi` the pool quote balance +/// - `bo` the pool base balance +/// - `ai` the quote amount to trade +pub fn compute_out_given_in( + wi: T, + wo: T, + bi: u128, + bo: u128, + ai: u128, +) -> Result +where + T::Inner: Into, +{ + let wi: u32 = wi.deconstruct().into(); + let wo: u32 = wo.deconstruct().into(); + let weight_sum = wi.safe_add(&wo)?; + let expected_weight_sum: u32 = T::one().deconstruct().into(); + ensure!(weight_sum == expected_weight_sum, ArithmeticError::Overflow); + + let ai = Decimal::from_u128(ai).ok_or(ArithmeticError::Overflow)?; + let bi = Decimal::from_u128(bi).ok_or(ArithmeticError::Overflow)?; + let bo = Decimal::from_u128(bo).ok_or(ArithmeticError::Overflow)?; + let weight_numer = Decimal::from_u32(wi).ok_or(ArithmeticError::Overflow)?; + let weight_denom = Decimal::from_u32(wo).ok_or(ArithmeticError::Overflow)?; + let weight_power = weight_numer.safe_div(&weight_denom)?; + let bi_div_bi_plus_ai = bi.safe_div(&bi.safe_add(&ai)?)?; + let term_to_weight_power = + bi_div_bi_plus_ai.checked_powd(weight_power).ok_or(ArithmeticError::Overflow)?; + let one_minus_term = Decimal::one().safe_sub(&term_to_weight_power)?; + let ao = bo.safe_mul(&one_minus_term)?.to_u128().ok_or(ArithmeticError::Overflow)?; + Ok(ao) +} + +/// From https://balancer.fi/whitepaper.pdf, equation (20) +/// Compute the amount of quote asset (in) given the expected amount of base asset (out). +/// - `wi` the weight on the quote asset +/// - `wo` the weight of the base asset +/// - `bi` the pool quote balance +/// - `bo` the pool base balance +/// - `ai` the quote amount to trade +pub fn compute_in_given_out( + wi: T, + wo: T, + bi: u128, + bo: u128, + ao: u128, +) -> Result +where + T::Inner: Into, +{ + let wi: u32 = wi.deconstruct().into(); + let wo: u32 = wo.deconstruct().into(); + let weight_sum = wi.safe_add(&wo)?; + let expected_weight_sum: u32 = T::one().deconstruct().into(); + ensure!(weight_sum == expected_weight_sum, ArithmeticError::Overflow); + + let ao = Decimal::from_u128(ao).ok_or(ArithmeticError::Overflow)?; + let bi = Decimal::from_u128(bi).ok_or(ArithmeticError::Overflow)?; + let bo = Decimal::from_u128(bo).ok_or(ArithmeticError::Overflow)?; + let weight_numer = Decimal::from_u32(wo).ok_or(ArithmeticError::Overflow)?; + let weight_denom = Decimal::from_u32(wi).ok_or(ArithmeticError::Overflow)?; + let weight_power = weight_numer.safe_div(&weight_denom)?; + let bo_div_bo_minus_ao = bo.safe_div(&bo.safe_sub(&ao)?)?; + let term_to_weight_power = + bo_div_bo_minus_ao.checked_powd(weight_power).ok_or(ArithmeticError::Overflow)?; + let term_minus_one = term_to_weight_power.safe_sub(&Decimal::one())?; + let ai = bi.safe_mul(&term_minus_one)?.to_u128().ok_or(ArithmeticError::Overflow)?; + Ok(ai) +} + +/// https://uniswap.org/whitepaper.pdf, equation (13) +/// Compute the initial share of an LP provider. +/// - `base_amount` the base asset amount deposited. +/// - `quote_amount` the quote asset amount deposited. +#[inline(always)] +pub fn compute_first_deposit_lp( + base_amount: u128, + quote_amount: u128, +) -> Result { + base_amount + .integer_sqrt_checked() + .ok_or(ArithmeticError::Overflow)? + .safe_mul("e_amount.integer_sqrt_checked().ok_or(ArithmeticError::Overflow)?) +} + +/// https://uniswap.org/whitepaper.pdf, equation (12) +/// Compute the share of an LP provider for an existing, non-empty pool. +/// - `lp_total_issuance` the total LP already issued to other LP providers. +/// - `base_amount` the base amount provided by the current LP provider. +/// - `pool_base_aum` the pool base asset under management. +/// - `pool_quote_aum` the pool quote asset under management. +#[inline(always)] +pub fn compute_deposit_lp( + lp_total_issuance: u128, + base_amount: u128, + quote_amount: u128, + pool_base_aum: u128, + pool_quote_aum: u128, +) -> Result<(u128, u128), ArithmeticError> { + let first_deposit = lp_total_issuance.is_zero(); + if first_deposit { + let lp_to_mint = compute_first_deposit_lp(base_amount, quote_amount)?; + Ok((quote_amount, lp_to_mint)) + } else { + let quote_amount = safe_multiply_by_rational(pool_quote_aum, base_amount, pool_base_aum)?; + let lp_to_mint = safe_multiply_by_rational(lp_total_issuance, base_amount, pool_base_aum)?; + Ok((quote_amount, lp_to_mint)) + } +} diff --git a/frame/composable-maths/src/dex/mod.rs b/frame/composable-maths/src/dex/mod.rs new file mode 100644 index 00000000000..d7601bacffb --- /dev/null +++ b/frame/composable-maths/src/dex/mod.rs @@ -0,0 +1,2 @@ +pub mod constant_product; +pub mod stable_swap; diff --git a/frame/composable-maths/src/dex/stable_swap.rs b/frame/composable-maths/src/dex/stable_swap.rs new file mode 100644 index 00000000000..c140a24fe5d --- /dev/null +++ b/frame/composable-maths/src/dex/stable_swap.rs @@ -0,0 +1,136 @@ +use sp_runtime::{biguint::BigUint, helpers_128bit::to_big_uint, ArithmeticError, DispatchError}; + +fn safe_div(a: &mut BigUint, b: &mut BigUint) -> Result { + a.lstrip(); + b.lstrip(); + let a = a.clone(); + if b.len() == 1 { + return Ok(a.div_unit(b.get(0))) + } + let div = a.div(b, false).ok_or(ArithmeticError::Overflow)?; + Ok(div.0) +} + +/// # Notes +/// +/// D invariant calculation in non-overflowing integer operations iteratively +/// +/// ```pseudocode +/// A * sum(x_i) * n^n + D = A * D * n^n + D^(n+1) / (n^n * prod(x_i)) +/// ``` +/// +/// Converging solution: +/// +/// ```pseudocode +/// D[j + 1] = (A * n^n * sum(x_i) - D[j]^(n+1) / (n^n * prod(x_i))) / (A * n^n - 1) +/// ``` +/// For two assets, n = 2 used while computation +pub fn compute_d( + base_asset_aum: u128, + quote_asset_aum: u128, + amp_coeff: u128, +) -> Result { + let base_asset_amount = to_big_uint(base_asset_aum); + let quote_asset_amount = to_big_uint(quote_asset_aum); + let amplification_coefficient = to_big_uint(amp_coeff); + // pool has only 2 assets + let n = to_big_uint(2_u128); + let zero = to_big_uint(0_u128); + let one = to_big_uint(1_u128); + + let sum = base_asset_amount.clone().add("e_asset_amount); + if sum == zero { + return Ok(0_u128) + } + let ann = amplification_coefficient.mul(&n).mul(&n); + let mut d = sum.clone(); + + let mut base_n = base_asset_amount.mul(&n); + let mut quote_n = quote_asset_amount.mul(&n); + for _ in 0..255 { + let mut d_p = d.clone(); + let ann_d = ann.clone().mul(&d); + // d_p = d_p * d / (x * n) + + let mut d_p_d = d_p.mul(&d); + d_p = safe_div(&mut d_p_d, &mut base_n)?; + let mut d_p_d = d_p.mul(&d); + d_p = safe_div(&mut d_p_d, &mut quote_n)?; + + let d_prev = d.clone(); + // d = (ann * sum + d_p * n) * d / (ann * d + (n + 1) * d_p - d) + let mut numerator = ann.clone().mul(&sum).add(&d_p.clone().mul(&n)).mul(&d); + let mut denominator = ann_d + .add(&n.clone().add(&one).mul(&d_p)) + .sub(&d) + .map_err(|_| ArithmeticError::Underflow)?; + d = safe_div(&mut numerator, &mut denominator)?; + + if d.clone() > d_prev { + if d.clone() - d_prev <= one { + d.lstrip(); + return Ok(d.try_into().map_err(|_| ArithmeticError::Overflow)?) + } + } else if d_prev - d.clone() <= one { + d.lstrip(); + return Ok(d.try_into().map_err(|_| ArithmeticError::Overflow)?) + } + } + Err(DispatchError::Other("could not compute d")) +} + +/// See https://github.com/equilibrium-eosdt/equilibrium-curve-amm/blob/master/docs/deducing-get_y-formulas.pdf +/// for detailed explanation about formulas this function uses. +/// +/// # Notes +/// +/// Done by solving quadratic equation iteratively. +/// +/// ```pseudocode +/// x_1^2 + x_1 * (sum' - (A * n^n - 1) * D / (A * n^n)) = D^(n+1) / (n^2n * prod' * A) +/// x_1^2 + b * x_1 = c +/// +/// x_1 = (x_1^2 + c) / (2 * x_1 + b) +/// ``` +/// For two assets, n = 2 used while computation +pub fn compute_base(new_quote: u128, amp_coeff: u128, d: u128) -> Result { + let mut n = to_big_uint(2_u128); + let two = to_big_uint(2_u128); + let one = to_big_uint(1_u128); + let mut d = to_big_uint(d); + let amplification_coefficient = to_big_uint(amp_coeff); + let ann = amplification_coefficient.mul(&n).mul(&n); + + // s and p are same as input base amount as pool supports only 2 assets. + let s = to_big_uint(new_quote); + let mut p = to_big_uint(new_quote); + + // term1 = d^(n + 1) / n^n * p + // term2 = 2*y + s - d + + let d_n = safe_div(&mut d, &mut n)?; + let mut c = d_n.clone().mul(&d_n).mul(&d); + let term1 = safe_div(&mut c, &mut p)?; + + let mut y = d.clone(); + + // y = (y^2 * ann + term1) / (ann * term2 + d) + for _ in 0..255 { + let y_prev = y.clone(); + let term2 = two.clone().mul(&y).add(&s).sub(&d).map_err(|_| ArithmeticError::Underflow)?; + let mut numerator = ann.clone().mul(&y).mul(&y).add(&term1); + let mut denominator = ann.clone().mul(&term2).add(&d); + + y = safe_div(&mut numerator, &mut denominator)?; + if y.clone() > y_prev { + if y.clone() - y_prev <= one { + y.lstrip(); + return Ok(y.try_into().map_err(|_| ArithmeticError::Overflow)?) + } + } else if y_prev - y.clone() <= one { + y.lstrip(); + return Ok(y.try_into().map_err(|_| ArithmeticError::Overflow)?) + } + } + Err(DispatchError::Other("could not compute d")) +} diff --git a/frame/composable-maths/src/lib.rs b/frame/composable-maths/src/lib.rs new file mode 100644 index 00000000000..bbfdff6885f --- /dev/null +++ b/frame/composable-maths/src/lib.rs @@ -0,0 +1,15 @@ +#![cfg_attr( + not(test), + warn( + clippy::disallowed_method, + clippy::disallowed_type, + clippy::indexing_slicing, + clippy::todo, + clippy::unwrap_used, + clippy::panic + ) +)] // allow in tests +#![warn(clippy::unseparated_literal_suffix)] +#![cfg_attr(not(feature = "std"), no_std)] + +pub mod dex; diff --git a/frame/composable-support/Cargo.toml b/frame/composable-support/Cargo.toml index a6ea8f071f8..1f3fb22bcd4 100644 --- a/frame/composable-support/Cargo.toml +++ b/frame/composable-support/Cargo.toml @@ -1,42 +1,44 @@ [package] -name = "composable-support" -version = "0.0.1" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" +homepage = "https://composable.finance" +name = "composable-support" rust-version = "1.56" +version = "0.0.1" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] -[dev-dependencies] -proptest = { version = "1.0" } -serde_json = "1.0.45" - [dependencies] -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sorted-vec = "0.7.0" -serde = { version = "1.0.130", features = [ "derive" ], optional = true } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } + +sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } + +codec = { version = "2.0.0", package = "parity-scale-codec", default-features = false, features = [ + "derive", +] } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } + is_sorted = { version = "0.1.1", default-features = false } +serde = { version = "1.0.130", features = ["derive"], optional = true } +sorted-vec = { version = "0.7.0", optional = true } -[dependencies.codec] -default-features = false -features = ["derive"] -package = "parity-scale-codec" -version = "2.0.0" +[dev-dependencies] +proptest = { version = "1.0" } +serde_json = "1.0.45" [features] default = ["std"] std = [ - "codec/std", - "frame-support/std", - "frame-system/std", - "sp-runtime/std", - "sp-std/std", - "scale-info/std", + "codec/std", + "frame-support/std", + "sp-std/std", + "scale-info/std", + "serde", + "sorted-vec", ] diff --git a/frame/composable-support/src/collections/vec/sorted/mod.rs b/frame/composable-support/src/collections/vec/sorted/mod.rs index c2f6e94ef38..b1dbc1c9d9a 100644 --- a/frame/composable-support/src/collections/vec/sorted/mod.rs +++ b/frame/composable-support/src/collections/vec/sorted/mod.rs @@ -6,13 +6,14 @@ //! - `SortedSet` -- sorted from least to greatest, unique elements use codec::{Decode, Encode, EncodeLike, WrapperTypeEncode}; use core::hash::Hash; +use frame_support::RuntimeDebug; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use sp_std::prelude::*; #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(all(feature = "serde", not(feature = "serde-nontransparent")), serde(transparent))] -#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)] +#[derive(Clone, RuntimeDebug, Eq, Ord, PartialEq, PartialOrd, Hash)] pub struct SortedVec { #[cfg_attr(feature = "serde", serde(deserialize_with = "parse_vec"))] #[cfg_attr(feature = "serde", serde(bound(deserialize = "T : serde::Deserialize <'de>")))] diff --git a/frame/composable-support/src/lib.rs b/frame/composable-support/src/lib.rs index 6c7d99386a4..7b8b3feed54 100644 --- a/frame/composable-support/src/lib.rs +++ b/frame/composable-support/src/lib.rs @@ -13,4 +13,5 @@ #![cfg_attr(not(feature = "std"), no_std)] pub mod collections; +pub mod rpc_helpers; pub mod validation; diff --git a/frame/composable-support/src/rpc_helpers.rs b/frame/composable-support/src/rpc_helpers.rs new file mode 100644 index 00000000000..7c1a701c735 --- /dev/null +++ b/frame/composable-support/src/rpc_helpers.rs @@ -0,0 +1,79 @@ +use codec::{Codec, Decode, Encode}; +#[cfg(feature = "std")] +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +/// https://github.com/interlay/interbtc/blob/a7c0e69ac041176a2531bafb1c4e35cbc2f7e192/crates/oracle/rpc/runtime-api/src/lib.rs#L10 +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Debug, PartialEq, Eq, Encode, Decode)] +pub struct SafeRpcWrapper( + #[cfg_attr(feature = "std", serde(serialize_with = "serialize_to_hex"))] + #[cfg_attr(feature = "std", serde(deserialize_with = "deserialize_from_hex"))] + pub T, +); + +pub trait SafeRpcWrapperType +where + Self: sp_std::fmt::LowerHex + FromHexStr + Codec, +{ +} + +impl SafeRpcWrapperType for T where T: sp_std::fmt::LowerHex + FromHexStr + Codec {} + +pub trait FromHexStr: sp_std::marker::Sized { + type Err: sp_std::fmt::Display; + + fn from_hex_str(src: &str) -> sp_std::result::Result; +} + +#[derive(Debug)] +pub enum FromHexStrErr { + No0xPrefix, + ParseIntError(sp_std::num::ParseIntError), +} + +impl sp_std::fmt::Display for FromHexStrErr { + fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { + match self { + FromHexStrErr::No0xPrefix => f.write_str("No `0x` prefix"), + FromHexStrErr::ParseIntError(parse_int_error) => + f.write_fmt(format_args!("{}", parse_int_error)), + } + } +} + +impl FromHexStr for u128 { + type Err = FromHexStrErr; + + fn from_hex_str(src: &str) -> sp_std::result::Result { + match src.strip_prefix("0x") { + Some(stripped) => + u128::from_str_radix(stripped, 16).map_err(FromHexStrErr::ParseIntError), + None => Err(FromHexStrErr::No0xPrefix), + } + } +} + +#[cfg(feature = "std")] +fn serialize_to_hex( + t: &T, + serializer: S, +) -> Result { + serializer.serialize_str(&format!("{:#x}", t)) +} + +#[cfg(feature = "std")] +fn deserialize_from_hex<'de, D: Deserializer<'de>, T: SafeRpcWrapperType>( + deserializer: D, +) -> Result { + use serde::de::Error; + let hex_string = String::deserialize(deserializer)?; + + T::from_hex_str(&hex_string).map_err(|err| { + D::Error::custom(format!( + "Unable to parse as 0x-prefixed hex string: {} (error: {})", + hex_string, err + )) + }) +} + +// TODO: tests? diff --git a/frame/composable-support/src/validation.rs b/frame/composable-support/src/validation.rs index 6f8340dc800..0d2e352b9db 100644 --- a/frame/composable-support/src/validation.rs +++ b/frame/composable-support/src/validation.rs @@ -1,7 +1,7 @@ //! Module for validating extrinsic inputs //! //! This module is made of two main parts that are needed to validate an -//! extrinsic input, the `Validated` struct and the `Valitate` trait. +//! extrinsic input, the `Validated` struct and the `Validate` trait. //! //! # Example //! ## Single Validation @@ -65,23 +65,56 @@ //! } //! ``` -use core::marker::PhantomData; +use core::{fmt, marker::PhantomData}; use scale_info::TypeInfo; use sp_runtime::DispatchError; +use sp_std::ops::Deref; /// Black box that embbed the validated value. -#[derive(Default, Copy, Clone, PartialEq, Eq, Debug, TypeInfo)] +/// Validated during construction or serde. +#[derive(Default, Copy, Clone)] pub struct Validated { value: T, _marker: PhantomData, } +impl TypeInfo for Validated +where + T: TypeInfo, +{ + type Identity = ::Identity; + + fn type_info() -> scale_info::Type { + T::type_info() + } +} + +impl PartialEq for Validated +where + T: PartialEq, +{ + fn eq(&self, other: &Self) -> bool { + self.value == other.value + } +} + +impl Eq for Validated where T: PartialEq + Eq {} + +impl fmt::Debug for Validated +where + T: core::fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.value.fmt(f) + } +} + impl Validated where Validated: Validate, U: Validate, { - pub fn new(value: T, _validator_tag: U) -> Result { + pub fn new(value: T) -> Result { match >::validate(value) { Ok(value) => Ok(Self { value, _marker: PhantomData }), Err(e) => Err(e), @@ -98,6 +131,16 @@ pub trait Validate { fn validate(input: T) -> Result; } +pub trait TryIntoValidated { + fn try_into_validated>(self) -> Result, &'static str>; +} + +impl TryIntoValidated for T { + fn try_into_validated>(self) -> Result, &'static str> { + Validated::new(self) + } +} + #[derive(Debug, Eq, PartialEq, Default)] pub struct Valid; @@ -182,18 +225,13 @@ impl> codec::Decode for Validated { } } -pub(crate) mod private { - use sp_std::ops::Deref; - - use super::Validated; +/// Originally there to have `WrapperTypeEncode` work, but now also used in order to prevent +/// .value() calls everywhere +impl Deref for Validated { + type Target = T; - /// just to have `WrapperTypeEncode` work - impl Deref for Validated { - type Target = T; - #[doc(hidden)] - fn deref(&self) -> &Self::Target { - &self.value - } + fn deref(&self) -> &Self::Target { + &self.value } } @@ -309,9 +347,9 @@ mod test { #[test] fn value() { - let value = Validated::new(42, Valid); + let value = Validated::<_, Valid>::new(42); assert_ok!(value); - let value = Validated::new(42, Invalid); + let value = Validated::<_, Invalid>::new(42); assert!(value.is_err()); } @@ -415,4 +453,18 @@ mod test { let invalid = Validated::::decode(&mut &bytes[..]); assert!(invalid.is_err()); } + + #[test] + fn try_into_valid() { + let value = 42_u32.try_into_validated::().unwrap(); + + assert_eq!(value, Validated { value: 42, _marker: PhantomData }); + } + + #[test] + fn try_into_invalid() { + let value = 42_u32.try_into_validated::(); + + assert!(value.is_err()); + } } diff --git a/frame/composable-tests-helpers/Cargo.toml b/frame/composable-tests-helpers/Cargo.toml index 9b581c4483c..8bdced2f2b0 100644 --- a/frame/composable-tests-helpers/Cargo.toml +++ b/frame/composable-tests-helpers/Cargo.toml @@ -1,20 +1,22 @@ [package] -name = "composable-tests-helpers" -version = "0.0.1" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" +homepage = "https://composable.finance" +name = "composable-tests-helpers" +version = "0.0.1" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [dependencies] -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } serde = { version = "1", optional = true } -sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } [dependencies.codec] @@ -26,9 +28,9 @@ version = "2.0.0" [features] default = ["std"] std = [ - "serde", - "codec/std", - "sp-runtime/std", - "scale-info/std", - "frame-support/std", + "serde", + "codec/std", + "sp-runtime/std", + "scale-info/std", + "frame-support/std", ] diff --git a/frame/composable-tests-helpers/src/test/helper.rs b/frame/composable-tests-helpers/src/test/helper.rs index c734e0195e9..fad34b1cdb2 100644 --- a/frame/composable-tests-helpers/src/test/helper.rs +++ b/frame/composable-tests-helpers/src/test/helper.rs @@ -1,13 +1,21 @@ use sp_runtime::{FixedPointNumber, FixedU128}; -/// Default is 0.1% -pub const DEFAULT_ACCEPTABLE_DEVIATION: u128 = 1000; +/// Default is percent +pub const DEFAULT_PRECISION: u128 = 1000; -/// Check that x/y ~ 1 up to a certain precision -pub fn acceptable_computation_error(x: u128, y: u128, precision: u128) -> Result<(), FixedU128> { +/// Per mill +pub const DEFAULT_EPSILON: u128 = 1; + +/// This function should be used in context of approximation. +/// It is extensively used in conjunction with proptest because of random input generation. +pub fn acceptable_computation_error( + x: u128, + y: u128, + precision: u128, + epsilon: u128, +) -> Result<(), FixedU128> { let delta = i128::abs(x as i128 - y as i128); if delta > 1 { - let epsilon: u128 = 1; let lower = FixedU128::saturating_from_rational(precision, precision.saturating_add(epsilon)); let upper = @@ -24,5 +32,5 @@ pub fn acceptable_computation_error(x: u128, y: u128, precision: u128) -> Result } pub fn default_acceptable_computation_error(x: u128, y: u128) -> Result<(), FixedU128> { - acceptable_computation_error(x, y, DEFAULT_ACCEPTABLE_DEVIATION) + acceptable_computation_error(x, y, DEFAULT_PRECISION, DEFAULT_EPSILON) } diff --git a/frame/composable-tests-helpers/src/test/proptest.rs b/frame/composable-tests-helpers/src/test/proptest.rs index 29eb942d7b7..1859ea33ab7 100644 --- a/frame/composable-tests-helpers/src/test/proptest.rs +++ b/frame/composable-tests-helpers/src/test/proptest.rs @@ -41,18 +41,21 @@ macro_rules! prop_assert_noop { $x:expr, $y:expr $(,)? ) => { - let h = frame_support::storage_root(); + let h = frame_support::storage_root(sp_core::storage::StateVersion::V0); composable_tests_helpers::prop_assert_err!($x, $y); - proptest::prop_assert_eq!(h, frame_support::storage_root()); + proptest::prop_assert_eq!( + h, + frame_support::storage_root(sp_core::storage::StateVersion::V0) + ); }; } /// Accept a `dust` deviation. #[macro_export] macro_rules! prop_assert_acceptable_computation_error { - ($x:expr, $y:expr, $precision:expr) => {{ + ($x:expr, $y:expr, $precision:expr, $epsilon:expr) => {{ match composable_tests_helpers::test::helper::acceptable_computation_error( - $x, $y, $precision, + $x, $y, $precision, $epsilon, ) { Ok(()) => {}, Err(q) => { @@ -64,7 +67,8 @@ macro_rules! prop_assert_acceptable_computation_error { prop_assert_acceptable_computation_error!( $x, $y, - composable_tests_helpers::test::helper::DEFAULT_ACCEPTABLE_DEVIATION + composable_tests_helpers::test::helper::DEFAULT_PRECISION, + composable_tests_helpers::test::helper::DEFAULT_EPSILON ); }}; } diff --git a/frame/composable-traits/Cargo.toml b/frame/composable-traits/Cargo.toml index 991cd5de616..29434821ebb 100644 --- a/frame/composable-traits/Cargo.toml +++ b/frame/composable-traits/Cargo.toml @@ -1,28 +1,28 @@ [package] -name = "composable-traits" -version = "0.0.1" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" - +homepage = "https://composable.finance" +name = "composable-traits" +version = "0.0.1" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [dependencies] -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -xcm = { default-features = false, package = "xcm", git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16" } -sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +xcm = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17" } -composable-support = {default-features = false, path = "../composable-support"} -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = '1', optional = true } -plotters = {version = "0.3.1", optional = true} bitflags = "1.3.2" +composable-support = { default-features = false, path = "../composable-support" } +plotters = { version = "0.3.1", optional = true } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } +serde = { version = '1', optional = true } [dev-dependencies] proptest = { version = "1.0" } @@ -36,16 +36,16 @@ version = "2.0.0" [features] default = ["std"] std = [ - "serde", - "codec/std", - "frame-support/std", - "frame-system/std", - "sp-runtime/std", - "sp-std/std", - "scale-info/std", - "xcm/std", + "serde", + "codec/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-std/std", + "scale-info/std", + "xcm/std", ] visualization = ["plotters"] [package.metadata.cargo-udeps.ignore] -normal = ["plotters"] \ No newline at end of file +normal = ["plotters"] diff --git a/frame/composable-traits/src/bonded_finance.rs b/frame/composable-traits/src/bonded_finance.rs index 9e6bd544665..0e6f247c9f5 100644 --- a/frame/composable-traits/src/bonded_finance.rs +++ b/frame/composable-traits/src/bonded_finance.rs @@ -1,20 +1,26 @@ -use frame_support::pallet_prelude::*; +use crate::math::{SafeDiv, SafeMul}; +use composable_support::validation::{Validate, Validated}; +use frame_support::{pallet_prelude::*, traits::Get}; use scale_info::TypeInfo; use sp_runtime::{traits::Zero, ArithmeticError}; -use crate::math::SafeArithmetic; - pub trait BondedFinance { type AccountId; type AssetId; type Balance; type BlockNumber; type BondOfferId; + type MinReward; + type MinVestedTransfer; /// Create a new offer. fn offer( from: &Self::AccountId, - offer: BondOffer, + offer: Validated< + BondOffer, + ValidBondOffer, + >, + keep_alive: bool, ) -> Result; /// Bond for an offer. @@ -22,6 +28,7 @@ pub trait BondedFinance { offer: Self::BondOfferId, from: &Self::AccountId, nb_of_bonds: Self::Balance, + keep_alive: bool, ) -> Result; } @@ -63,7 +70,81 @@ pub struct BondOfferReward { pub maturity: BlockNumber, } -impl +#[derive(Debug, Decode)] +pub struct ValidBondOffer { + _marker: PhantomData<(U, V)>, +} + +impl Copy for ValidBondOffer {} + +impl Clone for ValidBondOffer { + fn clone(&self) -> Self { + *self + } +} + +impl< + MinTransfer, + MinReward, + AccountId, + AssetId, + Balance: Zero + PartialOrd + SafeDiv + SafeMul, + BlockNumber: Zero, + > + Validate< + BondOffer, + ValidBondOffer, + > for ValidBondOffer +where + ValidBondOffer: Decode, + MinTransfer: Get, + MinReward: Get, +{ + fn validate( + input: BondOffer, + ) -> Result, &'static str> { + let nonzero_maturity = match &input.maturity { + BondDuration::Finite { return_in } => !return_in.is_zero(), + BondDuration::Infinite => true, + }; + + if !nonzero_maturity { + return Err("MATURITY_CANNOT_BE_ZERO") + } + + if input.bond_price < MinTransfer::get() { + return Err("BOND_PRICE_BELOW_MIN_TRANSFER") + } + + if input.nb_of_bonds.is_zero() { + return Err("NUMBER_OF_BOND_CANNOT_BE_ZERO") + } + + let valid_reward = input.reward.amount >= MinReward::get() && + input + .reward + .amount + .safe_div(&input.nb_of_bonds) + .unwrap_or_else(|_| Balance::zero()) >= + MinTransfer::get(); + + if !valid_reward { + return Err("INVALID_REWARD") + } + + if input.reward.maturity.is_zero() { + return Err("ZERO_REWARD_MATURITY") + } + + if input.total_price().is_err() { + return Err("INVALID_TOTAL_PRICE") + } + + Ok(input) + } +} + +impl BondOffer { /// An offer is completed once all it's nb_of_bonds has been sold. @@ -74,25 +155,4 @@ impl Result { self.nb_of_bonds.safe_mul(&self.bond_price) } - /// Check whether an offer is valid and can be submitted. - pub fn valid(&self, min_transfer: Balance, min_reward: Balance) -> bool { - let nonzero_maturity = match &self.maturity { - BondDuration::Finite { return_in } => !return_in.is_zero(), - BondDuration::Infinite => true, - }; - let valid_price = self.bond_price >= min_transfer; - let nonzero_nb_of_bonds = !self.nb_of_bonds.is_zero(); - let valid_reward = self.reward.amount >= min_reward && - self.reward - .amount - .safe_div(&self.nb_of_bonds) - .unwrap_or_else(|_| Balance::zero()) >= - min_transfer; - let nonzero_reward_maturity = !self.reward.maturity.is_zero(); - let valid_total = self.total_price().is_ok(); - nonzero_maturity && - nonzero_nb_of_bonds && - valid_price && nonzero_reward_maturity && - valid_reward && valid_total - } } diff --git a/frame/composable-traits/src/currency.rs b/frame/composable-traits/src/currency.rs index 9ffbe688e62..2d92c23bdb7 100644 --- a/frame/composable-traits/src/currency.rs +++ b/frame/composable-traits/src/currency.rs @@ -4,7 +4,7 @@ use scale_info::TypeInfo; use sp_runtime::traits::{AtLeast32BitUnsigned, Zero}; use sp_std::fmt::Debug; -use crate::math::SafeArithmetic; +use crate::math::{SafeAdd, SafeDiv, SafeMul, SafeSub}; /// really u8, but easy to do math operations pub type Exponent = u32; @@ -90,11 +90,30 @@ impl< /// so inner type is either u64 or u128 with helpers for producing `ArithmeticError`s instead of /// `Option`s. pub trait MathBalance: - PartialOrd + Zero + SafeArithmetic + Into + TryFrom + From + Copy + PartialOrd + + Zero + + SafeAdd + + SafeDiv + + SafeMul + + SafeSub + + Into + + TryFrom + + From + + Copy { } -impl + TryFrom + From + Copy> - MathBalance for T +impl< + T: PartialOrd + + Zero + + SafeAdd + + SafeDiv + + SafeMul + + SafeSub + + Into + + TryFrom + + From + + Copy, + > MathBalance for T { } diff --git a/frame/composable-traits/src/defi.rs b/frame/composable-traits/src/defi.rs index b4f4dadb2bd..a194e863cbf 100644 --- a/frame/composable-traits/src/defi.rs +++ b/frame/composable-traits/src/defi.rs @@ -8,6 +8,8 @@ use sp_runtime::{ ArithmeticError, DispatchError, FixedPointNumber, FixedPointOperand, FixedU128, }; +use sp_std::fmt::Debug; + use crate::currency::{AssetIdLike, BalanceLike, MathBalance}; #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Debug, Clone, PartialEq)] @@ -71,7 +73,7 @@ impl Sell { /// Example, can do - give `base`, how much `quote` needed for unit. /// Can be local `Copy` `AssetId` or remote XCM asset id pair. #[repr(C)] -#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Debug, Clone, PartialEq)] +#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Debug, Clone)] pub struct CurrencyPair { /// See [Base Currency](https://www.investopedia.com/terms/b/basecurrency.asp). /// Also can be named `native`(to the market) currency. @@ -83,6 +85,21 @@ pub struct CurrencyPair { pub quote: AssetId, } +impl PartialEq for CurrencyPair { + fn eq(&self, other: &Self) -> bool { + (self.base == other.base && self.quote == other.quote) || + (self.base == other.quote && self.quote == other.base) + } +} + +impl Eq for CurrencyPair {} + +impl CurrencyPair { + pub fn swap(&self) -> Self { + Self { base: self.quote, quote: self.base } + } +} + impl From<(AssetId, AssetId)> for CurrencyPair { fn from(other: (AssetId, AssetId)) -> Self { Self { base: other.0, quote: other.1 } @@ -205,7 +222,7 @@ pub trait SellEngine: DeFiEngine { } pub trait DeFiComposableConfig: frame_system::Config { - type MayBeAssetId: AssetIdLike + MaybeSerializeDeserialize + Default; + type MayBeAssetId: AssetIdLike + MaybeSerializeDeserialize + Default + MaxEncodedLen + Debug; type Balance: BalanceLike + MathBalance @@ -249,7 +266,6 @@ pub type Ratio = FixedU128; #[cfg(test)] mod tests { - use super::{Ratio, Take}; use sp_runtime::FixedPointNumber; diff --git a/frame/composable-traits/src/dex.rs b/frame/composable-traits/src/dex.rs index 823e5ddea48..a38b7130007 100644 --- a/frame/composable-traits/src/dex.rs +++ b/frame/composable-traits/src/dex.rs @@ -1,32 +1,63 @@ +use crate::{ + defi::CurrencyPair, + math::{SafeAdd, SafeSub}, +}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{traits::Get, BoundedVec, RuntimeDebug}; use scale_info::TypeInfo; -use sp_runtime::{DispatchError, FixedU128, Permill}; +use sp_arithmetic::traits::Saturating; +use sp_runtime::{ + traits::{CheckedMul, CheckedSub}, + ArithmeticError, DispatchError, Permill, +}; use sp_std::vec::Vec; -use crate::defi::CurrencyPair; - -/// Implement AMM curve from "StableSwap - efficient mechanism for Stablecoin liquidity by Micheal -/// Egorov" Also blog at https://miguelmota.com/blog/understanding-stableswap-curve/ has very good explanation. -pub trait CurveAmm { +/// Trait for automated market maker. +pub trait Amm { /// The asset ID type type AssetId; /// The balance type of an account type Balance; /// The user account identifier type for the runtime type AccountId; - /// Type that represents index type of token in the pool passed from the outside as an extrinsic - /// argument. - type PoolTokenIndex; - /// Type that represents pool id type PoolId; - /// Check pool with given id exists. fn pool_exists(pool_id: Self::PoolId) -> bool; - /// Current number of pools (also ID for the next created pool) - fn pool_count() -> Self::PoolId; + fn currency_pair(pool_id: Self::PoolId) -> Result, DispatchError>; + + /// Get pure exchange value for given units of given asset. (Note this does not include fees.) + /// `pool_id` the pool containing the `asset_id`. + /// `asset_id` the asset the user is interested in. + /// `amount` the amount of `asset_id` the user want to obtain. + /// Return the amount of quote asset if `asset_id` is base asset, otherwise the amount of base + /// asset. + fn get_exchange_value( + pool_id: Self::PoolId, + asset_id: Self::AssetId, + amount: Self::Balance, + ) -> Result; + + /// Buy given `amount` of given asset from the pool. + /// In buy user does not know how much assets he/she has to exchange to get desired amount. + fn buy( + who: &Self::AccountId, + pool_id: Self::PoolId, + asset_id: Self::AssetId, + amount: Self::Balance, + keep_alive: bool, + ) -> Result; + + /// Sell given `amount` of given asset to the pool. + /// In sell user specifies `amount` of asset he/she wants to exchange to get other asset. + fn sell( + who: &Self::AccountId, + pool_id: Self::PoolId, + asset_id: Self::AssetId, + amount: Self::Balance, + keep_alive: bool, + ) -> Result; /// Deposit coins into the pool /// `amounts` - list of amounts of coins to deposit, @@ -34,8 +65,10 @@ pub trait CurveAmm { fn add_liquidity( who: &Self::AccountId, pool_id: Self::PoolId, - amounts: Vec, + base_amount: Self::Balance, + quote_amount: Self::Balance, min_mint_amount: Self::Balance, + keep_alive: bool, ) -> Result<(), DispatchError>; /// Withdraw coins from the pool. @@ -45,30 +78,23 @@ pub trait CurveAmm { fn remove_liquidity( who: &Self::AccountId, pool_id: Self::PoolId, - amount: Self::Balance, - min_amounts: Vec, + lp_amount: Self::Balance, + min_base_amount: Self::Balance, + min_quote_amount: Self::Balance, ) -> Result<(), DispatchError>; - /// Perform an exchange between two coins. - /// `i` - index value of the coin to send, - /// `j` - index value of the coin to receive, - /// `dx` - amount of `i` being exchanged, - /// `min_dy` - minimum amount of `j` to receive. + /// Perform an exchange. + /// This operation is a buy order on the provided `pair`, effectively trading the quote asset + /// against the base one. The pair can be swapped to execute a sell order. + /// Implementor must check the pair. fn exchange( who: &Self::AccountId, pool_id: Self::PoolId, - i: Self::PoolTokenIndex, - j: Self::PoolTokenIndex, - dx: Self::Balance, - min_dy: Self::Balance, + pair: CurrencyPair, + quote_amount: Self::Balance, + min_receive: Self::Balance, + keep_alive: bool, ) -> Result; - - /// Withdraw admin fees - fn withdraw_admin_fees( - who: &Self::AccountId, - pool_id: Self::PoolId, - admin_fee_account: &Self::AccountId, - ) -> Result<(), DispatchError>; } /// Pool type @@ -76,14 +102,16 @@ pub trait CurveAmm { pub struct StableSwapPoolInfo { /// Owner of pool pub owner: AccountId, + /// Swappable assets + pub pair: CurrencyPair, /// AssetId of LP token, pub lp_token: AssetId, /// Initial amplification coefficient - pub amplification_coefficient: FixedU128, - /// Amount of the fee pool charges for the exchange + pub amplification_coefficient: u16, + /// Amount of the fee pool charges for the exchange, this goes to liquidity provider. pub fee: Permill, - /// Amount of the admin fee pool charges for the exchange - pub admin_fee: Permill, + /// Amount of the fee pool charges for the exchange + pub protocol_fee: Permill, } /// Describes a simple exchanges which does not allow advanced configurations such as slippage. @@ -112,10 +140,104 @@ pub trait SimpleExchange { pub struct ConstantProductPoolInfo { /// Owner of pool pub owner: AccountId, - /// AssetId of LP token, + /// Swappable assets + pub pair: CurrencyPair, + /// AssetId of LP token pub lp_token: AssetId, /// Amount of the fee pool charges for the exchange pub fee: Permill, + /// Amount of the fee pool charges for the exchange + pub owner_fee: Permill, +} + +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum SaleState { + NotStarted, + Ongoing, + Ended, +} + +#[derive(RuntimeDebug, Encode, Decode, MaxEncodedLen, Copy, Clone, PartialEq, Eq, TypeInfo)] +pub struct Sale { + /// Block at which the sale start. + pub start: BlockNumber, + /// Block at which the sale stop. + pub end: BlockNumber, + /// Initial weight of the base asset of the current pair. + pub initial_weight: Permill, + /// Final weight of the base asset of the current pair. + pub final_weight: Permill, +} + +impl + Ord + Copy + Saturating + SafeAdd + SafeSub> Sale { + // TODO unit test + pub fn current_weights( + &self, + current_block: BlockNumber, + ) -> Result<(Permill, Permill), DispatchError> { + /* NOTE(hussein-aitlahcen): currently only linear + + Linearly decrease the base asset initial_weight to final_weight. + Quote asset weight is simple 1-base_asset_weight + + Assuming final_weight < initial_weight + current_weight = initial_weight - (current - start) / (end - start) * (initial_weight - final_weight) + = initial_weight - normalized_current / sale_duration * weight_range + = initial_weight - point_in_sale * weight_range + */ + let normalized_current_block = current_block.safe_sub(&self.start)?; + let point_in_sale = Permill::from_rational( + normalized_current_block.try_into().map_err(|_| ArithmeticError::Overflow)?, + self.duration().try_into().map_err(|_| ArithmeticError::Overflow)?, + ); + let weight_range = self + .initial_weight + .checked_sub(&self.final_weight) + .ok_or(ArithmeticError::Underflow)?; + let current_base_weight = self + .initial_weight + .checked_sub( + &point_in_sale.checked_mul(&weight_range).ok_or(ArithmeticError::Overflow)?, + ) + .ok_or(ArithmeticError::Underflow)?; + let current_quote_weight = Permill::one() + .checked_sub(¤t_base_weight) + .ok_or(ArithmeticError::Underflow)?; + Ok((current_base_weight, current_quote_weight)) + } +} + +impl Sale { + pub fn duration(&self) -> BlockNumber { + // NOTE(hussein-aitlahcen): end > start as previously checked by PoolIsValid. + self.end.saturating_sub(self.start) + } +} + +impl Sale { + pub fn state(&self, current_block: BlockNumber) -> SaleState { + if current_block < self.start { + SaleState::NotStarted + } else if current_block >= self.end { + SaleState::Ended + } else { + SaleState::Ongoing + } + } +} + +#[derive(RuntimeDebug, Encode, Decode, MaxEncodedLen, Copy, Clone, PartialEq, Eq, TypeInfo)] +pub struct LiquidityBootstrappingPoolInfo { + /// Owner of the pool + pub owner: AccountId, + /// Asset pair of the pool along their weight. + /// Base asset is the project token. + /// Quote asset is the collateral token. + pub pair: CurrencyPair, + /// Sale period of the LBP. + pub sale: Sale, + /// Trading fees. + pub fee: Permill, } #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Eq, RuntimeDebug)] @@ -142,10 +264,22 @@ pub trait DexRouter { ) -> Result<(), DispatchError>; /// If route exist return `Some(Vec)`, else `None`. fn get_route(asset_pair: CurrencyPair) -> Option>>; - /// Exchange `dx` of given `asset_pair` to get `dy`. + /// Exchange `dx` of `base` asset of `asset_pair` with associated route. fn exchange( who: &AccountId, asset_pair: CurrencyPair, dx: Balance, ) -> Result; + /// Sell `amount` of `base` asset of asset_pair with associated route. + fn sell( + who: &AccountId, + asset_pair: CurrencyPair, + amount: Balance, + ) -> Result; + /// Buy `amount` of `quote` asset of asset_pair with associated route. + fn buy( + who: &AccountId, + asset_pair: CurrencyPair, + amount: Balance, + ) -> Result; } diff --git a/frame/composable-traits/src/lending/math.rs b/frame/composable-traits/src/lending/math.rs index e943a72370c..1badc383f57 100644 --- a/frame/composable-traits/src/lending/math.rs +++ b/frame/composable-traits/src/lending/math.rs @@ -14,7 +14,7 @@ use sp_arithmetic::per_things::Percent; use crate::{ defi::{LiftedFixedBalance, Rate, ZeroToOneFixedU128}, - math::SafeArithmetic, + math::{SafeAdd, SafeDiv, SafeMul}, time::{DurationSeconds, SECONDS_PER_YEAR_NAIVE}, }; diff --git a/frame/composable-traits/src/lending/mod.rs b/frame/composable-traits/src/lending/mod.rs index 976890be68a..cc592c99bb8 100644 --- a/frame/composable-traits/src/lending/mod.rs +++ b/frame/composable-traits/src/lending/mod.rs @@ -42,9 +42,9 @@ pub struct CreateInput { pub reserved_factor: Perquintill, } -#[derive(Clone, Copy, Debug, PartialEq, TypeInfo)] +#[derive(Clone, Copy, Debug, PartialEq, TypeInfo, Default)] pub struct MarketModelValid; -#[derive(Clone, Copy, Debug, PartialEq, TypeInfo)] +#[derive(Clone, Copy, Debug, PartialEq, TypeInfo, Default)] pub struct CurrencyPairIsNotSame; impl diff --git a/frame/composable-traits/src/math.rs b/frame/composable-traits/src/math.rs index 37b8f20ba35..79b4e6bf12f 100644 --- a/frame/composable-traits/src/math.rs +++ b/frame/composable-traits/src/math.rs @@ -1,44 +1,70 @@ use sp_runtime::{ + helpers_128bit::multiply_by_rational, traits::{CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, One, Saturating, Zero}, ArithmeticError, }; +/// Thin convenient wrapper to lift the Result in a Dispatch context. +pub fn safe_multiply_by_rational(a: u128, b: u128, c: u128) -> Result { + multiply_by_rational(a, b, c).map_err(|_| ArithmeticError::Overflow) +} + /// little bit slower than maximizing performance by knowing constraints. /// Example, you sum to negative numbers, can get underflow, so need to check on each add; but if /// you have positive number only, you cannot have underflow. Same for other constrains, like non /// zero divisor. -pub trait SafeArithmetic: Sized { + +pub trait SafeAdd: Sized { fn safe_add(&self, rhs: &Self) -> Result; +} + +pub trait SafeDiv: Sized { fn safe_div(&self, rhs: &Self) -> Result; +} + +pub trait SafeMul: Sized { fn safe_mul(&self, rhs: &Self) -> Result; +} + +pub trait SafeSub: Sized { fn safe_sub(&self, rhs: &Self) -> Result; } -impl SafeArithmetic for T { +pub trait SafeArithmetic: Sized + SafeAdd + SafeDiv + SafeMul + SafeSub {} + +impl SafeAdd for T { #[inline(always)] fn safe_add(&self, rhs: &Self) -> Result { self.checked_add(rhs).ok_or(ArithmeticError::Overflow) } +} + +impl SafeDiv for T { #[inline(always)] fn safe_div(&self, rhs: &Self) -> Result { if rhs.is_zero() { return Err(ArithmeticError::DivisionByZero) } - self.checked_div(rhs).ok_or(ArithmeticError::Overflow) } +} +impl SafeMul for T { #[inline(always)] fn safe_mul(&self, rhs: &Self) -> Result { self.checked_mul(rhs).ok_or(ArithmeticError::Overflow) } +} +impl SafeSub for T { #[inline(always)] fn safe_sub(&self, rhs: &Self) -> Result { self.checked_sub(rhs).ok_or(ArithmeticError::Underflow) } } +impl SafeArithmetic for T {} + /// An object from which we can derive a second object of the same type. /// This function cannot fail and might return the same object if a boundary is about to be crossed. // This kind of function is usually called an Endomorphism. But let's keep it simple. diff --git a/frame/composable-traits/src/oracle.rs b/frame/composable-traits/src/oracle.rs index 6af79b70698..2e12accab15 100644 --- a/frame/composable-traits/src/oracle.rs +++ b/frame/composable-traits/src/oracle.rs @@ -5,12 +5,31 @@ use crate::{ use frame_support::{dispatch::DispatchError, pallet_prelude::*}; use sp_std::vec::Vec; -#[derive(Encode, Decode, Default, Debug, PartialEq)] +// block timestamped value +#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, PartialEq, TypeInfo, Clone)] pub struct Price { + /// value pub price: PriceValue, pub block: BlockNumber, } +/// oracle that only works with single asset to some normalized asset at latest block in local +/// consensus usually normalized asset is stable coin or native currency +/// fallback in `Oracle` or `Market`(DEXes) lacks trusted prices +/// (or initial values before threre is market) +pub trait MinimalOracle { + type AssetId: Copy; + type Balance: From; + + /// Given `asset_id` and `amount` of price asset. + /// Returns what amount of `asset_id` will be required to be same price as `amount` of + /// some normalized currency + fn get_price_inverse( + asset_id: Self::AssetId, + amount: Self::Balance, + ) -> Result; +} + /// An object that is able to provide an asset price. /// Important: the current price-feed is providing prices in USDT only. pub trait Oracle { @@ -18,6 +37,9 @@ pub trait Oracle { type Balance: From; type Timestamp; type LocalAssets: LocalAssets; + type MaxAnswerBound: Get; + // type BlockNumber: From; + // type StalePrice: Get; /// Quote the `amount` of `asset_id` in normalized currency unit cent. Default is USDT Cent. /// Which is 0.01 of USDT. `Result::Err` is returned if `asset_id` not supported or price /// information not available. @@ -89,6 +111,7 @@ pub trait Oracle { /// Given `asset_id` and `amount` of price asset. /// Returns what amount of `asset_id` will be required to be same price as `amount` of /// normalized currency + /// `amount` - in smallest units fn get_price_inverse( asset_id: Self::AssetId, amount: Self::Balance, diff --git a/frame/composable-traits/src/vesting.rs b/frame/composable-traits/src/vesting.rs index b525bfd14bd..7f80279b08f 100644 --- a/frame/composable-traits/src/vesting.rs +++ b/frame/composable-traits/src/vesting.rs @@ -8,6 +8,7 @@ pub trait VestedTransfer { type AccountId; type AssetId; type BlockNumber; + type Moment; type Balance: HasCompact; type MinVestedTransfer: Get; @@ -16,20 +17,35 @@ pub trait VestedTransfer { asset: Self::AssetId, from: &Self::AccountId, to: &Self::AccountId, - schedule: VestingSchedule, + schedule: VestingSchedule, ) -> DispatchResult; } +/// Vesting window type for the vesting schedules. +#[cfg_attr(feature = "std", derive(serde::Deserialize, serde::Serialize))] +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)] +pub enum VestingWindow { + MomentBased { + /// Vesting start + start: Moment, + /// Number of moments between vest + period: Moment, + }, + BlockNumberBased { + /// Vesting start + start: BlockNumber, + /// Number of blocks between vest + period: BlockNumber, + }, +} + /// The vesting schedule. /// -/// Benefits would be granted gradually, `per_period` amount every `period` -/// of blocks after `start`. +/// Benefits would be granted gradually, `per_period` amount every `window.period` +/// of blocks after `window.start`. #[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)] -pub struct VestingSchedule { - /// Vesting starting block - pub start: BlockNumber, - /// Number of blocks between vest - pub period: BlockNumber, +pub struct VestingSchedule { + pub window: VestingWindow, /// Number of vest pub period_count: u32, /// Amount of tokens to release per vest @@ -37,13 +53,38 @@ pub struct VestingSchedule { pub per_period: Balance, } -impl - VestingSchedule +pub enum VestingWindowResult { + MomentResult(Moment), + BlockNumberResult(BlockNumber), +} + +impl< + BlockNumber: AtLeast32Bit + Copy, + Moment: AtLeast32Bit + Copy, + Balance: AtLeast32Bit + Copy, + > VestingSchedule { + /// Check if the period is zero + pub fn is_zero_period(&self) -> bool { + match self.window { + VestingWindow::BlockNumberBased { start: _, period } => period.is_zero(), + VestingWindow::MomentBased { start: _, period } => period.is_zero(), + } + } + /// Returns the end of all periods, `None` if calculation overflows. - pub fn end(&self) -> Option { + pub fn end(&self) -> Option> { // period * period_count + start - self.period.checked_mul(&self.period_count.into())?.checked_add(&self.start) + match self.window { + VestingWindow::BlockNumberBased { start, period } => period + .checked_mul(&self.period_count.into())? + .checked_add(&start) + .map(|val| VestingWindowResult::::BlockNumberResult(val)), + VestingWindow::MomentBased { start, period } => period + .checked_mul(&self.period_count.into())? + .checked_add(&start) + .map(|val| VestingWindowResult::::MomentResult(val)), + } } /// Returns all locked amount, `None` if calculation overflows. @@ -51,21 +92,119 @@ impl self.per_period.checked_mul(&self.period_count.into()) } - /// Returns locked amount for a given `time`. + /// Returns locked amount for a given schedule of VestingWindow. /// /// Note this func assumes schedule is a valid one(non-zero period and /// non-overflow total amount), and it should be guaranteed by callers. - pub fn locked_amount(&self, time: BlockNumber) -> Balance { + pub fn locked_amount(&self, block_number: BlockNumber, moment: Moment) -> Balance { // full = (time - start) / period // unrealized = period_count - full // per_period * unrealized - let full = time - .saturating_sub(self.start) - .checked_div(&self.period) - .expect("ensured non-zero period; qed"); - let unrealized = self.period_count.saturating_sub(full.unique_saturated_into()); + let unrealized = match self.window { + VestingWindow::BlockNumberBased { start, period } => { + let full = block_number + .saturating_sub(start) + .checked_div(&period) + .expect("ensured non-zero period; qed"); + self.period_count.saturating_sub(full.unique_saturated_into()) + }, + VestingWindow::MomentBased { start, period } => { + let full = moment + .saturating_sub(start) + .checked_div(&period) + .expect("ensured non-zero period; qed"); + self.period_count.saturating_sub(full.unique_saturated_into()) + }, + }; self.per_period .checked_mul(&unrealized.into()) .expect("ensured non-overflow total amount; qed") } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::vesting::VestingWindow::{BlockNumberBased, MomentBased}; + + #[test] + fn test_is_zero_period() { + let mut vesting_schedule_time_based = VestingSchedule:: { + window: MomentBased { start: 1u64, period: 10u64 }, + period_count: 100, + per_period: 1u64, + }; + assert!(!vesting_schedule_time_based.is_zero_period()); + vesting_schedule_time_based.window = MomentBased { start: 1, period: 0 }; + assert!(vesting_schedule_time_based.is_zero_period()); + + let mut vesting_schedule_block_number_based = VestingSchedule:: { + window: BlockNumberBased { start: 1u64, period: 10u64 }, + period_count: 100, + per_period: 1u64, + }; + assert!(!vesting_schedule_block_number_based.is_zero_period()); + vesting_schedule_block_number_based.window = BlockNumberBased { start: 1, period: 0 }; + assert!(vesting_schedule_block_number_based.is_zero_period()); + } + + #[test] + fn test_end() { + let vesting_schedule_time_based = VestingSchedule:: { + window: MomentBased { start: 1u64, period: 10u64 }, + period_count: 100, + per_period: 1u64, + }; + match vesting_schedule_time_based.end() { + None => {}, + Some(result) => match result { + VestingWindowResult::MomentResult(val) => assert_eq!(val, 1001), + VestingWindowResult::BlockNumberResult(_) => panic!("Unexpected BlockNumberResult"), + }, + } + let vesting_schedule_block_number_based = VestingSchedule:: { + window: BlockNumberBased { start: 1u64, period: 10u64 }, + period_count: 100, + per_period: 1u64, + }; + match vesting_schedule_block_number_based.end() { + None => {}, + Some(result) => match result { + VestingWindowResult::MomentResult(_) => panic!("Unexpected MomentResult"), + VestingWindowResult::BlockNumberResult(val) => assert_eq!(val, 1001), + }, + } + } + + #[test] + fn test_total_amount() { + let vesting_schedule = VestingSchedule:: { + window: BlockNumberBased { start: 1u64, period: 10u64 }, + period_count: 100, + per_period: 1u64, + }; + assert_eq!(vesting_schedule.total_amount().unwrap(), 100) + } + + /// TODO proptest for exhastive tests + #[test] + fn test_locked_amount() { + let vesting_schedule_time_based = VestingSchedule:: { + window: MomentBased { start: 1u64, period: 10u64 }, + period_count: 100, + per_period: 1u64, + }; + assert_eq!(vesting_schedule_time_based.locked_amount(1, 1), 100); + assert_eq!(vesting_schedule_time_based.locked_amount(1, 11), 99); + assert_eq!(vesting_schedule_time_based.locked_amount(1, 1001), 0); + + let vesting_schedule_block_number_based = VestingSchedule:: { + window: BlockNumberBased { start: 1u64, period: 10u64 }, + period_count: 100, + per_period: 1u64, + }; + assert_eq!(vesting_schedule_block_number_based.locked_amount(1, 1), 100); + assert_eq!(vesting_schedule_block_number_based.locked_amount(11, 1), 99); + assert_eq!(vesting_schedule_block_number_based.locked_amount(1001, 1), 0); + } +} diff --git a/frame/crowdloan-rewards/Cargo.toml b/frame/crowdloan-rewards/Cargo.toml index 1d27e34e9f6..95382909324 100644 --- a/frame/crowdloan-rewards/Cargo.toml +++ b/frame/crowdloan-rewards/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "pallet-crowdloan-rewards" -version = "0.0.1" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" +homepage = "https://composable.finance" +name = "pallet-crowdloan-rewards" +version = "0.0.1" [package.metadata.docs.rs] @@ -16,61 +16,67 @@ package = "parity-scale-codec" version = "2.0.0" [dev-dependencies] +hex-literal = "0.3.3" +libsecp256k1 = { version = "0.7.0" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } serde = "1.0.130" -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -libsecp256k1 = { version = "0.7.0", default-features = false, features = [ - "hmac", - "static-context", -] } -hex-literal = "0.3" -balances = { package = "pallet-balances", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false, features = [ "std" ]} +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } [dependencies] -### Benchmarking +# Benchmarking +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } hex-literal = { version = "0.3.3", optional = true } libsecp256k1 = { version = "0.7.0", default-features = false, optional = true, features = [ - "hmac", - "static-context", + "hmac", + "static-context", ] } -frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-application-crypto = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +sp-application-crypto = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +# FRAME +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +# substrate primitives +sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } + +# SCALE scale-info = { version = "1.0", default-features = false, features = [ - "derive", + "derive", ] } -serde = { version = "1.0.130", optional = true } -rustc-hex = { version = "2.1.0", default-features = false } + +# misc hex = { version = "0.4", default-features = false, features = ["alloc"] } +rustc-hex = { version = "2.1.0", default-features = false } +serde = { version = "1.0.130", optional = true } + +composable-traits = { path = "../composable-traits", default-features = false } [features] default = ["std"] std = [ - "codec/std", - "frame-support/std", - "frame-system/std", - "sp-runtime/std", - "sp-io/std", - "sp-core/std", - "sp-std/std", - "sp-arithmetic/std", - "scale-info/std", - "serde/std", + "codec/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-io/std", + "sp-core/std", + "sp-std/std", + "sp-arithmetic/std", + "scale-info/std", + "serde/std", ] runtime-benchmarks = [ - "hex-literal", - "libsecp256k1", - "frame-benchmarking", - "sp-application-crypto", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", + "hex-literal", + "libsecp256k1", + "frame-benchmarking", + "sp-application-crypto", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", ] diff --git a/frame/crowdloan-rewards/README.md b/frame/crowdloan-rewards/README.md index ac9de77a963..6cb7cbfc11f 100644 --- a/frame/crowdloan-rewards/README.md +++ b/frame/crowdloan-rewards/README.md @@ -1,18 +1,52 @@ # Crowdloan Rewards -This pallet allow contributors to claim their rewards. +The Crowdloan Rewards pallet allows contributors to claim their rewards. -A % of the reward is paid at the first claim, and the remaining % is vested over an arbitrary period splitted in windows `VestingPartition`. +## Rewards -Rewards are claiming using the following scheme. +A percentage of the reward is paid at the first claim, and the remaining +percentage is vested over an arbitrary period of time split into +`VestingPartition`s. -1. An `AdminOrigin` setup the reward accounts, consisting of a vector of triple (PublicKey, Amount, VestingPeriod) - The PublicKey is either comming from the relay chain (Kusama in this case) or from ETH. -2. Since the users don't own any funds on Picasso, the first claim has to be made using our service so that we sign the `associate` transaction using Composable `AssociationOrigin`. - The first claim result in the Picasso account being associated with the reward account. - Also, this association automatically trigger a claim, resulting in the first payment done (fixed % if first claim, vested amount otherwise) to the newly associated Picasso account. -3. Once the first claim has been made, the user has to wait until the next `VestingPartition` (probably 1 week). - After having waited for the vesting partition. The user is able to either `associate` a new account or directly `claim` using it's already associated Picasso account. - This can be repeated until the contributor has claimed all its reward. +Rewards are claimed using the following steps: -Note: both `associate` and `claim` calls are not charging fees if successful. +1. An `AdminOrigin` sets up the reward accounts, consisting of a vector of + (PublicKey, Amount, VestingPeriod). + The PublicKey is either comming from the relay chain (Kusama in this case) or + from ETH. + +2. Since the users don't own any funds on Picasso, the first claim has to be + made using our service so that we sign the `associate` transaction using + Composable's `AssociationOrigin`. + The first claim results in the Picasso account being associated with the + reward account. This association automatically triggers a claim, the claim + results in the first payment being distributed to the newly associated + Picasso account. + +3. Once the first claim has been made, the user has to wait until the next + `VestingPartition`. + After having waited for the vesting partition. The user is able to either + `associate` a new account or directly `claim` using their already associated + Picasso account. + This can be repeated until the contributor has claimed all of their reward. + +## Unsigned Transactions + +To enable unsigned transactions while still preventing spam, we implement +'ValidateUnsigned'. Our implementation insures the following. + +1. Transaction payloads contain the elements needed for validation (reward + account ID and proof). + +2. The pallet hes been initialized. + +3. The reward account exist and has not been associated. + +4. The proof is valid for the reward account and a remote account are accessible + from the proof. + +5. There is some reward to claim for the reward account. + +## Notes + +* both `associate` and `claim` calls do not charge fees if successful. diff --git a/frame/crowdloan-rewards/rpc/Cargo.toml b/frame/crowdloan-rewards/rpc/Cargo.toml new file mode 100644 index 00000000000..251ba03cba7 --- /dev/null +++ b/frame/crowdloan-rewards/rpc/Cargo.toml @@ -0,0 +1,36 @@ +[package] +authors = ["Composable Developers"] +edition = "2021" +homepage = "https://composable.finance" +name = "crowdloan-rewards-rpc" +rust-version = "1.56" +version = "0.0.1" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +# FRAME +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } + +# substrate primitives +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } + +# local +composable-support = { path = "../../composable-support" } +composable-traits = { path = "../../composable-traits" } +crowdloan-rewards-runtime-api = { path = "../runtime-api" } + +# SCALE +codec = { features = [ + "derive", +], package = "parity-scale-codec", version = "2.0.0" } +scale-info = { version = "1.0", features = ["derive"] } + +# rpc +jsonrpc-core = "18.0.0" +jsonrpc-core-client = "18.0.0" +jsonrpc-derive = "18.0.0" diff --git a/frame/crowdloan-rewards/rpc/src/lib.rs b/frame/crowdloan-rewards/rpc/src/lib.rs new file mode 100644 index 00000000000..c0439e320d0 --- /dev/null +++ b/frame/crowdloan-rewards/rpc/src/lib.rs @@ -0,0 +1,67 @@ +use composable_support::rpc_helpers::{SafeRpcWrapper, SafeRpcWrapperType}; +use crowdloan_rewards_runtime_api::CrowdloanRewardsRuntimeApi; +use frame_support::{pallet_prelude::MaybeSerializeDeserialize, Parameter}; +use jsonrpc_core::{Error as RpcError, ErrorCode, Result as RpcResult}; +use jsonrpc_derive::rpc; +use sp_api::ProvideRuntimeApi; +use sp_blockchain::HeaderBackend; +use sp_runtime::{generic::BlockId, traits::Block as BlockT}; +use sp_std::{marker::PhantomData, sync::Arc}; + +#[rpc] +pub trait CrowdloanRewardsApi +where + Balance: SafeRpcWrapperType, +{ + #[rpc(name = "crowdloanRewards_amountAvailableToClaimFor")] + fn amount_available_to_claim_for( + &self, + account: AccountId, + at: Option, + ) -> RpcResult>; +} + +/// A struct that implements the `CrowdloanRewardsApi`. +pub struct CrowdloanRewards { + client: Arc, + _marker: PhantomData, +} + +impl CrowdloanRewards { + /// Create new `CrowdloanRewards` instance with the given reference to the client. + pub fn new(client: Arc) -> Self { + Self { client, _marker: Default::default() } + } +} + +impl CrowdloanRewardsApi<::Hash, AccountId, Balance> + for CrowdloanRewards +where + Block: BlockT, + AccountId: Send + Sync + Parameter + MaybeSerializeDeserialize + Ord + 'static, + Balance: Send + Sync + 'static + SafeRpcWrapperType, + C: Send + Sync + ProvideRuntimeApi + HeaderBackend + 'static, + C::Api: CrowdloanRewardsRuntimeApi, +{ + fn amount_available_to_claim_for( + &self, + remote_account: AccountId, + at: Option<::Hash>, + ) -> RpcResult> { + let api = self.client.runtime_api(); + let at = BlockId::hash(at.unwrap_or_else(|| { + // If the block hash is not supplied assume the best block. + self.client.info().best_hash + })); + + let runtime_api_result = api.amount_available_to_claim_for(&at, remote_account); + // TODO(benluelo): Review what error message & code to use + runtime_api_result.map_err(|e| { + RpcError { + code: ErrorCode::ServerError(9876), // No real reason for this value + message: "Something wrong".into(), + data: Some(format!("{:?}", e).into()), + } + }) + } +} diff --git a/frame/crowdloan-rewards/runtime-api/Cargo.toml b/frame/crowdloan-rewards/runtime-api/Cargo.toml new file mode 100644 index 00000000000..32abb649ba9 --- /dev/null +++ b/frame/crowdloan-rewards/runtime-api/Cargo.toml @@ -0,0 +1,23 @@ +[package] +authors = ["Composable Developers"] +edition = "2021" +homepage = "https://composable.finance" +name = "crowdloan-rewards-runtime-api" +rust-version = "1.56" +version = "0.0.1" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { default-features = false, features = [ + "derive", +], package = "parity-scale-codec", version = "2.0.0" } +composable-support = { path = "../../composable-support", default-features = false } +sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } + + +# REVIEW: Does the runtime API need features? +[features] +default = ["std"] +std = ["sp-api/std", "composable-support/std"] diff --git a/frame/crowdloan-rewards/runtime-api/src/lib.rs b/frame/crowdloan-rewards/runtime-api/src/lib.rs new file mode 100644 index 00000000000..609d96e44dd --- /dev/null +++ b/frame/crowdloan-rewards/runtime-api/src/lib.rs @@ -0,0 +1,18 @@ +#![cfg_attr(not(feature = "std"), no_std)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::unnecessary_mut_passed)] + +use codec::Codec; +use composable_support::rpc_helpers::{SafeRpcWrapper, SafeRpcWrapperType}; + +// Here we declare the runtime API. It is implemented it the `impl` block in +// runtime amalgamator file (the `runtime/src/lib.rs`) +sp_api::decl_runtime_apis! { + pub trait CrowdloanRewardsRuntimeApi + where + AccountId: Codec, + Balance: SafeRpcWrapperType, + { + fn amount_available_to_claim_for(account: AccountId) -> SafeRpcWrapper; + } +} diff --git a/frame/crowdloan-rewards/src/lib.rs b/frame/crowdloan-rewards/src/lib.rs index 8bd0565534b..774d744c5fb 100644 --- a/frame/crowdloan-rewards/src/lib.rs +++ b/frame/crowdloan-rewards/src/lib.rs @@ -56,6 +56,7 @@ mod mocks; #[cfg(test)] mod tests; +// FIXME: runtime signature generation must use host features. // #[cfg(feature = "runtime-benchmarks")] // mod benchmarking; @@ -63,32 +64,43 @@ pub mod weights; #[frame_support::pallet] pub mod pallet { - use codec::Codec; - use frame_support::{pallet_prelude::*, traits::fungible::Mutate, transactional}; + use super::models::{EcdsaSignature, EthereumAddress, Proof, RemoteAccount, Reward}; + use crate::weights::WeightInfo; + use codec::{Codec, FullCodec}; + use composable_traits::math::SafeAdd; + use frame_support::{ + dispatch::PostDispatchInfo, + pallet_prelude::*, + traits::{ + fungible::{Inspect, Transfer}, + Time, + }, + transactional, PalletId, + }; use frame_system::pallet_prelude::*; use sp_io::hashing::keccak_256; use sp_runtime::{ traits::{ - AtLeast32BitUnsigned, CheckedAdd, CheckedMul, CheckedSub, Convert, Saturating, Verify, - Zero, + AccountIdConversion, AtLeast32Bit, AtLeast32BitUnsigned, CheckedAdd, CheckedMul, + CheckedSub, Convert, Saturating, Verify, Zero, }, - AccountId32, MultiSignature, Perbill, + AccountId32, DispatchErrorWithPostInfo, MultiSignature, Perbill, }; use sp_std::vec::Vec; - use crate::weights::WeightInfo; - - use super::models::{EcdsaSignature, EthereumAddress, Proof, RemoteAccount, Reward}; - + pub type MomentOf = ::Moment; pub type RemoteAccountOf = RemoteAccount<::RelayChainAccountId>; - pub type RewardOf = Reward<::Balance, ::BlockNumber>; - pub type VestingPeriodOf = ::BlockNumber; + pub type RewardOf = Reward<::Balance, MomentOf>; + pub type VestingPeriodOf = MomentOf; pub type RewardAmountOf = ::Balance; pub type ProofOf = Proof<::RelayChainAccountId>; #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { + Initialized { + at: MomentOf, + }, Claimed { remote_account: RemoteAccountOf, reward_account: T::AccountId, @@ -104,11 +116,14 @@ pub mod pallet { pub enum Error { NotInitialized, AlreadyInitialized, + BackToTheFuture, + RewardsNotFunded, InvalidProof, InvalidClaim, NothingToClaim, NotAssociated, AlreadyAssociated, + NotClaimableYet, } #[pallet::config] @@ -130,14 +145,20 @@ pub mod pallet { + MaxEncodedLen + Zero; - /// The currency used to mint the rewards - type Currency: Mutate; + /// The RewardAsset used to transfer the rewards + type RewardAsset: Inspect + + Transfer; + + type Moment: AtLeast32Bit + Parameter + Default + Copy + MaxEncodedLen + FullCodec; + + /// The time provider. + type Time: Time; /// The origin that is allowed to `initialize` the pallet. type AdminOrigin: EnsureOrigin; - /// A conversion function frop `Self::BlockNumber` to `Self::Balance` - type Convert: Convert; + /// A conversion function frop `Self::Moment` to `Self::Balance` + type Convert: Convert; /// The relay chain account id. type RelayChainAccountId: Parameter @@ -150,16 +171,20 @@ pub mod pallet { #[pallet::constant] type InitialPayment: Get; - /// The number of blocks a fragment of the reward is vested. + /// The time you have to wait to unlock another part of your reward. #[pallet::constant] - type VestingStep: Get; + type VestingStep: Get>; /// The arbitrary prefix used for the proof #[pallet::constant] type Prefix: Get<&'static [u8]>; - // Extrinsic weights + /// The implementation of extrinsics weight. type WeightInfo: WeightInfo; + + /// The unique identifier of this pallet. + #[pallet::constant] + type PalletId: Get; } #[pallet::storage] @@ -190,7 +215,7 @@ pub mod pallet { /// The block at which the users are able to claim their rewards. #[pallet::storage] #[pallet::getter(fn vesting_block_start)] - pub type VestingBlockStart = StorageValue<_, T::BlockNumber, OptionQuery>; + pub type VestingTimeStart = StorageValue<_, MomentOf, OptionQuery>; /// Associate a local account with a remote one. #[pallet::storage] @@ -209,8 +234,16 @@ pub mod pallet { #[transactional] pub fn initialize(origin: OriginFor) -> DispatchResult { T::AdminOrigin::ensure_origin(origin)?; - ensure!(!VestingBlockStart::::exists(), Error::::AlreadyInitialized); - Self::do_initialize() + let now = T::Time::now(); + Self::do_initialize(now) + } + + /// Initialize the pallet at the given transaction block. + #[pallet::weight(::WeightInfo::initialize(TotalContributors::::get()))] + #[transactional] + pub fn initialize_at(origin: OriginFor, at: MomentOf) -> DispatchResult { + T::AdminOrigin::ensure_origin(origin)?; + Self::do_initialize(at) } /// Populate pallet by adding more rewards. @@ -261,10 +294,21 @@ pub mod pallet { } } + #[pallet::extra_constants] + impl Pallet { + /// The AccountId of this pallet. + pub fn account_id() -> T::AccountId { + T::PalletId::get().into_account() + } + } + impl Pallet { - pub(crate) fn do_initialize() -> DispatchResult { - let current_block = frame_system::Pallet::::block_number(); - VestingBlockStart::::set(Some(current_block)); + pub(crate) fn do_initialize(at: MomentOf) -> DispatchResult { + ensure!(!VestingTimeStart::::exists(), Error::::AlreadyInitialized); + let now = T::Time::now(); + ensure!(at >= now, Error::::BackToTheFuture); + VestingTimeStart::::set(Some(at)); + Self::deposit_event(Event::Initialized { at }); Ok(()) } @@ -272,13 +316,19 @@ pub mod pallet { reward_account: T::AccountId, proof: ProofOf, ) -> DispatchResultWithPostInfo { + let now = T::Time::now(); + let enabled = VestingTimeStart::::get().ok_or(Error::::NotInitialized)? <= now; + ensure!(enabled, Error::::NotClaimableYet); let remote_account = get_remote_account::(proof, &reward_account, T::Prefix::get())?; - // NOTE(hussein-aitlahcen): this is also checked by the signed extension. theoretically - // useless, but 1:1 to make it clear + // NOTE(hussein-aitlahcen): this is also checked by the ValidateUnsigned implementation + // of the pallet. theoretically useless, but 1:1 to make it clear ensure!( !Associations::::contains_key(reward_account.clone()), Error::::AlreadyAssociated ); + // NOTE(hussein-aitlahcen): very important to have a claim here because we do the + // upfront payment, which will allow the user to execute transactions because he had 0 + // funds prior to this call. let claimed = Self::do_claim(remote_account.clone(), &reward_account)?; Associations::::insert(reward_account.clone(), remote_account.clone()); Self::deposit_event(Event::Associated { @@ -292,12 +342,11 @@ pub mod pallet { pub(crate) fn do_populate( rewards: Vec<(RemoteAccountOf, RewardAmountOf, VestingPeriodOf)>, ) -> DispatchResult { - ensure!(!VestingBlockStart::::exists(), Error::::AlreadyInitialized); - let _ = Rewards::::remove_all(None); + ensure!(!VestingTimeStart::::exists(), Error::::AlreadyInitialized); rewards .into_iter() .for_each(|(remote_account, account_reward, vesting_period)| { - // Populate and possibly overwrite. + // This will eliminate duplicated entries. Rewards::::insert( remote_account, Reward { @@ -307,60 +356,51 @@ pub mod pallet { }, ); }); - // NOTE(hussein-aitlahcen): recompute instead of adding to avoid issues with duplicates - let (total_rewards, total_contributors) = Rewards::::iter_values().fold( + let (total_rewards, total_contributors) = Rewards::::iter_values().try_fold( (T::Balance::zero(), 0), - |(total_rewards, total_contributors), contributor_reward| { - (total_rewards + contributor_reward.total, total_contributors + 1) + |(total_rewards, total_contributors), + contributor_reward| + -> Result<(T::Balance, u32), DispatchError> { + Ok(( + total_rewards.safe_add(&contributor_reward.total)?, + total_contributors.safe_add(&1)?, + )) }, - ); + )?; TotalRewards::::set(total_rewards); TotalContributors::::set(total_contributors); + let available_funds = T::RewardAsset::balance(&Self::account_id()); + ensure!(available_funds == total_rewards, Error::::RewardsNotFunded); Ok(()) } /// Do claim the reward for a given remote account, rewarding the `reward_account`. - /// Returns `InvalidProof` if the user is not a contributor or `NothingToClaim` if not + /// Returns `InvalidProof` if the user is not a contributor or `NothingToClaim` if no /// reward can be claimed yet. pub(crate) fn do_claim( remote_account: RemoteAccountOf, reward_account: &T::AccountId, ) -> Result { - let start = VestingBlockStart::::get().ok_or(Error::::NotInitialized)?; Rewards::::try_mutate(remote_account, |reward| { reward .as_mut() .map(|reward| { - let upfront_payment = T::InitialPayment::get().mul_floor(reward.total); - let should_have_claimed = { - let current_block = frame_system::Pallet::::block_number(); - // Current point in time - let vesting_point = current_block.saturating_sub(start); - if vesting_point >= reward.vesting_period { - // If the user is claiming when the period is over, he should - // probably have already claimed everything. - reward.total - } else { - let vesting_step = T::VestingStep::get(); - // Current window, rounded to previous window. - let vesting_window = vesting_point - (vesting_point % vesting_step); - // The user should have claimed the upfront payment + the vested - // amount until this window point. - let vested_reward = reward.total - upfront_payment; - upfront_payment + - (vested_reward - .saturating_mul(T::Convert::convert(vesting_window)) / - T::Convert::convert(reward.vesting_period)) - } - }; - let available_to_claim = should_have_claimed - reward.claimed; + let should_have_claimed = should_have_claimed::(reward)?; + let available_to_claim = should_have_claimed.saturating_sub(reward.claimed); ensure!( available_to_claim > T::Balance::zero(), Error::::NothingToClaim ); - T::Currency::mint_into(reward_account, available_to_claim)?; - (*reward).claimed += available_to_claim; - ClaimedRewards::::mutate(|x| *x += available_to_claim); + let funds_account = Self::account_id(); + // No need to keep the pallet account alive. + T::RewardAsset::transfer( + &funds_account, + reward_account, + available_to_claim, + false, + )?; + (*reward).claimed = available_to_claim.saturating_add(reward.claimed); + ClaimedRewards::::mutate(|x| *x = x.saturating_add(available_to_claim)); Ok(available_to_claim) }) .unwrap_or_else(|| Err(Error::::InvalidProof.into())) @@ -368,14 +408,50 @@ pub mod pallet { } } + /// The reward amount a user should have claimed until now. + pub fn should_have_claimed( + reward: &RewardOf, + ) -> Result { + let start = VestingTimeStart::::get().ok_or(Error::::NotInitialized)?; + let upfront_payment = T::InitialPayment::get().mul_floor(reward.total); + + let now = T::Time::now(); + // Current point in time + let vesting_point = now.saturating_sub(start); + if vesting_point >= reward.vesting_period { + // If the user is claiming when the period is over, he should + // probably have already claimed everything. + Ok(reward.total) + } else { + let vesting_step = T::VestingStep::get(); + // Current window, rounded to previous window. + let vesting_window = vesting_point.saturating_sub(vesting_point % vesting_step); + // The user should have claimed the upfront payment + the vested + // amount until this window point. + let vested_reward = reward.total.saturating_sub(upfront_payment); + Ok(upfront_payment.saturating_add( + vested_reward.saturating_mul(T::Convert::convert(vesting_window)) / + T::Convert::convert(reward.vesting_period), + )) + } + } + + /// Returns the amount available to claim for the specified account. + pub fn amount_available_to_claim_for( + account_id: ::AccountId, + ) -> Result { + let association = Associations::::get(account_id).ok_or(Error::::NotAssociated)?; + let reward = Rewards::::get(association).ok_or(Error::::InvalidProof)?; + let should_have_claimed = should_have_claimed::(&reward)?; + let available_to_claim = should_have_claimed.saturating_sub(reward.claimed); + Ok(available_to_claim) + } + pub fn get_remote_account( - proof: Proof<::RelayChainAccountId>, + proof: ProofOf, reward_account: &::AccountId, prefix: &[u8], - ) -> Result< - RemoteAccount<::RelayChainAccountId>, - sp_runtime::DispatchErrorWithPostInfo, - > { + ) -> Result, DispatchErrorWithPostInfo> { let remote_account = match proof { Proof::Ethereum(eth_proof) => { let reward_account_encoded = @@ -408,16 +484,17 @@ pub mod pallet { relay_account: RelayChainAccountId, proof: &MultiSignature, ) -> bool { - let wrapped_prefix: &[u8] = b""; - let wrapped_postfix: &[u8] = b""; - let mut msg = wrapped_prefix.to_vec(); + /// Polkadotjs wraps the message in this tag before signing. + const WRAPPED_PREFIX: &[u8] = b""; + const WRAPPED_POSTFIX: &[u8] = b""; + let mut msg = WRAPPED_PREFIX.to_vec(); msg.append(&mut prefix.to_vec()); msg.append(&mut reward_account.using_encoded(|x| hex::encode(x).as_bytes().to_vec())); - msg.append(&mut wrapped_postfix.to_vec()); + msg.append(&mut WRAPPED_POSTFIX.to_vec()); proof.verify(&msg[..], &relay_account.into()) } - /// Signable message that would be generated by eth_sign + /// Sign a message and produce an `eth_sign` compatible signature. pub fn ethereum_signable_message(prefix: &[u8], msg: &[u8]) -> Vec { let mut l = prefix.len() + msg.len(); let mut msg_len = Vec::new(); @@ -432,7 +509,8 @@ pub mod pallet { v } - /// Recover the public key + /// Recover the public key of an `eth_sign` signature. + /// The original message is required for this extraction to be possible. pub fn ethereum_recover( prefix: &[u8], msg: &[u8], @@ -452,6 +530,14 @@ pub mod pallet { fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { if let Call::associate { reward_account, proof } = call { + let now = T::Time::now(); + let enabled = VestingTimeStart::::get() + .ok_or(InvalidTransaction::Custom(ValidityError::NotClaimableYet as u8))? <= + now; + if !enabled { + return InvalidTransaction::Custom(ValidityError::NotClaimableYet as u8).into() + } + if Associations::::get(reward_account).is_some() { return InvalidTransaction::Custom(ValidityError::AlreadyAssociated as u8).into() } @@ -482,5 +568,6 @@ pub mod pallet { InvalidProof = 0, NoReward = 1, AlreadyAssociated = 2, + NotClaimableYet = 3, } } diff --git a/frame/crowdloan-rewards/src/mocks.rs b/frame/crowdloan-rewards/src/mocks.rs index 297352e35d1..e14ee68a9a4 100644 --- a/frame/crowdloan-rewards/src/mocks.rs +++ b/frame/crowdloan-rewards/src/mocks.rs @@ -5,6 +5,7 @@ use crate::{ use codec::Encode; use frame_support::{ construct_runtime, dispatch::DispatchResultWithPostInfo, parameter_types, traits::Everything, + PalletId, }; use frame_system as system; use sp_core::{ed25519, keccak_256, Pair, H256}; @@ -18,18 +19,13 @@ use system::EnsureRoot; pub type RelayKey = ed25519::Pair; pub type EthKey = libsecp256k1::SecretKey; +pub type Moment = u64; pub type BlockNumber = u32; pub type AccountId = AccountId32; pub type RelayChainAccountId = [u8; 32]; pub type Balance = u128; -pub const MILLISECS_PER_BLOCK: u32 = 6000; -pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); -pub const HOURS: BlockNumber = MINUTES * 60; -pub const DAYS: BlockNumber = HOURS * 24; -pub const WEEKS: BlockNumber = DAYS * 7; - -pub const VESTING_STEP: BlockNumber = WEEKS; +pub const VESTING_STEP: Moment = 3600 * 24 * 7; pub const INITIAL_PAYMENT: Perbill = Perbill::from_percent(50); pub const ALICE: AccountId = AccountId32::new([0_u8; 32]); @@ -59,7 +55,7 @@ impl system::Config for Test { type BlockLength = (); type Version = (); type PalletInfo = PalletInfo; - type AccountData = balances::AccountData; + type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); type DbWeight = (); @@ -70,7 +66,7 @@ impl system::Config for Test { type MaxConsumers = (MaxConsumers, MaxOverFlow); } -impl balances::Config for Test { +impl pallet_balances::Config for Test { type Balance = Balance; type Event = Event; type DustRemoval = (); @@ -83,14 +79,15 @@ impl balances::Config for Test { } parameter_types! { + pub const CrowdloanRewardsPalletId: PalletId = PalletId(*b"pal_crow"); pub const InitialPayment: Perbill = INITIAL_PAYMENT; - pub const VestingStep: BlockNumber = VESTING_STEP; + pub const VestingStep: Moment = VESTING_STEP; pub const Prefix: &'static [u8] = PROOF_PREFIX; } impl pallet_crowdloan_rewards::Config for Test { type Event = Event; - type Currency = Balances; + type RewardAsset = Balances; type Balance = Balance; type Convert = ConvertInto; type RelayChainAccountId = RelayChainAccountId; @@ -99,6 +96,22 @@ impl pallet_crowdloan_rewards::Config for Test { type Prefix = Prefix; type AdminOrigin = EnsureRoot; type WeightInfo = (); + type PalletId = CrowdloanRewardsPalletId; + type Moment = Moment; + type Time = Timestamp; +} + +parameter_types! { + pub const MinimumPeriod: u64 = 6000; +} + +impl pallet_timestamp::Config for Test { + /// A timestamp: milliseconds since the Unix epoch. + type Moment = Moment; + /// What to do when SLOT_DURATION has passed? + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); } type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; @@ -111,7 +124,8 @@ construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic, { System: frame_system::{Pallet, Call, Storage, Config, Event}, - Balances: balances::{Pallet, Storage, Event, Config}, + Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, + Balances: pallet_balances::{Pallet, Storage, Event, Config}, CrowdloanRewards: pallet_crowdloan_rewards::{Pallet, Storage, Call, Event}, } ); @@ -124,7 +138,7 @@ pub struct ExtBuilder { impl ExtBuilder { pub fn build(self) -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - balances::GenesisConfig:: { balances: self.balances } + pallet_balances::GenesisConfig:: { balances: self.balances } .assimilate_storage(&mut t) .unwrap(); t.into() diff --git a/frame/crowdloan-rewards/src/models.rs b/frame/crowdloan-rewards/src/models.rs index 061e886e043..22146e75c7e 100644 --- a/frame/crowdloan-rewards/src/models.rs +++ b/frame/crowdloan-rewards/src/models.rs @@ -3,10 +3,10 @@ use scale_info::TypeInfo; use sp_runtime::{MultiSignature, RuntimeDebug}; #[derive(Encode, Decode, PartialEq, Copy, Clone, TypeInfo, MaxEncodedLen)] -pub struct Reward { +pub struct Reward { pub(crate) total: Balance, pub(crate) claimed: Balance, - pub(crate) vesting_period: BlockNumber, + pub(crate) vesting_period: Period, } #[derive(Clone, RuntimeDebug, PartialEq, Encode, Decode, MaxEncodedLen, TypeInfo)] diff --git a/frame/crowdloan-rewards/src/tests.rs b/frame/crowdloan-rewards/src/tests.rs index e5b69e952fe..c9941ebdf3c 100644 --- a/frame/crowdloan-rewards/src/tests.rs +++ b/frame/crowdloan-rewards/src/tests.rs @@ -1,9 +1,9 @@ use crate::{ ethereum_recover, mocks::{ - ethereum_address, generate_accounts, AccountId, Balance, Balances, BlockNumber, ClaimKey, - CrowdloanRewards, EthKey, ExtBuilder, Origin, System, Test, ALICE, INITIAL_PAYMENT, - PROOF_PREFIX, VESTING_STEP, WEEKS, + ethereum_address, generate_accounts, AccountId, Balance, Balances, ClaimKey, + CrowdloanRewards, EthKey, ExtBuilder, Moment, Origin, System, Test, Timestamp, ALICE, + INITIAL_PAYMENT, PROOF_PREFIX, VESTING_STEP, }, models::{EcdsaSignature, EthereumAddress, Proof, RemoteAccount}, Error, RemoteAccountOf, RewardAmountOf, VestingPeriodOf, @@ -11,13 +11,13 @@ use crate::{ use codec::Encode; use frame_support::{assert_noop, assert_ok, traits::Currency}; use hex_literal::hex; -use sp_core::{ed25519, Pair}; +use sp_core::{ed25519, storage::StateVersion, Pair}; fn with_rewards( count: u128, reward: Balance, - vesting_period: BlockNumber, - execute: impl FnOnce(&dyn Fn(BlockNumber), Vec<(AccountId, ClaimKey)>) -> R, + vesting_period: Moment, + execute: impl FnOnce(&dyn Fn(Moment), Vec<(AccountId, ClaimKey)>) -> R, ) -> R { let accounts = generate_accounts(count as _); let rewards = accounts @@ -25,24 +25,72 @@ fn with_rewards( .map(|(_, account)| (account.as_remote_public(), reward, vesting_period)) .collect(); ExtBuilder::default().build().execute_with(|| { - let random_block_start = 0xCAF * WEEKS; - let set_block = |x: BlockNumber| System::set_block_number(random_block_start + x); - set_block(0); + System::set_block_number(0xDEADC0DE); + let random_moment_start = 0xCAFEBABE; + let set_moment = |x: Moment| Timestamp::set_timestamp(random_moment_start + x); + set_moment(0); + Balances::make_free_balance_be(&CrowdloanRewards::account_id(), reward * count); assert_ok!(CrowdloanRewards::populate(Origin::root(), rewards)); - execute(&set_block, accounts) + execute(&set_moment, accounts) }) } const DEFAULT_NB_OF_CONTRIBUTORS: u128 = 100; -const DEFAULT_VESTING_PERIOD: BlockNumber = 10 * WEEKS; +const DEFAULT_VESTING_PERIOD: Moment = 3600 * 24 * 7 * 10; const DEFAULT_REWARD: Balance = 10_000; fn with_rewards_default( - execute: impl FnOnce(&dyn Fn(BlockNumber), Vec<(AccountId, ClaimKey)>) -> R, + execute: impl FnOnce(&dyn Fn(Moment), Vec<(AccountId, ClaimKey)>) -> R, ) -> R { with_rewards(DEFAULT_NB_OF_CONTRIBUTORS, DEFAULT_REWARD, DEFAULT_VESTING_PERIOD, execute) } +#[test] +fn test_populate_rewards_not_funded() { + let gen = |c, r| -> Vec<(RemoteAccountOf, RewardAmountOf, VestingPeriodOf)> { + generate_accounts(c) + .into_iter() + .map(|(_, account)| (account.as_remote_public(), r, DEFAULT_VESTING_PERIOD)) + .collect() + }; + ExtBuilder::default().build().execute_with(|| { + Balances::make_free_balance_be(&CrowdloanRewards::account_id(), 0); + assert_noop!( + CrowdloanRewards::populate(Origin::root(), gen(100, DEFAULT_REWARD)), + Error::::RewardsNotFunded + ); + }); +} + +#[test] +fn test_incremental_populate() { + let gen = |c, r| -> Vec<(RemoteAccountOf, RewardAmountOf, VestingPeriodOf)> { + generate_accounts(c) + .into_iter() + .map(|(_, account)| (account.as_remote_public(), r, DEFAULT_VESTING_PERIOD)) + .collect() + }; + ExtBuilder::default().build().execute_with(|| { + let accounts = gen(10_000, DEFAULT_REWARD); + for i in 0..10 { + let start = i * 1000; + let slice = accounts[start..start + 1000].to_vec(); + let expected_total_rewards = (i + 1) as u128 * 1000 * DEFAULT_REWARD; + Balances::make_free_balance_be(&CrowdloanRewards::account_id(), expected_total_rewards); + assert_ok!(CrowdloanRewards::populate(Origin::root(), slice)); + assert_eq!(CrowdloanRewards::total_rewards(), expected_total_rewards); + } + // Repopulating using the same accounts must overwrite existing entries. + let expected_total_rewards = 10_000 * DEFAULT_REWARD; + for i in 0..10 { + let start = i * 1000; + let slice = accounts[start..start + 1000].to_vec(); + assert_ok!(CrowdloanRewards::populate(Origin::root(), slice)); + assert_eq!(CrowdloanRewards::total_rewards(), expected_total_rewards); + } + }); +} + #[test] fn test_populate_ok() { let gen = |c, r| -> Vec<(RemoteAccountOf, RewardAmountOf, VestingPeriodOf)> { @@ -52,25 +100,34 @@ fn test_populate_ok() { .collect() }; ExtBuilder::default().build().execute_with(|| { + let expected_total_rewards = 0; + Balances::make_free_balance_be(&CrowdloanRewards::account_id(), expected_total_rewards); assert_ok!(CrowdloanRewards::populate(Origin::root(), gen(0, DEFAULT_REWARD))); - assert_eq!(CrowdloanRewards::total_rewards(), 0); + assert_eq!(CrowdloanRewards::total_rewards(), expected_total_rewards); assert_eq!(CrowdloanRewards::claimed_rewards(), 0); + + let expected_total_rewards = 100 * DEFAULT_REWARD; + Balances::make_free_balance_be(&CrowdloanRewards::account_id(), expected_total_rewards); assert_ok!(CrowdloanRewards::populate(Origin::root(), gen(100, DEFAULT_REWARD))); - assert_eq!(CrowdloanRewards::total_rewards(), 100 * DEFAULT_REWARD); + assert_eq!(CrowdloanRewards::total_rewards(), expected_total_rewards); assert_eq!(CrowdloanRewards::claimed_rewards(), 0); // Try to repopulate using the same generated accounts // In this case, the total shouldn't change as its duplicate // No error will be yield but the process should be = identity - let s = frame_support::storage_root(); + let s = frame_support::storage_root(StateVersion::V1); + let expected_total_rewards = 100 * DEFAULT_REWARD; + Balances::make_free_balance_be(&CrowdloanRewards::account_id(), expected_total_rewards); assert_ok!(CrowdloanRewards::populate(Origin::root(), gen(100, DEFAULT_REWARD))); - assert_eq!(s, frame_support::storage_root()); - assert_eq!(CrowdloanRewards::total_rewards(), 100 * DEFAULT_REWARD); + assert_eq!(s, frame_support::storage_root(StateVersion::V1)); + assert_eq!(CrowdloanRewards::total_rewards(), expected_total_rewards); assert_eq!(CrowdloanRewards::claimed_rewards(), 0); // Overwrite rewards + 100 new contributors + let expected_total_rewards = 200 * (DEFAULT_REWARD + 1); + Balances::make_free_balance_be(&CrowdloanRewards::account_id(), expected_total_rewards); assert_ok!(CrowdloanRewards::populate(Origin::root(), gen(200, DEFAULT_REWARD + 1))); - assert_eq!(CrowdloanRewards::total_rewards(), 200 * (DEFAULT_REWARD + 1)); + assert_eq!(CrowdloanRewards::total_rewards(), expected_total_rewards); assert_eq!(CrowdloanRewards::claimed_rewards(), 0); }); } @@ -95,6 +152,47 @@ fn test_initialize_ok() { }); } +#[test] +fn test_initialize_at_ok() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(CrowdloanRewards::initialize_at(Origin::root(), 10)); + assert_eq!(CrowdloanRewards::total_rewards(), 0); + assert_eq!(CrowdloanRewards::claimed_rewards(), 0); + }); +} + +#[test] +fn test_initialize_at_ko() { + ExtBuilder::default().build().execute_with(|| { + Timestamp::set_timestamp(100); + assert_noop!( + CrowdloanRewards::initialize_at(Origin::root(), 99), + Error::::BackToTheFuture + ); + }); +} + +#[test] +fn test_invalid_early_at_claim() { + with_rewards_default(|set_moment, accounts| { + let now = Timestamp::now(); + assert_ok!(CrowdloanRewards::initialize_at(Origin::root(), now + 10)); + + for (picasso_account, remote_account) in accounts.clone().into_iter() { + assert_noop!( + remote_account.associate(picasso_account.clone()), + Error::::NotClaimableYet + ); + assert_noop!(remote_account.claim(picasso_account), Error::::NotAssociated); + } + + set_moment(11); + for (picasso_account, remote_account) in accounts.clone().into_iter() { + assert_ok!(remote_account.associate(picasso_account.clone()),); + } + }); +} + #[test] fn test_initialize_once() { ExtBuilder::default().build().execute_with(|| { @@ -187,16 +285,16 @@ fn test_association_ko() { #[test] fn test_invalid_less_than_a_week() { - with_rewards_default(|set_block, accounts| { + with_rewards_default(|set_moment, accounts| { assert_ok!(CrowdloanRewards::initialize(Origin::root())); for (picasso_account, remote_account) in accounts.clone().into_iter() { assert_ok!(remote_account.associate(picasso_account)); } - set_block(VESTING_STEP - 1); + set_moment(VESTING_STEP - 1); for (picasso_account, remote_account) in accounts.clone().into_iter() { assert_noop!(remote_account.claim(picasso_account), Error::::NothingToClaim); } - set_block(VESTING_STEP); + set_moment(VESTING_STEP); for (picasso_account, remote_account) in accounts.into_iter() { assert_ok!(remote_account.claim(picasso_account)); } @@ -208,7 +306,7 @@ fn test_valid_claim_full() { let total_initial_reward = INITIAL_PAYMENT * DEFAULT_NB_OF_CONTRIBUTORS * DEFAULT_REWARD; let total_vested_reward = DEFAULT_NB_OF_CONTRIBUTORS * DEFAULT_REWARD - total_initial_reward; let nb_of_vesting_step = DEFAULT_VESTING_PERIOD / VESTING_STEP; - with_rewards_default(|set_block, accounts| { + with_rewards_default(|set_moment, accounts| { assert_ok!(CrowdloanRewards::initialize(Origin::root())); // Initial payment for (picasso_account, remote_account) in accounts.clone().into_iter() { @@ -216,7 +314,7 @@ fn test_valid_claim_full() { } assert_eq!(CrowdloanRewards::claimed_rewards(), total_initial_reward); for i in 1..(nb_of_vesting_step + 1) { - set_block(i * VESTING_STEP); + set_moment(i * VESTING_STEP); for (picasso_account, remote_account) in accounts.clone().into_iter() { assert_ok!(remote_account.claim(picasso_account)); } @@ -266,17 +364,19 @@ fn test_valid_eth_hardcoded() { assert_eq!(Some(eth_address), recovered_address); + let reward_amount = DEFAULT_REWARD; let rewards = - vec![(RemoteAccount::Ethereum(eth_address), DEFAULT_REWARD, DEFAULT_VESTING_PERIOD)]; + vec![(RemoteAccount::Ethereum(eth_address), reward_amount, DEFAULT_VESTING_PERIOD)]; let proof = Proof::Ethereum(eth_proof); ExtBuilder::default().build().execute_with(|| { + Balances::make_free_balance_be(&CrowdloanRewards::account_id(), reward_amount); assert_ok!(CrowdloanRewards::populate(Origin::root(), rewards)); assert_ok!(CrowdloanRewards::initialize(Origin::root())); assert_ok!(CrowdloanRewards::associate(Origin::none(), ALICE, proof)); - System::set_block_number(VESTING_STEP); + Timestamp::set_timestamp(VESTING_STEP); assert_ok!(CrowdloanRewards::claim(Origin::signed(ALICE))); - System::set_block_number(DEFAULT_VESTING_PERIOD); + Timestamp::set_timestamp(DEFAULT_VESTING_PERIOD); assert_ok!(CrowdloanRewards::claim(Origin::signed(ALICE))); assert_eq!(CrowdloanRewards::claimed_rewards(), CrowdloanRewards::total_rewards()); }); diff --git a/frame/currency-factory/Cargo.toml b/frame/currency-factory/Cargo.toml index e02a7e8ee60..5323b99b1c5 100644 --- a/frame/currency-factory/Cargo.toml +++ b/frame/currency-factory/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "pallet-currency-factory" -version = "0.0.1" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" +homepage = "https://composable.finance" +name = "pallet-currency-factory" +version = "0.0.1" [package.metadata.docs.rs] @@ -16,40 +16,46 @@ package = "parity-scale-codec" version = "2.0.0" [dependencies] -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-benchmarking = { default-features = false, optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.16' } - -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -composable-traits = { path = "../composable-traits", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +# FRAME +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } + +# substrate primitives +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } +sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } + +# local +composable-traits = { path = "../composable-traits", default-features = false } [dev-dependencies] -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } -proptest = "0.9.6" -composable-tests-helpers = { version = "0.0.1", path = "../composable-tests-helpers", default-features = false } +composable-tests-helpers = { version = "0.0.1", path = "../composable-tests-helpers" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +proptest = "1.0.0" [features] default = ["std"] std = [ - "codec/std", - "frame-support/std", - "frame-system/std", - "sp-runtime/std", - "sp-io/std", - "sp-core/std", - "sp-std/std", - "sp-arithmetic/std", - "composable-traits/std", - "scale-info/std", + "codec/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-io/std", + "sp-core/std", + "sp-std/std", + "sp-arithmetic/std", + "composable-traits/std", + "scale-info/std", ] runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", ] diff --git a/frame/curve-amm/Cargo.toml b/frame/curve-amm/Cargo.toml index 23ef3319011..bf54570d769 100644 --- a/frame/curve-amm/Cargo.toml +++ b/frame/curve-amm/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "pallet-curve-amm" -version = "0.0.1" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" +homepage = "https://composable.finance" +name = "pallet-curve-amm" +version = "0.0.1" [package.metadata.docs.rs] @@ -19,55 +19,57 @@ package = "parity-scale-codec" version = "2.0.0" [dependencies] -frame-benchmarking = { default-features = false, optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.16' } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } pallet-oracle = { default-features = false, optional = true, version = "1.0.0", path = "../oracle" } pallet-vault = { default-features = false, version = "0.0.1", path = "../vault", optional = true } +composable-traits = { default-features = false, version = "0.0.1", path = "../composable-traits" } log = { version = "0.4.14", default-features = false } num-traits = { version = "0.2.14", default-features = false } plotters = { version = "0.3.1", optional = true } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } serde = { version = '1', optional = true } -composable-traits = { default-features = false, version = "0.0.1", path = "../composable-traits" } [dev-dependencies] -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } +composable-tests-helpers = { path = "../composable-tests-helpers" } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } pallet-currency-factory = { version = "0.0.1", path = "../currency-factory" } -proptest = "0.9.6" +proptest = "1.0" [features] default = ["std"] std = [ - "serde/std", - "codec/std", - "log/std", - "frame-support/std", - "frame-system/std", - "sp-runtime/std", - "sp-io/std", - "sp-core/std", - "sp-std/std", - "sp-arithmetic/std", - "pallet-vault/std", - "scale-info/std", + "serde/std", + "codec/std", + "log/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-io/std", + "sp-core/std", + "sp-std/std", + "sp-arithmetic/std", + "pallet-vault/std", + "scale-info/std", ] runtime-benchmarks = [ - "frame-benchmarking", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "pallet-oracle/runtime-benchmarks", + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-oracle/runtime-benchmarks", ] visualization = ["plotters"] diff --git a/frame/curve-amm/README.md b/frame/curve-amm/README.md index 2a9cf3873be..4d33e5102f1 100644 --- a/frame/curve-amm/README.md +++ b/frame/curve-amm/README.md @@ -1 +1,2 @@ -CurveAmm pallet which has stable-swap like alogrithm as explained in https://miguelmota.com/blog/understanding-stableswap-curve/ +CurveAmm pallet which has stable-swap as explained in https://curve.fi/files/stableswap-paper.pdf +Other relevant documents https://raw.githubusercontent.com/equilibrium-eosdt/equilibrium-curve-amm/master/docs/deducing-get_y-formulas.pdf and https://miguelmota.com/blog/understanding-stableswap-curve/ diff --git a/frame/curve-amm/curve_base.png b/frame/curve-amm/curve_base.png new file mode 100644 index 0000000000000000000000000000000000000000..3117b2b568536b2919d1fd4e2a10a506fd487c59 GIT binary patch literal 54802 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 literal 0 HcmV?d00001 diff --git a/frame/curve-amm/curve_graph.png b/frame/curve-amm/curve_graph.png new file mode 100644 index 0000000000000000000000000000000000000000..94ced0eaf519ebfc93906ba9db1ae7cf6d3703a0 GIT binary patch literal 57555 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 literal 0 HcmV?d00001 diff --git a/frame/curve-amm/curve_slippage.png b/frame/curve-amm/curve_slippage.png new file mode 100644 index 0000000000000000000000000000000000000000..f5e61734c363d344ac48593f0a21ee719a06a880 GIT binary patch literal 52401 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 F`X@B60(<}f literal 0 HcmV?d00001 diff --git a/frame/curve-amm/src/benchmarking.rs b/frame/curve-amm/src/benchmarking.rs new file mode 100644 index 00000000000..54fa3e78ada --- /dev/null +++ b/frame/curve-amm/src/benchmarking.rs @@ -0,0 +1,174 @@ +use super::*; +use crate::Pallet as StableSwap; +use composable_traits::{defi::CurrencyPair, dex::Amm}; +use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_support::{ + assert_ok, + traits::fungibles::{Inspect, Mutate}, +}; +use frame_system::RawOrigin; +use sp_arithmetic::Permill; + +benchmarks! { + where_clause { where T::Balance: From, T::AssetId: From } + + create { + let usdc: T::AssetId = 100.into(); + let usdt: T::AssetId = 101.into(); + let owner = whitelisted_caller(); + let pair = CurrencyPair::new(usdc, usdt); + let amplification_factor = 100_u16; + let fee = Permill::from_percent(1); + let protocol_fee = Permill::from_percent(1); + } : _(RawOrigin::Signed(owner), pair, amplification_factor, fee, protocol_fee) + + add_liquidity { + let usdc: T::AssetId = 100.into(); + let usdt: T::AssetId = 101.into(); + let owner = whitelisted_caller(); + let pool_id = StableSwap::::do_create_pool( + &owner, + CurrencyPair::new(usdc, usdt), + 1000_u16, + Permill::from_percent(1), + Permill::from_percent(1), + ) .expect("impossible; qed;"); + let unit = 1_000_000_000_000; + // 100_000_000 USDC , 100_000_000 USDT + let initial_usdc: T::Balance = (100_000_000_u128 * unit).into(); + let initial_usdt: T::Balance = (100_000_000_u128 * unit).into(); + // Mint the tokens + assert_ok!(T::Assets::mint_into(usdc, &owner, initial_usdc)); + assert_ok!(T::Assets::mint_into(usdt, &owner, initial_usdt)); + }: _(RawOrigin::Signed(owner), pool_id, initial_usdc, initial_usdt, 0.into(), false) + + remove_liquidity { + let usdc: T::AssetId = 100.into(); + let usdt: T::AssetId = 101.into(); + let owner = whitelisted_caller(); + let pool_id = StableSwap::::do_create_pool( + &owner, + CurrencyPair::new(usdc, usdt), + 1000_u16, + Permill::from_percent(1), + Permill::from_percent(1), + ) .expect("impossible; qed;"); + let unit = 1_000_000_000_000; + // 100_000_000 USDC , 100_000_000 USDT + let initial_usdc: T::Balance = (100_000_000_u128 * unit).into(); + let initial_usdt: T::Balance = (100_000_000_u128 * unit).into(); + // Mint the tokens + assert_ok!(T::Assets::mint_into(usdc, &owner, initial_usdc)); + assert_ok!(T::Assets::mint_into(usdt, &owner, initial_usdt)); + // Add the liquidity + assert_ok!( as Amm>::add_liquidity( + &owner, + pool_id, + initial_usdc, + initial_usdt, + 0.into(), + false + )); + let pool_info = StableSwap::::get_pool(pool_id).expect("impossible; qed;"); + let lp_amount = T::Assets::balance(pool_info.lp_token, &owner); + }: _(RawOrigin::Signed(owner), pool_id, lp_amount, (0_u128).into(), (0_u128).into()) + + buy { + let usdc: T::AssetId = 100.into(); + let usdt: T::AssetId = 101.into(); + let owner = whitelisted_caller(); + let pool_id = StableSwap::::do_create_pool( + &owner, + CurrencyPair::new(usdc, usdt), + 1000_u16, + Permill::from_percent(1), + Permill::from_percent(1), + ) .expect("impossible; qed;"); + let unit = 1_000_000_000_000; + // 100_000_000 USDC , 100_000_000 USDT + let initial_usdc: T::Balance = (100_000_000_u128 * unit).into(); + let initial_usdt: T::Balance = (100_000_000_u128 * unit).into(); + // Mint the tokens + assert_ok!(T::Assets::mint_into(usdc, &owner, initial_usdc)); + assert_ok!(T::Assets::mint_into(usdt, &owner, initial_usdt)); + // Add the liquidity + assert_ok!( as Amm>::add_liquidity( + &owner, + pool_id, + initial_usdc, + initial_usdt, + 0.into(), + false + )); + let user = account("user", 0, 0); + assert_ok!(T::Assets::mint_into(usdt, &user, (1000_u128 * unit).into())); + // buy 1000 USDC + }: _(RawOrigin::Signed(user), pool_id, usdc, (1000_u128 * unit).into(), false) + + sell { + let usdc: T::AssetId = 100.into(); + let usdt: T::AssetId = 101.into(); + let owner = whitelisted_caller(); + let pool_id = StableSwap::::do_create_pool( + &owner, + CurrencyPair::new(usdc, usdt), + 100_u16, + Permill::from_percent(1), + Permill::from_percent(1), + ) .expect("impossible; qed;"); + let unit = 1_000_000_000_000; + // 100_000_000 USDC , 100_000_000 USDT + let initial_usdc: T::Balance = (100_000_000_u128 * unit).into(); + let initial_usdt: T::Balance = (100_000_000_u128 * unit).into(); + // Mint the tokens + assert_ok!(T::Assets::mint_into(usdc, &owner, initial_usdc)); + assert_ok!(T::Assets::mint_into(usdt, &owner, initial_usdt)); + // Add the liquidity + assert_ok!( as Amm>::add_liquidity( + &owner, + pool_id, + initial_usdc, + initial_usdt, + 0.into(), + false + )); + let user = account("user", 0, 0); + assert_ok!(T::Assets::mint_into(usdc, &user, (1000_u128 * unit).into())); + // sell 1000 USDC + }: _(RawOrigin::Signed(user), pool_id, usdc, (1000_u128 * unit).into(), false) + + swap { + let usdc: T::AssetId = 100.into(); + let usdt: T::AssetId = 101.into(); + let owner = whitelisted_caller(); + let pair = CurrencyPair::new(usdc, usdt); + let pool_id = StableSwap::::do_create_pool( + &owner, + pair, + 100_u16, + Permill::from_percent(1), + Permill::from_percent(1), + ) .expect("impossible; qed;"); + let unit = 1_000_000_000_000; + // 100_000_000 USDC , 100_000_000 USDT + let initial_usdc: T::Balance = (100_000_000_u128 * unit).into(); + let initial_usdt: T::Balance = (100_000_000_u128 * unit).into(); + // Mint the tokens + assert_ok!(T::Assets::mint_into(usdc, &owner, initial_usdc)); + assert_ok!(T::Assets::mint_into(usdt, &owner, initial_usdt)); + // Add the liquidity + assert_ok!( as Amm>::add_liquidity( + &owner, + pool_id, + initial_usdc, + initial_usdt, + 0.into(), + false + )); + let user = account("user", 0, 0); + assert_ok!(T::Assets::mint_into(usdt, &user, (1000_u128 * unit).into())); + // swap 1000 USDC + }: _(RawOrigin::Signed(user), pool_id, pair, (1000_u128 * unit).into(), 0.into(), false) +} + +impl_benchmark_test_suite!(StableSwap, crate::mock::new_test_ext(), crate::mock::Test); diff --git a/frame/curve-amm/src/lib.rs b/frame/curve-amm/src/lib.rs index 6f389bc9e24..2c12b980ec7 100644 --- a/frame/curve-amm/src/lib.rs +++ b/frame/curve-amm/src/lib.rs @@ -31,7 +31,6 @@ trivial_numeric_casts, unused_extern_crates )] -#![allow(clippy::all)] pub use pallet::*; @@ -41,28 +40,41 @@ mod mock; #[cfg(test)] mod tests; +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; +mod maths; + +pub mod weights; +pub use crate::weights::WeightInfo; + #[frame_support::pallet] pub mod pallet { + use crate::{ + maths::{compute_base, compute_d}, + weights::WeightInfo, + }; use codec::{Codec, FullCodec}; use composable_traits::{ - currency::CurrencyFactory, - defi::{CurrencyPair, LiftedFixedBalance}, - dex::{CurveAmm, StableSwapPoolInfo}, + currency::{CurrencyFactory, RangeId}, + defi::CurrencyPair, + dex::{Amm, StableSwapPoolInfo}, + math::{safe_multiply_by_rational, SafeAdd, SafeSub}, }; use frame_support::{ pallet_prelude::*, traits::fungibles::{Inspect, Mutate, Transfer}, - PalletId, + transactional, PalletId, }; + use frame_system::{ensure_signed, pallet_prelude::OriginFor}; use scale_info::TypeInfo; use sp_runtime::{ - traits::{ - AccountIdConversion, AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul, - CheckedSub, One, Zero, - }, - FixedPointNumber, FixedPointOperand, FixedU128, Permill, + traits::{AccountIdConversion, CheckedAdd, Convert, One, Zero}, + ArithmeticError, Permill, }; - use sp_std::{collections::btree_set::BTreeSet, fmt::Debug, iter::FromIterator}; + use sp_std::{fmt::Debug, ops::Mul}; + + type PoolOf = + StableSwapPoolInfo<::AccountId, ::AssetId>; #[pallet::config] pub trait Config: frame_system::Config { @@ -83,22 +95,15 @@ pub mod pallet { + MaxEncodedLen + Copy + Ord - + CheckedAdd - + CheckedSub - + CheckedMul - + AtLeast32BitUnsigned - + From // at least 64 bit + Zero + One - + FixedPointOperand - + Into - + Into; // cannot do From, until LiftedFixedBalance integer part is larger than 128 - // bit + + SafeAdd + + SafeSub; + type Convert: Convert + Convert; type CurrencyFactory: CurrencyFactory<::AssetId>; - type LpToken: Transfer::AssetId> + type Assets: Transfer::AssetId> + Mutate::AssetId> + Inspect::AssetId>; - type Precision: Get; type PoolId: FullCodec + MaxEncodedLen + Default @@ -108,10 +113,15 @@ pub mod pallet { + Ord + Copy + Debug - + CheckedAdd - + One; - type PoolTokenIndex: Copy + Debug + Eq + Into + From; + + One + + Zero + + SafeAdd + + SafeSub; + + #[pallet::constant] type PalletId: Get; + + type WeightInfo: WeightInfo; } #[pallet::pallet] @@ -123,7 +133,12 @@ pub mod pallet { #[pallet::getter(fn pool_count)] // Absence of pool count is equivalent to 0, so ValueQuery is allowed. #[allow(clippy::disallowed_type)] - pub type PoolCount = StorageValue<_, T::PoolId, ValueQuery>; + pub type PoolCount = StorageValue<_, T::PoolId, ValueQuery, PoolCountOnEmpty>; + + #[pallet::type_value] + pub fn PoolCountOnEmpty() -> T::PoolId { + Zero::zero() + } /// Existing pools #[pallet::storage] @@ -131,69 +146,18 @@ pub mod pallet { pub type Pools = StorageMap<_, Blake2_128Concat, T::PoolId, StableSwapPoolInfo>; - /// Pair of assets supported by the pool - #[pallet::storage] - #[pallet::getter(fn pool_assets)] - pub type PoolAssets = - StorageMap<_, Blake2_128Concat, T::PoolId, CurrencyPair>; - - /// Balance of asset for given pool excluding admin_fee - #[pallet::storage] - #[pallet::getter(fn pool_asset_balance)] - // Absence of pool asset balance is equivalent to 0, so ValueQuery is allowed. - #[allow(clippy::disallowed_type)] - pub type PoolAssetBalance = StorageDoubleMap< - _, - Blake2_128Concat, - T::PoolId, - Blake2_128Concat, - T::AssetId, - T::Balance, - ValueQuery, - >; - - /// Balance of asset for given pool including admin_fee - #[pallet::storage] - #[pallet::getter(fn pool_asset_total_balance)] - // Absence of pool asset balance is equivalent to 0, so ValueQuery is allowed. - #[allow(clippy::disallowed_type)] - pub type PoolAssetTotalBalance = StorageDoubleMap< - _, - Blake2_128Concat, - T::PoolId, - Blake2_128Concat, - T::AssetId, - T::Balance, - ValueQuery, - >; - #[pallet::hooks] impl Hooks for Pallet {} #[pallet::error] pub enum Error { - /// Could not create new asset - AssetNotCreated, - /// Values in the storage are inconsistent - InconsistentStorage, - /// Not enough assets provided - NotEnoughAssets, - /// Some provided assets are not unique - DuplicateAssets, - /// Pool with specified id is not found - PoolNotFound, - /// Error occurred while performing math calculations - Math, - /// Specified asset amount is wrong AssetAmountMustBePositiveNumber, - /// Required amount of some token did not reached during adding or removing liquidity - RequiredAmountNotReached, - /// Source does not have required amount of coins to complete operation - InsufficientFunds, - /// Specified index is out of range - IndexOutOfRange, - /// The `AssetChecker` can use this error in case it can't provide better error - ExternalAssetCheckFailed, + InvalidFees, + InvalidPair, + PoolNotFound, + PairMismatch, + CannotRespectMinimumRequested, + AmpFactorMustBeGreaterThanZero, } #[pallet::event] @@ -213,14 +177,10 @@ pub mod pallet { who: T::AccountId, /// Pool id to which liquidity added. pool_id: T::PoolId, - /// Added token amounts. - token_amounts: Vec, - /// Charged fees. - fees: Vec, - /// Invariant after liquidity addition. - invariant: T::Balance, - /// Updated lp token supply. - token_supply: T::Balance, + /// Base amount added to pool. + base_amount: T::Balance, + /// Quote amount added to pool. + quote_amount: T::Balance, /// Amount of minted lp tokens. mint_amount: T::Balance, }, @@ -231,597 +191,446 @@ pub mod pallet { who: T::AccountId, /// Pool id to which liquidity added. pool_id: T::PoolId, - /// Removed token amounts. - token_amounts: Vec, - /// Charged fees. - fees: Vec, + /// Amount of base asset removed from pool. + base_amount: T::Balance, + /// Amount of quote asset removed from pool. + quote_amount: T::Balance, /// Updated lp token supply. - token_supply: T::Balance, + total_issuance: T::Balance, }, /// Token exchange happened. - TokenExchanged { + Swapped { /// Account id who exchanged token. who: T::AccountId, /// Pool id on which exchange done. pool_id: T::PoolId, - /// Index of sent token. - sent_token_index: T::PoolTokenIndex, - /// Amount of sent token. - sent_amount: T::Balance, - /// Index of received token. - received_token_index: T::PoolTokenIndex, - /// Amount of received token. - received_amount: T::Balance, + /// Id of asset used as input. + base_asset: T::AssetId, + /// Id of asset used as output. + quote_asset: T::AssetId, + /// Amount of base asset received. + base_amount: T::Balance, + /// Amount of quote asset provided. + quote_amount: T::Balance, /// Charged fees. fee: T::Balance, }, - - /// Withdraw admin fees `Vec` from pool `T::PoolId` by user `T::AccountId` - AdminFeesWithdrawn { - /// Account id which withdrew admin fee. - who: T::AccountId, - /// Pool id from which fee withdrew. - pool_id: T::PoolId, - /// Account id to which fee deposited. - admin_fee_account: T::AccountId, - /// Amounts of fees. - admin_fees: Vec, - }, } #[pallet::call] - impl Pallet {} + impl Pallet { + /// Create a new pool. + /// + /// Emits `PoolCreated` event when successful. + #[pallet::weight(T::WeightInfo::create())] + pub fn create( + origin: OriginFor, + pair: CurrencyPair, + amplification_coefficient: u16, + fee: Permill, + owner_fee: Permill, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = Self::do_create_pool(&who, pair, amplification_coefficient, fee, owner_fee)?; + Ok(()) + } + + /// Execute a buy order on pool. + /// + /// Emits `Swapped` event when successful. + #[pallet::weight(T::WeightInfo::buy())] + pub fn buy( + origin: OriginFor, + pool_id: T::PoolId, + asset_id: T::AssetId, + amount: T::Balance, + keep_alive: bool, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = ::buy(&who, pool_id, asset_id, amount, keep_alive)?; + Ok(()) + } + + /// Execute a sell order on pool. + /// + /// Emits `Swapped` event when successful. + #[pallet::weight(T::WeightInfo::sell())] + pub fn sell( + origin: OriginFor, + pool_id: T::PoolId, + asset_id: T::AssetId, + amount: T::Balance, + keep_alive: bool, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = ::sell(&who, pool_id, asset_id, amount, keep_alive)?; + Ok(()) + } + + /// Execute a specific swap operation. + /// + /// The `quote_amount` is always the quote asset amount (A/B => B), (B/A => A). + /// + /// Emits `Swapped` event when successful. + #[pallet::weight(T::WeightInfo::swap())] + pub fn swap( + origin: OriginFor, + pool_id: T::PoolId, + pair: CurrencyPair, + quote_amount: T::Balance, + min_receive: T::Balance, + keep_alive: bool, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = ::exchange( + &who, + pool_id, + pair, + quote_amount, + min_receive, + keep_alive, + )?; + Ok(()) + } + + /// Add liquidity to a stable-swap pool. + /// + /// Emits `LiquidityAdded` event when successful. + #[pallet::weight(T::WeightInfo::add_liquidity())] + pub fn add_liquidity( + origin: OriginFor, + pool_id: T::PoolId, + base_amount: T::Balance, + quote_amount: T::Balance, + min_mint_amount: T::Balance, + keep_alive: bool, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = ::add_liquidity( + &who, + pool_id, + base_amount, + quote_amount, + min_mint_amount, + keep_alive, + )?; + Ok(()) + } - impl CurveAmm for Pallet { + /// Remove liquidity from stable-swap pool. + /// + /// Emits `LiquidityRemoved` event when successful. + #[pallet::weight(T::WeightInfo::remove_liquidity())] + pub fn remove_liquidity( + origin: OriginFor, + pool_id: T::PoolId, + lp_amount: T::Balance, + min_base_amount: T::Balance, + min_quote_amount: T::Balance, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = ::remove_liquidity( + &who, + pool_id, + lp_amount, + min_base_amount, + min_quote_amount, + )?; + Ok(()) + } + } + + impl Amm for Pallet { type AssetId = T::AssetId; type Balance = T::Balance; type AccountId = T::AccountId; type PoolId = T::PoolId; - type PoolTokenIndex = T::PoolTokenIndex; - fn pool_exists(pool_id: T::PoolId) -> bool { + fn pool_exists(pool_id: Self::PoolId) -> bool { Pools::::contains_key(pool_id) } - fn pool_count() -> T::PoolId { - PoolCount::::get() + fn currency_pair( + pool_id: Self::PoolId, + ) -> Result, DispatchError> { + let pool = Self::get_pool(pool_id)?; + Ok(pool.pair) } + fn get_exchange_value( + pool_id: Self::PoolId, + asset_id: Self::AssetId, + amount: Self::Balance, + ) -> Result { + let pool = Self::get_pool(pool_id)?; + let pool_account = Self::account_id(&pool_id); + let pair = if asset_id == pool.pair.base { pool.pair } else { pool.pair.swap() }; + let pool_base_aum = T::Assets::balance(pair.base, &pool_account); + let pool_quote_aum = T::Assets::balance(pair.quote, &pool_account); + let amp = T::Convert::convert(pool.amplification_coefficient.into()); + let d = Self::get_d(pool_base_aum, pool_quote_aum, amp)?; + let new_quote_amount = pool_quote_aum.safe_add(&amount)?; + let new_base_amount = Self::get_base(new_quote_amount, amp, d)?; + let exchange_value = pool_base_aum.safe_sub(&new_base_amount)?; + Ok(exchange_value) + } + + #[transactional] + fn buy( + who: &Self::AccountId, + pool_id: Self::PoolId, + asset_id: Self::AssetId, + amount: Self::Balance, + keep_alive: bool, + ) -> Result { + let pool = Self::get_pool(pool_id)?; + let pair = if asset_id == pool.pair.base { pool.pair } else { pool.pair.swap() }; + // Since when buying asset user can't executed exchange as he don't know how much + // amount of token he has to trade-in to get expected buy tokens. + // So we compute price assuming user wants to sell instead of buy. + // And then do exchange computed amount with token indices flipped. + let dx = Self::get_exchange_value(pool_id, asset_id, amount)?; + Self::exchange(who, pool_id, pair, dx, T::Balance::zero(), keep_alive)?; + Ok(amount) + } + + #[transactional] + fn sell( + who: &Self::AccountId, + pool_id: Self::PoolId, + asset_id: Self::AssetId, + amount: Self::Balance, + keep_alive: bool, + ) -> Result { + let pool = Self::get_pool(pool_id)?; + let pair = if asset_id == pool.pair.base { pool.pair.swap() } else { pool.pair }; + let dy = Self::exchange(who, pool_id, pair, amount, Self::Balance::zero(), keep_alive)?; + Ok(dy) + } + + #[transactional] fn add_liquidity( who: &Self::AccountId, - pool_id: T::PoolId, - amounts: Vec, + pool_id: Self::PoolId, + base_amount: Self::Balance, + quote_amount: Self::Balance, min_mint_amount: Self::Balance, + keep_alive: bool, ) -> Result<(), DispatchError> { let zero = Self::Balance::zero(); - ensure!( - amounts.iter().all(|&x| x >= zero), - Error::::AssetAmountMustBePositiveNumber - ); - - let pool = Self::get_pool_info(pool_id).ok_or(Error::::PoolNotFound)?; - let pool_lp_asset = pool.lp_token; - let assets_pair = PoolAssets::::get(pool_id).ok_or(Error::::PoolNotFound)?; - let assets = assets_pair.as_slice(); - let old_balances = assets - .iter() - .map(|asset_id| { - let balance = PoolAssetBalance::::get(pool_id, asset_id); - let balance: u128 = (balance).into(); - FixedU128::saturating_from_integer(balance) - }) - .collect::>(); - - let n_coins = assets.len(); - - ensure!(assets.len() == amounts.len(), Error::::IndexOutOfRange); - - let amplification_coefficient = pool.amplification_coefficient; - let ann = Self::get_ann(amplification_coefficient, n_coins).ok_or(Error::::Math)?; - - let d0 = Self::get_d(&old_balances, ann).ok_or(Error::::Math)?; - - let token_supply = T::LpToken::total_issuance(pool_lp_asset); - let token_supply_u: u128 = token_supply.into(); - let token_supply_f = FixedU128::saturating_from_integer(token_supply_u); - - let mut new_balances = old_balances - .iter() - .zip(&amounts) - .map(|(balance, amount)| -> Result<_, _> { - if token_supply == zero { - ensure!(amount > &zero, Error::::AssetAmountMustBePositiveNumber); - } - balance - .checked_add(&FixedU128::saturating_from_integer(*amount)) - .ok_or(Error::::Math) - }) - .collect::, _>>()?; - - let d1 = Self::get_d(&new_balances, ann).ok_or(Error::::Math)?; + ensure!(base_amount > zero, Error::::AssetAmountMustBePositiveNumber); + ensure!(quote_amount > zero, Error::::AssetAmountMustBePositiveNumber); + // pool supports only 2 assets + let pool = Self::get_pool(pool_id)?; + let pool_account = Self::account_id(&pool_id); + let pool_base_aum = T::Assets::balance(pool.pair.base, &pool_account); + let pool_quote_aum = T::Assets::balance(pool.pair.quote, &pool_account); + + let lp_issued = T::Assets::total_issuance(pool.lp_token); + let amp = T::Convert::convert(pool.amplification_coefficient.into()); + let d0 = Self::get_d(pool_base_aum, pool_quote_aum, amp)?; + let new_base_amount = pool_base_aum.safe_add(&base_amount)?; + let new_quote_amount = pool_quote_aum.safe_add("e_amount)?; + let d1 = Self::get_d(new_base_amount, new_quote_amount, amp)?; ensure!(d1 > d0, Error::::AssetAmountMustBePositiveNumber); - let d1_b = d1.checked_mul_int(1_u64).ok_or(Error::::Math)?.into(); - let mut fees = vec![FixedU128::zero(); n_coins]; - - // Only account for fees if we are not the first to deposit - let mint_amount: ::Balance = if token_supply > zero { - // Deposit x + withdraw y would charge about same + let (mint_amount, base_protocol_fee, quote_protocol_fee) = if lp_issued > zero { + // Deposit x + withdraw y sould charge about same // fees as a swap. Otherwise, one could exchange w/o paying fees. // And this formula leads to exactly that equality // fee = pool.fee * n_coins / (4 * (n_coins - 1)) - let one = FixedU128::saturating_from_integer(1_u8); - let four = FixedU128::saturating_from_integer(4_u8); - let n_coins_f = FixedU128::saturating_from_integer(n_coins as u128); - let fee_f: FixedU128 = pool.fee.into(); - let fee_f = fee_f - .checked_mul(&n_coins_f) - .ok_or(Error::::Math)? - .checked_div( - &four - .checked_mul(&n_coins_f.checked_sub(&one).ok_or(Error::::Math)?) - .ok_or(Error::::Math)?, - ) - .ok_or(Error::::Math)?; - let admin_fee_f: FixedU128 = pool.admin_fee.into(); - - for (((asset_id, &old_balance), new_balance), fee) in assets - .iter() - .zip(&old_balances) - .zip(new_balances.iter_mut()) - .zip(fees.iter_mut()) - { - // ideal_balance = d1 * old_balances[i] / d0 - let ideal_balance = d1 - .checked_mul(&old_balance) - .map(|x| x.checked_div(&d0)) - .flatten() - .ok_or(Error::::Math)?; - - // difference = abs(ideal_balance - new_balance) - let difference = if ideal_balance > *new_balance { - ideal_balance.checked_sub(&new_balance) - } else { - new_balance.checked_sub(&ideal_balance) - } - .ok_or(Error::::Math)?; - - *fee = fee_f.checked_mul(&difference).ok_or(Error::::Math)?; - - // new_pool_balance = new_balance - (fees[i] * admin_fee) - let new_pool_balance = new_balance - .checked_sub(&fee.checked_mul(&admin_fee_f).ok_or(Error::::Math)?) - .ok_or(Error::::Math)?; - - PoolAssetBalance::::mutate( - pool_id, - asset_id, - |balance| -> DispatchResult { - *balance = new_pool_balance - .checked_mul_int(1_u64) - .ok_or(Error::::Math)? - .into(); - Ok(()) - }, - )?; - - *new_balance = new_balance.checked_sub(&fee).ok_or(Error::::Math)?; - } - - let d2 = Self::get_d(&new_balances, ann).ok_or(Error::::Math)?; - - // mint_amount = token_supply * (d2 - d0) / d0 - token_supply_f - .checked_mul( - &d2.checked_sub(&d0) - .ok_or(Error::::Math)? - .checked_div(&d0) - .ok_or(Error::::Math)?, - ) - .ok_or(Error::::Math)? - .checked_mul_int(1_u64) - .ok_or(Error::::Math)? - .into() + // pool supports only two coins. + let share: Permill = Permill::from_rational(2_u32, 4_u32); + let fee = pool.fee.mul(share); + + let ideal_base_balance = T::Convert::convert(safe_multiply_by_rational( + T::Convert::convert(d1), + T::Convert::convert(pool_base_aum), + T::Convert::convert(d0), + )?); + let ideal_quote_balance = T::Convert::convert(safe_multiply_by_rational( + T::Convert::convert(d1), + T::Convert::convert(pool_quote_aum), + T::Convert::convert(d0), + )?); + + let base_difference = Self::abs_difference(ideal_base_balance, new_base_amount)?; + let quote_difference = Self::abs_difference(ideal_quote_balance, new_quote_amount)?; + + let base_fee = fee.mul_floor(T::Convert::convert(base_difference)); + let quote_fee = fee.mul_floor(T::Convert::convert(quote_difference)); + let base_protocol_fee = T::Convert::convert(pool.protocol_fee.mul_floor(base_fee)); + let quote_protocol_fee = + T::Convert::convert(pool.protocol_fee.mul_floor(quote_fee)); + let base_fee = T::Convert::convert(base_fee); + let quote_fee = T::Convert::convert(quote_fee); + let new_base_balance = new_base_amount.safe_sub(&base_fee)?; + let new_quote_balance = new_quote_amount.safe_sub("e_fee)?; + + let d2 = Self::get_d(new_base_balance, new_quote_balance, amp)?; + let mint_amount = T::Convert::convert(safe_multiply_by_rational( + T::Convert::convert(lp_issued), + T::Convert::convert(d2.safe_sub(&d0)?), + T::Convert::convert(d0), + )?); + (mint_amount, base_protocol_fee, quote_protocol_fee) } else { - for (asset_id, new_balance) in assets.iter().zip(&new_balances) { - PoolAssetBalance::::mutate( - pool_id, - asset_id, - |balance| -> DispatchResult { - *balance = - new_balance.checked_mul_int(1_u64).ok_or(Error::::Math)?.into(); - Ok(()) - }, - )?; - } - d1_b + (d1, T::Balance::zero(), T::Balance::zero()) }; - ensure!(mint_amount >= min_mint_amount, Error::::RequiredAmountNotReached); - - let new_token_supply = - token_supply.checked_add(&mint_amount).ok_or(Error::::Math)?; - - // Ensure that for all tokens user has sufficient amount - for (amount, asset) in amounts.iter().zip(assets) { - ensure!(T::LpToken::balance(*asset, who) >= *amount, Error::::InsufficientFunds); - } + ensure!(mint_amount >= min_mint_amount, Error::::CannotRespectMinimumRequested); + + T::Assets::transfer(pool.pair.base, who, &pool_account, base_amount, keep_alive)?; + T::Assets::transfer(pool.pair.quote, who, &pool_account, quote_amount, keep_alive)?; + // owner's fee is transferred upfront. + T::Assets::transfer( + pool.pair.base, + &pool_account, + &pool.owner, + base_protocol_fee, + keep_alive, + )?; + T::Assets::transfer( + pool.pair.quote, + &pool_account, + &pool.owner, + quote_protocol_fee, + keep_alive, + )?; + T::Assets::mint_into(pool.lp_token, who, mint_amount)?; - // Transfer funds to pool - for (i, amount) in amounts.iter().enumerate() { - if amount > &zero { - Self::transfer_liquidity_into_pool( - &Self::account_id(&pool_id), - pool_id, - who, - i, - *amount, - )?; - } - } - - T::LpToken::mint_into(pool_lp_asset, who, mint_amount)?; - let fees: Vec = fees - .iter() - .map(|b_f| Ok(b_f.checked_mul_int(1_u64).ok_or(Error::::Math)?.into())) - .collect::, Error>>()?; - - Self::deposit_event(Event::LiquidityAdded { + Self::deposit_event(Event::::LiquidityAdded { who: who.clone(), pool_id, - token_amounts: amounts, - fees, - invariant: d1_b, - token_supply: new_token_supply, + base_amount, + quote_amount, mint_amount, }); - Ok(()) } + // NOTE: This function does not charge fees as it does not impact pool's invariant in + // imbalanced way. + #[transactional] fn remove_liquidity( who: &Self::AccountId, - pool_id: T::PoolId, - amount: Self::Balance, - min_amounts: Vec, + pool_id: Self::PoolId, + lp_amount: Self::Balance, + min_base_amount: Self::Balance, + min_quote_amount: Self::Balance, ) -> Result<(), DispatchError> { - let zero = FixedU128::zero(); - let b_zero = Self::Balance::zero(); + let pool = Self::get_pool(pool_id)?; + + let pool_account = Self::account_id(&pool_id); + let pool_base_aum = T::Assets::balance(pool.pair.base, &pool_account); + let pool_quote_aum = T::Assets::balance(pool.pair.quote, &pool_account); + let lp_issued = T::Assets::total_issuance(pool.lp_token); + let base_amount = T::Convert::convert(safe_multiply_by_rational( + T::Convert::convert(lp_amount), + T::Convert::convert(pool_base_aum), + T::Convert::convert(lp_issued), + )?); + let quote_amount = T::Convert::convert(safe_multiply_by_rational( + T::Convert::convert(lp_amount), + T::Convert::convert(pool_quote_aum), + T::Convert::convert(lp_issued), + )?); - ensure!(amount >= b_zero, Error::::AssetAmountMustBePositiveNumber); + ensure!( + base_amount >= min_base_amount && quote_amount >= min_quote_amount, + Error::::CannotRespectMinimumRequested + ); - let amount_f = { - let amount_u: u128 = amount.into(); - FixedU128::saturating_from_integer(amount_u) - }; + let total_issuance = lp_issued.safe_sub(&lp_amount)?; - let min_amounts_f: Vec = min_amounts - .iter() - .map(|balance| { - let balance: u128 = (*balance).into(); - FixedU128::saturating_from_integer(balance) - }) - .collect(); - - let pool = Self::get_pool_info(pool_id).ok_or(Error::::PoolNotFound)?; - let pool_lp_asset = pool.lp_token; - let assets_pair = PoolAssets::::get(pool_id).ok_or(Error::::PoolNotFound)?; - let assets = assets_pair.as_slice(); - let balances: Vec<::Balance> = assets - .iter() - .copied() - .map(|asset_id| PoolAssetBalance::::get(pool_id, asset_id)) - .collect(); - - ensure!(assets.len() == min_amounts.len(), Error::::IndexOutOfRange); - - let token_supply = T::LpToken::total_issuance(pool_lp_asset); - let token_supply_u: u128 = token_supply.into(); - - let amounts_f = assets - .iter() - .zip(balances) - .zip(min_amounts_f) - .map( - |((asset_id, old_balance), min_amount_f)| -> Result { - let old_balance = { - let old_balance: u128 = old_balance.into(); - FixedU128::saturating_from_integer(old_balance) - }; - // value = old_balance * n_amount / token_supply - let value = old_balance - .checked_mul(&amount_f) - .ok_or(Error::::Math)? - .checked_div(&FixedU128::saturating_from_integer(token_supply_u)) - .ok_or(Error::::Math)?; - - ensure!(value >= min_amount_f, Error::::RequiredAmountNotReached); - - PoolAssetBalance::::mutate( - pool_id, - asset_id, - |balance| -> DispatchResult { - *balance = old_balance - .checked_sub(&value) - .ok_or(Error::::InsufficientFunds)? - .checked_mul_int(1_u64) - .ok_or(Error::::Math)? - .into(); - Ok(()) - }, - )?; - Ok(value) - }, - ) - .collect::, _>>()?; - - let amounts: Vec = amounts_f - .iter() - .map(|b_f| b_f.checked_mul_int(1_u64).ok_or(Error::::Math).map(T::Balance::from)) - .collect::, Error>>()?; - - let new_token_supply = token_supply.checked_sub(&amount).ok_or(Error::::Math)?; - - let fees = vec![T::Balance::zero(); assets.len()]; - - T::LpToken::burn_from(pool_lp_asset, who, amount)?; - - // Ensure that for all tokens we have sufficient amount - for (asset_id, amount) in assets.iter().zip(&amounts) { - ensure!( - T::LpToken::balance(*asset_id, &Self::account_id(&pool_id)) >= *amount, - Error::::InsufficientFunds - ); - } - - for (index, (amount_f, amount)) in amounts_f.iter().zip(&amounts).enumerate() { - if amount_f > &zero { - Self::transfer_liquidity_from_pool( - &Self::account_id(&pool_id), - pool_id, - index, - who, - *amount, - )?; - } - } - - Self::deposit_event(Event::LiquidityRemoved { - who: who.clone(), + // NOTE(hussein-aitlance): no need to keep alive the pool account + T::Assets::transfer(pool.pair.base, &pool_account, who, base_amount, false)?; + T::Assets::transfer(pool.pair.quote, &pool_account, who, quote_amount, false)?; + T::Assets::burn_from(pool.lp_token, who, lp_amount)?; + Self::deposit_event(Event::::LiquidityRemoved { pool_id, - token_amounts: amounts, - fees, - token_supply: new_token_supply, + who: who.clone(), + base_amount, + quote_amount, + total_issuance, }); - Ok(()) } + #[transactional] fn exchange( who: &Self::AccountId, - pool_id: T::PoolId, - i_token: T::PoolTokenIndex, - j_token: T::PoolTokenIndex, - dx: Self::Balance, - min_dy: Self::Balance, + pool_id: Self::PoolId, + pair: CurrencyPair, + quote_amount: Self::Balance, + min_receive: Self::Balance, + keep_alive: bool, ) -> Result { - let prec = T::Precision::get(); - let zero_b = Self::Balance::zero(); - ensure!(dx >= zero_b, Error::::AssetAmountMustBePositiveNumber); - - let pool = Self::get_pool_info(pool_id).ok_or(Error::::PoolNotFound)?; - let i = i_token.into() as usize; - let j = j_token.into() as usize; - - let assets_pair = PoolAssets::::get(pool_id).ok_or(Error::::PoolNotFound)?; - let assets = assets_pair.as_slice(); - let mut balances = Vec::new(); - for asset_id in assets { - balances.push(PoolAssetBalance::::get(pool_id, asset_id)); - } - let n_coins = assets.len(); - - ensure!(i < n_coins && j < n_coins, Error::::IndexOutOfRange); - - let dx_u: u128 = dx.into(); - let dx_f = FixedU128::saturating_from_integer(dx_u); - let min_dy_u: u128 = min_dy.into(); - let min_dy_f = FixedU128::saturating_from_integer(min_dy_u); - - let xp: Vec = balances - .iter() - .map(|b| { - let b_u: u128 = (*b).into(); - FixedU128::saturating_from_integer(b_u) - }) - .collect(); - - // xp[i] + dx - let xp_i = xp.get(i).ok_or(Error::::InconsistentStorage)?; - let x = xp_i.checked_add(&dx_f).ok_or(Error::::Math)?; - - let amp_f = pool.amplification_coefficient; - let ann = Self::get_ann(amp_f, n_coins).ok_or(Error::::Math)?; - let y = Self::get_y(i, j, x, &xp, ann).ok_or(Error::::Math)?; - - // -1 just in case there were some rounding errors - // dy = xp[j] - y - 1 - let xp_j = xp.get(j).ok_or(Error::::InconsistentStorage)?; - let dy_f = xp_j - .checked_sub(&y) - .ok_or(Error::::Math)? - .checked_sub(&prec) - .ok_or(Error::::Math)?; - - let fee_f: FixedU128 = pool.fee.into(); - let dy_fee_f = dy_f.checked_mul(&fee_f).ok_or(Error::::Math)?; - let dy_fee = dy_fee_f.checked_mul_int(1_u64).ok_or(Error::::Math)?.into(); - let dy_f = dy_f.checked_sub(&dy_fee_f).ok_or(Error::::Math)?; - ensure!(dy_f >= min_dy_f, Error::::RequiredAmountNotReached); - - let admin_fee_f: FixedU128 = pool.admin_fee.into(); - let dy_admin_fee_f = dy_fee_f.checked_mul(&admin_fee_f).ok_or(Error::::Math)?; - let dy: Self::Balance = dy_f.checked_mul_int(1_u64).ok_or(Error::::Math)?.into(); - let asset_id_i = assets.get(i).ok_or(Error::::InconsistentStorage)?; - let asset_id_j = assets.get(j).ok_or(Error::::InconsistentStorage)?; - PoolAssetBalance::::mutate(pool_id, asset_id_i, |balance| -> DispatchResult { - *balance = x.checked_mul_int(1_u64).ok_or(Error::::Math)?.into(); - Ok(()) - })?; - // When rounding errors happen, we undercharge admin fee in favor of LP - let bal_j = xp_j - .checked_sub(&dy_f) - .ok_or(Error::::Math)? - .checked_sub(&dy_admin_fee_f) - .ok_or(Error::::Math)?; - PoolAssetBalance::::mutate(pool_id, asset_id_j, |balance| -> DispatchResult { - *balance = bal_j.checked_mul_int(1_u64).ok_or(Error::::Math)?.into(); - Ok(()) - })?; - - ensure!(T::LpToken::balance(*asset_id_i, &who) >= dx, Error::::InsufficientFunds); + let pool = Self::get_pool(pool_id)?; + // /!\ NOTE(hussein-aitlahcen): after this check, do not use pool.pair as the provided + // pair might have been swapped + ensure!(pair == pool.pair, Error::::PairMismatch); + let (base_amount_excluding_fees, quote_amount, lp_fees, protocol_fees) = + Self::do_compute_swap(pool_id, pair, quote_amount, true)?; ensure!( - T::LpToken::balance(*asset_id_j, &Self::account_id(&pool_id)) >= dy, - Error::::InsufficientFunds + base_amount_excluding_fees >= min_receive, + Error::::CannotRespectMinimumRequested ); + let pool_account = Self::account_id(&pool_id); + T::Assets::transfer(pair.quote, who, &pool_account, quote_amount, keep_alive)?; - Self::transfer_liquidity_into_pool(&Self::account_id(&pool_id), pool_id, &who, i, dx)?; - Self::transfer_liquidity_from_pool(&Self::account_id(&pool_id), pool_id, j, &who, dy)?; - - Self::deposit_event(Event::TokenExchanged { - who: who.clone(), + // NOTE(hussein-aitlance): no need to keep alive the pool account + T::Assets::transfer(pair.base, &pool_account, &pool.owner, protocol_fees, false)?; + T::Assets::transfer(pair.base, &pool_account, who, base_amount_excluding_fees, false)?; + Self::deposit_event(Event::::Swapped { pool_id, - sent_token_index: i_token, - sent_amount: dx, - received_token_index: j_token, - received_amount: dy, - fee: dy_fee, - }); - Ok(dy) - } - - fn withdraw_admin_fees( - who: &Self::AccountId, - pool_id: T::PoolId, - admin_fee_account: &Self::AccountId, - ) -> Result<(), DispatchError> { - let assets_pair = PoolAssets::::get(pool_id).ok_or(Error::::PoolNotFound)?; - let assets = assets_pair.as_slice(); - let mut balances = Vec::new(); - for asset_id in assets { - balances.push(PoolAssetBalance::::get(pool_id, asset_id)); - } - let mut total_balances = Vec::new(); - for asset_id in assets { - total_balances.push(PoolAssetTotalBalance::::get(pool_id, asset_id)); - } - let n_coins = assets.len(); - - ensure!(n_coins == balances.len(), Error::::InconsistentStorage); - - let admin_fees = total_balances - .iter() - .zip(balances) - .map(|(tb, b)| { - let admin_fee = tb.checked_sub(&b).ok_or(Error::::Math)?; - - Ok(admin_fee) - }) - .collect::, DispatchError>>()?; - - let assets = assets.clone(); - - for ((asset_id, total_balance), admin_fee) in - assets.iter().zip(&total_balances).zip(&admin_fees) - { - let new_total_balance = - total_balance.checked_sub(&admin_fee).ok_or(Error::::Math)?; - PoolAssetTotalBalance::::mutate( - pool_id, - asset_id, - |total_balance| -> DispatchResult { - *total_balance = new_total_balance; - Ok(()) - }, - )?; - } - - for (asset, amount) in assets.into_iter().zip(admin_fees.iter().copied()) { - T::LpToken::transfer( - *asset, - &Self::account_id(&pool_id), - admin_fee_account, - amount, - true, - )?; - } - - Self::deposit_event(Event::AdminFeesWithdrawn { who: who.clone(), - pool_id, - admin_fee_account: admin_fee_account.clone(), - admin_fees, + base_asset: pair.base, + quote_asset: pair.quote, + base_amount: base_amount_excluding_fees, + quote_amount, + fee: lp_fees.safe_add(&protocol_fees)?, }); - Ok(()) + Ok(base_amount_excluding_fees) } } impl Pallet { - pub fn create_pool( + #[transactional] + pub fn do_create_pool( who: &T::AccountId, - assets: Vec, - amplification_coefficient: FixedU128, + pair: CurrencyPair, + amplification_coefficient: u16, fee: Permill, - admin_fee: Permill, + protocol_fee: Permill, ) -> Result { - // Assets related checks - ensure!(assets.len() > 1, Error::::NotEnoughAssets); - let unique_assets = BTreeSet::::from_iter(assets.iter().copied()); - ensure!(unique_assets.len() == assets.len(), Error::::DuplicateAssets); + ensure!(amplification_coefficient > 0, Error::::AmpFactorMustBeGreaterThanZero); + ensure!(pair.base != pair.quote, Error::::InvalidPair); + let total_fees = fee.checked_add(&protocol_fee).ok_or(ArithmeticError::Overflow)?; + ensure!(total_fees < Permill::one(), Error::::InvalidFees); + + let lp_token = T::CurrencyFactory::create(RangeId::LP_TOKENS)?; // Add new pool let pool_id = PoolCount::::try_mutate(|pool_count| -> Result { let pool_id = *pool_count; - Pools::::try_mutate_exists(pool_id, |maybe_pool_info| -> DispatchResult { - // We expect that PoolInfos have sequential keys. - // No PoolInfo can have key greater or equal to PoolCount - ensure!(maybe_pool_info.is_none(), Error::::InconsistentStorage); - let lp_asset = T::CurrencyFactory::reserve_lp_token_id()?; - - *maybe_pool_info = Some(StableSwapPoolInfo { + Pools::::insert( + pool_id, + StableSwapPoolInfo { owner: who.clone(), - lp_token: lp_asset, + pair, + lp_token, amplification_coefficient, fee, - admin_fee, - }); - - Ok(()) - })?; - - for asset_id in &assets { - PoolAssetBalance::::insert(pool_id, asset_id, T::Balance::zero()); - PoolAssetTotalBalance::::insert(pool_id, asset_id, T::Balance::zero()); - } - - PoolAssets::::try_mutate(pool_id, |pool_assets| -> DispatchResult { - ensure!(pool_assets.is_none(), Error::::InconsistentStorage); - *pool_assets = Some(CurrencyPair::new( - *assets.get(0).ok_or(Error::::IndexOutOfRange)?, - *assets.get(1).ok_or(Error::::IndexOutOfRange)?, - )); - Ok(()) - })?; - - *pool_count = pool_id - .checked_add(&T::PoolId::one()) - .ok_or(Error::::InconsistentStorage)?; - + protocol_fee, + }, + ); + *pool_count = pool_id.safe_add(&T::PoolId::one())?; Ok(pool_id) })?; @@ -831,291 +640,76 @@ pub mod pallet { } /// Return pool information for given pool_id. - pub fn get_pool_info( - pool_id: T::PoolId, - ) -> Option> { - Pools::::get(pool_id) + pub(crate) fn get_pool(pool_id: T::PoolId) -> Result, DispatchError> { + Pools::::get(pool_id).ok_or_else(|| Error::::PoolNotFound.into()) } - /// Find `ann = amp * n^n` where `amp` - amplification coefficient, - /// `n` - number of coins. - pub fn get_ann(amp: FixedU128, n: usize) -> Option { - let n_coins = FixedU128::saturating_from_integer(n as u128); - let mut ann = amp; - for _ in 0..n { - ann = ann.checked_mul(&n_coins)?; - } - Some(ann) - } - /// Find `d` preserving StableSwap invariant. - /// Here `d` - total amount of coins when they have an equal price, - /// `xp` - coin amounts, `ann` is amplification coefficient multiplied by `n^n`, - /// where `n` is number of coins. - /// - /// # Notes - /// - /// D invariant calculation in non-overflowing integer operations iteratively - /// - /// ```pseudocode - /// A * sum(x_i) * n^n + D = A * D * n^n + D^(n+1) / (n^n * prod(x_i)) - /// ``` - /// - /// Converging solution: - /// - /// ```pseudocode - /// D[j + 1] = (A * n^n * sum(x_i) - D[j]^(n+1) / (n^n * prod(x_i))) / (A * n^n - 1) - /// ``` - pub fn get_d(xp_f: &[FixedU128], ann_f: FixedU128) -> Option { - let zero = FixedU128::zero(); - let one = FixedU128::one(); - let prec = T::Precision::get(); - let n = FixedU128::saturating_from_integer(u128::try_from(xp_f.len()).ok()?); - let sum = xp_f.iter().try_fold(zero, |s, x| s.checked_add(x))?; - if sum == zero { - return Some(zero) - } - let mut d = sum; - - for _ in 0..255 { - let mut d_p = d; - for x in xp_f.iter() { - // d_p = d_p * d / (x * n) - d_p = d_p.checked_mul(&d)?.checked_div(&x.checked_mul(&n)?)?; - } - let d_prev = d; - // d = (ann * sum + d_p * n) * d / ((ann - 1) * d + (n + 1) * d_p) - d = ann_f.checked_mul(&sum)?.checked_add(&d_p.checked_mul(&n)?)?.checked_mul( - &d.checked_div( - &ann_f - .checked_sub(&one)? - .checked_mul(&d)? - .checked_add(&n.checked_add(&one)?.checked_mul(&d_p)?)?, - )?, - )?; - - if d > d_prev { - if d.checked_sub(&d_prev)? <= prec { - return Some(d) - } - } else if d_prev.checked_sub(&d)? <= prec { - return Some(d) - } - } - None - } - - /// Here `xp` - coin amounts, `ann` is amplification coefficient multiplied by `n^n`, where - /// `n` is number of coins. - /// - /// See https://github.com/equilibrium-eosdt/equilibrium-curve-amm/blob/master/docs/deducing-get_y-formulas.pdf - /// for detailed explanation about formulas this function uses. - /// - /// # Notes - /// - /// Done by solving quadratic equation iteratively. - /// - /// ```pseudocode - /// x_1^2 + x_1 * (sum' - (A * n^n - 1) * D / (A * n^n)) = D^(n+1) / (n^2n * prod' * A) - /// x_1^2 + b * x_1 = c - /// - /// x_1 = (x_1^2 + c) / (2 * x_1 + b) - /// ``` - pub fn get_y( - i: usize, - j: usize, - x_f: FixedU128, - xp_f: &[FixedU128], - ann_f: FixedU128, - ) -> Option { - let zero = FixedU128::zero(); - let prec = T::Precision::get(); - let two = FixedU128::saturating_from_integer(2_u8); - let n = FixedU128::try_from(xp_f.len() as u128).ok()?; - - // Same coin - if i == j { - return None - } - // j above n - if j >= xp_f.len() { - return None - } - if i >= xp_f.len() { - return None - } - let d_f = Self::get_d(xp_f, ann_f)?; - let mut c = d_f; - let mut s = zero; - - // Calculate s and c - // p is implicitly calculated as part of c - // note that loop makes n - 1 iterations - for (k, xp_k) in xp_f.iter().enumerate() { - let x_k: FixedU128; - if k == i { - x_k = x_f; - } else if k != j { - x_k = *xp_k; - } else { - continue - } - // s = s + x_k - s = s.checked_add(&x_k)?; - // c = c * d / (x_k * n) - c = c.checked_mul(&d_f)?.checked_div(&x_k.checked_mul(&n)?)?; - } - // c = c * d / (ann * n) - // At this step we have d^n in the numerator of c - // and n^(n-1) in its denominator. - // So we multiplying it by remaining d/n - c = c.checked_mul(&d_f)?.checked_div(&ann_f.checked_mul(&n)?)?; - - // b = s + d / ann - // We subtract d later - let b = s.checked_add(&d_f.checked_div(&ann_f)?)?; - let mut y = d_f; - - for _ in 0..255 { - let y_prev = y; - // y = (y^2 + c) / (2 * y + b - d) - // Subtract d to calculate b finally - y = y - .checked_mul(&y)? - .checked_add(&c)? - .checked_div(&two.checked_mul(&y)?.checked_add(&b)?.checked_sub(&d_f)?)?; - - // Equality with the specified precision - if y > y_prev { - if y.checked_sub(&y_prev)? <= prec { - return Some(y) - } - } else if y_prev.checked_sub(&y)? <= prec { - return Some(y) - } - } - - None - } - /// Here `xp` - coin amounts, `ann` is amplification coefficient multiplied by `n^n`, where - /// `n` is number of coins. - /// Calculate `x[i]` if one reduces `d` from being calculated for `xp` to `d`. - /// - /// # Notes - /// - /// Done by solving quadratic equation iteratively. - /// - /// ```pseudocode - /// x_1^2 + x_1 * (sum' - (A * n^n - 1) * D / (A * n^n)) = D^(n+1) / (n^2n * prod' * A) - /// x_1^2 + b * x_1 = c - /// - /// x_1 = (x_1^2 + c) / (2 * x_1 + b) - /// ``` - pub fn get_y_d( - i: usize, - d_f: FixedU128, - xp_f: &[FixedU128], - ann_f: FixedU128, - ) -> Option { - let zero = FixedU128::zero(); - let prec = T::Precision::get(); - let two = FixedU128::saturating_from_integer(2_u8); - let n = FixedU128::try_from(xp_f.len() as u128).ok()?; - - if i >= xp_f.len() { - return None - } - - let mut c = d_f; - let mut s = zero; - - for (k, xp_k) in xp_f.iter().enumerate() { - if k == i { - continue - } - - let x = xp_k; - - s = s.checked_add(x)?; - // c = c * d / (x * n) - c = c.checked_mul(&d_f)?.checked_div(&x.checked_mul(&n)?)?; - } - // c = c * d / (ann * n) - c = c.checked_mul(&d_f)?.checked_div(&ann_f.checked_mul(&n)?)?; - // b = s + d / ann - let b = s.checked_add(&d_f.checked_div(&ann_f)?)?; - let mut y = d_f; - - for _ in 0..255 { - let y_prev = y; - // y = (y*y + c) / (2 * y + b - d) - y = y - .checked_mul(&y)? - .checked_add(&c)? - .checked_div(&two.checked_mul(&y)?.checked_add(&b)?.checked_sub(&d_f)?)?; - - // Equality with the specified precision - if y > y_prev { - if y.checked_sub(&y_prev)? <= prec { - return Some(y) - } - } else if y_prev.checked_sub(&y)? <= prec { - return Some(y) - } - } - - None + /// Account of a pool + pub(crate) fn account_id(pool_id: &T::PoolId) -> T::AccountId { + T::PalletId::get().into_sub_account(pool_id) } - fn transfer_liquidity_into_pool( - pool_account_id: &T::AccountId, - pool_id: T::PoolId, - source: &T::AccountId, - destination_asset_index: usize, - amount: T::Balance, - ) -> DispatchResult { - let assets_pair = PoolAssets::::get(pool_id).ok_or(Error::::PoolNotFound)?; - let assets = assets_pair.as_slice(); - let asset_id = - assets.get(destination_asset_index).ok_or(Error::::IndexOutOfRange)?; - T::LpToken::transfer(*asset_id, source, pool_account_id, amount, true)?; - PoolAssetTotalBalance::::mutate( - pool_id, - asset_id, - |total_balance| -> DispatchResult { - *total_balance = total_balance.checked_add(&amount).ok_or(Error::::Math)?; - Ok(()) - }, + pub fn get_d( + base_asset_aum: T::Balance, + quote_asset_aum: T::Balance, + amp_coeff: T::Balance, + ) -> Result { + let d = compute_d( + T::Convert::convert(base_asset_aum), + T::Convert::convert(quote_asset_aum), + T::Convert::convert(amp_coeff), )?; - Ok(()) + Ok(T::Convert::convert(d)) } - fn transfer_liquidity_from_pool( - pool_account_id: &T::AccountId, - pool_id: T::PoolId, - source_asset_index: usize, - destination: &T::AccountId, - amount: T::Balance, - ) -> DispatchResult { - let assets_pair = PoolAssets::::get(pool_id).ok_or(Error::::PoolNotFound)?; - let assets = assets_pair.as_slice(); - let asset_id = assets.get(source_asset_index).ok_or(Error::::IndexOutOfRange)?; - T::LpToken::transfer(*asset_id, pool_account_id, destination, amount, true)?; - - PoolAssetTotalBalance::::mutate( - pool_id, - asset_id, - |total_balance| -> DispatchResult { - *total_balance = total_balance.checked_sub(&amount).ok_or(Error::::Math)?; - Ok(()) - }, + pub fn get_base( + new_quote: T::Balance, + amp_coeff: T::Balance, + d: T::Balance, + ) -> Result { + let base = compute_base( + T::Convert::convert(new_quote), + T::Convert::convert(amp_coeff), + T::Convert::convert(d), )?; + Ok(T::Convert::convert(base)) + } - Ok(()) + fn abs_difference( + new_balance: T::Balance, + old_balance: T::Balance, + ) -> Result { + let difference = if old_balance > new_balance { + old_balance.safe_sub(&new_balance) + } else { + new_balance.safe_sub(&old_balance) + }?; + Ok(difference) } - pub fn account_id(pool_id: &T::PoolId) -> T::AccountId { - T::PalletId::get().into_sub_account(pool_id) + pub(crate) fn do_compute_swap( + pool_id: T::PoolId, + pair: CurrencyPair, + quote_amount: T::Balance, + apply_fees: bool, + ) -> Result<(T::Balance, T::Balance, T::Balance, T::Balance), DispatchError> { + let pool = Self::get_pool(pool_id)?; + let base_amount = Self::get_exchange_value(pool_id, pair.base, quote_amount)?; + let base_amount_u: u128 = T::Convert::convert(base_amount); + + let (lp_fee, protocol_fee) = if apply_fees { + let lp_fee = pool.fee.mul_floor(base_amount_u); + let protocol_fee = pool.protocol_fee.mul_floor(lp_fee); + let lp_fee = T::Convert::convert(lp_fee); + let protocol_fee = T::Convert::convert(protocol_fee); + (lp_fee, protocol_fee) + } else { + (T::Balance::zero(), T::Balance::zero()) + }; + + let base_amount_excluding_fees = base_amount.safe_sub(&lp_fee)?; + Ok((base_amount_excluding_fees, quote_amount, lp_fee, protocol_fee)) } } } diff --git a/frame/curve-amm/src/maths.rs b/frame/curve-amm/src/maths.rs new file mode 100644 index 00000000000..c140a24fe5d --- /dev/null +++ b/frame/curve-amm/src/maths.rs @@ -0,0 +1,136 @@ +use sp_runtime::{biguint::BigUint, helpers_128bit::to_big_uint, ArithmeticError, DispatchError}; + +fn safe_div(a: &mut BigUint, b: &mut BigUint) -> Result { + a.lstrip(); + b.lstrip(); + let a = a.clone(); + if b.len() == 1 { + return Ok(a.div_unit(b.get(0))) + } + let div = a.div(b, false).ok_or(ArithmeticError::Overflow)?; + Ok(div.0) +} + +/// # Notes +/// +/// D invariant calculation in non-overflowing integer operations iteratively +/// +/// ```pseudocode +/// A * sum(x_i) * n^n + D = A * D * n^n + D^(n+1) / (n^n * prod(x_i)) +/// ``` +/// +/// Converging solution: +/// +/// ```pseudocode +/// D[j + 1] = (A * n^n * sum(x_i) - D[j]^(n+1) / (n^n * prod(x_i))) / (A * n^n - 1) +/// ``` +/// For two assets, n = 2 used while computation +pub fn compute_d( + base_asset_aum: u128, + quote_asset_aum: u128, + amp_coeff: u128, +) -> Result { + let base_asset_amount = to_big_uint(base_asset_aum); + let quote_asset_amount = to_big_uint(quote_asset_aum); + let amplification_coefficient = to_big_uint(amp_coeff); + // pool has only 2 assets + let n = to_big_uint(2_u128); + let zero = to_big_uint(0_u128); + let one = to_big_uint(1_u128); + + let sum = base_asset_amount.clone().add("e_asset_amount); + if sum == zero { + return Ok(0_u128) + } + let ann = amplification_coefficient.mul(&n).mul(&n); + let mut d = sum.clone(); + + let mut base_n = base_asset_amount.mul(&n); + let mut quote_n = quote_asset_amount.mul(&n); + for _ in 0..255 { + let mut d_p = d.clone(); + let ann_d = ann.clone().mul(&d); + // d_p = d_p * d / (x * n) + + let mut d_p_d = d_p.mul(&d); + d_p = safe_div(&mut d_p_d, &mut base_n)?; + let mut d_p_d = d_p.mul(&d); + d_p = safe_div(&mut d_p_d, &mut quote_n)?; + + let d_prev = d.clone(); + // d = (ann * sum + d_p * n) * d / (ann * d + (n + 1) * d_p - d) + let mut numerator = ann.clone().mul(&sum).add(&d_p.clone().mul(&n)).mul(&d); + let mut denominator = ann_d + .add(&n.clone().add(&one).mul(&d_p)) + .sub(&d) + .map_err(|_| ArithmeticError::Underflow)?; + d = safe_div(&mut numerator, &mut denominator)?; + + if d.clone() > d_prev { + if d.clone() - d_prev <= one { + d.lstrip(); + return Ok(d.try_into().map_err(|_| ArithmeticError::Overflow)?) + } + } else if d_prev - d.clone() <= one { + d.lstrip(); + return Ok(d.try_into().map_err(|_| ArithmeticError::Overflow)?) + } + } + Err(DispatchError::Other("could not compute d")) +} + +/// See https://github.com/equilibrium-eosdt/equilibrium-curve-amm/blob/master/docs/deducing-get_y-formulas.pdf +/// for detailed explanation about formulas this function uses. +/// +/// # Notes +/// +/// Done by solving quadratic equation iteratively. +/// +/// ```pseudocode +/// x_1^2 + x_1 * (sum' - (A * n^n - 1) * D / (A * n^n)) = D^(n+1) / (n^2n * prod' * A) +/// x_1^2 + b * x_1 = c +/// +/// x_1 = (x_1^2 + c) / (2 * x_1 + b) +/// ``` +/// For two assets, n = 2 used while computation +pub fn compute_base(new_quote: u128, amp_coeff: u128, d: u128) -> Result { + let mut n = to_big_uint(2_u128); + let two = to_big_uint(2_u128); + let one = to_big_uint(1_u128); + let mut d = to_big_uint(d); + let amplification_coefficient = to_big_uint(amp_coeff); + let ann = amplification_coefficient.mul(&n).mul(&n); + + // s and p are same as input base amount as pool supports only 2 assets. + let s = to_big_uint(new_quote); + let mut p = to_big_uint(new_quote); + + // term1 = d^(n + 1) / n^n * p + // term2 = 2*y + s - d + + let d_n = safe_div(&mut d, &mut n)?; + let mut c = d_n.clone().mul(&d_n).mul(&d); + let term1 = safe_div(&mut c, &mut p)?; + + let mut y = d.clone(); + + // y = (y^2 * ann + term1) / (ann * term2 + d) + for _ in 0..255 { + let y_prev = y.clone(); + let term2 = two.clone().mul(&y).add(&s).sub(&d).map_err(|_| ArithmeticError::Underflow)?; + let mut numerator = ann.clone().mul(&y).mul(&y).add(&term1); + let mut denominator = ann.clone().mul(&term2).add(&d); + + y = safe_div(&mut numerator, &mut denominator)?; + if y.clone() > y_prev { + if y.clone() - y_prev <= one { + y.lstrip(); + return Ok(y.try_into().map_err(|_| ArithmeticError::Overflow)?) + } + } else if y_prev - y.clone() <= one { + y.lstrip(); + return Ok(y.try_into().map_err(|_| ArithmeticError::Overflow)?) + } + } + Err(DispatchError::Other("could not compute d")) +} diff --git a/frame/curve-amm/src/mock.rs b/frame/curve-amm/src/mock.rs index 4658cd50068..3c7f804ad1a 100644 --- a/frame/curve-amm/src/mock.rs +++ b/frame/curve-amm/src/mock.rs @@ -3,12 +3,11 @@ use frame_support::{parameter_types, traits::Everything, PalletId}; use frame_system as system; use orml_traits::parameter_type_with_key; -use sp_arithmetic::{traits::Zero, FixedU128}; +use sp_arithmetic::traits::Zero; use sp_core::H256; use sp_runtime::{ testing::Header, - traits::{BlakeTwo256, IdentityLookup}, - FixedPointNumber, + traits::{BlakeTwo256, ConvertInto, IdentityLookup}, }; use system::EnsureRoot; @@ -28,8 +27,7 @@ frame_support::construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic, { System: frame_system::{Pallet, Call, Config, Storage, Event}, - Balances: pallet_balances::{Pallet, Call, Storage, Event}, - CurveAmm: curve_amm::{Pallet, Call, Storage, Event}, + StableSwap: curve_amm::{Pallet, Call, Storage, Event}, LpTokenFactory: pallet_currency_factory::{Pallet, Storage, Event}, Tokens: orml_tokens::{Pallet, Call, Storage, Config, Event}, } @@ -48,7 +46,7 @@ parameter_types! { pub const SS58Prefix: u8 = 42; } -pub type AccountId = u64; +pub type AccountId = u128; #[allow(dead_code)] pub static ALICE: AccountId = 1; @@ -77,7 +75,7 @@ impl system::Config for Test { type BlockHashCount = BlockHashCount; type Version = (); type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; + type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); type SystemWeightInfo = (); @@ -86,25 +84,10 @@ impl system::Config for Test { type MaxConsumers = frame_support::traits::ConstU32<16>; } -parameter_types! { - pub const ExistentialDeposit: u64 = 1; -} - -impl pallet_balances::Config for Test { - type MaxLocks = (); - type Balance = Balance; - type DustRemoval = (); - type Event = Event; - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; -} - pub type Balance = u128; pub type AssetId = u128; pub type Amount = i128; +pub type PoolId = u128; parameter_type_with_key! { pub ExistentialDeposits: |_currency_id: AssetId| -> Balance { @@ -125,7 +108,7 @@ impl orml_tokens::Config for Test { } parameter_types! { - pub Precision: FixedU128 = FixedU128::saturating_from_rational(1, 1_000_000_000); + pub Precision: u128 = 100_u128; pub TestPalletID : PalletId = PalletId(*b"curve_am"); } @@ -134,11 +117,11 @@ impl curve_amm::Config for Test { type AssetId = AssetId; type Balance = Balance; type CurrencyFactory = LpTokenFactory; - type Precision = Precision; - type LpToken = Tokens; - type PoolId = u32; - type PoolTokenIndex = u32; + type Assets = Tokens; + type Convert = ConvertInto; + type PoolId = PoolId; type PalletId = TestPalletID; + type WeightInfo = (); } // Build genesis storage according to the mock runtime. diff --git a/frame/curve-amm/src/tests.rs b/frame/curve-amm/src/tests.rs index d6d40fa22c9..78e64c35907 100644 --- a/frame/curve-amm/src/tests.rs +++ b/frame/curve-amm/src/tests.rs @@ -1,426 +1,854 @@ -use frame_support::assert_ok; - -use crate::mock::*; -use composable_traits::dex::CurveAmm as CurveAmmTrait; -use frame_support::traits::fungibles::{Inspect, Mutate}; -use proptest::prelude::*; -use sp_runtime::{ - helpers_128bit::multiply_by_rational, - traits::{Saturating, Zero}, - FixedPointNumber, FixedU128, Permill, +use crate::mock::{StableSwap, *}; +use composable_tests_helpers::{ + prop_assert_ok, + test::helper::{acceptable_computation_error, default_acceptable_computation_error}, }; -use sp_std::cmp::Ordering; - -/// Accepts -2, -1, 0, 1, 2 -macro_rules! prop_assert_zero_epsilon { - ($x:expr) => {{ - let epsilon = 2; - let upper = 0 + epsilon; - let lower = 0; - prop_assert!(upper >= $x && $x >= lower, "{} => {} >= {}", upper, $x, lower); - }}; +use composable_traits::{defi::CurrencyPair, dex::Amm}; +use frame_support::{ + assert_noop, assert_ok, + traits::fungibles::{Inspect, Mutate}, +}; +use proptest::prelude::*; +use sp_runtime::{Permill, TokenError}; + +fn create_pool( + base_asset: AssetId, + quote_asset: AssetId, + base_amount: Balance, + quote_amount: Balance, + amplification_factor: u16, + lp_fee: Permill, + protocol_fee: Permill, +) -> PoolId { + let pool_id = StableSwap::do_create_pool( + &ALICE, + CurrencyPair::new(base_asset, quote_asset), + amplification_factor, + lp_fee, + protocol_fee, + ) + .expect("pool creation failed"); + // Mint the tokens + assert_ok!(Tokens::mint_into(base_asset, &ALICE, base_amount)); + assert_ok!(Tokens::mint_into(quote_asset, &ALICE, quote_amount)); + + // Add the liquidity + assert_ok!(StableSwap::add_liquidity( + Origin::signed(ALICE), + pool_id, + base_amount, + quote_amount, + 0, + false + )); + pool_id +} + +#[test] +fn test_amp_zero_failure() { + new_test_ext().execute_with(|| { + assert_noop!( + StableSwap::do_create_pool( + &ALICE, + CurrencyPair::new(USDC, USDT), + 0_u16, + Permill::zero(), + Permill::zero(), + ), + crate::Error::::AmpFactorMustBeGreaterThanZero + ); + }); } -/// Accept a 'dust' deviation -macro_rules! prop_assert_epsilon { - ($x:expr, $y:expr) => {{ - let precision = 1000; - let epsilon = 5; - let upper = precision + epsilon; - let lower = precision - epsilon; - let q = multiply_by_rational($x, precision, $y).expect("qed;"); - prop_assert!( - upper >= q && q >= lower, - "({}) => {} >= {} * {} / {} >= {}", - q, - upper, - $x, +#[test] +fn test_dex_demo() { + new_test_ext().execute_with(|| { + let pool_id = StableSwap::do_create_pool( + &ALICE, + CurrencyPair::new(USDC, USDT), + 100_u16, + Permill::zero(), + Permill::zero(), + ) + .expect("pool creation failed"); + + let pool = StableSwap::pools(pool_id).expect("pool not found"); + + let unit = 1_000_000_000_000_u128; + let usdc_price = 1 * unit; + + let nb_of_usdc = 1_000_000_000; + let usdt_price = 1 * unit; + + let nb_of_usdt = 1_000_000_000; + + // 10^9 USDC/10^9 USDT + let initial_usdc = nb_of_usdc * usdc_price; + let initial_usdt = nb_of_usdt * usdt_price; + + // Mint the tokens + assert_ok!(Tokens::mint_into(USDC, &ALICE, initial_usdc)); + assert_ok!(Tokens::mint_into(USDT, &ALICE, initial_usdt)); + + // Add the liquidity + assert_ok!(StableSwap::add_liquidity( + Origin::signed(ALICE), + pool_id, + initial_usdc, + initial_usdt, + 0, + false + )); + + let precision = 100; + let epsilon = 1; + // 1 unit of usdc == 1 unit of usdt + let ratio = ::get_exchange_value(pool_id, USDC, unit) + .expect("get_exchange_value failed"); + assert_ok!(acceptable_computation_error(ratio, unit, precision, epsilon)); + + let swap_usdc = 100_u128 * unit; + assert_ok!(Tokens::mint_into(USDC, &BOB, swap_usdc)); + // mint 1 USDT, after selling 100 USDC we get 99 USDT so to buy 100 USDC we need 100 USDT + assert_ok!(Tokens::mint_into(USDT, &BOB, unit)); + + StableSwap::sell(Origin::signed(BOB), pool_id, USDC, swap_usdc, false) + .expect("sell failed"); + + StableSwap::buy(Origin::signed(BOB), pool_id, USDC, swap_usdc, false).expect("buy failed"); + + let bob_usdc = Tokens::balance(USDC, &BOB); + + assert_ok!(acceptable_computation_error( + bob_usdc.into(), + swap_usdc.into(), precision, - $y, - lower + epsilon + )); + let lp = Tokens::balance(pool.lp_token, &ALICE); + assert_ok!(StableSwap::remove_liquidity(Origin::signed(ALICE), pool_id, lp, 0, 0)); + + // Alice should get back a different amount of tokens. + let alice_usdc = Tokens::balance(USDC, &ALICE); + let alice_usdt = Tokens::balance(USDT, &ALICE); + assert_ok!(default_acceptable_computation_error(alice_usdc.into(), initial_usdc.into())); + assert_ok!(default_acceptable_computation_error(alice_usdt.into(), initial_usdt.into())); + }); +} + +//- test lp mint/burn +#[test] +fn add_remove_lp() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_usdt = 1_000_000_000_000_u128 * unit; + let initial_usdc = 1_000_000_000_000_u128 * unit; + let pool_id = create_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::zero(), + Permill::zero(), ); - }}; + let pool = StableSwap::pools(pool_id).expect("pool not found"); + let bob_usdc = 1000 * unit; + let bob_usdt = 1000 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDC, &BOB, bob_usdc)); + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + + let lp = Tokens::balance(pool.lp_token, &BOB); + assert_eq!(lp, 0_u128); + // Add the liquidity + assert_ok!(StableSwap::add_liquidity( + Origin::signed(BOB), + pool_id, + bob_usdc, + bob_usdt, + 0, + false + )); + let lp = Tokens::balance(pool.lp_token, &BOB); + // must have received some lp tokens + assert!(lp == bob_usdt + bob_usdc); + assert_ok!(StableSwap::remove_liquidity(Origin::signed(BOB), pool_id, lp, 0, 0)); + let lp = Tokens::balance(pool.lp_token, &BOB); + // all lp tokens must have been burnt + assert_eq!(lp, 0_u128); + }); } +// +// - add liquidity which creates imbalance in pool #[test] -fn compute_d_works() { - let xp = vec![ - FixedU128::saturating_from_rational(11_u128, 10_u128), - FixedU128::saturating_from_rational(88_u128, 100_u128), - ]; - let amp = FixedU128::saturating_from_rational(292_u128, 100_u128); - let ann = CurveAmm::get_ann(amp, xp.len()).unwrap(); - let d = CurveAmm::get_d(&xp, ann); - // expected d is 1.978195735374521596 - // expected precision is 1e-13 - let delta = d - .map(|x| { - x.saturating_sub(FixedU128::saturating_from_rational( - 1978195735374521596_u128, - 10_000_000_000_000_000_u128, - )) - .saturating_abs() - }) - .map(|x| x.cmp(&FixedU128::saturating_from_rational(1_u128, 10_000_000_000_000_u128))); - assert_eq!(delta, Some(Ordering::Less)); +fn add_lp_imbalanced() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_usdt = 1_000_000_000_000_u128 * unit; + let initial_usdc = 1_000_000_000_000_u128 * unit; + let pool_id = create_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::from_float(0.05), // 5% lp fee. + Permill::from_float(0.10), // 10% of lp fee goes to owner + ); + let pool = StableSwap::pools(pool_id).expect("pool not found"); + let bob_usdc = 1000 * unit; + let bob_usdt = 1000 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDC, &BOB, bob_usdc)); + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + + let lp = Tokens::balance(pool.lp_token, &BOB); + assert_eq!(lp, 0_u128); + // Add the liquidity in balanced way + assert_ok!(StableSwap::add_liquidity( + Origin::signed(BOB), + pool_id, + bob_usdc, + bob_usdt, + 0, + false + )); + let lp = Tokens::balance(pool.lp_token, &BOB); + // must have received some lp tokens + assert!(lp == bob_usdt + bob_usdc); + // there must not be any fee charged. simple way is to check owner (ALICE) has not got any + // tokens as owner fee. + let alice_usdc = Tokens::balance(USDC, &ALICE); + let alice_usdt = Tokens::balance(USDT, &ALICE); + assert!(alice_usdt == 0); + assert!(alice_usdc == 0); + + let bob_usdc = 100000 * unit; + let bob_usdt = 5000 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDC, &BOB, bob_usdc)); + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + // Add the liquidity in imbalanced way + assert_ok!(StableSwap::add_liquidity( + Origin::signed(BOB), + pool_id, + bob_usdc, + bob_usdt, + 0, + false + )); + // there must fee charged. simple way is to check owner (ALICE) has got + // tokens as owner fee. + let alice_usdc = Tokens::balance(USDC, &ALICE); + let alice_usdt = Tokens::balance(USDT, &ALICE); + assert!(alice_usdt != 0); + assert!(alice_usdc != 0); + }); } +// test add liquidity with min_mint_amount #[test] -fn compute_d_empty() { - let xp = vec![]; - let amp = FixedU128::saturating_from_rational(292_u128, 100_u128); - let ann = CurveAmm::get_ann(amp, xp.len()).unwrap(); - let result = CurveAmm::get_d(&xp, ann); - assert_eq!(result, Some(FixedU128::zero())); +fn add_lp_with_min_mint_amount_success() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_usdt = 1_000_000_000_000_u128 * unit; + let initial_usdc = 1_000_000_000_000_u128 * unit; + let pool_id = create_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::zero(), + Permill::zero(), + ); + let pool = StableSwap::pools(pool_id).expect("pool not found"); + let bob_usdc = 1000 * unit; + let bob_usdt = 1000 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDC, &BOB, bob_usdc)); + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + + let lp = Tokens::balance(pool.lp_token, &BOB); + assert_eq!(lp, 0_u128); + let expected_min_value = bob_usdt + bob_usdc; + // Add the liquidity in balanced way + assert_ok!(StableSwap::add_liquidity( + Origin::signed(BOB), + pool_id, + bob_usdc, + bob_usdt, + expected_min_value, + false + )); + let lp = Tokens::balance(pool.lp_token, &BOB); + // must have received some lp tokens + assert!(lp == bob_usdc + bob_usdt); + + let bob_usdc = 1000 * unit; + let bob_usdt = 900 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDC, &BOB, bob_usdc)); + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + // Add the liquidity in imbalanced way, but have expected_min_value higher + assert_noop!( + StableSwap::add_liquidity( + Origin::signed(BOB), + pool_id, + bob_usdc, + bob_usdt, + expected_min_value, + false + ), + crate::Error::::CannotRespectMinimumRequested + ); + }); } +// test add liquidity with min_mint_amount #[test] -fn get_y_successful() { - let i = 0; - let j = 1; - let x = FixedU128::saturating_from_rational(111_u128, 100_u128); - let xp = vec![ - FixedU128::saturating_from_rational(11_u128, 10_u128), - FixedU128::saturating_from_rational(88_u128, 100_u128), - ]; - let amp = FixedU128::saturating_from_rational(292_u128, 100_u128); - let ann = CurveAmm::get_ann(amp, xp.len()).unwrap(); - - let result = CurveAmm::get_y(i, j, x, &xp, ann); - // expected y is 1.247108067356516682 - // expected precision is 1e-13 - let delta = result - .map(|x| { - x.saturating_sub(FixedU128::saturating_from_rational( - 1247108067356516682_u128, - 10_000_000_000_000_000_u128, - )) - .saturating_abs() - }) - .map(|x| x.cmp(&FixedU128::saturating_from_rational(1_u128, 10_000_000_000_000_u128))); - assert_eq!(delta, Some(Ordering::Less)); +fn add_lp_with_min_mint_amount_fail() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_usdt = 1_000_000_000_000_u128 * unit; + let initial_usdc = 1_000_000_000_000_u128 * unit; + let pool_id = create_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::zero(), + Permill::zero(), + ); + + let bob_usdc = 1000 * unit; + let bob_usdt = 900 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDC, &BOB, bob_usdc)); + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + let expected_min_value = bob_usdt + bob_usdc + 1_u128; + // Add the liquidity in imbalanced way, but have expected_min_value higher + assert_noop!( + StableSwap::add_liquidity( + Origin::signed(BOB), + pool_id, + bob_usdc, + bob_usdt, + expected_min_value, + false + ), + crate::Error::::CannotRespectMinimumRequested + ); + }); } +// +// - test error if trying to remove > lp than we have #[test] -fn get_y_same_coin() { - let i = 1; - let j = 1; - let x = FixedU128::saturating_from_rational(111_u128, 100_u128); - let xp = vec![ - FixedU128::saturating_from_rational(11_u128, 10_u128), - FixedU128::saturating_from_rational(88_u128, 100_u128), - ]; - let amp = FixedU128::saturating_from_rational(292_u128, 100_u128); - let ann = CurveAmm::get_ann(amp, xp.len()).unwrap(); - - let result = CurveAmm::get_y(i, j, x, &xp, ann); - - assert_eq!(result, None); +fn remove_lp_failure() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_usdt = 1_000_000_000_000_u128 * unit; + let initial_usdc = 1_000_000_000_000_u128 * unit; + let pool_id = create_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::zero(), + Permill::zero(), + ); + let pool = StableSwap::pools(pool_id).expect("pool not found"); + let bob_usdc = 1000 * unit; + let bob_usdt = 1000 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDC, &BOB, bob_usdc)); + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + + // Add the liquidity + assert_ok!(StableSwap::add_liquidity( + Origin::signed(BOB), + pool_id, + bob_usdc, + bob_usdt, + 0, + false + )); + let lp = Tokens::balance(pool.lp_token, &BOB); + assert_noop!( + StableSwap::remove_liquidity(Origin::signed(BOB), pool_id, lp + 1, 0, 0), + TokenError::NoFunds + ); + let min_expected_usdt = 1001 * unit; + let min_expected_usdc = 1001 * unit; + assert_noop!( + StableSwap::remove_liquidity( + Origin::signed(BOB), + pool_id, + lp, + min_expected_usdc, + min_expected_usdt + ), + crate::Error::::CannotRespectMinimumRequested + ); + }); } +// +// - test exchange failure #[test] -fn get_y_i_greater_than_n() { - let i = 33; - let j = 1; - let x = FixedU128::saturating_from_rational(111_u128, 100_u128); - let xp = vec![ - FixedU128::saturating_from_rational(11_u128, 10_u128), - FixedU128::saturating_from_rational(88_u128, 100_u128), - ]; - let amp = FixedU128::saturating_from_rational(292_u128, 100_u128); - let ann = CurveAmm::get_ann(amp, xp.len()).unwrap(); - - let result = CurveAmm::get_y(i, j, x, &xp, ann); - - assert_eq!(result, None); +fn exchange_failure() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_usdt = 1_000_000_u128 * unit; + let initial_usdc = 1_000_000_u128 * unit; + let pool_id = create_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::zero(), + Permill::zero(), + ); + let bob_usdc = 1000 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDC, &BOB, bob_usdc)); + + let exchange_usdc = 1001 * unit; + assert_noop!( + StableSwap::swap( + Origin::signed(BOB), + pool_id, + CurrencyPair::new(USDT, USDC), + exchange_usdc, + 0, + false + ), + orml_tokens::Error::::BalanceTooLow + ); + let exchange_value = 1000 * unit; + let expected_value = 1001 * unit; + assert_noop!( + StableSwap::swap( + Origin::signed(BOB), + pool_id, + CurrencyPair::new(USDT, USDC), + exchange_value, + expected_value, + false + ), + crate::Error::::CannotRespectMinimumRequested + ); + }); } +// +// - test lp fees #[test] -fn get_y_j_greater_than_n() { - let i = 1; - let j = 33; - let x = FixedU128::saturating_from_rational(111_u128, 100_u128); - let xp = vec![ - FixedU128::saturating_from_rational(11_u128, 10_u128), - FixedU128::saturating_from_rational(88_u128, 100_u128), - ]; - let amp = FixedU128::saturating_from_rational(292_u128, 100_u128); - let ann = CurveAmm::get_ann(amp, xp.len()).unwrap(); - - let result = CurveAmm::get_y(i, j, x, &xp, ann); - - assert_eq!(result, None); +fn lp_fee() { + new_test_ext().execute_with(|| { + let precision = 100; + let epsilon = 1; + let unit = 1_000_000_000_000_u128; + let initial_usdt = 1_000_000_000_000_u128 * unit; + let initial_usdc = 1_000_000_000_000_u128 * unit; + let lp_fee = Permill::from_float(0.05); + let pool_id = + create_pool(USDC, USDT, initial_usdc, initial_usdt, 100_u16, lp_fee, Permill::zero()); + let bob_usdt = 1000 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + + assert_ok!(StableSwap::sell(Origin::signed(BOB), pool_id, USDT, bob_usdt, false)); + let usdc_balance = Tokens::balance(USDC, &BOB); + // received usdc should bob_usdt - lp_fee + assert_ok!(acceptable_computation_error( + usdc_balance, + bob_usdt - lp_fee.mul_ceil(bob_usdt), + precision, + epsilon + )); + }); } +// +// - test protocol fees #[test] -fn add_remove_liquidity() { +fn protocol_fee() { new_test_ext().execute_with(|| { - let assets = vec![USDC, USDT]; - let amp_coeff = FixedU128::saturating_from_rational(1_000_i128, 1_i128); - let fee = Permill::zero(); - let admin_fee = Permill::zero(); - - assert_eq!(Tokens::balance(USDT, &ALICE), 0); - assert_ok!(Tokens::mint_into(USDT, &ALICE, 200_000)); - assert_eq!(Tokens::balance(USDT, &ALICE), 200_000); - - assert_eq!(Tokens::balance(USDC, &ALICE), 0); - assert_ok!(Tokens::mint_into(USDC, &ALICE, 200_000)); - assert_eq!(Tokens::balance(USDC, &ALICE), 200_000); - - assert_eq!(Tokens::balance(USDT, &BOB), 0); - assert_ok!(Tokens::mint_into(USDT, &BOB, 200_000)); - assert_eq!(Tokens::balance(USDT, &BOB), 200_000); - - assert_eq!(Tokens::balance(USDC, &BOB), 0); - assert_ok!(Tokens::mint_into(USDC, &BOB, 200_000)); - assert_eq!(Tokens::balance(USDC, &BOB), 200_000); - - let p = CurveAmm::create_pool(&ALICE, assets, amp_coeff, fee, admin_fee); - assert_ok!(&p); - let pool_id = p.unwrap(); - let pool = CurveAmm::get_pool_info(pool_id); - assert!(pool.is_some()); - let pool = pool.unwrap(); - - let pool_lp_asset = pool.lp_token; - - // 1 USDC = 1 USDT - let amounts = vec![130_000_u128, 130_000_u128]; - assert_ok!(CurveAmm::add_liquidity(&ALICE, pool_id, amounts.clone(), 0_u128)); - let alice_lp_asset_balance = Tokens::balance(pool_lp_asset, &ALICE); - assert_ne!(alice_lp_asset_balance, 0); - assert_eq!(Tokens::balance(USDT, &ALICE), 200_000 - 1300_00); - assert_eq!(Tokens::balance(USDC, &ALICE), 200_000 - 1300_00); - let pool = CurveAmm::get_pool_info(pool_id); - assert!(pool.is_some()); - assert_ok!(CurveAmm::add_liquidity(&BOB, pool_id, amounts.clone(), 0_u128)); - - let bob_lp_asset_balance = Tokens::balance(pool_lp_asset, &BOB); - assert_ne!(bob_lp_asset_balance, 0); - assert_eq!(Tokens::balance(USDT, &BOB), 200_000 - 130_000); - assert_eq!(Tokens::balance(USDC, &BOB), 200_000 - 130_000); - - let min_amt = vec![0_u128, 0_u128]; - assert_eq!(Tokens::balance(USDC, &CurveAmm::account_id(&pool_id)), 260_000); - assert_eq!(Tokens::balance(USDT, &CurveAmm::account_id(&pool_id)), 260_000); - - assert_ok!(CurveAmm::remove_liquidity( - &ALICE, - pool_id, - alice_lp_asset_balance, - min_amt.clone() + let precision = 100; + let epsilon = 1; + let unit = 1_000_000_000_000_u128; + let initial_usdt = 1_000_000_000_000_u128 * unit; + let initial_usdc = 1_000_000_000_000_u128 * unit; + let lp_fee = Permill::from_float(0.05); + let protocol_fee = Permill::from_float(0.01); // 10% of lp fees goes to pool owner + let pool_id = + create_pool(USDC, USDT, initial_usdc, initial_usdt, 100_u16, lp_fee, protocol_fee); + let bob_usdt = 1000 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + assert_ok!(StableSwap::sell(Origin::signed(BOB), pool_id, USDT, bob_usdt, false)); + let usdc_balance = Tokens::balance(USDC, &BOB); + // received usdc should bob_usdt - lp_fee + assert_ok!(acceptable_computation_error( + usdc_balance, + bob_usdt - lp_fee.mul_floor(bob_usdt), + precision, + epsilon )); - assert_eq!(Tokens::balance(pool_lp_asset, &ALICE), 0); - assert_eq!(Tokens::balance(USDT, &ALICE), 200_000); - assert_eq!(Tokens::balance(USDC, &ALICE), 200_000); - assert_eq!(Tokens::balance(USDC, &CurveAmm::account_id(&pool_id)), 130_000); - assert_eq!(Tokens::balance(USDT, &CurveAmm::account_id(&pool_id)), 130_000); - - assert_ok!(CurveAmm::remove_liquidity( - &BOB, - pool_id, - bob_lp_asset_balance, - min_amt.clone() + // from lp_fee 1 % (as per protocol_fee) goes to pool owner (ALICE) + let alice_usdc_bal = Tokens::balance(USDC, &ALICE); + assert_ok!(acceptable_computation_error( + alice_usdc_bal, + protocol_fee.mul_floor(lp_fee.mul_floor(bob_usdt)), + precision, + epsilon )); - assert_eq!(Tokens::balance(pool_lp_asset, &BOB), 0); - assert_eq!(Tokens::balance(USDT, &BOB), 200_000); - assert_eq!(Tokens::balance(USDC, &BOB), 200_000); - assert_eq!(Tokens::balance(USDC, &CurveAmm::account_id(&pool_id)), 0); - assert_eq!(Tokens::balance(USDT, &CurveAmm::account_id(&pool_id)), 0); }); } +// +// - test high slippage scenario +// trying to exchange a large value, will result in high_slippage scenario +// there should be substential difference between expected exchange value and received amount. #[test] -fn exchange_test() { +fn high_slippage() { new_test_ext().execute_with(|| { - let assets = vec![USDC, USDT]; - let amp_coeff = FixedU128::saturating_from_rational(1000_i128, 1_i128); - let fee = Permill::zero(); - let admin_fee = Permill::zero(); - - assert_eq!(Tokens::balance(USDT, &ALICE), 0); - assert_ok!(Tokens::mint_into(USDT, &ALICE, 200000)); - assert_eq!(Tokens::balance(USDT, &ALICE), 200000); - assert_eq!(Tokens::balance(USDC, &ALICE), 0); - assert_ok!(Tokens::mint_into(USDC, &ALICE, 200000)); - assert_eq!(Tokens::balance(USDC, &ALICE), 200000); - assert_eq!(Tokens::balance(USDT, &BOB), 0); - assert_ok!(Tokens::mint_into(USDT, &BOB, 200000)); - assert_eq!(Tokens::balance(USDT, &BOB), 200000); - assert_eq!(Tokens::balance(USDC, &BOB), 0); - assert_ok!(Tokens::mint_into(USDC, &BOB, 200000)); - assert_eq!(Tokens::balance(USDC, &BOB), 200000); - assert_eq!(Tokens::balance(USDT, &CHARLIE), 0); - assert_ok!(Tokens::mint_into(USDT, &CHARLIE, 200000)); - assert_eq!(Tokens::balance(USDT, &CHARLIE), 200000); - let p = CurveAmm::create_pool(&ALICE, assets, amp_coeff, fee, admin_fee); - assert_ok!(&p); - let pool_id = p.unwrap(); - let pool = CurveAmm::get_pool_info(pool_id); - assert!(pool.is_some()); - let pool = pool.unwrap(); - let pool_lp_asset = pool.lp_token; - // 1 USDC = 1 USDT - let amounts = vec![130000_u128, 130000_u128]; - assert_ok!(CurveAmm::add_liquidity(&ALICE, pool_id, amounts.clone(), 0_u128)); - let alice_balance = Tokens::balance(pool_lp_asset, &ALICE); - assert_ne!(alice_balance, 0); - assert_eq!(Tokens::balance(USDT, &ALICE), 200000 - 130000); - assert_eq!(Tokens::balance(USDC, &ALICE), 200000 - 130000); - let pool = CurveAmm::get_pool_info(pool_id); - assert!(pool.is_some()); - assert_ok!(CurveAmm::add_liquidity(&BOB, pool_id, amounts.clone(), 0_u128)); - let bob_balance = Tokens::balance(pool_lp_asset, &BOB); - assert_ne!(bob_balance, 0); - assert_eq!(Tokens::balance(USDT, &BOB), 200000 - 130000); - assert_eq!(Tokens::balance(USDC, &BOB), 200000 - 130000); - assert_eq!(Tokens::balance(USDC, &CHARLIE), 0); - assert_ok!(CurveAmm::exchange(&CHARLIE, pool_id, 1, 0, 65000, 0)); - assert!(65000 - Tokens::balance(USDC, &CHARLIE) < 10); + let unit = 1_000_000_000_000_u128; + let initial_usdt = 1_000_000_000_000_u128 * unit; + let initial_usdc = 1_000_000_000_000_u128 * unit; + let pool_id = create_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::zero(), + Permill::zero(), + ); + let bob_usdt = 1_000_000_000_00_u128 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + + assert_ok!(StableSwap::sell(Origin::signed(BOB), pool_id, USDT, bob_usdt, false)); + let usdc_balance = Tokens::balance(USDC, &BOB); + assert!((bob_usdt - usdc_balance) > 5_u128); }); } proptest! { #![proptest_config(ProptestConfig::with_cases(10000))] - #[test] - fn proptest_exchange(alice_balance in 1..u32::MAX, - bob_balance in 1..u32::MAX) { + fn add_remove_liquidity_proptest( + usdc_balance in 1..u32::MAX, + usdt_balance in 1..u32::MAX, + ) { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let usdt_balance = usdt_balance as u128 * unit; + let usdc_balance = usdc_balance as u128 * unit; + let initial_usdt = u64::MAX as u128 * unit; + let initial_usdc = u64::MAX as u128 * unit; + let pool_id = create_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::zero(), + Permill::zero(), + ); + let pool = StableSwap::pools(pool_id).expect("pool not found"); + prop_assert_ok!(Tokens::mint_into(USDT, &BOB, usdt_balance)); + prop_assert_ok!(Tokens::mint_into(USDC, &BOB, usdc_balance)); + prop_assert_ok!(StableSwap::add_liquidity( + Origin::signed(BOB), + pool_id, + usdc_balance, + usdt_balance, + 0, + false + )); + let lp = Tokens::balance(pool.lp_token, &BOB); + let expected_lp = usdt_balance + usdc_balance; + prop_assert_ok!(default_acceptable_computation_error(lp, expected_lp)); + prop_assert_ok!(StableSwap::remove_liquidity( + Origin::signed(BOB), + pool_id, + lp, + 0, + 0, + )); + let bob_usdc = Tokens::balance(USDC, &BOB); + let bob_usdt = Tokens::balance(USDT, &BOB); + prop_assert_ok!(default_acceptable_computation_error(usdc_balance + usdt_balance, bob_usdc + bob_usdt)); + Ok(()) + })?; + } + #[test] + fn buy_sell_proptest( + value in 1..u32::MAX, + ) { new_test_ext().execute_with(|| { - // configuration for DEX Pool - let assets = vec![USDC, USDT]; - let amp_coeff = FixedU128::saturating_from_rational(10000_i128, 1_i128); - let fee = Permill::zero(); - let admin_fee = Permill::zero(); - - // Add funds to ALICE's account. - assert_eq!(Tokens::balance(USDT, &ALICE), 0); - assert_ok!(Tokens::mint_into(USDT, &ALICE, alice_balance.into())); - assert_eq!(Tokens::balance(USDT, &ALICE), alice_balance.into()); - assert_eq!(Tokens::balance(USDC, &ALICE), 0); - assert_ok!(Tokens::mint_into(USDC, &ALICE, alice_balance.into())); - assert_eq!(Tokens::balance(USDC, &ALICE), alice_balance.into()); - - // Add funds to BOB's account. - assert_eq!(Tokens::balance(USDT, &BOB), 0); - assert_ok!(Tokens::mint_into(USDT, &BOB, bob_balance.into())); - assert_eq!(Tokens::balance(USDT, &BOB), bob_balance.into()); - assert_eq!(Tokens::balance(USDC, &BOB), 0); - assert_ok!(Tokens::mint_into(USDC, &BOB, bob_balance.into())); - assert_eq!(Tokens::balance(USDC, &BOB), bob_balance.into()); - - // Add funds to CHARLIE's account. - assert_eq!(Tokens::balance(USDT, &CHARLIE), 0); - assert_ok!(Tokens::mint_into(USDT, &CHARLIE, alice_balance.into())); - assert_eq!(Tokens::balance(USDT, &CHARLIE), alice_balance.into()); - - - // create DEX pool for 1 USDC = 1 USDT - let p = CurveAmm::create_pool(&ALICE, assets, amp_coeff, fee, admin_fee); - assert_ok!(&p); - let pool_id = p.unwrap(); - let pool = CurveAmm::get_pool_info(pool_id); - assert!(pool.is_some()); - let pool = pool.unwrap(); - let pool_lp_asset = pool.lp_token; - - // ALICE adds liquidity to DEX pool. - let alice_amounts = vec![alice_balance as u128, alice_balance as u128]; - assert_ok!(CurveAmm::add_liquidity(&ALICE, pool_id, alice_amounts.clone(), 0_u128)); - let alice_lp_balance = Tokens::balance(pool_lp_asset, &ALICE); - assert_ne!(alice_lp_balance, 0); - assert_eq!(Tokens::balance(USDT, &ALICE), 0); - assert_eq!(Tokens::balance(USDC, &ALICE), 0); - - // BOB adds liquidity to DEX pool. - let bob_amounts = vec![bob_balance as u128, bob_balance as u128]; - assert_ok!(CurveAmm::add_liquidity(&BOB, pool_id, bob_amounts.clone(), 0_u128)); - let bob_lp_balance = Tokens::balance(pool_lp_asset, &BOB); - assert_ne!(bob_lp_balance, 0); - assert_eq!(Tokens::balance(USDT, &BOB), 0); - assert_eq!(Tokens::balance(USDC, &BOB), 0); - - // CHARLIE exchanges USDT for USDC, CHARLIE has same balance of USDT as of ALICE. - assert_eq!(Tokens::balance(USDC, &CHARLIE), 0); - assert_ok!(CurveAmm::exchange(&CHARLIE, pool_id, 1, 0, alice_balance as u128, 0)); - prop_assert_epsilon!(alice_balance as u128, Tokens::balance(USDC, &CHARLIE)); + let unit = 1_000_000_000_000_u128; + let initial_usdt = u64::MAX as u128 * unit; + let initial_usdc = u64::MAX as u128 * unit; + let value = value as u128 * unit; + let pool_id = create_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::zero(), + Permill::zero(), + ); + prop_assert_ok!(Tokens::mint_into(USDT, &BOB, value)); + prop_assert_ok!(StableSwap::sell(Origin::signed(BOB), pool_id, USDT, value, false)); + // mint 1 extra USDC so that original amount of USDT can be buy back even with small slippage + prop_assert_ok!(Tokens::mint_into(USDC, &BOB, unit)); + prop_assert_ok!(StableSwap::buy(Origin::signed(BOB), pool_id, USDT, value, false)); + let bob_usdt = Tokens::balance(USDT, &BOB); + prop_assert_ok!(default_acceptable_computation_error(bob_usdt, value)); Ok(()) - }).unwrap(); + })?; } #[test] - fn proptest_add_remove_liquidity(alice_balance in 0..u32::MAX, - bob_balance in 0..u32::MAX) { + fn swap_proptest( + value in 1..u32::MAX, + ) { new_test_ext().execute_with(|| { - // configuration for DEX Pool - let assets = vec![USDC, USDT]; - let amp_coeff = FixedU128::saturating_from_rational(1000_i128, 1_i128); - let fee = Permill::zero(); - let admin_fee = Permill::zero(); - - // Add funds to ALICE's account. - assert_eq!(Tokens::balance(USDT, &ALICE), 0); - assert_ok!(Tokens::mint_into(USDT, &ALICE, alice_balance.into())); - assert_eq!(Tokens::balance(USDT, &ALICE), alice_balance.into()); - assert_eq!(Tokens::balance(USDC, &ALICE), 0); - assert_ok!(Tokens::mint_into(USDC, &ALICE, alice_balance.into())); - assert_eq!(Tokens::balance(USDC, &ALICE), alice_balance.into()); - - // Add funds to BOB's account. - assert_eq!(Tokens::balance(USDT, &BOB), 0); - assert_ok!(Tokens::mint_into(USDT, &BOB, bob_balance.into())); - assert_eq!(Tokens::balance(USDT, &BOB), bob_balance.into()); - assert_eq!(Tokens::balance(USDC, &BOB), 0); - assert_ok!(Tokens::mint_into(USDC, &BOB, bob_balance.into())); - assert_eq!(Tokens::balance(USDC, &BOB), bob_balance.into()); - - // create DEX pool for 1 USDC = 1 USDT - let p = CurveAmm::create_pool(&ALICE, assets, amp_coeff, fee, admin_fee); - assert_ok!(&p); - let pool_id = p.unwrap(); - let pool = CurveAmm::get_pool_info(pool_id); - assert!(pool.is_some()); - let pool = pool.unwrap(); - let pool_lp_asset = pool.lp_token; - - // ALICE adds liquidity to DEX pool. - let alice_amounts = vec![alice_balance as u128, alice_balance as u128]; - assert_ok!(CurveAmm::add_liquidity(&ALICE, pool_id, alice_amounts.clone(), 0_u128)); - let alice_lp_balance = Tokens::balance(pool_lp_asset, &ALICE); - assert_ne!(alice_lp_balance, 0); - assert_eq!(Tokens::balance(USDT, &ALICE), 0); - assert_eq!(Tokens::balance(USDC, &ALICE), 0); - - // BOB adds liquidity to DEX pool. - let bob_amounts = vec![bob_balance as u128, bob_balance as u128]; - assert_ok!(CurveAmm::add_liquidity(&BOB, pool_id, bob_amounts.clone(), 0_u128)); - let bob_lp_balance = Tokens::balance(pool_lp_asset, &BOB); - assert_ne!(bob_balance, 0); - assert_eq!(Tokens::balance(USDT, &BOB), 0); - assert_eq!(Tokens::balance(USDC, &BOB), 0); - - let min_amt = vec![0_u128, 0_u128]; - assert_eq!(Tokens::balance(USDC, &CurveAmm::account_id(&pool_id)), alice_balance as u128 + bob_balance as u128); - assert_eq!(Tokens::balance(USDT, &CurveAmm::account_id(&pool_id)), alice_balance as u128 + bob_balance as u128); - - // ALICE removes liquidity from DEX pool. - assert_ok!(CurveAmm::remove_liquidity(&ALICE, pool_id, alice_lp_balance, min_amt.clone())); - prop_assert_zero_epsilon!(Tokens::balance(pool_lp_asset, &ALICE)); - prop_assert_epsilon!(Tokens::balance(USDT, &ALICE), alice_balance as u128); - prop_assert_epsilon!(Tokens::balance(USDC, &ALICE), alice_balance as u128); - prop_assert_epsilon!(Tokens::balance(USDC, &CurveAmm::account_id(&pool_id)), bob_balance as u128); - prop_assert_epsilon!(Tokens::balance(USDT, &CurveAmm::account_id(&pool_id)), bob_balance as u128); - - // BOB removes liquidity from DEX pool. - assert_ok!(CurveAmm::remove_liquidity(&BOB, pool_id, bob_lp_balance, min_amt.clone())); - prop_assert_zero_epsilon!(Tokens::balance(pool_lp_asset, &BOB)); - prop_assert_zero_epsilon!(Tokens::balance(USDC, &CurveAmm::account_id(&pool_id))); - prop_assert_zero_epsilon!(Tokens::balance(USDT, &CurveAmm::account_id(&pool_id))); - prop_assert_epsilon!(Tokens::balance(USDT, &BOB), bob_balance as u128); - prop_assert_epsilon!(Tokens::balance(USDC, &BOB), bob_balance as u128); + let unit = 1_000_000_000_000_u128; + let initial_usdt = u64::MAX as u128 * unit; + let initial_usdc = u64::MAX as u128 * unit; + let value = value as u128 * unit; + let pool_id = create_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::from_float(0.025), + Permill::zero(), + ); + let pool = StableSwap::pools(pool_id).expect("pool not found"); + prop_assert_ok!(Tokens::mint_into(USDT, &BOB, value)); + prop_assert_ok!(StableSwap::swap(Origin::signed(BOB), pool_id, CurrencyPair::new(USDC, USDT), value, 0, false)); + let bob_usdc = Tokens::balance(USDC, &BOB); + let expected_usdc = value - pool.fee.mul_floor(value); + prop_assert_ok!(default_acceptable_computation_error(bob_usdc, expected_usdc)); Ok(()) - }).unwrap(); + })?; } } + +#[cfg(feature = "visualization")] +#[test] +fn get_base_graph() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_usdt = 100000_u128 * unit; + let initial_usdc = 100000_u128 * unit; + let pool_id = create_pool( + USDC, + SDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::zero(), + Permill::zero(), + ); + + let start_quote = 0; + let end_quote = 120000; + let points = (start_quote..end_quote) + .map(|quote| { + ( + quote, + ::get_exchange_value(pool_id, USDC, quote * unit) + .expect("get_exchange_value not found") as f64 / + unit as f64, + ) + }) + .collect::>(); + let max_amount = points.iter().copied().fold(f64::NAN, |x, (_, y)| f64::max(x, y)); + + use plotters::prelude::*; + let area = BitMapBackend::new("./curve_base.png", (1024, 768)).into_drawing_area(); + area.fill(&WHITE).unwrap(); + + let mut chart = ChartBuilder::on(&area) + .caption("Curve price, pool has 100000 USDC 100000 USDT", ("Arial", 25).into_font()) + .margin(100u32) + .x_label_area_size(30u32) + .y_label_area_size(30u32) + .build_cartesian_2d(start_quote..end_quote, 0f64..max_amount) + .unwrap(); + + chart + .configure_mesh() + .y_desc("base amount") + .x_desc("quote amount") + .draw() + .unwrap(); + chart.draw_series(LineSeries::new(points, &RED)).unwrap(); + chart + .configure_series_labels() + .background_style(&WHITE.mix(0.8)) + .border_style(&BLACK) + .draw() + .unwrap(); + }); +} + +#[cfg(feature = "visualization")] +#[test] +fn slippage_graph() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_usdt = 1000000_u128 * unit; + let initial_usdc = 1000000_u128 * unit; + let pool_id = create_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::zero(), + Permill::zero(), + ); + + let start_quote = 0; + let end_quote = 120000; + let points = (start_quote..end_quote) + .map(|quote| { + let quote = quote * unit; + let base = ::get_exchange_value(pool_id, USDC, quote) + .expect("get_exchange_value failed"); + let slippage = if base <= quote { quote - base } else { base }; + (quote / unit, slippage as f64 / unit as f64) + }) + .collect::>(); + let max_amount = points.iter().copied().fold(f64::NAN, |x, (_, y)| f64::max(x, y)); + + use plotters::prelude::*; + let area = BitMapBackend::new("./curve_slippage.png", (1024, 768)).into_drawing_area(); + area.fill(&WHITE).unwrap(); + + let mut chart = ChartBuilder::on(&area) + .caption("Curve price, pool has 100000 USDC 100000 USDT", ("Arial", 25).into_font()) + .margin(100u32) + .x_label_area_size(30u32) + .y_label_area_size(30u32) + .build_cartesian_2d(start_quote..end_quote, 0f64..max_amount) + .unwrap(); + + chart.configure_mesh().y_desc("slippage").x_desc("quote amount").draw().unwrap(); + chart.draw_series(LineSeries::new(points, &RED)).unwrap(); + chart + .configure_series_labels() + .background_style(&WHITE.mix(0.8)) + .border_style(&BLACK) + .draw() + .unwrap(); + }); +} + +#[cfg(feature = "visualization")] +#[test] +fn curve_graph() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_usdt = 5_u128 * unit; + let initial_usdc = initial_usdt; + let pool_id = create_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 5_u16, + Permill::zero(), + Permill::zero(), + ); + let window = 15u128; + let max_base = (initial_usdt + window * unit) as f64 / unit as f64; + let max_quote = max_base; + let pool_account = StableSwap::account_id(&pool_id); + let range: Vec = (0..window).collect(); + + let quote_balance = Tokens::balance(USDT, &pool_account); + let base_balance = Tokens::balance(USDC, &pool_account); + let points1 = range + .iter() + .map(|_| { + let amount = unit; + Tokens::mint_into(USDC, &BOB, amount); + let _base = ::sell(&BOB, pool_id, USDC, amount, true) + .expect("sell failed"); + let pool_sell_asset_balance = + Tokens::balance(USDC, &pool_account) as f64 / unit as f64; + let pool_buy_asset_balance = + Tokens::balance(USDT, &pool_account) as f64 / unit as f64; + (pool_buy_asset_balance, pool_sell_asset_balance) + }) + .collect::>(); + let pool_id = create_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 5_u16, + Permill::zero(), + Permill::zero(), + ); + let pool_account = StableSwap::account_id(&pool_id); + let points2 = range + .iter() + .map(|_| { + let amount = unit; + Tokens::mint_into(USDT, &BOB, amount); + let _base = ::sell(&BOB, pool_id, USDT, amount, true) + .expect("sell failed"); + let pool_sell_asset_balance = + Tokens::balance(USDC, &pool_account) as f64 / unit as f64; + let pool_buy_asset_balance = + Tokens::balance(USDT, &pool_account) as f64 / unit as f64; + (pool_buy_asset_balance, pool_sell_asset_balance) + }) + .collect::>(); + let points: Vec<_> = points1.into_iter().rev().chain(points2.into_iter()).collect(); + use plotters::prelude::*; + let area = BitMapBackend::new("./curve_graph.png", (1024, 768)).into_drawing_area(); + area.fill(&WHITE).unwrap(); + + let mut chart = ChartBuilder::on(&area) + .caption("Curve price, pool has 1000 USDC 1000 USDT", ("Arial", 25).into_font()) + .margin(100u32) + .x_label_area_size(30u32) + .y_label_area_size(30u32) + .build_cartesian_2d(0f64..max_base as f64, 0f64..max_quote as f64) + .unwrap(); + + chart + .configure_mesh() + .y_desc("quote amount") + .x_desc("base amount") + .draw() + .unwrap(); + chart.draw_series(LineSeries::new(points, &RED)).unwrap(); + chart + .configure_series_labels() + .background_style(&WHITE.mix(0.8)) + .border_style(&BLACK) + .draw() + .unwrap(); + }); +} diff --git a/frame/curve-amm/src/weights.rs b/frame/curve-amm/src/weights.rs new file mode 100644 index 00000000000..3f12a09a1c3 --- /dev/null +++ b/frame/curve-amm/src/weights.rs @@ -0,0 +1,43 @@ +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(clippy::unnecessary_cast)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +pub trait WeightInfo { + fn create() -> Weight; + fn buy() -> Weight; + fn sell() -> Weight; + fn swap() -> Weight; + fn add_liquidity() -> Weight; + fn remove_liquidity() -> Weight; +} + +// For backwards compatibility and tests +impl WeightInfo for () { + fn create() -> Weight { + 10_000 + } + + fn buy() -> Weight { + 10_000 + } + + fn sell() -> Weight { + 10_000 + } + + fn swap() -> Weight { + 10_000 + } + + fn add_liquidity() -> Weight { + 10_000 + } + + fn remove_liquidity() -> Weight { + 10_000 + } +} diff --git a/frame/democracy/Cargo.toml b/frame/democracy/Cargo.toml index 27a14573ae6..f0852fa91db 100644 --- a/frame/democracy/Cargo.toml +++ b/frame/democracy/Cargo.toml @@ -1,56 +1,60 @@ [package] -name = "pallet-democracy" -version = "0.0.1" authors = ["Composable Developers"] -homepage = "https://composable.finance" +description = "FRAME pallet for democracy with multi currency support" edition = "2018" +homepage = "https://composable.finance" license = "Apache-2.0" -description = "FRAME pallet for democracy with multi currency support" +name = "pallet-democracy" readme = "README.md" +version = "0.0.1" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [dependencies] +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ + "derive", +] } composable-traits = { default-features = false, path = "../composable-traits" } +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } serde = { version = "1.0.130", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive" ] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-benchmarking = { default-features = false, optional = true, git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.16' } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } [dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } pallet-governance-registry = { path = "../governance-registry" } -pallet-scheduler = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -pallet-preimage = { package = "pallet-preimage", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +pallet-preimage = { package = "pallet-preimage", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +pallet-scheduler = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } [features] default = ["std"] -std = [ - "composable-traits/std", - "serde", - "codec/std", - "scale-info/std", - "sp-std/std", - "sp-io/std", - "frame-support/std", - "sp-runtime/std", - "frame-system/std", - "orml-tokens/std", - "orml-traits/std", -] runtime-benchmarks = [ - "frame-benchmarking", - "frame-system/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", + "frame-benchmarking", + "frame-system/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] +std = [ + "composable-traits/std", + "serde", + "codec/std", + "scale-info/std", + "sp-std/std", + "sp-io/std", + "frame-support/std", + "sp-runtime/std", + "frame-system/std", + "orml-tokens/std", + "orml-traits/std", ] try-runtime = ["frame-support/try-runtime"] diff --git a/frame/dex-router/Cargo.toml b/frame/dex-router/Cargo.toml index 7a33b1b3031..4365fe9de57 100644 --- a/frame/dex-router/Cargo.toml +++ b/frame/dex-router/Cargo.toml @@ -1,30 +1,32 @@ [package] -name = "pallet-dex-router" -version = "0.0.1" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" +homepage = "https://composable.finance" +name = "pallet-dex-router" rust-version = "1.56" +version = "0.0.1" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [dependencies] -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } composable-traits = { path = "../composable-traits", default-features = false } -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = '1', optional = true } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } pallet-curve-amm = { path = "../curve-amm", default-features = false } pallet-uniswap-v2 = { path = "../uniswap-v2", default-features = false } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } +serde = { version = '1', optional = true } [dependencies.codec] default-features = false @@ -33,20 +35,21 @@ package = "parity-scale-codec" version = "2.0.0" [dev-dependencies] -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6" } +composable-tests-helpers = { path = "../composable-tests-helpers" } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } pallet-currency-factory = { version = "0.0.1", path = "../currency-factory" } [features] default = ["std"] std = [ - "serde/std", - "codec/std", - "scale-info/std", - "frame-support/std", - "frame-system/std", - "sp-runtime/std", - "pallet-curve-amm/std", - "orml-traits/std", - "pallet-uniswap-v2/std", + "serde/std", + "codec/std", + "scale-info/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "pallet-curve-amm/std", + "orml-traits/std", + "pallet-uniswap-v2/std", ] diff --git a/frame/dex-router/src/lib.rs b/frame/dex-router/src/lib.rs index d26ae2f11f0..e77774d3c23 100644 --- a/frame/dex-router/src/lib.rs +++ b/frame/dex-router/src/lib.rs @@ -19,17 +19,13 @@ mod tests; pub mod pallet { use codec::{Codec, FullCodec}; use composable_traits::{ - defi::{CurrencyPair, LiftedFixedBalance}, - dex::{CurveAmm, DexRoute, DexRouteNode, DexRouter}, + defi::CurrencyPair, + dex::{Amm, DexRoute, DexRouteNode, DexRouter}, + math::SafeArithmetic, }; use core::fmt::Debug; use frame_support::pallet_prelude::*; - use sp_runtime::{ - traits::{ - AtLeast32BitUnsigned, CheckedAdd, CheckedMul, CheckedSub, IntegerSquareRoot, One, Zero, - }, - FixedPointOperand, - }; + use sp_runtime::traits::{CheckedAdd, One, Zero}; #[pallet::config] pub trait Config: frame_system::Config { @@ -49,19 +45,9 @@ pub mod pallet { + Codec + MaxEncodedLen + Copy - + Ord - + CheckedAdd - + CheckedSub - + CheckedMul - + AtLeast32BitUnsigned - + From // at least 64 bit + Zero - + One - + IntegerSquareRoot - + FixedPointOperand - + Into - + Into; // cannot do From, until LiftedFixedBalance integer part is larger than 128 - // bit + + Ord + + SafeArithmetic; /// The maximum hops in the route. #[pallet::constant] type MaxHopsInRoute: Get + MaxEncodedLen + TypeInfo; @@ -77,19 +63,16 @@ pub mod pallet { + CheckedAdd + Zero + One; - type PoolTokenIndex: Copy + Debug + Eq + Into + From; - type StableSwapDex: CurveAmm< + type StableSwapDex: Amm< AssetId = Self::AssetId, Balance = Self::Balance, AccountId = Self::AccountId, - PoolTokenIndex = Self::PoolTokenIndex, PoolId = Self::PoolId, >; - type ConstantProductDex: CurveAmm< + type ConstantProductDex: Amm< AssetId = Self::AssetId, Balance = Self::Balance, AccountId = Self::AccountId, - PoolTokenIndex = Self::PoolTokenIndex, PoolId = Self::PoolId, >; } @@ -117,8 +100,6 @@ pub mod pallet { PoolDoesNotExist, /// For given asset pair no route found. NoRouteFound, - /// Some error occured while performing exchange. - ExchangeError, } #[pallet::event] @@ -245,32 +226,101 @@ pub mod pallet { for route_node in &route { match route_node { DexRouteNode::Curve(pool_id) => { + let currency_pair = T::StableSwapDex::currency_pair(*pool_id)?; dy_t = T::StableSwapDex::exchange( who, *pool_id, - 0_u8.into(), - 1_u8.into(), + currency_pair, dx_t, T::Balance::zero(), - ) - .map_err(|_| Error::::ExchangeError)?; + true, + )?; dx_t = dy_t; }, DexRouteNode::Uniswap(pool_id) => { + let currency_pair = T::ConstantProductDex::currency_pair(*pool_id)?; dy_t = T::ConstantProductDex::exchange( who, *pool_id, - 0_u8.into(), - 1_u8.into(), + currency_pair, dx_t, T::Balance::zero(), - ) - .map_err(|_| Error::::ExchangeError)?; + true, + )?; dx_t = dy_t; }, } } Ok(dy_t) } + + fn sell( + who: &T::AccountId, + asset_pair: CurrencyPair, + amount: T::Balance, + ) -> Result { + Self::exchange(who, asset_pair, amount) + } + + fn buy( + who: &T::AccountId, + asset_pair: CurrencyPair, + amount: T::Balance, + ) -> Result { + let route = Self::get_route(asset_pair).ok_or(Error::::NoRouteFound)?; + let mut dy_t = amount; + let mut dx_t = T::Balance::zero(); + for route_node in route.iter().rev() { + match route_node { + DexRouteNode::Curve(pool_id) => { + let currency_pair = T::StableSwapDex::currency_pair(*pool_id)?; + dx_t = T::StableSwapDex::get_exchange_value( + *pool_id, + currency_pair.base, + dy_t, + )?; + dy_t = dx_t; + }, + DexRouteNode::Uniswap(pool_id) => { + let currency_pair = T::ConstantProductDex::currency_pair(*pool_id)?; + dx_t = T::ConstantProductDex::get_exchange_value( + *pool_id, + currency_pair.base, + dy_t, + )?; + dy_t = dx_t; + }, + } + } + for route_node in route { + match route_node { + DexRouteNode::Curve(pool_id) => { + let currency_pair = T::StableSwapDex::currency_pair(pool_id)?; + let dy_t = T::StableSwapDex::exchange( + who, + pool_id, + currency_pair, + dx_t, + T::Balance::zero(), + true, + )?; + dx_t = dy_t; + }, + DexRouteNode::Uniswap(pool_id) => { + let currency_pair = T::ConstantProductDex::currency_pair(pool_id)?; + let dy_t = T::ConstantProductDex::exchange( + who, + pool_id, + currency_pair, + dx_t, + T::Balance::zero(), + true, + )?; + dx_t = dy_t; + }, + } + } + Ok(dx_t) + } } } diff --git a/frame/dex-router/src/mock.rs b/frame/dex-router/src/mock.rs index 248acc77989..433d713ee1c 100644 --- a/frame/dex-router/src/mock.rs +++ b/frame/dex-router/src/mock.rs @@ -7,7 +7,7 @@ use sp_arithmetic::{traits::Zero, FixedU128}; use sp_core::H256; use sp_runtime::{ testing::Header, - traits::{BlakeTwo256, IdentityLookup}, + traits::{BlakeTwo256, ConvertInto, IdentityLookup}, FixedPointNumber, }; use system::EnsureRoot; @@ -34,7 +34,7 @@ frame_support::construct_runtime!( { System: frame_system::{Pallet, Call, Config, Storage, Event}, Balances: pallet_balances::{Pallet, Call, Storage, Event}, - CurveAmm: pallet_curve_amm::{Pallet, Call, Storage, Event}, + StableSwapAmm: pallet_curve_amm::{Pallet, Call, Storage, Event}, ConstantProductAmm: pallet_uniswap_v2::{Pallet, Call, Storage, Event}, LpTokenFactory: pallet_currency_factory::{Pallet, Storage, Event}, Tokens: orml_tokens::{Pallet, Call, Storage, Config, Event}, @@ -133,7 +133,6 @@ impl orml_tokens::Config for Test { } parameter_types! { - pub CurveAmmPrecision: FixedU128 = FixedU128::saturating_from_rational(1, 1_000_000_000); pub CurveAmmTestPalletID : PalletId = PalletId(*b"curve_am"); } @@ -142,11 +141,11 @@ impl pallet_curve_amm::Config for Test { type AssetId = AssetId; type Balance = Balance; type CurrencyFactory = LpTokenFactory; - type Precision = CurveAmmPrecision; - type LpToken = Tokens; + type Convert = ConvertInto; + type Assets = Tokens; type PoolId = PoolId; - type PoolTokenIndex = u32; type PalletId = CurveAmmTestPalletID; + type WeightInfo = (); } parameter_types! { @@ -159,11 +158,11 @@ impl pallet_uniswap_v2::Config for Test { type AssetId = AssetId; type Balance = Balance; type CurrencyFactory = LpTokenFactory; - type Precision = ConstantProductAmmPrecision; - type LpToken = Tokens; + type Convert = ConvertInto; + type Assets = Tokens; type PoolId = PoolId; - type PoolTokenIndex = u32; type PalletId = ConstantProductAmmTestPalletID; + type WeightInfo = (); } parameter_types! { #[derive(codec::Encode, codec::Decode, codec::MaxEncodedLen, TypeInfo)] @@ -176,8 +175,7 @@ impl dex_router::Config for Test { type Balance = Balance; type MaxHopsInRoute = MaxHopsCount; type PoolId = u32; - type PoolTokenIndex = u32; - type StableSwapDex = CurveAmm; + type StableSwapDex = StableSwapAmm; type ConstantProductDex = ConstantProductAmm; } diff --git a/frame/dex-router/src/tests.rs b/frame/dex-router/src/tests.rs index ba341698acc..d8e2c3043e5 100644 --- a/frame/dex-router/src/tests.rs +++ b/frame/dex-router/src/tests.rs @@ -1,70 +1,91 @@ use crate::{mock::*, Error}; +use composable_tests_helpers::test::helper::acceptable_computation_error; use composable_traits::{ defi::CurrencyPair, - dex::{CurveAmm as CurveAmmTrait, DexRouteNode, DexRouter as DexRouterTrait}, + dex::{Amm as AmmTrait, DexRouteNode, DexRouter as DexRouterTrait}, }; use frame_support::{assert_noop, assert_ok, traits::fungibles::Mutate}; -use sp_runtime::{FixedPointNumber, FixedU128, Permill}; +use sp_runtime::Permill; -// Create CurveAmm pool with given amounts added as liquidity to the pool. +// Create Amm pool with given amounts added as liquidity to the pool. fn create_curve_amm_pool( - assets: Vec, + assets: CurrencyPair, amounts: Vec, - amp_coeff: FixedU128, + amp_coeff: u16, fee: Permill, admin_fee: Permill, ) -> PoolId { - assert_ok!(Tokens::mint_into(assets[0], &ALICE, amounts[0])); - assert_ok!(Tokens::mint_into(assets[1], &ALICE, amounts[1])); - assert_ok!(Tokens::mint_into(assets[0], &BOB, amounts[0])); - assert_ok!(Tokens::mint_into(assets[1], &BOB, amounts[1])); + let base = assets.base; + let quote = assets.quote; + assert_ok!(Tokens::mint_into(base, &ALICE, amounts[0])); + assert_ok!(Tokens::mint_into(quote, &ALICE, amounts[1])); + assert_ok!(Tokens::mint_into(base, &BOB, amounts[0])); + assert_ok!(Tokens::mint_into(quote, &BOB, amounts[1])); - let p = CurveAmm::create_pool(&ALICE, assets, amp_coeff, fee, admin_fee); + let p = StableSwapAmm::do_create_pool(&ALICE, assets, amp_coeff, fee, admin_fee); assert_ok!(&p); let pool_id = p.unwrap(); // 1 USDC = 1 USDT - assert_ok!(CurveAmm::add_liquidity(&ALICE, pool_id, amounts.clone(), 0_u128)); - assert_ok!(CurveAmm::add_liquidity(&BOB, pool_id, amounts, 0_u128)); + assert_ok!(::add_liquidity( + &ALICE, pool_id, amounts[0], amounts[1], 0_u128, true + )); + assert_ok!(::add_liquidity( + &BOB, pool_id, amounts[0], amounts[1], 0_u128, true + )); pool_id } // Create ConstantProductAmm pool with given amounts added as liquidity to the pool. fn create_constant_product_amm_pool( - assets: Vec, + assets: CurrencyPair, amounts: Vec, fee: Permill, admin_fee: Permill, ) -> PoolId { - assert_ok!(Tokens::mint_into(assets[0], &ALICE, amounts[0])); - assert_ok!(Tokens::mint_into(assets[1], &ALICE, amounts[1])); - assert_ok!(Tokens::mint_into(assets[0], &BOB, amounts[0])); - assert_ok!(Tokens::mint_into(assets[1], &BOB, amounts[1])); + let base = assets.base; + let quote = assets.quote; + assert_ok!(Tokens::mint_into(base, &ALICE, amounts[0])); + assert_ok!(Tokens::mint_into(quote, &ALICE, amounts[1])); + assert_ok!(Tokens::mint_into(base, &BOB, amounts[0])); + assert_ok!(Tokens::mint_into(quote, &BOB, amounts[1])); // Create ConstantProductAmm pool - let p = ConstantProductAmm::create_pool(&ALICE, assets, fee, admin_fee); + let p = ConstantProductAmm::do_create_pool(&ALICE, assets, fee, admin_fee); assert_ok!(&p); let pool_id = p.unwrap(); // Add liquidity from ALICE's account to pool - assert_ok!(ConstantProductAmm::add_liquidity(&ALICE, pool_id, amounts.clone(), 0_u128)); + assert_ok!(::add_liquidity( + &ALICE, pool_id, amounts[0], amounts[1], 0_u128, true + )); // Add liquidity from BOB's account to pool - assert_ok!(ConstantProductAmm::add_liquidity(&BOB, pool_id, amounts, 0_u128)); + assert_ok!(::add_liquidity( + &BOB, pool_id, amounts[0], amounts[1], 0_u128, true + )); pool_id } -fn create_usdc_usdt_pool() -> PoolId { - let amp_coeff = FixedU128::saturating_from_rational(1000_i128, 1_i128); +fn create_usdt_usdc_pool() -> PoolId { + let unit = 1_000_000_000_000_u128; + // usdc usdt have same price which is 1 USD + let initial_usdc = 1_000_000_000 * unit; + let initial_usdt = 1_000_000_000 * unit; + let amp_coeff = 100; let fee = Permill::zero(); let admin_fee = Permill::zero(); - let assets = vec![USDC, USDT]; - let amounts = vec![100000, 100000]; + let assets = CurrencyPair::new(USDT, USDC); + let amounts = vec![initial_usdt, initial_usdc]; create_curve_amm_pool(assets, amounts, amp_coeff, fee, admin_fee) } -fn create_eth_usdc_pool() -> PoolId { +fn create_usdc_eth_pool() -> PoolId { + let unit = 1_000_000_000_000_u128; + let eth_price = 3000_u128; + let eth_balance = 1_000_000_000 * unit; + let usdc_balance = eth_price * eth_balance; let fee = Permill::zero(); let admin_fee = Permill::zero(); - let assets = vec![ETH, USDC]; - let amounts = vec![1000, 3000000]; + let assets = CurrencyPair::new(USDC, ETH); + let amounts = vec![usdc_balance, eth_balance]; create_constant_product_amm_pool(assets, amounts, fee, admin_fee) } @@ -75,8 +96,8 @@ fn get_route_tests() { assert_eq!(DexRouter::get_route(currency_pair), None); let dex_route = vec![ - DexRouteNode::Uniswap(create_eth_usdc_pool()), - DexRouteNode::Curve(create_usdc_usdt_pool()), + DexRouteNode::Uniswap(create_usdc_eth_pool()), + DexRouteNode::Curve(create_usdt_usdc_pool()), ]; assert_ok!(DexRouter::update_route( &ALICE, @@ -95,8 +116,8 @@ fn update_route_tests() { // insert let dex_route = vec![ - DexRouteNode::Uniswap(create_eth_usdc_pool()), - DexRouteNode::Curve(create_usdc_usdt_pool()), + DexRouteNode::Uniswap(create_usdc_eth_pool()), + DexRouteNode::Curve(create_usdt_usdc_pool()), ]; assert_ok!(DexRouter::update_route( &ALICE, @@ -107,8 +128,8 @@ fn update_route_tests() { // update let dex_route = vec![ - DexRouteNode::Curve(create_usdc_usdt_pool()), - DexRouteNode::Uniswap(create_eth_usdc_pool()), + DexRouteNode::Curve(create_usdt_usdc_pool()), + DexRouteNode::Uniswap(create_usdc_eth_pool()), ]; assert_ok!(DexRouter::update_route( &ALICE, @@ -123,9 +144,9 @@ fn update_route_tests() { // invalid route, case #1 let dex_route = vec![ - DexRouteNode::Curve(create_usdc_usdt_pool()), + DexRouteNode::Curve(create_usdt_usdc_pool()), DexRouteNode::Curve(42), // fake route - DexRouteNode::Uniswap(create_eth_usdc_pool()), + DexRouteNode::Uniswap(create_usdc_eth_pool()), ]; assert_noop!( DexRouter::update_route(&ALICE, currency_pair, Some(dex_route.try_into().unwrap())), @@ -134,8 +155,8 @@ fn update_route_tests() { // invalid route, case #2 let dex_route = vec![ - DexRouteNode::Curve(create_usdc_usdt_pool()), - DexRouteNode::Uniswap(create_eth_usdc_pool()), + DexRouteNode::Curve(create_usdt_usdc_pool()), + DexRouteNode::Uniswap(create_usdc_eth_pool()), DexRouteNode::Uniswap(42), // fake route ]; assert_noop!( @@ -148,21 +169,55 @@ fn update_route_tests() { #[test] fn exchange_tests() { new_test_ext().execute_with(|| { - let currency_pair = CurrencyPair { base: ETH, quote: USDT }; + let unit = 1_000_000_000_000_u128; + let currency_pair = CurrencyPair { base: USDT, quote: ETH }; + let dex_route = vec![ + DexRouteNode::Uniswap(create_usdc_eth_pool()), + DexRouteNode::Curve(create_usdt_usdc_pool()), + ]; + assert_ok!(DexRouter::update_route( + &ALICE, + currency_pair, + Some(dex_route.try_into().unwrap()) + )); + assert_ok!(Tokens::mint_into(ETH, &CHARLIE, 10_u128 * unit)); + let dy = DexRouter::exchange(&CHARLIE, currency_pair, 1_u128 * unit); + assert_ok!(dy); + let dy = dy.unwrap(); + sp_std::if_std! { + println!("exchange value {:?}", dy); + } + let expected_value = 3000 * unit; + let precision = 100; + let epsilon = 1; + assert_ok!(acceptable_computation_error(dy, expected_value, precision, epsilon)); + }); +} + +#[test] +fn buy_test() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let currency_pair = CurrencyPair { base: USDT, quote: ETH }; let dex_route = vec![ - DexRouteNode::Uniswap(create_eth_usdc_pool()), - DexRouteNode::Curve(create_usdc_usdt_pool()), + DexRouteNode::Uniswap(create_usdc_eth_pool()), + DexRouteNode::Curve(create_usdt_usdc_pool()), ]; + // USDC/ETH + // USDT/USDC + // USDT/ETH assert_ok!(DexRouter::update_route( &ALICE, currency_pair, Some(dex_route.try_into().unwrap()) )); - assert_ok!(Tokens::mint_into(ETH, &CHARLIE, 10_u128)); - let dy = DexRouter::exchange(&CHARLIE, currency_pair, 1_u128); + assert_ok!(Tokens::mint_into(ETH, &CHARLIE, 2_u128 * unit)); + let dy = DexRouter::buy(&CHARLIE, currency_pair, 3000_u128 * unit); assert_ok!(dy); let dy = dy.unwrap(); - assert!(3000 >= dy); - assert!(2995 < dy); + let expected_value = 3000 * unit; + let precision = 100; + let epsilon = 1; + assert_ok!(acceptable_computation_error(dy, expected_value, precision, epsilon)); }); } diff --git a/frame/dutch-auction/Cargo.toml b/frame/dutch-auction/Cargo.toml index 18c3a866a15..1b6bee2c931 100644 --- a/frame/dutch-auction/Cargo.toml +++ b/frame/dutch-auction/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "pallet-dutch-auction" -version = "0.0.1" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" +homepage = "https://composable.finance" +name = "pallet-dutch-auction" +version = "0.0.1" [package.metadata.docs.rs] @@ -16,30 +16,32 @@ package = "parity-scale-codec" version = "2.0.0" [dependencies] -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -smallvec = "1.7.0" -serde = { version = "1.0.130", optional = true } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } +composable-traits = { path = "../composable-traits", default-features = false } +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } num-traits = { version = "0.2.14", default-features = false } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-benchmarking = { default-features = false, optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.16' } -composable-traits = { path = "../composable-traits", default-features = false } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } +serde = { version = "1.0.130", optional = true } +smallvec = "1.7.0" +sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } [dev-dependencies] -proptest = "1.0" -pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +composable-tests-helpers = { path = "../composable-tests-helpers" } +hex-literal = { version = "0.3.3" } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +pallet-assets = { path = '../assets' } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } pallet-currency-factory = { path = "../currency-factory" } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -pallet-assets = { path = '../assets', default-features = false} -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -hex-literal = {version = "0.3.3", default-features = false } -composable-tests-helpers = { path = "../composable-tests-helpers" } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +proptest = "1.0" [package.metadata.cargo-udeps.ignore] development = ["composable-tests-helpers"] @@ -47,22 +49,22 @@ development = ["composable-tests-helpers"] [features] default = ["std"] std = [ - "sp-std/std", - "sp-runtime/std", - "sp-io/std", - "sp-core/std", - "sp-arithmetic/std", - "serde", - "scale-info/std", - "orml-traits/std", - "frame-system/std", - "frame-support/std", - "codec/std", - "composable-traits/std", + "sp-std/std", + "sp-runtime/std", + "sp-io/std", + "sp-core/std", + "sp-arithmetic/std", + "serde", + "scale-info/std", + "orml-traits/std", + "frame-system/std", + "frame-support/std", + "codec/std", + "composable-traits/std", ] runtime-benchmarks = [ - "frame-benchmarking", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", ] diff --git a/frame/dutch-auction/src/math.rs b/frame/dutch-auction/src/math.rs index 53ffefd8282..34d2ac322a1 100644 --- a/frame/dutch-auction/src/math.rs +++ b/frame/dutch-auction/src/math.rs @@ -4,7 +4,7 @@ use composable_traits::{ defi::LiftedFixedBalance, - math::SafeArithmetic, + math::{SafeDiv, SafeMul}, time::{DurationSeconds, LinearDecrease, StairstepExponentialDecrease, TimeReleaseFunction}, }; diff --git a/frame/dutch-auction/src/mock/runtime.rs b/frame/dutch-auction/src/mock/runtime.rs index 8311781c22e..ffa2a4e10fd 100644 --- a/frame/dutch-auction/src/mock/runtime.rs +++ b/frame/dutch-auction/src/mock/runtime.rs @@ -54,56 +54,32 @@ frame_support::construct_runtime! { parameter_types! { pub const SS58Prefix: u8 = 42; pub const BlockHashCount: u64 = 250; - } impl frame_system::Config for Runtime { type BaseCallFilter = Everything; - type BlockWeights = (); - type BlockLength = (); - type Origin = Origin; - type Call = Call; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Header = Header; - type Event = Event; - type BlockHashCount = BlockHashCount; - type DbWeight = (); - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = SS58Prefix; - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; } diff --git a/frame/governance-registry/Cargo.toml b/frame/governance-registry/Cargo.toml index 7358350c1cf..1cd13a66e65 100644 --- a/frame/governance-registry/Cargo.toml +++ b/frame/governance-registry/Cargo.toml @@ -1,27 +1,29 @@ [package] -name = "pallet-governance-registry" -version = "0.0.1" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" +homepage = "https://composable.finance" +name = "pallet-governance-registry" +version = "0.0.1" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [dependencies] -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } composable-traits = { path = "../composable-traits", default-features = false } -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } [dependencies.codec] default-features = false @@ -30,14 +32,14 @@ package = "parity-scale-codec" version = "2.0.0" [dev-dependencies] -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } [features] default = ["std"] std = [ - "codec/std", - "frame-support/std", - "frame-system/std", - "sp-runtime/std", - "orml-traits/std", + "codec/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "orml-traits/std", ] diff --git a/frame/lending/Cargo.toml b/frame/lending/Cargo.toml index 72a2b9467b6..f1f8155c893 100644 --- a/frame/lending/Cargo.toml +++ b/frame/lending/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "pallet-lending" -version = "0.0.1" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" +homepage = "https://composable.finance" +name = "pallet-lending" +version = "0.0.1" [package.metadata.docs.rs] @@ -19,65 +19,73 @@ package = "parity-scale-codec" version = "2.0.0" [dependencies] -frame-benchmarking = { default-features = false, optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.16' } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", optional = true } +pallet-timestamp = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", optional = true } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -composable-traits = { default-features = false, path = "../composable-traits" } composable-support = { default-features = false, path = "../composable-support" } -pallet-oracle = { default-features = false, optional = true, version = "1.0.0", path = "../oracle" } +composable-traits = { default-features = false, path = "../composable-traits" } +pallet-oracle = { default-features = false, optional = true, path = "../oracle" } pallet-vault = { default-features = false, path = "../vault", optional = true } log = { version = "0.4.14", default-features = false } num-traits = { version = "0.2.14", default-features = false } plotters = { version = "0.3.1", optional = true } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = '1.0.130' } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } [dev-dependencies] +composable-tests-helpers = { path = "../composable-tests-helpers" } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } hex-literal = "0.3.3" once_cell = "1.8.0" -proptest = "0.9.6" -smallvec = "1.7.0" -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +pallet-assets = { path = "../assets" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } pallet-currency-factory = { path = "../currency-factory" } +pallet-dutch-auction = { path = "../dutch-auction" } pallet-liquidations = { path = "../liquidations" } -pallet-dutch-auction = { path = "../dutch-auction", default-features = false } -composable-tests-helpers = { path = "../composable-tests-helpers", default-features = false } -pallet-assets = { path = '../assets', default-features = false} - +pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +proptest = "1.0" +serde = { version = "1.0.130" } +smallvec = "1.7.0" [features] default = ["std"] std = [ - "codec/std", - "log/std", - "frame-support/std", - "frame-system/std", - "sp-runtime/std", - "sp-io/std", - "sp-core/std", - "sp-std/std", - "sp-arithmetic/std", - "composable-traits/std", - "pallet-vault/std", - "scale-info/std", + "codec/std", + "log/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-io/std", + "sp-core/std", + "sp-std/std", + "sp-arithmetic/std", + "composable-traits/std", + "pallet-vault/std", + "scale-info/std", + "pallet-oracle/std", ] runtime-benchmarks = [ - "frame-benchmarking", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "pallet-oracle/runtime-benchmarks", + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-oracle/runtime-benchmarks", + "pallet-vault/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", ] visualization = ["plotters"] diff --git a/frame/lending/README.md b/frame/lending/README.md index 8a375fd900a..c0b11ffa4ad 100644 --- a/frame/lending/README.md +++ b/frame/lending/README.md @@ -1,14 +1,12 @@ - - # [Overview](https://app.clickup.com/20465559/v/dc/kghwq-20761/kghwq-3621) See overview of more bussiness and architectural state of lending and all know features. ## Technical Reference -Lending = Self + [Liquidations](liqudaitons) + [Oracle](../oracle) + [Vault](../vault) + OCW +Lending = Self + [Liquidations](liquidations) + [Oracle](../oracle) + [Vault](../vault) + OCW -Market = Isolated Currency Pair + Configuration. +Market = Isolated Currency Pair + Configuration. Oracle = only Pairs with Prices are allowed. @@ -24,4 +22,4 @@ Lending is executed after Vault. On block initialization. If can withdraw from V Borrowing is not allowed if we must liquidate (the vault is expecting the strategy to be liquidated) or if we market have enough funds or if have not enough collateral. -When repaying, we do not transfer the amount back to the vault. This is done within the pallet hooks on each block update.. It actually allows to use some deposit asset by other transactions in same block to borrow. \ No newline at end of file +When repaying, we do not transfer the amount back to the vault. This is done within the pallet hooks on each block update.. It actually allows to use some deposit asset by other transactions in same block to borrow. diff --git a/frame/lending/lending.plantuml b/frame/lending/lending.plantuml index f780fb9c795..06b6636b6a1 100644 --- a/frame/lending/lending.plantuml +++ b/frame/lending/lending.plantuml @@ -3,7 +3,7 @@ actor Bob as bob actor Charlie as charlie participant Lending as lending - participant Liquidation as liqudation + participant Liquidation as liquidation control Governance as governance participant Vault as vault @@ -37,20 +37,20 @@ ... - group Liqudaiton (IN PROGRESS) + group Liquidation (IN PROGRESS) charlie -> lending : Borrow ... oracle_bot -> oracle : Make collateral factor bad lending_bot -> lending : Liquidate Charlie collateral - lending -> liqudation: Liquidate - liqudation -> sell: Sell via choses strategy + lending -> liquidation: Liquidate + liquidation -> sell: Sell via choses strategy note left - default is auction (multiblock) - can be DEX or external (XCMP) DEX - XCMP is multi block process end note ... - lending_bot -> lending : Finalize liqudaiton + lending_bot -> lending : Finalize liquidation end @enduml diff --git a/frame/lending/proptest-regressions/tests.txt b/frame/lending/proptest-regressions/tests.txt index c3a14efc06e..aae5affd53a 100644 --- a/frame/lending/proptest-regressions/tests.txt +++ b/frame/lending/proptest-regressions/tests.txt @@ -8,3 +8,4 @@ cc 105541697ded40d7111e1cd357efd01fe710dfdeda9d88044a73316520487f24 # shrinks to cc 738fc7fe1be060a08d13e3e2fa521af22fd53a5b0f5a50d8042fe88c4ca2a5a4 # shrinks to depth = 0 cc 52628c1411e4d9f8f7abaf6ad392c47e27083cf0a67294329a08f2f28a05e624 # shrinks to amount = 1000 cc ef61546023a270a01b0b7586ed06ea032b11e5b016464600d167dfc39cd3298c # shrinks to amount = 1000 +cc a86d61e12bf3f1b42d240a6c693f8845bede3f36f44274996b9af889df6d2fcc # shrinks to (amount1, amount2) = (1000, 1000) diff --git a/frame/lending/src/benchmarking.rs b/frame/lending/src/benchmarking.rs index 633b22eca19..3d8c23366ab 100644 --- a/frame/lending/src/benchmarking.rs +++ b/frame/lending/src/benchmarking.rs @@ -1,16 +1,23 @@ -use super::*; +//! Benchmarks and sanity tests for lending. Only test that action do not error, not that produce +//! positive side effects -use crate::Pallet as Lending; +use super::{setup::*, *}; +use crate::{self as pallet_lending, Pallet as Lending}; +use composable_support::validation::Validated; use composable_traits::{ - lending::{math::InterestRateModel, CreateInput, Lending as LendingTrait}, - vault::Vault, + defi::{CurrencyPair, DeFiComposableConfig, MoreThanOneFixedU128}, + lending::{math::InterestRateModel, CreateInput, Lending as LendingTrait, UpdateInput}, + oracle::Price, + vault::StrategicVault, }; use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller}; -use frame_system::{EventRecord, RawOrigin}; +use frame_support::traits::fungibles::Mutate; +use frame_system::EventRecord; use sp_runtime::{FixedPointNumber, Percent, Perquintill}; use sp_std::prelude::*; -fn assert_last_event(generic_event: ::Event) { +#[allow(dead_code)] +pub fn assert_last_event(generic_event: ::Event) { let events = frame_system::Pallet::::events(); let system_event: ::Event = generic_event.into(); // compare to the last event record @@ -18,224 +25,289 @@ fn assert_last_event(generic_event: ::Event) { assert_eq!(event, &system_event); } -const BTC: u128 = 1000; -const USDT: u128 = 2000; - -fn set_price(asset_id: u128, price: u64) { +pub fn set_price< + T: pallet_lending::Config + pallet_oracle::Config + composable_traits::defi::DeFiComposableConfig, +>( + asset_id: T::MayBeAssetId, + price: u64, +) { + let asset_id = asset_id.encode(); + let asset_id = ::AssetId::decode(&mut &asset_id[..]).unwrap(); pallet_oracle::Prices::::insert( - ::AssetId::from(asset_id), - pallet_oracle::Price { - price: ::PriceValue::from(price), - block: 0u32.into(), - }, + asset_id, + Price { price: ::PriceValue::from(price), block: 0_u32.into() }, ); } fn set_prices() { - set_price::(BTC, 48_000u64); - set_price::(USDT, 1u64); + let pair = assets::(); + set_price::(pair.base, 48_000_000_000_u64); + set_price::(pair.quote, 1_000_000_000_u64); } -fn create_market( +#[allow(dead_code)] +fn create_new_market( manager: T::AccountId, - borrow_asset: u128, - collateral_asset: u128, + borrow_asset: ::MayBeAssetId, + collateral_asset: ::MayBeAssetId, ) -> (crate::MarketIndex, ::VaultId) { - let market_config = CreateInput { - liquidator: None, - manager, - reserved: Perquintill::from_percent(10), - collateral_factor: MoreThanOneFixedU128::saturating_from_rational(200, 100), - under_collaterized_warn_percent: Percent::from_percent(10), - }; - Lending::::create( - ::AssetId::from(borrow_asset), - ::AssetId::from(collateral_asset), - market_config, - &InterestRateModel::default(), - ) - .unwrap() + let market_config = create_market_config::(borrow_asset, collateral_asset); + Lending::::create(manager, market_config).unwrap() } -benchmarks! { - create_new_market { - let caller: T::AccountId = whitelisted_caller(); - let borrow_asset_id = ::AssetId::from(BTC); - let collateral_asset_id = ::AssetId::from(USDT); - let reserved_factor = Perquintill::from_percent(10); - let collateral_factor = MoreThanOneFixedU128::saturating_from_rational(200, 100); - let under_collaterized_warn_percent = Percent::from_percent(10); - let market_id = MarketIndex::new(1); - let vault_id = 1u64.into(); - set_prices::(); - }: _( - RawOrigin::Signed(caller.clone()), - borrow_asset_id, - collateral_asset_id, - reserved_factor, - collateral_factor, - under_collaterized_warn_percent, - InterestRateModel::default(), - None - ) - verify { - assert_last_event::(Event::NewMarketCreated { - market_id, - vault_id, - manager: caller, - borrow_asset_id, - collateral_asset_id, - reserved_factor, - collateral_factor, - }.into()) - } - - deposit_collateral { - let caller: T::AccountId = whitelisted_caller(); - let market: MarketIndex = MarketIndex::new(1u32); - let amount: T::Balance = 1_000_000u64.into(); - set_prices::(); - let _ = create_market::(caller.clone(), BTC, USDT); - ::Currency::mint_into(USDT.into(), &caller, amount).unwrap(); - }: _(RawOrigin::Signed(caller.clone()), market, amount) - verify { - assert_last_event::(Event::CollateralDeposited { - sender: caller, - market_id: market, - amount, - }.into()) +fn create_market_config( + collateral_asset: ::MayBeAssetId, + borrow_asset: ::MayBeAssetId, +) -> CreateInput<::LiquidationStrategyId, ::MayBeAssetId> { + CreateInput { + updatable: UpdateInput { + collateral_factor: MoreThanOneFixedU128::saturating_from_rational(200_u128, 100_u128), + under_collaterized_warn_percent: Percent::from_percent(10), + liquidators: vec![], + interest_rate_model: InterestRateModel::default(), + }, + reserved_factor: Perquintill::from_percent(10), + currency_pair: CurrencyPair::new(collateral_asset, borrow_asset), } +} - withdraw_collateral { - let caller: T::AccountId = whitelisted_caller(); - let market: MarketIndex = MarketIndex::new(1_u32); - let amount: T::Balance = 1_000_000_u64.into(); - set_prices::(); - let (market, _vault_id) = create_market::(caller.clone(), BTC, USDT); - ::Currency::mint_into(USDT.into(), &caller, amount).unwrap(); - Lending::::deposit_collateral_internal(&market, &caller, amount).unwrap(); - }: _(RawOrigin::Signed(caller.clone()), market, amount) - verify { - assert_last_event::(Event::CollateralWithdrawn { - sender: caller, - market_id: market, - amount - }.into()) +benchmarks! { + where_clause { + where + T: + pallet_oracle::Config + + pallet_lending::Config + + DeFiComposableConfig + + pallet_balances::Config + + frame_system::Config + + pallet_timestamp::Config + + pallet_vault::Config, + ::Balance : From, + ::BlockNumber : From, + ::Moment : From, + ::Balance : From, } - - borrow { - let caller: T::AccountId = whitelisted_caller(); - let balance: T::Balance = 1_000_000u64.into(); + create_market { + let caller= whitelisted_caller::(); + let origin = whitelisted_origin::(); + let amount: ::Balance = 1_000_000_u64.into(); + let bank: ::Balance = 10_000_000_000_000_u64.into(); + let pair = assets::(); set_prices::(); - let (market_id, vault_id) = create_market::(caller.clone(), BTC, USDT); - ::Currency::mint_into(USDT.into(), &caller, balance * 6u64.into()).unwrap(); - ::Currency::mint_into(BTC.into(), &caller, balance * 6u64.into()).unwrap(); - Lending::::deposit_collateral_internal(&market_id, &caller, balance * 2u64.into()).unwrap(); - ::Vault::deposit(&vault_id, &caller, balance * 2u64.into()).unwrap(); - let amount_to_borrow: T::Balance = 0u32.into(); - }: _(RawOrigin::Signed(caller.clone()), market_id, amount_to_borrow) - verify { - assert_last_event::(Event::Borrowed { - sender: caller, - market_id, - amount: amount_to_borrow - }.into()) + let input = create_market_config::(pair.base, pair.quote); + ::MultiCurrency::mint_into(pair.base, &caller, bank).unwrap(); + ::MultiCurrency::mint_into(pair.quote, &caller, bank).unwrap(); + } : { + Lending::::create_market(origin.into(), Validated::new(input).unwrap()).unwrap() } - - repay_borrow { - let caller: T::AccountId = whitelisted_caller(); + deposit_collateral { + let caller= whitelisted_caller::(); + let origin = whitelisted_origin::(); + let amount: ::Balance = 1_000_000_u64.into(); + let bank: ::Balance = 10_000_000_000_000_u64.into(); + let pair = assets::(); + let input = create_market_config::(pair.base, pair.quote); set_prices::(); - let (market_id, vault_id) = create_market::(caller.clone(), BTC, USDT); - let balance: T::Balance = 1_000_000u64.into(); - ::Currency::mint_into(USDT.into(), &caller, balance * 6u64.into()).unwrap(); - ::Currency::mint_into(BTC.into(), &caller, balance * 6u64.into()).unwrap(); - Lending::::deposit_collateral_internal(&market_id, &caller, balance * 2u64.into()).unwrap(); - ::Vault::deposit(&vault_id, &caller, balance * 2u64.into()).unwrap(); - let repay_amount: T::Balance = 0u32.into(); - Lending::::borrow_internal(&market_id, &caller, repay_amount).unwrap(); - crate::LastBlockTimestamp::::put(6); - }: _(RawOrigin::Signed(caller.clone()), market_id, caller.clone(), repay_amount) - verify { - assert_last_event::( - Event::RepaidBorrow { - sender: caller.clone(), - market_id, - beneficiary: caller, - amount: repay_amount, - }.into() - ) - } - - now { - }: { - Lending::::now() - } - - accrue_interest { - let caller: T::AccountId = whitelisted_caller(); - let (borrow_asset_id, collateral_asset_id) = (1u32, 2u32); - set_price::(borrow_asset_id.into(), u64::from(borrow_asset_id) * 10); - set_price::(collateral_asset_id.into(), u64::from(collateral_asset_id) * 10); - let (market_id, _) = create_market::(caller, borrow_asset_id.into(), collateral_asset_id.into()); - }: { - Lending::::accrue_interest(&market_id, 6).unwrap() - } - - account_id { - let caller: T::AccountId = whitelisted_caller(); - let (borrow_asset_id, collateral_asset_id) = (1u32, 2u32); - set_price::(borrow_asset_id.into(), u64::from(borrow_asset_id) * 10); - set_price::(collateral_asset_id.into(), u64::from(collateral_asset_id) * 10); - let (market_id, _) = create_market::(caller, borrow_asset_id.into(), collateral_asset_id.into()); - }: { - Lending::::account_id(&market_id) - } - - available_funds { - let caller: T::AccountId = whitelisted_caller(); - let (borrow_asset_id, collateral_asset_id) = (1u32, 2u32); - set_price::(borrow_asset_id.into(), u64::from(borrow_asset_id) * 10); - set_price::(collateral_asset_id.into(), u64::from(collateral_asset_id) * 10); - let (market_id, _) = create_market::(caller.clone(), borrow_asset_id.into(), collateral_asset_id.into()); - let market_config = Markets::::try_get(market_id).unwrap(); - }: { - Lending::::available_funds(&market_config, &caller).unwrap() - } - - handle_withdrawable { - let caller: T::AccountId = whitelisted_caller(); - let (borrow_asset_id, collateral_asset_id) = (1_u32, 2u32); - set_price::(borrow_asset_id.into(), u64::from(borrow_asset_id) * 10); - set_price::(collateral_asset_id.into(), u64::from(collateral_asset_id) * 10); - let (market_id, vault_id) = create_market::(caller.clone(), borrow_asset_id.into(), collateral_asset_id.into()); - let market_config = Markets::::try_get(market_id).unwrap(); - let balance = 0_u32.into(); - }: { - Lending::::handle_withdrawable(&market_config, &caller, balance).unwrap() - } + ::MultiCurrency::mint_into(pair.base, &caller, bank).unwrap(); + ::MultiCurrency::mint_into(pair.quote, &caller, bank).unwrap(); + Lending::::create_market(origin.clone().into(), Validated::new(input).unwrap()).unwrap(); + let market_id = MarketIndex::new(1); + }: { + Lending::::deposit_collateral(origin.into(), market_id, amount).unwrap(); + } + withdraw_collateral { + let caller= whitelisted_caller::(); + let origin = whitelisted_origin::(); + let amount: ::Balance = 1_000_000_u64.into(); + let part: ::Balance = 1_000_u64.into(); + let bank: ::Balance = 10_000_000_000_000_u64.into(); + let pair = assets::(); + let input = create_market_config::(pair.base, pair.quote); + set_prices::(); + ::MultiCurrency::mint_into(pair.base, &caller, bank).unwrap(); + ::MultiCurrency::mint_into(pair.quote, &caller, bank).unwrap(); + Lending::::create_market(origin.clone().into(), Validated::new(input).unwrap()).unwrap(); + let market_id = MarketIndex::new(1); + Lending::::deposit_collateral(origin.clone().into(), market_id, amount).unwrap(); + }: { + Lending::::withdraw_collateral(origin.into(), market_id, part).unwrap(); + } + borrow { + let caller= whitelisted_caller::(); + let origin = whitelisted_origin::(); + let amount: ::Balance = 1_000_000_u64.into(); + let part: ::Balance = 1_000_u64.into(); + let bank: ::Balance = 10_000_000_000_000_u64.into(); + let pair = assets::(); + let input = create_market_config::(pair.base, pair.quote); + set_prices::(); + //pallet_balances:::: + as frame_support::traits::fungible::Mutate>::mint_into(&caller, 10_000_000_000_000_u64.into()).unwrap(); + ::MultiCurrency::mint_into(pair.base, &caller, bank).unwrap(); + ::MultiCurrency::mint_into(pair.quote, &caller, bank).unwrap(); + Lending::::create_market(origin.clone().into(), Validated::new(input).unwrap()).unwrap(); + let market_id = MarketIndex::new(1); + Lending::::deposit_collateral(origin.clone().into(), market_id, amount).unwrap(); + }: { + Lending::::borrow(origin.into(), market_id, part).unwrap(); + } + repay_borrow { + let caller= whitelisted_caller::(); + let origin = whitelisted_origin::(); + let amount: ::Balance = 1_000_000_000_000_u64.into(); + let borrow_amount: ::Balance = 1_000_000_000_u64.into(); + let part: ::Balance = 1_000_u64.into(); + let bank: ::Balance = 10_000_000_000_000_u64.into(); + let pair = assets::(); + let input = create_market_config::(pair.base, pair.quote); + set_prices::(); + as frame_support::traits::fungible::Mutate>::mint_into(&caller, 10_000_000_000_000_u64.into()).unwrap(); + ::MultiCurrency::mint_into(pair.base, &caller, bank).unwrap(); + ::MultiCurrency::mint_into(pair.quote, &caller, bank).unwrap(); + Lending::::create_market(origin.clone().into(), Validated::new(input).unwrap()).unwrap(); + let market_id = MarketIndex::new(1); + Lending::::deposit_collateral(origin.clone().into(), market_id, amount).unwrap(); + Lending::::borrow(origin.clone().into(), market_id, borrow_amount).unwrap(); + produce_block::(42_u32.into(),4200_u64.into()); + produce_block::(43_u32.into(),4300_u64.into()); - handle_depositable { - let caller: T::AccountId = whitelisted_caller(); - let (borrow_asset_id, collateral_asset_id) = (1u32, 2u32); - set_price::(borrow_asset_id.into(), u64::from(borrow_asset_id) * 10); - set_price::(collateral_asset_id.into(), u64::from(collateral_asset_id) * 10); - let (market_id, _) = create_market::(caller.clone(), borrow_asset_id.into(), collateral_asset_id.into()); - let market_config = Markets::::try_get(market_id).unwrap(); - let balance = 1_000_000u32.into(); - }: { - Lending::::handle_depositable(&market_config, &caller, balance).unwrap() - } + }: { + Lending::::repay_borrow(origin.clone().into(), market_id, caller, part).unwrap(); + } + now { + }: { + Lending::::now() + } - handle_must_liquidate { - let caller: T::AccountId = whitelisted_caller(); - let (borrow_asset_id, collateral_asset_id) = (1u32, 2u32); - set_price::(borrow_asset_id.into(), u64::from(borrow_asset_id) * 10); - set_price::(collateral_asset_id.into(), u64::from(collateral_asset_id) * 10); - let (market_id, _) = create_market::(caller.clone(), borrow_asset_id.into(), collateral_asset_id.into()); - let market_config = Markets::::try_get(market_id).unwrap(); - }: { - Lending::::handle_must_liquidate(&market_config, &caller).unwrap() - } + accrue_interest { + let caller= whitelisted_caller::(); + let origin = whitelisted_origin::(); + let amount: ::Balance = 1_000_000_000_000_u64.into(); + let borrow_amount: ::Balance = 1_000_000_000_u64.into(); + let part: ::Balance = 1_000_u64.into(); + let bank: ::Balance = 10_000_000_000_000_u64.into(); + let pair = assets::(); + let input = create_market_config::(pair.base, pair.quote); + set_prices::(); + as frame_support::traits::fungible::Mutate>::mint_into(&caller, 10_000_000_000_000_u64.into()).unwrap(); + ::MultiCurrency::mint_into(pair.base, &caller, bank).unwrap(); + ::MultiCurrency::mint_into(pair.quote, &caller, bank).unwrap(); + Lending::::create_market(origin.clone().into(), Validated::new(input).unwrap()).unwrap(); + let market_id = MarketIndex::new(1); + Lending::::deposit_collateral(origin.clone().into(), market_id, amount).unwrap(); + Lending::::borrow(origin.into(), market_id, borrow_amount).unwrap(); + produce_block::(42_u32.into(),4200_u64.into()); + produce_block::(43_u32.into(),4300_u64.into()); + }: { + // TODO: fix it, make timestamp depend on x increased OR make the value passed be DELTA + Lending::::accrue_interest(&market_id, 4400_u64).unwrap(); + } + account_id { + let caller= whitelisted_caller::(); + let origin = whitelisted_origin::(); + let amount: ::Balance = 1_000_000_000_000_u64.into(); + let part: ::Balance = 1_000_u64.into(); + let bank: ::Balance = 10_000_000_000_000_u64.into(); + let pair = assets::(); + let input = create_market_config::(pair.base, pair.quote); + set_prices::(); + as frame_support::traits::fungible::Mutate>::mint_into(&caller, 10_000_000_000_000_u64.into()).unwrap(); + ::MultiCurrency::mint_into(pair.base, &caller, bank).unwrap(); + ::MultiCurrency::mint_into(pair.quote, &caller, bank).unwrap(); + Lending::::create_market(origin.into(), Validated::new(input).unwrap()).unwrap(); + let market_id = MarketIndex::new(1); + }: { + // TODO: fix it, make timestamp depend on x increased OR make the value passed be DELTA + Lending::::account_id(&market_id) + } + available_funds { + let caller= whitelisted_caller::(); + let origin = whitelisted_origin::(); + let amount: ::Balance = 1_000_000_000_000_u64.into(); + let part: ::Balance = 1_000_u64.into(); + let bank: ::Balance = 10_000_000_000_000_u64.into(); + let pair = assets::(); + let input = create_market_config::(pair.base, pair.quote); + set_prices::(); + as frame_support::traits::fungible::Mutate>::mint_into(&caller, 10_000_000_000_000_u64.into()).unwrap(); + ::MultiCurrency::mint_into(pair.base, &caller, bank).unwrap(); + ::MultiCurrency::mint_into(pair.quote, &caller, bank).unwrap(); + Lending::::create_market(origin.into(), Validated::new(input).unwrap()).unwrap(); + let market_id = MarketIndex::new(1); + let market_config = Markets::::try_get(market_id).unwrap(); + }: { + // TODO: make changes to vault state so something happens + Lending::::available_funds(&market_config, &caller).unwrap() + } + handle_withdrawable { + let caller= whitelisted_caller::(); + let origin = whitelisted_origin::(); + let amount: ::Balance = 1_000_000_000_000_u64.into(); + let part: ::Balance = 1_000_u64.into(); + let bank: ::Balance = 10_000_000_000_000_u64.into(); + let pair = assets::(); + let input = create_market_config::(pair.base, pair.quote); + set_prices::(); + as frame_support::traits::fungible::Mutate>::mint_into(&caller, 10_000_000_000_000_u64.into()).unwrap(); + ::MultiCurrency::mint_into(pair.base, &caller, bank).unwrap(); + ::MultiCurrency::mint_into(pair.quote, &caller, bank).unwrap(); + Lending::::create_market(origin.clone().into(), Validated::new(input).unwrap()).unwrap(); + let market_id = MarketIndex::new(1); + Lending::::deposit_collateral(origin.into(), market_id, amount).unwrap(); + let market_config = Markets::::try_get(market_id).unwrap(); + let account = &Lending::::account_id(&market_id); + ::MultiCurrency::mint_into(pair.base, account, bank).unwrap(); + ::MultiCurrency::mint_into(pair.quote, account, bank).unwrap(); + ::Vault::deposit(&market_config.borrow, account, bank).unwrap(); + }: { + Lending::::handle_withdrawable(&market_config, &caller, part ).unwrap() + } + handle_depositable { + let caller= whitelisted_caller::(); + let origin = whitelisted_origin::(); + let amount: ::Balance = 1_000_000_000_000_u64.into(); + let part: ::Balance = 1_000_u64.into(); + let bank: ::Balance = 10_000_000_000_000_u64.into(); + let pair = assets::(); + let input = create_market_config::(pair.base, pair.quote); + set_prices::(); + as frame_support::traits::fungible::Mutate>::mint_into(&caller, 10_000_000_000_000_u64.into()).unwrap(); + ::MultiCurrency::mint_into(pair.base, &caller, bank).unwrap(); + ::MultiCurrency::mint_into(pair.quote, &caller, bank).unwrap(); + Lending::::create_market(origin.clone().into(), Validated::new(input).unwrap()).unwrap(); + let market_id = MarketIndex::new(1); + Lending::::deposit_collateral(origin.into(), market_id, amount).unwrap(); + let market_config = Markets::::try_get(market_id).unwrap(); + let account = &Lending::::account_id(&market_id); + ::MultiCurrency::mint_into(pair.base, account, bank).unwrap(); + ::MultiCurrency::mint_into(pair.quote, account, bank).unwrap(); + }: { + // TODO: make it variable with x + Lending::::handle_depositable(&market_config, &caller, part ).unwrap() + } + handle_must_liquidate { + let caller= whitelisted_caller::(); + let origin = whitelisted_origin::(); + let amount: ::Balance = 1_000_000_000_000_u64.into(); + let part: ::Balance = 1_000_u64.into(); + let bank: ::Balance = 10_000_000_000_000_u64.into(); + let pair = assets::(); + let input = create_market_config::(pair.base, pair.quote); + set_prices::(); + as frame_support::traits::fungible::Mutate>::mint_into(&caller, 10_000_000_000_000_u64.into()).unwrap(); + ::MultiCurrency::mint_into(pair.base, &caller, bank).unwrap(); + ::MultiCurrency::mint_into(pair.quote, &caller, bank).unwrap(); + Lending::::create_market(origin.clone().into(), Validated::new(input).unwrap()).unwrap(); + let market_id = MarketIndex::new(1); + Lending::::deposit_collateral(origin.into(), market_id, amount).unwrap(); + let market_config = Markets::::try_get(market_id).unwrap(); + let account = &Lending::::account_id(&market_id); + ::MultiCurrency::mint_into(pair.base, account, bank).unwrap(); + ::MultiCurrency::mint_into(pair.quote, account, bank).unwrap(); + }: { + // TODO: make it variable with x + Lending::::handle_must_liquidate(&market_config, &caller ).unwrap() + } } -impl_benchmark_test_suite!(Lending, crate::mock::new_test_ext(), crate::mock::Test,); +impl_benchmark_test_suite!(Lending, crate::mocks::new_test_ext(), crate::mocks::Runtime,); diff --git a/frame/lending/src/currency.rs b/frame/lending/src/currency.rs new file mode 100644 index 00000000000..c75c74069b5 --- /dev/null +++ b/frame/lending/src/currency.rs @@ -0,0 +1,87 @@ +/// A const-generic currency. generic over the ID and EXPONENT. +/// +/// # Examples +/// +/// Intended usage: +/// +/// ``` +/// # use pallet_lending::currency::Currency; +/// +/// type ACOIN = Currency<12345, 10>; +/// type BCOIN = Currency<54321, 12>; +/// +/// let one_hundred_a_tokens = ACOIN::units(100); +/// let one_value_of_b = BCOIN::one(); +/// ``` +#[derive(Debug, Clone, Copy)] +pub struct Currency {} + +impl Currency { + /// The exponent of the currency. Specifies the precision level; can be thought of as the number + /// of decimal points in base 10. + /// + /// A [`Currency`] with an EXPONENT of `0` has no decimals and is the exact same as a [`u128`]. + /// + /// # NOTE + /// + /// Although this is a [`u8`], there are some (not yet inforced) constraints/ caveats: + /// - an exponent of `0` technically works, but is probably not what you want as there will be + /// no decimal precision. + /// - any value higher than `38` does not make sense (`10^39 > 2^128`) and will automatically + /// saturate at [`u128::MAX`]. + pub const EXPONENT: u8 = EXPONENT; + + /// The id of the currency. This is fairly arbitrary, and is only used to differentiate between + /// different currencies. + pub const ID: u128 = ID; + + /// Returns the provided amount of the currency, cannonicalized to [`Self::one()`], saturating + /// at the numeric bounds ([`u128::MAX`]). + /// + /// # Examples + /// + /// ``` + /// # use pallet_lending::currency::Currency; + /// + /// type ACOIN = Currency<12345, 10>; + /// assert_eq!(ACOIN::units(7), 70_000_000_000); + /// + /// // saturates at u128::MAX + /// assert_eq!(ACOIN::units(u128::MAX), u128::MAX); + /// ``` + pub fn units(ones: u128) -> u128 { + ones.saturating_mul(Self::one()) + } + + /// The `one` value of the currency, calculated with [`Self::EXPONENT`]. + /// + /// # Examples + /// + /// ``` + /// # use pallet_lending::currency::Currency; + /// + /// type ACOIN = Currency<12345, 10>; + /// assert_eq!(ACOIN::one(), 10_000_000_000); + /// ``` + pub const fn one() -> u128 { + 10_u128.pow(Self::EXPONENT as u32) + } +} + +// separate module so that the `allow` attribute isn't appllied to the entirety of the currency +// module. +pub mod defs { + #![allow(clippy::upper_case_acronyms)] + + use super::Currency; + + pub type PICA = Currency<1, 12>; + pub type BTC = Currency<2000, 12>; + pub type USDT = Currency<1000, 12>; + + pub type NORMALIZED = USDT; +} + +pub use defs::*; + +pub type CurrencyId = u128; diff --git a/frame/lending/src/lib.rs b/frame/lending/src/lib.rs index 6e85b929b82..8edf77393ef 100644 --- a/frame/lending/src/lib.rs +++ b/frame/lending/src/lib.rs @@ -7,7 +7,8 @@ clippy::indexing_slicing, clippy::todo, clippy::unwrap_used, - clippy::panic + clippy::panic, + clippy::identity_op, ) )] // allow in tests #![warn(clippy::unseparated_literal_suffix)] @@ -43,8 +44,14 @@ mod mocks; #[cfg(test)] mod tests; -#[cfg(feature = "runtime-benchmarks")] +#[cfg(any(feature = "runtime-benchmarks", test))] mod benchmarking; +#[cfg(any(feature = "runtime-benchmarks", test))] +mod setup; + +#[cfg(any(feature = "runtime-benchmarks", test))] +pub mod currency; + pub mod weights; mod models; @@ -65,7 +72,7 @@ pub mod pallet { MarketConfig, MarketModelValid, UpdateInput, }, liquidation::Liquidation, - math::SafeArithmetic, + math::{SafeAdd, SafeDiv, SafeMul, SafeSub}, oracle::Oracle, time::{DurationSeconds, Timestamp, SECONDS_PER_YEAR_NAIVE}, vault::{Deposit, FundsAvailability, StrategicVault, Vault, VaultConfig}, @@ -212,7 +219,8 @@ pub mod pallet { /// Id of proxy to liquidate type LiquidationStrategyId: Parameter + Default + PartialEq + Clone + Debug + TypeInfo; - /// Minimal price of borrow asset in Oracle price required to create + /// Minimal price of borrow asset in Oracle price required to create. + /// Examples, 100 USDC. /// Creators puts that amount and it is staked under Vault account. /// So he does not owns it anymore. /// So borrow is both stake and tool to create market. @@ -237,7 +245,7 @@ pub mod pallet { /// Vault can take that amount if reconfigured so, but that may be changed during runtime /// upgrades. #[pallet::constant] - type MarketCreationStake: Get; + type OracleMarketCreationStake: Get; #[pallet::constant] type PalletId: Get; @@ -282,6 +290,7 @@ pub mod pallet { return } for (market_id, account, _) in DebtIndex::::iter() { + // TODO: check that it should liquidate before liquidations let results = signer.send_signed_transaction(|_account| Call::liquidate { market_id, borrowers: vec![account.clone()], @@ -339,7 +348,8 @@ pub mod pallet { BorrowerDataCalculationFailed, Unauthorized, NotEnoughRent, - PriceOfInitialBorrowVaultShoyldBeGreaterThanZero, + /// borrow assets should have enough value as per oracle + PriceOfInitialBorrowVaultShouldBeGreaterThanZero, } #[pallet::event] @@ -350,7 +360,7 @@ pub mod pallet { market_id: MarketIndex, vault_id: T::VaultId, manager: T::AccountId, - input: CreateInput, + currency_pair: CurrencyPair, }, MarketUpdated { market_id: MarketIndex, @@ -530,7 +540,10 @@ pub mod pallet { impl Pallet { /// Create a new lending market. /// - `origin` : Sender of this extrinsic. Manager for new market to be created. Can pause - /// borrow & deposits of assets. + /// borrow operations. + /// - `input` : Borrow & deposits of assets, persentages. + /// + /// `origin` irreversibly pays `T::OracleMarketCreationStake`. #[pallet::weight(::WeightInfo::create_new_market())] #[transactional] pub fn create_market( @@ -539,12 +552,13 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; let input = input.value(); - let (market_id, vault_id) = Self::create(who.clone(), input.clone())?; + let pair = input.currency_pair; + let (market_id, vault_id) = Self::create(who.clone(), input)?; Self::deposit_event(Event::::MarketCreated { market_id, vault_id, manager: who, - input, + currency_pair: pair, }); Ok(().into()) } @@ -667,9 +681,8 @@ pub mod pallet { market_id: MarketIndex, borrowers: Vec, ) -> DispatchResultWithPostInfo { - let sender = &(ensure_signed(origin)?); - // TODO: should this be restricted to certain users? - Self::liquidate_internal(Some(sender), &market_id, borrowers.clone())?; + let sender = ensure_signed(origin.clone())?; + Self::liquidate_internal(&sender, &market_id, borrowers.clone())?; Self::deposit_event(Event::LiquidationInitiated { market_id, borrowers }); Ok(().into()) } @@ -810,7 +823,7 @@ pub mod pallet { /// if liquidation is required and `liquidate` is successful then return `Ok(true)` /// if there is any error then propagate that error. pub fn liquidate_internal( - liquidator: Option<&::AccountId>, + liquidator: &::AccountId, market_id: &::MarketId, borrowers: Vec<::AccountId>, ) -> Result<(), DispatchError> { @@ -832,7 +845,6 @@ pub mod pallet { if let Some(deposit) = BorrowRent::::get(market_id, account) { let market_account = Self::account_id(market_id); - let liquidator = liquidator.unwrap_or(account); ::NativeCurrency::transfer( &market_account, liquidator, @@ -977,9 +989,8 @@ pub mod pallet { market_id: &MarketIndex, debt_owner: &T::AccountId, amount_to_borrow: T::Balance, + debt_asset_id: ::MayBeAssetId, ) -> Result { - let debt_asset_id = DebtMarkets::::get(market_id); - let market_index = BorrowIndex::::try_get(market_id).map_err(|_| Error::::MarketDoesNotExist)?; @@ -988,11 +999,20 @@ pub mod pallet { let existing_borrow_amount = ::MultiCurrency::balance(debt_asset_id, debt_owner); - // TODO: split out math from update, make update last step - ::MultiCurrency::mint_into(debt_asset_id, debt_owner, amount_to_borrow)?; - // TODO: decide if need to split out dept tracking vs debt token - ::MultiCurrency::hold(debt_asset_id, debt_owner, amount_to_borrow)?; + Self::calc_updated_account_interest_index( + market_index, + amount_to_borrow, + existing_borrow_amount, + account_interest_index, + ) + } + fn calc_updated_account_interest_index( + market_index: ZeroToOneFixedU128, + amount_to_borrow: T::Balance, + existing_borrow_amount: T::Balance, + account_interest_index: ZeroToOneFixedU128, + ) -> Result { let total_borrow_amount = existing_borrow_amount.safe_add(&amount_to_borrow)?; let existing_borrow_share = Percent::from_rational(existing_borrow_amount, total_borrow_amount); @@ -1157,15 +1177,18 @@ pub mod pallet { }, )?; - let initial_price_amount = T::MarketCreationStake::get(); + let initial_price_amount = T::OracleMarketCreationStake::get(); + let initial_pool_size = T::Oracle::get_price_inverse( config_input.borrow_asset(), initial_price_amount, )?; + ensure!( initial_pool_size > T::Balance::zero(), - Error::::PriceOfInitialBorrowVaultShoyldBeGreaterThanZero + Error::::PriceOfInitialBorrowVaultShouldBeGreaterThanZero ); + T::MultiCurrency::transfer( config_input.borrow_asset(), &manager, @@ -1174,13 +1197,6 @@ pub mod pallet { false, )?; - // TODO: discuss on why we do not reposit all amount to vault - // ::deposit( - // &borrow_asset_vault, - // &Self::account_id(&market_id), - // initial_pool_size, - // )?; - let config = MarketConfig { manager, borrow: borrow_asset_vault.clone(), @@ -1194,6 +1210,7 @@ pub mod pallet { }; let debt_asset_id = T::CurrencyFactory::reserve_lp_token_id()?; + DebtMarkets::::insert(market_id, debt_asset_id); Markets::::insert(market_id, config); BorrowIndex::::insert(market_id, ZeroToOneFixedU128::one()); @@ -1233,9 +1250,16 @@ pub mod pallet { Self::can_borrow(market_id, debt_owner, amount_to_borrow, market, &market_account)?; - let new_account_interest_index = - Self::updated_account_interest_index(market_id, debt_owner, amount_to_borrow)?; + let debt_asset_id = DebtMarkets::::get(market_id); + let new_account_interest_index = Self::updated_account_interest_index( + market_id, + debt_owner, + amount_to_borrow, + debt_asset_id, + )?; + ::MultiCurrency::mint_into(debt_asset_id, debt_owner, amount_to_borrow)?; + ::MultiCurrency::hold(debt_asset_id, debt_owner, amount_to_borrow)?; ::MultiCurrency::transfer( borrow_asset, &market_account, @@ -1298,7 +1322,8 @@ pub mod pallet { total_repay_amount } else { let repay_borrow_amount = total_repay_amount - burn_amount; - remaining_borrow_amount -= repay_borrow_amount; + remaining_borrow_amount = + remaining_borrow_amount.safe_sub(&repay_borrow_amount)?; ::MultiCurrency::burn_from( debt_asset_id, &market_account, diff --git a/frame/lending/src/mocks/currency.rs b/frame/lending/src/mocks/currency.rs deleted file mode 100644 index 48c4b4a81d8..00000000000 --- a/frame/lending/src/mocks/currency.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub type CurrencyId = u128; - -pub const PICA: CurrencyId = 0; -pub const BTC: CurrencyId = 1; -pub const USDT: CurrencyId = 2; -pub const ETH: CurrencyId = 3; -pub const LTC: CurrencyId = 5; diff --git a/frame/lending/src/mocks/mod.rs b/frame/lending/src/mocks/mod.rs index d2c07efe70e..c0c2c592d47 100644 --- a/frame/lending/src/mocks/mod.rs +++ b/frame/lending/src/mocks/mod.rs @@ -2,8 +2,10 @@ use self::currency::CurrencyId; pub use self::currency::*; use crate::{self as pallet_lending, *}; use composable_traits::{ + currency::{Exponent, LocalAssets}, defi::DeFiComposableConfig, governance::{GovernanceRegistry, SignedRawOrigin}, + oracle::Price, }; use frame_support::{ ord_parameter_types, parameter_types, @@ -23,14 +25,11 @@ use sp_runtime::{ traits::{ BlakeTwo256, ConvertInto, Extrinsic as ExtrinsicT, IdentifyAccount, IdentityLookup, Verify, }, - Perbill, + DispatchError, Perbill, }; -pub mod currency; -pub mod oracle; - -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -type Block = frame_system::mocking::MockBlock; +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; pub type Balance = u128; pub type Amount = i128; pub type BlockNumber = u64; @@ -45,7 +44,7 @@ parameter_types! { pub type ParachainId = u32; -pub const MINIMUM_BALANCE: Balance = 1000; +pub const MINIMUM_BALANCE: Balance = 1_000_000; pub static ALICE: Lazy = Lazy::new(|| { AccountId::from_raw(hex!("0000000000000000000000000000000000000000000000000000000000000000")) @@ -63,7 +62,7 @@ pub static UNRESERVED: Lazy = Lazy::new(|| { // Configure a mock runtime to test the pallet. frame_support::construct_runtime!( - pub enum Test where + pub enum Runtime where Block = Block, NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic, @@ -77,8 +76,8 @@ frame_support::construct_runtime!( Assets: pallet_assets::{Pallet, Call, Storage}, Liquidations: pallet_liquidations::{Pallet, Call, Event}, Lending: pallet_lending::{Pallet, Call, Config, Storage, Event}, - Oracle: pallet_lending::mocks::oracle::{Pallet}, DutchAuction: pallet_dutch_auction::{Pallet, Call, Storage, Event}, + Oracle: pallet_oracle::{Pallet, Call, Storage, Event}, } ); @@ -87,7 +86,7 @@ parameter_types! { pub const SS58Prefix: u8 = 42; } -impl frame_system::Config for Test { +impl frame_system::Config for Runtime { type BaseCallFilter = Everything; type BlockWeights = (); type BlockLength = (); @@ -118,7 +117,7 @@ parameter_types! { pub const ExistentialDeposit: u64 = 1000; } -impl pallet_balances::Config for Test { +impl pallet_balances::Config for Runtime { type Balance = Balance; type Event = Event; type DustRemoval = (); @@ -136,14 +135,14 @@ parameter_types! { pub const MinimumPeriod: u64 = MILLISECS_PER_BLOCK / 2; } -impl pallet_timestamp::Config for Test { +impl pallet_timestamp::Config for Runtime { type Moment = u64; type OnTimestampSet = (); type MinimumPeriod = MinimumPeriod; type WeightInfo = (); } -impl pallet_currency_factory::Config for Test { +impl pallet_currency_factory::Config for Runtime { type Event = Event; type AssetId = CurrencyId; type AddOrigin = EnsureRoot; @@ -153,7 +152,7 @@ impl pallet_currency_factory::Config for Test { parameter_types! { pub const MaxStrategies: usize = 255; - pub const NativeAssetId: CurrencyId = PICA; + pub const NativeAssetId: CurrencyId = PICA::ID; pub const CreationDeposit: Balance = 10; pub const RentPerBlock: Balance = 1; pub const MinimumDeposit: Balance = 0; @@ -162,7 +161,7 @@ parameter_types! { pub const TombstoneDuration: u64 = 42; } -impl pallet_vault::Config for Test { +impl pallet_vault::Config for Runtime { type Event = Event; type Currency = Tokens; type AssetId = CurrencyId; @@ -192,7 +191,7 @@ parameter_types! { pub MaxLocks: u32 = 2; } -impl orml_tokens::Config for Test { +impl orml_tokens::Config for Runtime { type Event = Event; type Balance = Balance; type Amount = Amount; @@ -227,7 +226,7 @@ impl } } -impl pallet_assets::Config for Test { +impl pallet_assets::Config for Runtime { type NativeAssetId = NativeAssetId; type GenerateCurrencyId = LpTokenFactory; type AssetId = CurrencyId; @@ -239,12 +238,38 @@ impl pallet_assets::Config for Test { type GovernanceRegistry = NoopRegistry; } -impl crate::mocks::oracle::Config for Test { - type VaultId = VaultId; - type Vault = Vault; +parameter_types! { + pub const MinBalance : Balance = 0; + pub const MinU32 : u32 = 0; + pub const MinU64 : u64 = 0; } -impl DeFiComposableConfig for Test { +pub struct Decimals; +impl LocalAssets for Decimals { + fn decimals(_currency_id: CurrencyId) -> Result { + Ok(12) + } +} + +impl pallet_oracle::Config for Runtime { + type Event = Event; + type Currency = Assets; + type AssetId = CurrencyId; + type PriceValue = Balance; + type AuthorityId = pallet_oracle::crypto::BathurstStId; + type MinStake = MinBalance; + type StakeLock = MinU64; + type StalePrice = MinU64; + type AddOracle = EnsureSignedBy; + type MaxAnswerBound = MinU32; + type MaxAssetsCount = MinU32; + type MaxHistory = MinU32; + type MaxPrePrices = MinU32; + type WeightInfo = (); + type LocalAssets = Decimals; +} + +impl DeFiComposableConfig for Runtime { type MayBeAssetId = CurrencyId; type Balance = Balance; } @@ -288,7 +313,7 @@ impl WeightToFeePolynomial for DutchAuctionsMocks { } } -impl pallet_dutch_auction::Config for Test { +impl pallet_dutch_auction::Config for Runtime { type Event = Event; type OrderId = OrderId; type UnixTime = Timestamp; @@ -299,7 +324,7 @@ impl pallet_dutch_auction::Config for Test { type WeightToFee = DutchAuctionsMocks; } -impl pallet_liquidations::Config for Test { +impl pallet_liquidations::Config for Runtime { type Event = Event; type UnixTime = Timestamp; type DutchAuction = DutchAuction; @@ -313,12 +338,12 @@ impl pallet_liquidations::Config for Test { pub type Extrinsic = TestXt; pub type AccountId = <::Signer as IdentifyAccount>::AccountId; -impl frame_system::offchain::SigningTypes for Test { +impl frame_system::offchain::SigningTypes for Runtime { type Public = ::Signer; type Signature = Signature; } -impl frame_system::offchain::SendTransactionTypes for Test +impl frame_system::offchain::SendTransactionTypes for Runtime where Call: From, { @@ -326,7 +351,7 @@ where type Extrinsic = Extrinsic; } -impl frame_system::offchain::CreateSignedTransaction for Test +impl frame_system::offchain::CreateSignedTransaction for Runtime where Call: From, { @@ -343,7 +368,7 @@ where parameter_types! { pub const MaxLendingCount: u32 = 10; pub LendingPalletId: PalletId = PalletId(*b"liqiudat"); - pub MarketCreationStake : Balance = 10^15; + pub OracleMarketCreationStake : Balance = NORMALIZED::one(); } parameter_types! { @@ -363,7 +388,7 @@ impl WeightToFeePolynomial for WeightToFee { } } -impl pallet_lending::Config for Test { +impl pallet_lending::Config for Runtime { type Oracle = Oracle; type VaultId = VaultId; type Vault = Vault; @@ -378,31 +403,37 @@ impl pallet_lending::Config for Test { type WeightInfo = (); type LiquidationStrategyId = LiquidationStrategyId; type PalletId = LendingPalletId; - type MarketCreationStake = MarketCreationStake; + type OracleMarketCreationStake = OracleMarketCreationStake; type WeightToFee = WeightToFee; } +pub fn set_price(asset_id: CurrencyId, balance: Balance) { + let price = Price { price: balance, block: System::block_number() }; + pallet_oracle::Prices::::insert(asset_id, price); +} + // Build genesis storage according to the mock runtime. pub fn new_test_ext() -> sp_io::TestExternalities { - let mut storage = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let mut storage = frame_system::GenesisConfig::default().build_storage::().unwrap(); let balances = vec![(*ALICE, 1_000_000_000), (*BOB, 1_000_000_000), (*CHARLIE, 1_000_000_000)]; - pallet_balances::GenesisConfig:: { balances } + pallet_balances::GenesisConfig:: { balances } .assimilate_storage(&mut storage) .unwrap(); pallet_lending::GenesisConfig {} - .assimilate_storage::(&mut storage) - .unwrap(); - GenesisBuild::::assimilate_storage(&pallet_liquidations::GenesisConfig {}, &mut storage) + .assimilate_storage::(&mut storage) .unwrap(); + GenesisBuild::::assimilate_storage( + &pallet_liquidations::GenesisConfig {}, + &mut storage, + ) + .unwrap(); let mut ext = sp_io::TestExternalities::new(storage); ext.execute_with(|| { System::set_block_number(0); Timestamp::set_timestamp(MILLISECS_PER_BLOCK); - // Initialize BTC price to 50000 - pallet_lending::mocks::oracle::BTCValue::::set(50000_u128); }); ext } @@ -424,7 +455,7 @@ pub fn process_block(n: BlockNumber) { Lending::on_finalize(n); } -fn next_block(n: u64) { +pub fn next_block(n: u64) { System::set_block_number(n); Lending::on_initialize(n); Timestamp::set_timestamp(MILLISECS_PER_BLOCK * n); diff --git a/frame/lending/src/mocks/oracle.rs b/frame/lending/src/mocks/oracle.rs deleted file mode 100644 index 301f113a8bb..00000000000 --- a/frame/lending/src/mocks/oracle.rs +++ /dev/null @@ -1,131 +0,0 @@ -pub use pallet::*; - -#[frame_support::pallet] -pub mod pallet { - use codec::Codec; - use composable_traits::{ - currency::LocalAssets, - math::SafeArithmetic, - oracle::{Oracle, Price}, - vault::Vault, - }; - use frame_support::pallet_prelude::*; - use sp_runtime::{ - helpers_128bit::multiply_by_rational, ArithmeticError, DispatchError, FixedPointNumber, - FixedU128, - }; - use sp_std::fmt::Debug; - - use crate::mocks::{currency::*, Balance}; - - #[pallet::config] - pub trait Config: frame_system::Config { - type VaultId: Clone + Codec + Debug + PartialEq + Default + Parameter; - type Vault: Vault; - } - - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(_); - - #[pallet::storage] - #[pallet::getter(fn btc_value)] - // FIXME: Temporary fix to get CI to pass, separate PRs will be made per pallet to refactor to - // use OptionQuery instead - #[allow(clippy::disallowed_type)] - pub type BTCValue = StorageValue<_, u128, ValueQuery>; - - impl Pallet { - pub fn get_price( - asset: CurrencyId, - amount: Balance, - ) -> Result, DispatchError> { - ::get_price(asset, amount) - } - pub fn set_btc_price(price: u128) { - BTCValue::::set(price) - } - } - - impl Oracle for Pallet { - type AssetId = CurrencyId; - type Balance = Balance; - type Timestamp = (); - type LocalAssets = (); - - fn get_price( - asset: Self::AssetId, - amount: Balance, - ) -> Result, DispatchError> { - let derive_price = |p: u128, a: u128| { - let e = 10_u128 - .checked_pow(Self::LocalAssets::decimals(asset)?) - .ok_or(DispatchError::Arithmetic(ArithmeticError::Overflow))?; - let price = multiply_by_rational(p, a, e) - .map_err(|_| DispatchError::Arithmetic(ArithmeticError::Overflow))?; - Ok(Price { price, block: () }) - }; - - #[allow(clippy::inconsistent_digit_grouping)] // values are in cents - match asset { - /* NOTE(hussein-aitlahcen) - Ideally we would have all the static currency quoted against USD cents on chain. - So that we would be able to derive LP tokens price. - */ - USDT => Ok(Price { price: amount, block: () }), - PICA => derive_price(10_00, amount), - BTC => derive_price(Self::btc_value(), amount), - ETH => derive_price(3400_00, amount), - LTC => derive_price(180_00, amount), - - /* NOTE(hussein-aitlahcen) - If we want users to be able to consider LP tokens as currency, - the oracle should know the whole currency system in order to - recursively resolve the price of an LP token generated by an - arbitrary level of vaults. - - The base asset represented by the level 0 (out of LpToken case) - should have a price defined. - - One exception can occur if the LP token hasn't been generated by a vault. - */ - x => { - let vault = T::Vault::token_vault(x)?; - let base = T::Vault::asset_id(&vault)?; - let Price { price, block } = Self::get_price(base, amount)?; - let rate = T::Vault::stock_dilution_rate(&vault)?; - let derived = rate - .checked_mul_int(price) - .ok_or(DispatchError::Arithmetic(ArithmeticError::Overflow))?; - Ok(Price { price: derived, block }) - }, - } - } - - fn get_twap( - _of: Self::AssetId, - _weights: Vec, - ) -> Result { - Ok(0_u32.into()) - } - - fn get_ratio( - pair: composable_traits::defi::CurrencyPair, - ) -> Result { - let base: u128 = Self::get_price(pair.base, (10_u32 ^ 12).into())?.price; - let quote: u128 = Self::get_price(pair.quote, (10_u32 ^ 12).into())?.price; - let base = FixedU128::saturating_from_integer(base); - let quote = FixedU128::saturating_from_integer(quote); - Ok(base.safe_div("e)?) - } - - fn get_price_inverse( - asset_id: Self::AssetId, - amount: Self::Balance, - ) -> Result { - let price = Self::get_price(asset_id, 10 ^ 12)?; - let inversed = (amount / price.price / 10) ^ 12; - Ok(inversed) - } - } -} diff --git a/frame/lending/src/models.rs b/frame/lending/src/models.rs index c6fff257bdc..072b8097baa 100644 --- a/frame/lending/src/models.rs +++ b/frame/lending/src/models.rs @@ -1,10 +1,11 @@ use composable_traits::{ currency::MathBalance, defi::{LiftedFixedBalance, MoreThanOneFixedU128, Rate}, - math::SafeArithmetic, + math::{SafeAdd, SafeDiv, SafeMul}, }; use sp_runtime::{traits::Saturating, ArithmeticError, FixedPointNumber, Percent}; +#[derive(Debug)] pub struct BorrowerData { pub collateral_balance_value: LiftedFixedBalance, pub borrow_balance_value: LiftedFixedBalance, diff --git a/frame/lending/src/setup.rs b/frame/lending/src/setup.rs new file mode 100644 index 00000000000..2ce02813f0f --- /dev/null +++ b/frame/lending/src/setup.rs @@ -0,0 +1,40 @@ +//! most usable things, 20% of all , for tests +/// test should be freely use external API +pub use codec::{Codec, Decode, Encode, FullCodec, MaxEncodedLen}; + +use composable_traits::defi::{CurrencyPair, DeFiComposableConfig}; +use frame_benchmarking::whitelisted_caller; +use frame_support::traits::Hooks; +use frame_system::RawOrigin; + +use crate::{self as pallet_lending, currency::*}; + +pub fn whitelisted_origin() -> RawOrigin { + let caller: T::AccountId = whitelisted_caller(); + RawOrigin::Signed(caller) +} + +pub type AssetIdOf = ::MayBeAssetId; + +pub fn assets() -> CurrencyPair> +where + T: frame_system::Config + composable_traits::defi::DeFiComposableConfig, +{ + let a = USDT::ID.encode(); + let b = BTC::ID.encode(); + CurrencyPair::new( + AssetIdOf::::decode(&mut &a[..]).unwrap(), + AssetIdOf::::decode(&mut &b[..]).unwrap(), + ) +} + +pub fn produce_block< + T: frame_system::Config + pallet_lending::Config + pallet_timestamp::Config, +>( + n: T::BlockNumber, + time: T::Moment, +) { + frame_system::Pallet::::set_block_number(n); + as Hooks>::on_initialize(n); + >::set_timestamp(time); +} diff --git a/frame/lending/src/tests.rs b/frame/lending/src/tests.rs index a0926913727..2052fafbdde 100644 --- a/frame/lending/src/tests.rs +++ b/frame/lending/src/tests.rs @@ -1,11 +1,18 @@ +//! Test for Lending. Runtime is almost real. +//! TODO: cover testing events - so make sure that each even is handled at least once +//! (events can be obtained from System pallet as in banchmarking.rs before this commit) +//! TODO: OCW of liquidations (like in Oracle) +//! TODO: test on small numbers via proptests - detect edge case what is minimal amounts it starts +//! to accure(and miminal block delta), and maximal amounts when it overflows + use std::ops::Mul; use crate::{ - accrue_interest_internal, - mocks::{currency::*, *}, - models::BorrowerData, + self as pallet_lending, accrue_interest_internal, currency::*, mocks::*, models::BorrowerData, Error, MarketIndex, }; +use codec::{Decode, Encode}; +use composable_support::validation::Validated; use composable_tests_helpers::{prop_assert_acceptable_computation_error, prop_assert_ok}; use composable_traits::{ defi::{CurrencyPair, LiftedFixedBalance, MoreThanOneFixedU128, Rate, ZeroToOneFixedU128}, @@ -17,12 +24,12 @@ use frame_support::{ assert_err, assert_noop, assert_ok, traits::fungibles::{Inspect, Mutate}, }; +use frame_system::EventRecord; use pallet_vault::models::VaultInfo; use proptest::{prelude::*, test_runner::TestRunner}; use sp_arithmetic::assert_eq_error_rate; -use sp_core::U256; +use sp_core::{H256, U256}; use sp_runtime::{ArithmeticError, FixedPointNumber, Percent, Perquintill}; - type BorrowAssetVault = VaultId; type CollateralAsset = CurrencyId; @@ -30,21 +37,19 @@ type CollateralAsset = CurrencyId; const DEFAULT_MARKET_VAULT_RESERVE: Perquintill = Perquintill::from_percent(10); const DEFAULT_MARKET_VAULT_STRATEGY_SHARE: Perquintill = Perquintill::from_percent(90); const DEFAULT_COLLATERAL_FACTOR: u128 = 2; -const INITIAL_BORROW_ASSET_AMOUNT: u128 = 10 ^ 30; +const INITIAL_BORROW_ASSET_AMOUNT: u128 = 10_u128.pow(30); /// Create a very simple vault for the given currency, 100% is reserved. fn create_simple_vault( asset_id: CurrencyId, ) -> (VaultId, VaultInfo) { - let v = Vault::do_create_vault( - Deposit::Existential, - VaultConfig { - asset_id, - manager: *ALICE, - reserved: Perquintill::from_percent(100), - strategies: [].iter().cloned().collect(), - }, - ); + let config = VaultConfig { + asset_id, + manager: *ALICE, + reserved: Perquintill::from_percent(100), + strategies: [].iter().cloned().collect(), + }; + let v = Vault::do_create_vault(Deposit::Existential, Validated::new(config).unwrap()); assert_ok!(&v); v.expect("unreachable; qed;") } @@ -56,6 +61,8 @@ fn create_market( reserved: Perquintill, collateral_factor: MoreThanOneFixedU128, ) -> (MarketIndex, BorrowAssetVault) { + set_price(BTC::ID, 50_000 * NORMALIZED::one()); + set_price(USDT::ID, NORMALIZED::one()); let config = CreateInput { updatable: UpdateInput { collateral_factor, @@ -66,17 +73,19 @@ fn create_market( reserved_factor: reserved, currency_pair: CurrencyPair::new(collateral_asset, borrow_asset), }; - Tokens::mint_into(borrow_asset, &manager, 1_000_000_000).unwrap(); + Tokens::mint_into(borrow_asset, &manager, USDT::units(1000)).unwrap(); + Tokens::mint_into(collateral_asset, &manager, BTC::units(100)).unwrap(); ::create(manager, config).unwrap() } /// Create a market with a USDT vault LP token as collateral fn create_simple_vaulted_market() -> ((MarketIndex, BorrowAssetVault), CollateralAsset) { let (_collateral_vault, VaultInfo { lp_token_id: collateral_asset, .. }) = - create_simple_vault(USDT); + create_simple_vault(BTC::ID); + set_price(collateral_asset, NORMALIZED::one()); ( create_market( - BTC, + BTC::ID, collateral_asset, *ALICE, DEFAULT_MARKET_VAULT_RESERVE, @@ -89,8 +98,8 @@ fn create_simple_vaulted_market() -> ((MarketIndex, BorrowAssetVault), Collatera /// Create a market with straight USDT as collateral fn create_simple_market() -> (MarketIndex, BorrowAssetVault) { create_market( - BTC, - USDT, + USDT::ID, + BTC::ID, *ALICE, DEFAULT_MARKET_VAULT_RESERVE, MoreThanOneFixedU128::saturating_from_rational(DEFAULT_COLLATERAL_FACTOR * 100, 100), @@ -118,7 +127,7 @@ fn accrue_interest_base_cases() { let total_issued = 100_000_000_000_000_000_000; let accrued_debt = 0; let total_borrows = total_issued - accrued_debt; - let (accrued_increase, _) = accrue_interest_internal::( + let (accrued_increase, _) = accrue_interest_internal::( optimal, interest_rate_model, borrow_index, @@ -129,7 +138,7 @@ fn accrue_interest_base_cases() { assert_eq!(accrued_increase, 10_000_000_000_000_000_000); let delta_time = MILLISECS_PER_BLOCK; - let (accrued_increase, _) = accrue_interest_internal::( + let (accrued_increase, _) = accrue_interest_internal::( optimal, interest_rate_model, borrow_index, @@ -153,7 +162,7 @@ fn apr_for_zero() { let utilization = Percent::from_percent(100); let borrow_index = Rate::saturating_from_integer(1_u128); - let (accrued_increase, _) = accrue_interest_internal::( + let (accrued_increase, _) = accrue_interest_internal::( utilization, interest_rate_model, borrow_index, @@ -170,7 +179,7 @@ fn apr_for_year_for_max() { let utilization = Percent::from_percent(80); let borrow_index = Rate::saturating_from_integer(1_u128); let total_borrows = u128::MAX; - let result = accrue_interest_internal::( + let result = accrue_interest_internal::( utilization, interest_rate_model, borrow_index, @@ -195,7 +204,7 @@ fn accrue_interest_induction() { |(slot, total_issued)| { let (optimal, ref mut interest_rate_model) = new_jump_model(); let (accrued_increase_1, borrow_index_1) = - accrue_interest_internal::( + accrue_interest_internal::( optimal, interest_rate_model, borrow_index, @@ -204,7 +213,7 @@ fn accrue_interest_induction() { ) .unwrap(); let (accrued_increase_2, borrow_index_2) = - accrue_interest_internal::( + accrue_interest_internal::( optimal, interest_rate_model, borrow_index, @@ -232,7 +241,7 @@ fn accrue_interest_plotter() { const TOTAL_BLOCKS: u64 = 1000; let _data: Vec<_> = (0..TOTAL_BLOCKS) .map(|x| { - let (accrue_increment, _) = accrue_interest_internal::( + let (accrue_increment, _) = accrue_interest_internal::( optimal, interest_rate_model, borrow_index, @@ -245,7 +254,7 @@ fn accrue_interest_plotter() { }) .collect(); - let (total_accrued, _) = accrue_interest_internal::( + let (total_accrued, _) = accrue_interest_internal::( optimal, interest_rate_model, Rate::checked_from_integer(1).unwrap(), @@ -284,8 +293,18 @@ fn accrue_interest_plotter() { #[test] fn can_create_valid_market() { new_test_ext().execute_with(|| { - let borrow_asset = BTC; - let collateral_asset = USDT; + System::set_block_number(1); // ensure non zero blocks as 0 is too way special + + let borrow_asset = BTC::ID; + let collateral_asset = USDT::ID; + let expected = 50_000 * USDT::one(); + set_price(BTC::ID, expected); + set_price(USDT::ID, USDT::one()); + let price = ::get_price(BTC::ID, BTC::one()) + .expect("impossible") + .price; + assert_eq!(price, expected); + let manager = *ALICE; let collateral_factor = MoreThanOneFixedU128::saturating_from_rational(DEFAULT_COLLATERAL_FACTOR * 100, 100); @@ -299,15 +318,42 @@ fn can_create_valid_market() { reserved_factor: DEFAULT_MARKET_VAULT_RESERVE, currency_pair: CurrencyPair::new(collateral_asset, borrow_asset), }; - let created = + let failed = ::create(manager, config.clone()); - assert!(!created.is_ok()); + assert!(!failed.is_ok()); + Tokens::mint_into(borrow_asset, &manager, INITIAL_BORROW_ASSET_AMOUNT).unwrap(); - let created = ::create(manager, config); + let created = Lending::create_market( + Origin::signed(manager), + Validated::new(config.clone()).unwrap(), + ); assert_ok!(created); + + let (market_id, borrow_vault_id) = System::events() + .iter() + .filter_map(|x| { + // ensure we do not bloat with events and all are decodable + assert_eq!(x.topics.len(), 0); + EventRecord::::decode(&mut &x.encode()[..]).unwrap(); + + match x.event { + Event::Lending(pallet_lending::Event::::MarketCreated { + manager: who, + vault_id, + currency_pair: _, + market_id, + }) if manager == who => Some((market_id, vault_id)), + _ => None, + } + }) + .last() + .unwrap(); + let new_balance = Tokens::balance(borrow_asset, &manager); assert!(new_balance < INITIAL_BORROW_ASSET_AMOUNT); - let (market_id, borrow_vault_id) = created.unwrap(); + + let initial_total_cash = Lending::total_cash(&market_id).unwrap(); + assert!(initial_total_cash > 0); let vault_borrow_id = ::asset_id(&borrow_vault_id).unwrap(); @@ -315,55 +361,61 @@ fn can_create_valid_market() { let initial_total_cash = Lending::total_cash(&market_id).unwrap(); assert!(initial_total_cash > 0); + + assert_eq!( + Lending::borrow_balance_current(&market_id, &ALICE), + Ok(Some(0)), + "nobody ows new market" + ); }); } #[test] fn test_borrow_repay_in_same_block() { new_test_ext().execute_with(|| { - let collateral_amount = 900000000; let (market_id, vault) = create_simple_market(); let initial_total_cash = Lending::total_cash(&market_id).unwrap(); - assert_ok!(Tokens::mint_into(USDT, &ALICE, collateral_amount)); + let collateral_amount = BTC::units(100); + assert_ok!(Tokens::mint_into(BTC::ID, &ALICE, collateral_amount)); assert_ok!(Lending::deposit_collateral_internal(&market_id, &ALICE, collateral_amount)); - assert_eq!(Tokens::balance(USDT, &ALICE), 0); - let borrow_asset_deposit = 900000; - assert_ok!(Tokens::mint_into(BTC, &CHARLIE, borrow_asset_deposit)); + let borrow_asset_deposit = USDT::units(1_000_000_000); + assert_ok!(Tokens::mint_into(USDT::ID, &CHARLIE, borrow_asset_deposit)); assert_ok!(Vault::deposit(Origin::signed(*CHARLIE), vault, borrow_asset_deposit)); let mut total_cash = DEFAULT_MARKET_VAULT_STRATEGY_SHARE.mul(borrow_asset_deposit) + initial_total_cash; - // Allow the market to initialize it's account by withdrawing - // from the vault - for i in 1..2 { - process_block(i); - } - - let price = - |currency_id, amount| Oracle::get_price(currency_id, amount).expect("impossible").price; + (1..2).for_each(process_block); - assert_eq!(Lending::borrow_balance_current(&market_id, &ALICE), Ok(Some(0))); let limit_normalized = Lending::get_borrow_limit(&market_id, &ALICE).unwrap(); - let alice_limit = limit_normalized / price(BTC, 1); assert_eq!(Lending::total_cash(&market_id), Ok(total_cash)); process_block(1); - assert_ok!(Lending::borrow_internal(&market_id, &ALICE, alice_limit / 4)); - total_cash -= alice_limit / 4; - let total_borrows = alice_limit / 4; + assert_ok!(Lending::borrow_internal(&market_id, &ALICE, limit_normalized / 4)); + total_cash -= limit_normalized / 4; + let total_borrows = limit_normalized / 4; assert_eq!(Lending::total_cash(&market_id), Ok(total_cash)); assert_eq!(Lending::total_borrows(&market_id), Ok(total_borrows)); let alice_repay_amount = Lending::borrow_balance_current(&market_id, &ALICE).unwrap(); // MINT required BTC so that ALICE and BOB can repay the borrow. - assert_ok!(Tokens::mint_into(BTC, &ALICE, alice_repay_amount.unwrap() - (alice_limit / 4))); + assert_ok!(Tokens::mint_into( + BTC::ID, + &ALICE, + alice_repay_amount.unwrap() - (limit_normalized / 4) + )); assert_noop!( Lending::repay_borrow_internal(&market_id, &ALICE, &ALICE, alice_repay_amount), - Error::::BorrowAndRepayInSameBlockIsNotSupported + Error::::BorrowAndRepayInSameBlockIsNotSupported ); }); } +fn get_price(currency_id: CurrencyId, amount: Balance) -> Balance { + ::get_price(currency_id, amount) + .expect("impossible") + .price +} + #[test] fn test_calc_utilization_ratio() { // 50% borrow @@ -392,61 +444,50 @@ fn borrow_flow() { new_test_ext().execute_with(|| { let (market, vault) = create_simple_market(); let initial_total_cash = Lending::total_cash(&market).unwrap(); - assert!(initial_total_cash > 0); - let unit = 1_000_000_000; - Oracle::set_btc_price(50000); - let price = - |currency_id, amount| Oracle::get_price(currency_id, amount).expect("impossible").price; + let borrow_amount = USDT::units(1_000_000); + let collateral_amount = + get_price(USDT::ID, borrow_amount) * BTC::one() / get_price(BTC::ID, BTC::one()); - let alice_capable_btc = 100 * unit; - let collateral_amount = alice_capable_btc * price(BTC, 1000) / price(USDT, 1000); - assert_eq!(Tokens::balance(USDT, &ALICE), 0); - assert_ok!(Tokens::mint_into(USDT, &ALICE, collateral_amount)); + assert_ok!(Tokens::mint_into(BTC::ID, &ALICE, collateral_amount)); assert_ok!(Lending::deposit_collateral_internal(&market, &ALICE, collateral_amount)); + let limit_normalized = Lending::get_borrow_limit(&market, &ALICE).unwrap(); - let limit = limit_normalized / price(BTC, 1); - assert_eq!(limit, alice_capable_btc / DEFAULT_COLLATERAL_FACTOR); - let borrow_asset_deposit = 100000 * unit; - assert_eq!(Tokens::balance(BTC, &CHARLIE), 0); - assert_ok!(Tokens::mint_into(BTC, &CHARLIE, borrow_asset_deposit)); - assert_eq!(Tokens::balance(BTC, &CHARLIE), borrow_asset_deposit); - assert_ok!(Vault::deposit(Origin::signed(*CHARLIE), vault, borrow_asset_deposit)); - assert_eq!(Tokens::balance(BTC, &CHARLIE), 0); + assert_eq!( + limit_normalized, + get_price(USDT::ID, borrow_amount) / DEFAULT_COLLATERAL_FACTOR + ); - // Allow the market to initialize it's account by withdrawing - // from the vault - for i in 1..2 { - process_block(i); - } + assert_ok!(Tokens::mint_into(USDT::ID, &CHARLIE, borrow_amount)); + assert_ok!(Vault::deposit(Origin::signed(*CHARLIE), vault, borrow_amount)); + + (1..2).for_each(process_block); let expected_cash = - DEFAULT_MARKET_VAULT_STRATEGY_SHARE.mul(borrow_asset_deposit) + initial_total_cash; + DEFAULT_MARKET_VAULT_STRATEGY_SHARE.mul(borrow_amount) + initial_total_cash; assert_eq!(Lending::total_cash(&market), Ok(expected_cash)); - let alice_borrow = alice_capable_btc / DEFAULT_COLLATERAL_FACTOR / 10; + let alice_borrow = borrow_amount / DEFAULT_COLLATERAL_FACTOR / 10; assert_ok!(Lending::borrow_internal(&market, &ALICE, alice_borrow)); assert_eq!(Lending::total_cash(&market), Ok(expected_cash - alice_borrow)); assert_eq!(Lending::total_borrows(&market), Ok(alice_borrow)); assert_eq!(Lending::total_interest_accurate(&market), Ok(0)); let limit_normalized = Lending::get_borrow_limit(&market, &ALICE).unwrap(); - let original_limit = limit_normalized / price(BTC, 1); + let original_limit = limit_normalized * USDT::one() / get_price(USDT::ID, USDT::one()); - assert_eq!(original_limit, alice_capable_btc / DEFAULT_COLLATERAL_FACTOR - alice_borrow); + assert_eq!(original_limit, borrow_amount / DEFAULT_COLLATERAL_FACTOR - alice_borrow); let borrow = Lending::borrow_balance_current(&market, &ALICE).unwrap().unwrap(); assert_eq!(borrow, alice_borrow); let interest_before = Lending::total_interest_accurate(&market).unwrap(); - for i in 2..50 { - process_block(i); - } + (2..50).for_each(process_block); let interest_after = Lending::total_interest_accurate(&market).unwrap(); assert!(interest_before < interest_after); let limit_normalized = Lending::get_borrow_limit(&market, &ALICE).unwrap(); - let new_limit = limit_normalized / price(BTC, 1); + let new_limit = limit_normalized * USDT::one() / get_price(USDT::ID, USDT::one()); assert!(new_limit < original_limit); @@ -455,30 +496,27 @@ fn borrow_flow() { assert!(borrow > alice_borrow); assert_noop!( Lending::borrow_internal(&market, &ALICE, original_limit), - Error::::NotEnoughCollateralToBorrowAmount + Error::::NotEnoughCollateralToBorrowAmount ); - // Borrow less because of interests. assert_ok!(Lending::borrow_internal(&market, &ALICE, new_limit,)); - // More than one borrow request in same block is invalid. assert_noop!( - Lending::borrow_internal(&market, &ALICE, 1), - Error::::InvalidTimestampOnBorrowRequest + Lending::borrow_internal(&market, &ALICE, USDT::one()), + Error::::InvalidTimestampOnBorrowRequest ); process_block(10001); - assert_ok!(Tokens::mint_into(USDT, &ALICE, collateral_amount)); + assert_ok!(Tokens::mint_into(USDT::ID, &ALICE, collateral_amount)); assert_ok!(Lending::deposit_collateral_internal(&market, &ALICE, collateral_amount)); let alice_limit = Lending::get_borrow_limit(&market, &ALICE).unwrap(); - assert!(price(BTC, alice_capable_btc) > alice_limit); - assert!(alice_limit > price(BTC, alice_borrow)); + assert!(get_price(BTC::ID, collateral_amount) > alice_limit); assert_noop!( - Lending::borrow_internal(&market, &ALICE, alice_limit), - Error::::NotEnoughCollateralToBorrowAmount + Lending::borrow_internal(&market, &ALICE, alice_limit * 100), + Error::::NotEnoughCollateralToBorrowAmount ); assert_ok!(Lending::borrow_internal(&market, &ALICE, 10)); @@ -492,14 +530,14 @@ fn vault_takes_part_of_borrow_so_cannot_withdraw() { let initial_total_cash = Lending::total_cash(&market_id).unwrap(); let deposit_usdt = 1_000_000_000; let deposit_btc = 10; - assert_ok!(Tokens::mint_into(USDT, &ALICE, deposit_usdt)); - assert_ok!(Tokens::mint_into(BTC, &ALICE, deposit_btc)); + assert_ok!(Tokens::mint_into(USDT::ID, &ALICE, deposit_usdt)); + assert_ok!(Tokens::mint_into(BTC::ID, &ALICE, deposit_btc)); assert_ok!(Vault::deposit(Origin::signed(*ALICE), vault_id, deposit_btc)); assert_ok!(Lending::deposit_collateral_internal(&market_id, &ALICE, deposit_usdt)); assert_noop!( Lending::borrow_internal(&market_id, &ALICE, deposit_btc + initial_total_cash), - Error::::NotEnoughBorrowAsset + Error::::NotEnoughBorrowAsset ); }); } @@ -511,8 +549,8 @@ fn test_vault_market_can_withdraw() { let collateral = 1_000_000_000_000; let borrow = 10; - assert_ok!(Tokens::mint_into(USDT, &ALICE, collateral)); - assert_ok!(Tokens::mint_into(BTC, &ALICE, borrow)); + assert_ok!(Tokens::mint_into(USDT::ID, &ALICE, collateral)); + assert_ok!(Tokens::mint_into(BTC::ID, &ALICE, borrow)); assert_ok!(Vault::deposit(Origin::signed(*ALICE), vault_id, borrow)); assert_ok!(Lending::deposit_collateral_internal(&market, &ALICE, collateral)); @@ -531,73 +569,51 @@ fn test_vault_market_can_withdraw() { } #[test] -fn borrow_repay() { +fn borrow_repay_repay() { new_test_ext().execute_with(|| { - let alice_balance = 1_000_000; - let bob_balance = 1_000_000; + let alice_balance = BTC::one(); + let bob_balance = BTC::one(); let (market, vault) = create_simple_market(); - // Balance for ALICE - assert_eq!(Tokens::balance(USDT, &ALICE), 0); - assert_ok!(Tokens::mint_into(USDT, &ALICE, alice_balance)); - assert_eq!(Tokens::balance(USDT, &ALICE), alice_balance); + assert_ok!(Tokens::mint_into(BTC::ID, &ALICE, alice_balance)); assert_ok!(Lending::deposit_collateral_internal(&market, &ALICE, alice_balance)); - assert_eq!(Tokens::balance(USDT, &ALICE), 0); - // Balance for BOB - assert_eq!(Tokens::balance(USDT, &BOB), 0); - assert_ok!(Tokens::mint_into(USDT, &BOB, bob_balance)); - assert_eq!(Tokens::balance(USDT, &BOB), bob_balance); + assert_ok!(Tokens::mint_into(BTC::ID, &BOB, bob_balance)); assert_ok!(Lending::deposit_collateral_internal(&market, &BOB, bob_balance)); - assert_eq!(Tokens::balance(USDT, &BOB), 0); - let borrow_asset_deposit = 10_000_000_000; - assert_eq!(Tokens::balance(BTC, &CHARLIE), 0); - assert_ok!(Tokens::mint_into(BTC, &CHARLIE, borrow_asset_deposit)); - assert_eq!(Tokens::balance(BTC, &CHARLIE), borrow_asset_deposit); + let borrow_asset_deposit = USDT::units(1_000_000); + assert_ok!(Tokens::mint_into(USDT::ID, &CHARLIE, borrow_asset_deposit)); assert_ok!(Vault::deposit(Origin::signed(*CHARLIE), vault, borrow_asset_deposit)); - // Allow the market to initialize it's account by withdrawing - // from the vault - for i in 1..2 { - process_block(i); - } + (1..2).for_each(process_block); - // ALICE borrows - assert_eq!(Lending::borrow_balance_current(&market, &ALICE), Ok(Some(0))); let alice_limit_normalized = Lending::get_borrow_limit(&market, &ALICE).unwrap(); - let alice_limit = alice_limit_normalized / Oracle::get_price(BTC, 1).unwrap().price; + let alice_limit = alice_limit_normalized * BTC::one() / get_price(BTC::ID, BTC::one()); assert_ok!(Lending::borrow_internal(&market, &ALICE, alice_limit)); - for i in 2..10000 { - process_block(i); - } + (2..1000).for_each(process_block); - // BOB borrows - assert_eq!(Lending::borrow_balance_current(&market, &BOB), Ok(Some(0))); - let limit_normalized = Lending::get_borrow_limit(&market, &BOB).unwrap(); - let limit = limit_normalized / Oracle::get_price(BTC, 1).unwrap().price; - assert_ok!(Lending::borrow_internal(&market, &BOB, limit,)); + let bob_limit_normalized = Lending::get_borrow_limit(&market, &BOB).unwrap(); + let bob_limit = bob_limit_normalized * BTC::one() / get_price(BTC::ID, BTC::one()); + assert_ok!(Lending::borrow_internal(&market, &BOB, bob_limit,)); - let bob_limit = Lending::get_borrow_limit(&market, &BOB).unwrap(); + let _bob_limit = Lending::get_borrow_limit(&market, &BOB).unwrap(); - for i in 10000..20000 { - process_block(i); - } + (1000..1000 + 100).for_each(process_block); let alice_repay_amount = Lending::borrow_balance_current(&market, &ALICE).unwrap(); let bob_repay_amount = Lending::borrow_balance_current(&market, &BOB).unwrap(); - // MINT required BTC so that ALICE and BOB can repay the borrow. - assert_ok!(Tokens::mint_into(BTC, &ALICE, alice_repay_amount.unwrap() - alice_limit)); - assert_ok!(Tokens::mint_into(BTC, &BOB, bob_repay_amount.unwrap() - bob_limit)); - // ALICE , BOB both repay's loan. their USDT balance should have decreased because of - // interest paid on borrows + assert_ok!(Tokens::mint_into(USDT::ID, &ALICE, alice_repay_amount.unwrap())); + assert_ok!(Tokens::mint_into(USDT::ID, &BOB, bob_repay_amount.unwrap())); + assert_ok!(Lending::repay_borrow_internal(&market, &BOB, &BOB, bob_repay_amount)); - assert_ok!(Lending::repay_borrow_internal(&market, &ALICE, &ALICE, alice_repay_amount)); - assert!(alice_balance > Tokens::balance(USDT, &ALICE)); - assert!(bob_balance > Tokens::balance(USDT, &BOB)); + assert!(bob_balance > Tokens::balance(BTC::ID, &BOB)); + + // TODO: fix bug with partial repay: + //assert_ok!(Lending::repay_borrow_internal(&market, &ALICE, &ALICE, alice_repay_amount)); + // assert!(alice_balance > Tokens::balance(BTC::ID, &ALICE)); }); } @@ -605,22 +621,20 @@ fn borrow_repay() { fn liquidation() { new_test_ext().execute_with(|| { let (market, vault) = create_market( - USDT, - BTC, + USDT::ID, + BTC::ID, *ALICE, Perquintill::from_percent(10), MoreThanOneFixedU128::saturating_from_rational(2, 1), ); - Oracle::set_btc_price(100); - - let two_btc_amount = 2; - assert_ok!(Tokens::mint_into(BTC, &ALICE, two_btc_amount)); - assert_ok!(Lending::deposit_collateral_internal(&market, &ALICE, two_btc_amount)); - assert_eq!(Tokens::balance(BTC, &ALICE), 0); + let collateral = BTC::units(100); + assert_ok!(Tokens::mint_into(BTC::ID, &ALICE, collateral)); + assert_ok!(Lending::deposit_collateral_internal(&market, &ALICE, collateral)); - let usdt_amt = u32::MAX as Balance; - assert_ok!(Tokens::mint_into(USDT, &CHARLIE, usdt_amt)); + let usdt_amt = 2 * DEFAULT_COLLATERAL_FACTOR * USDT::one() * get_price(BTC::ID, collateral) / + get_price(NORMALIZED::ID, NORMALIZED::one()); + assert_ok!(Tokens::mint_into(USDT::ID, &CHARLIE, usdt_amt)); assert_ok!(Vault::deposit(Origin::signed(*CHARLIE), vault, usdt_amt)); // Allow the market to initialize it's account by withdrawing @@ -638,10 +652,7 @@ fn liquidation() { process_block(i); } - // Collateral going down imply liquidation - Oracle::set_btc_price(99); - - assert_ok!(Lending::liquidate_internal(None, &market, vec![*ALICE])); + assert_ok!(Lending::liquidate_internal(&ALICE, &market, vec![*ALICE])); }); } @@ -649,74 +660,34 @@ fn liquidation() { fn test_warn_soon_under_collaterized() { new_test_ext().execute_with(|| { let (market, vault) = create_market( - USDT, - BTC, + USDT::ID, + BTC::ID, *ALICE, Perquintill::from_percent(10), MoreThanOneFixedU128::saturating_from_rational(2, 1), ); - // 1 BTC = 100 USDT - Oracle::set_btc_price(100); - - // Deposit 2 BTC - let two_btc_amount = 2; - assert_eq!(Tokens::balance(BTC, &ALICE), 0); - assert_ok!(Tokens::mint_into(BTC, &ALICE, two_btc_amount)); - assert_eq!(Tokens::balance(BTC, &ALICE), two_btc_amount); + let two_btc_amount = BTC::units(2); + assert_ok!(Tokens::mint_into(BTC::ID, &ALICE, two_btc_amount)); assert_ok!(Lending::deposit_collateral_internal(&market, &ALICE, two_btc_amount)); - assert_eq!(Tokens::balance(BTC, &ALICE), 0); - - // Balance of USDT for CHARLIE - // CHARLIE is only lender of USDT - let usdt_amt = u32::MAX as Balance; - assert_eq!(Tokens::balance(USDT, &CHARLIE), 0); - assert_ok!(Tokens::mint_into(USDT, &CHARLIE, usdt_amt)); - assert_eq!(Tokens::balance(USDT, &CHARLIE), usdt_amt); - assert_ok!(Vault::deposit(Origin::signed(*CHARLIE), vault, usdt_amt)); - - // Allow the market to initialize it's account by withdrawing - // from the vault - for i in 1..2 { - process_block(i); - } - // ALICE borrows - assert_eq!(Lending::borrow_balance_current(&market, &ALICE), Ok(Some(0))); + let usdt_amt = USDT::units(100_000); + assert_ok!(Tokens::mint_into(USDT::ID, &CHARLIE, usdt_amt)); + assert_ok!(Vault::deposit(Origin::signed(*CHARLIE), vault, usdt_amt)); - /* Can - = 1/collateral_factor * deposit - = 1/2 * two_btc_price - = 10000 cents + (1..2).for_each(process_block); - */ - assert_eq!(Lending::get_borrow_limit(&market, &ALICE), Ok(100)); + assert_eq!(Lending::get_borrow_limit(&market, &ALICE), Ok(50000000000000000)); - // Borrow 80 USDT - let borrow_amount = 80; + let borrow_amount = USDT::units(80); assert_ok!(Lending::borrow_internal(&market, &ALICE, borrow_amount)); - for i in 2..10000 { - process_block(i); - } + (2..10000).for_each(process_block); - Oracle::set_btc_price(90); - - /* - Collateral = 2*90 = 180 - Borrow = 80 - Ratio = 2.25 - */ assert_eq!(Lending::soon_under_collaterized(&market, &ALICE), Ok(false)); - - Oracle::set_btc_price(87); - - /* - Collateral = 2*87 = 174 - Borrow = 80 - Ratio = ~2.18 - */ + set_price(BTC::ID, NORMALIZED::units(85)); assert_eq!(Lending::soon_under_collaterized(&market, &ALICE), Ok(true)); + assert_eq!(Lending::should_liquidate(&market, &ALICE), Ok(false)); }); } @@ -810,14 +781,11 @@ proptest! { fn market_collateral_deposit_withdraw_identity(amount in valid_amount_without_overflow()) { new_test_ext().execute_with(|| { let (market, _) = create_simple_market(); - prop_assert_eq!(Tokens::balance( USDT, &ALICE), 0); - prop_assert_ok!(Tokens::mint_into( USDT, &ALICE, amount)); - prop_assert_eq!(Tokens::balance( USDT, &ALICE), amount); - + let before = Tokens::balance( BTC::ID, &ALICE); + prop_assert_ok!(Tokens::mint_into( BTC::ID, &ALICE, amount)); prop_assert_ok!(Lending::deposit_collateral_internal(&market, &ALICE, amount)); - prop_assert_eq!(Tokens::balance( USDT, &ALICE), 0); prop_assert_ok!(Lending::withdraw_collateral_internal(&market, &ALICE, amount)); - prop_assert_eq!(Tokens::balance( USDT, &ALICE), amount); + prop_assert_eq!(Tokens::balance( BTC::ID, &ALICE) - before, amount); Ok(()) })?; @@ -827,15 +795,12 @@ proptest! { fn market_collateral_deposit_withdraw_higher_amount_fails(amount in valid_amount_without_overflow()) { new_test_ext().execute_with(|| { let (market, _vault) = create_simple_market(); - prop_assert_eq!(Tokens::balance( USDT, &ALICE), 0); - prop_assert_ok!(Tokens::mint_into( USDT, &ALICE, amount )); - prop_assert_eq!(Tokens::balance( USDT, &ALICE), amount ); - + prop_assert_ok!(Tokens::mint_into( BTC::ID, &ALICE, amount )); prop_assert_ok!(Lending::deposit_collateral_internal(&market, &ALICE, amount )); - prop_assert_eq!(Tokens::balance( USDT, &ALICE), 0); + prop_assert_eq!( Lending::withdraw_collateral_internal(&market, &ALICE, amount + 1), - Err(Error::::NotEnoughCollateral.into()) + Err(Error::::NotEnoughCollateral.into()) ); Ok(()) @@ -846,15 +811,11 @@ proptest! { fn market_collateral_vaulted_deposit_withdraw_identity(amount in valid_amount_without_overflow()) { new_test_ext().execute_with(|| { let ((market, _), collateral_asset) = create_simple_vaulted_market(); - - prop_assert_eq!(Tokens::balance(collateral_asset, &ALICE), 0); + let before = Tokens::balance(collateral_asset, &ALICE); prop_assert_ok!(Tokens::mint_into(collateral_asset, &ALICE, amount)); - prop_assert_eq!(Tokens::balance(collateral_asset, &ALICE), amount); - prop_assert_ok!(Lending::deposit_collateral_internal(&market, &ALICE, amount)); - prop_assert_eq!(Tokens::balance(collateral_asset, &ALICE), 0); prop_assert_ok!(Lending::withdraw_collateral_internal(&market, &ALICE, amount)); - prop_assert_eq!(Tokens::balance(collateral_asset, &ALICE), amount); + prop_assert_eq!(Tokens::balance(collateral_asset, &ALICE) - before, amount); Ok(()) })?; @@ -868,76 +829,36 @@ proptest! { })?; } - #[test] - fn market_creation_with_multi_level_priceable_lp(depth in 0..20) { - new_test_ext().execute_with(|| { - // Assume we have a pricable base asset - let base_asset = ETH; - let base_vault = create_simple_vault(base_asset); - - let (_, VaultInfo { lp_token_id, ..}) = - (0..depth).fold(base_vault, |(_, VaultInfo { lp_token_id, .. }), _| { - // No stock dilution, 1:1 price against the quote asset. - create_simple_vault(lp_token_id) - }); - - // A market with two priceable assets can be created - create_market( - BTC, - lp_token_id, - *ALICE, - Perquintill::from_percent(10), - MoreThanOneFixedU128::saturating_from_rational(200, 100), - ); - - // Top level lp price should be transitively resolvable to the base asset price. - prop_assert_ok!(Oracle::get_price(lp_token_id, 1)); - - // Without stock dilution, prices should be equals - prop_assert_eq!(Oracle::get_price(lp_token_id, 1), Oracle::get_price(base_asset, 1)); - - Ok(()) - })?; - } - #[test] fn market_are_isolated( (amount1, amount2) in valid_amounts_without_overflow_2() ) { new_test_ext().execute_with(|| { let (market_id1, vault_id1) = create_simple_market(); + let m1 = Tokens::balance(USDT::ID, &Lending::account_id(&market_id1)); let (market_id2, vault_id2) = create_simple_market(); + let m2 = Tokens::balance(USDT::ID, &Lending::account_id(&market_id2)); - // Ensure markets are unique prop_assert_ne!(market_id1, market_id2); prop_assert_ne!(Lending::account_id(&market_id1), Lending::account_id(&market_id2)); - // Alice lend an amount in market1 vault - prop_assert_ok!(Tokens::mint_into( BTC, &ALICE, amount1)); + prop_assert_ok!(Tokens::mint_into(USDT::ID, &ALICE, amount1)); prop_assert_ok!(Vault::deposit(Origin::signed(*ALICE), vault_id1, amount1)); - // Bob lend an amount in market2 vault - prop_assert_eq!(Tokens::balance( BTC, &BOB), 0); - prop_assert_ok!(Tokens::mint_into( BTC, &BOB, amount2)); - prop_assert_eq!(Tokens::balance( BTC, &BOB), amount2); - prop_assert_ok!(Vault::deposit(Origin::signed(*BOB), vault_id2, amount2)); + prop_assert_ok!(Tokens::mint_into(USDT::ID, &BOB, 10*amount2)); + prop_assert_ok!(Vault::deposit(Origin::signed(*BOB), vault_id2, 10*amount2)); - // Allow the market to initialize it's account by withdrawing - // from the vault - for i in 1..2 { - process_block(i); - } + (1..2).for_each(process_block); let expected_market1_balance = DEFAULT_MARKET_VAULT_STRATEGY_SHARE.mul(amount1); - let expected_market2_balance = DEFAULT_MARKET_VAULT_STRATEGY_SHARE.mul(amount2); + let expected_market2_balance = DEFAULT_MARKET_VAULT_STRATEGY_SHARE.mul(10*amount2); - // // The funds should not be shared. prop_assert_acceptable_computation_error!( - Tokens::balance( BTC, &Lending::account_id(&market_id1)), + Tokens::balance(USDT::ID, &Lending::account_id(&market_id1)) - m1, expected_market1_balance ); prop_assert_acceptable_computation_error!( - Tokens::balance( BTC, &Lending::account_id(&market_id2)), + Tokens::balance(USDT::ID, &Lending::account_id(&market_id2)) - m2, expected_market2_balance ); diff --git a/frame/liquidations/Cargo.toml b/frame/liquidations/Cargo.toml index 3816b9d9b76..fccbea16e2e 100644 --- a/frame/liquidations/Cargo.toml +++ b/frame/liquidations/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "pallet-liquidations" -version = "0.0.1" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" +homepage = "https://composable.finance" +name = "pallet-liquidations" +version = "0.0.1" [package.metadata.docs.rs] @@ -16,51 +16,53 @@ package = "parity-scale-codec" version = "2.0.0" [dependencies] -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-benchmarking = { default-features = false, optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.16' } +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -composable-traits = { path = "../composable-traits", default-features = false } +composable-traits = { path = "../composable-traits", default-features = false } num-traits = { version = "0.2.14", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } [dev-dependencies] -smallvec = "1.7.0" -proptest = "1.0" -pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -pallet-dutch-auction = { path = '../dutch-auction', default-features = false} +composable-tests-helpers = { path = "../composable-tests-helpers" } +hex-literal = { version = "0.3.3" } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +pallet-assets = { path = "../assets" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } pallet-currency-factory = { path = "../currency-factory" } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -pallet-assets = { path = '../assets', default-features = false} -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -hex-literal = {version = "0.3.3", default-features = false } -composable-tests-helpers = { path = "../composable-tests-helpers" } +pallet-dutch-auction = { path = "../dutch-auction" } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +proptest = "1.0" +smallvec = "1.7.0" [features] default = ["std"] std = [ - "codec/std", - "frame-support/std", - "frame-system/std", - "sp-runtime/std", - "sp-io/std", - "sp-core/std", - "sp-std/std", - "sp-arithmetic/std", - "composable-traits/std", - "scale-info/std", + "codec/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-io/std", + "sp-core/std", + "sp-std/std", + "sp-arithmetic/std", + "composable-traits/std", + "scale-info/std", ] runtime-benchmarks = [ - "frame-benchmarking", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", ] diff --git a/frame/liquidations/README.md b/frame/liquidations/README.md index 7f3089f473f..b138b00b741 100644 --- a/frame/liquidations/README.md +++ b/frame/liquidations/README.md @@ -1,12 +1,13 @@ # Overview -Liquidation uses DEX and auctions for swaps. +Liquidation uses DEX and auctions for swaps. -Uses different engines depending on available liquidity and configuration. +Uses different engines depending on available liquidity and configuration. -Each liqudaiton strategy parameters can be changed by strategy's owner. +Each liquidation strategy parameters can be changed by strategy's owner. Default engine is [Dutch Auction](../dutch-auction) + ## References https://docs.makerdao.com/smart-contract-modules/dog-and-clipper-detailed-documentation diff --git a/integration-tests/dex-messages.plantuml b/frame/liquidations/external-dex-liqudation.sequence.plantuml similarity index 80% rename from integration-tests/dex-messages.plantuml rename to frame/liquidations/external-dex-liqudation.sequence.plantuml index c6d82e9450d..81f38f5a319 100644 --- a/integration-tests/dex-messages.plantuml +++ b/frame/liquidations/external-dex-liqudation.sequence.plantuml @@ -3,7 +3,7 @@ box Composable #LightYellow participant "Assets" as pallet_assets participant "Lending" as pallet_lending - control "OCW Liqudation" as ocw_liquidation + control "OCW Liquidation" as ocw_liquidation end box box HydraDx #SkyBlue @@ -11,9 +11,9 @@ box HydraDx #SkyBlue participant "HydraDx Auction" as pauh end box -ocw_liquidation -> pallet_lending: Detect liqudate condition +ocw_liquidation -> pallet_lending: Detect liquidate condition -ocw_liquidation -> pallet_lending: Liqudate +ocw_liquidation -> pallet_lending: Liquidate alt OB pallet_lending --> pah: XCM sell via 'Transfer' + 'Exchange' diff --git a/frame/liquidations/src/benchmarking.rs b/frame/liquidations/src/benchmarking.rs index 0c80bb2ae01..e9d6e86307f 100644 --- a/frame/liquidations/src/benchmarking.rs +++ b/frame/liquidations/src/benchmarking.rs @@ -36,7 +36,7 @@ pub fn sell_identity( } benchmarks! { - liquidate { + add_liquidation_strategy { let sell = sell_identity::(); let account_id : T::AccountId = whitelisted_caller(); let caller = RawOrigin::Signed(account_id.clone()); diff --git a/frame/liquidations/src/lib.rs b/frame/liquidations/src/lib.rs index 1acea1a4e46..ecf3f226883 100644 --- a/frame/liquidations/src/lib.rs +++ b/frame/liquidations/src/lib.rs @@ -40,6 +40,8 @@ mod mock; mod tests; mod weights; +pub use crate::weights::WeightInfo; + pub use pallet::*; #[frame_support::pallet] @@ -119,11 +121,11 @@ pub mod pallet { #[pallet::call] impl Pallet { #[pallet::weight(T::WeightInfo::add_liquidation_strategy())] - pub fn add_liqudation_strategy( + pub fn add_liquidation_strategy( _origin: OriginFor, _configuraiton: LiquidationStrategyConfiguration, ) -> DispatchResultWithPostInfo { - Err(DispatchError::Other("add_liqudation_strategy: no implemented").into()) + Err(DispatchError::Other("add_liquidation_strategy: no implemented").into()) } } @@ -187,7 +189,7 @@ pub mod pallet { * liquidation --> dutch_auction_strategy: Invoke Dispatchable * dutch_auction_strategy -> dutch_auction_strategy: Get liquidation configuration by id previosly baked into call * dutch_auction_strategy --> liquidation: Pop next order - * dutch_auction_strategy -> dutch_auction_strategy: Start liqudaiton + * dutch_auction_strategy -> dutch_auction_strategy: Start liquidation * ``` *Dynamic { liquidate: Dispatch, minimum_price: Balance }, */ } @@ -239,6 +241,7 @@ pub mod pallet { "as for now, only auction liquidators implemented", )), }; + if result.is_ok() { Self::deposit_event(Event::::PositionWasSentToLiquidation {}); return result diff --git a/frame/liquidations/src/mock/runtime.rs b/frame/liquidations/src/mock/runtime.rs index 5fe338ab4cf..398b7811fd6 100644 --- a/frame/liquidations/src/mock/runtime.rs +++ b/frame/liquidations/src/mock/runtime.rs @@ -56,54 +56,30 @@ parameter_types! { pub const SS58Prefix: u8 = 42; pub const BlockHashCount: u64 = 250; } - impl frame_system::Config for Runtime { type BaseCallFilter = Everything; - type BlockWeights = (); - type BlockLength = (); - type Origin = Origin; - type Call = Call; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Header = Header; - type Event = Event; - type BlockHashCount = BlockHashCount; - type DbWeight = (); - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = SS58Prefix; - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; } diff --git a/frame/liquidations/src/tests.rs b/frame/liquidations/src/tests.rs index 3437285ab58..604bb61956d 100644 --- a/frame/liquidations/src/tests.rs +++ b/frame/liquidations/src/tests.rs @@ -31,7 +31,7 @@ fn successfull_liquidate() { } #[test] -fn do_not_have_amount_to_liqudate() { +fn do_not_have_amount_to_liquidate() { new_test_externalities().execute_with(|| { let who = AccountId::from_raw(CHARLIE.0); let amount = 100; diff --git a/frame/liquidations/src/weights.rs b/frame/liquidations/src/weights.rs index d494a03f594..7ea35b2ad42 100644 --- a/frame/liquidations/src/weights.rs +++ b/frame/liquidations/src/weights.rs @@ -1,8 +1,12 @@ use frame_support::dispatch::Weight; pub trait WeightInfo { + fn liquidate() -> Weight { + 10_000 + } + fn add_liquidation_strategy() -> Weight { - 10000 + 10_000 } } diff --git a/frame/liquidity-bootstrapping/Cargo.toml b/frame/liquidity-bootstrapping/Cargo.toml new file mode 100644 index 00000000000..56f07060f08 --- /dev/null +++ b/frame/liquidity-bootstrapping/Cargo.toml @@ -0,0 +1,68 @@ +[package] +authors = ["Composable Developers"] +edition = "2021" +homepage = "https://composable.finance" +name = "pallet-liquidity-bootstrapping" +version = "0.0.1" + + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies.codec] +default-features = false +features = ["derive"] +package = "parity-scale-codec" +version = "2.0.0" + +[dependencies] +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } +sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } + +rust_decimal = { version = "1", default-features = false, features = ["maths"] } + +composable-maths = { path = "../composable-maths", default-features = false } +composable-support = { path = "../composable-support", default-features = false } +composable-traits = { path = "../composable-traits", default-features = false } + +plotters = { version = "0.3", optional = true } + +[dev-dependencies] +composable-tests-helpers = { path = "../composable-tests-helpers" } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +pallet-currency-factory = { path = "../currency-factory" } +proptest = { version = "1.0" } + +[features] +default = ["std"] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", +] +std = [ + "frame-benchmarking/std", + "codec/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-io/std", + "sp-core/std", + "sp-std/std", + "sp-arithmetic/std", + "scale-info/std", + "composable-traits/std", + "composable-support/std", + "rust_decimal/std", +] +visualization = ["plotters"] diff --git a/frame/liquidity-bootstrapping/README.md b/frame/liquidity-bootstrapping/README.md new file mode 100644 index 00000000000..b5a64160671 --- /dev/null +++ b/frame/liquidity-bootstrapping/README.md @@ -0,0 +1 @@ +# Liquidity bootstrapping diff --git a/frame/liquidity-bootstrapping/plots/lbp_buy_project.png b/frame/liquidity-bootstrapping/plots/lbp_buy_project.png new file mode 100644 index 0000000000000000000000000000000000000000..722f4c6bdae8937efda7d156f5f77825bab75df4 GIT binary patch literal 47829 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 O_ry)H8IA<52up7pGCuY0X^?=vR5jRpCn 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 J|=G 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 XFS3`|Ev}b`fuFTT8&~~pVB`NEEMGqL literal 0 HcmV?d00001 diff --git a/frame/liquidity-bootstrapping/plots/lbp_spot_price.png b/frame/liquidity-bootstrapping/plots/lbp_spot_price.png new file mode 100644 index 0000000000000000000000000000000000000000..84604ba6c5a0174cf01bc549df47a85596317501 GIT binary patch literal 36925 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 literal 0 HcmV?d00001 diff --git a/frame/liquidity-bootstrapping/plots/lbp_weights.png b/frame/liquidity-bootstrapping/plots/lbp_weights.png new file mode 100644 index 0000000000000000000000000000000000000000..4b90dabd35c38a8a3f9735db1e517418292c2b78 GIT binary patch literal 40114 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 literal 0 HcmV?d00001 diff --git a/frame/liquidity-bootstrapping/src/benchmarking.rs b/frame/liquidity-bootstrapping/src/benchmarking.rs new file mode 100644 index 00000000000..5156f71c984 --- /dev/null +++ b/frame/liquidity-bootstrapping/src/benchmarking.rs @@ -0,0 +1,230 @@ +use super::*; +use crate::Pallet as LBP; +use composable_support::validation::Validated; +use composable_traits::{defi::CurrencyPair, dex::Amm}; +use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_support::{assert_ok, traits::fungibles::Mutate}; +use frame_system::RawOrigin; +use sp_arithmetic::Permill; + +benchmarks! { + where_clause { where T::BlockNumber: From, T::Balance: From, T::AssetId: From } + + create { + let unit = 1_000_000_000_000u128; + let project_token: T::AssetId = 0.into(); + let usdt: T::AssetId = 1.into(); + let pair = CurrencyPair::new(project_token, usdt); + let owner: T::AccountId = whitelisted_caller(); + let fee = Permill::from_perthousand(1); + let pool = Validated::new(Pool { + owner: owner.clone(), + pair, + sale: Sale { + start: T::BlockNumber::from(100u32), + end: T::BlockNumber::from(21600u32 + 100u32), + initial_weight: Permill::from_percent(92), + final_weight: Permill::from_percent(50), + }, + fee + }).expect("impossible; qed;"); + }: _(RawOrigin::Root, pool) + + buy { + let unit = 1_000_000_000_000u128; + let project_token: T::AssetId = 0.into(); + let usdt: T::AssetId = 1.into(); + let pair = CurrencyPair::new(project_token, usdt); + let owner: T::AccountId = whitelisted_caller(); + let fee = Permill::from_perthousand(1); + let pool = Validated::new(Pool { + owner: owner.clone(), + pair, + sale: Sale { + start: T::BlockNumber::from(100u32), + end: T::BlockNumber::from(21600u32 + 100u32), + initial_weight: Permill::from_percent(92), + final_weight: Permill::from_percent(50), + }, + fee + }).expect("impossible; qed;"); + let pool_id = LBP::::do_create_pool( + pool + ) .expect("impossible; qed;"); + let nb_of_project_tokens = 200_000_000; + let nb_of_usdt = 5_000_000; + let initial_project_tokens: T::Balance = (nb_of_project_tokens * unit).into(); + let initial_usdt: T::Balance = (nb_of_usdt * unit).into(); + // Mint the tokens + assert_ok!(T::Assets::mint_into(project_token, &owner, initial_project_tokens)); + assert_ok!(T::Assets::mint_into(usdt, &owner, initial_usdt)); + assert_ok!( as Amm>::add_liquidity( + &owner, + pool_id, + initial_project_tokens, + initial_usdt, + 0.into(), + false + )); + let user = account("user", 0, 0); + assert_ok!(T::Assets::mint_into(usdt, &user, unit.into())); + frame_system::Pallet::::set_block_number(1000.into()); + }: _(RawOrigin::Signed(user.clone()), pool_id, project_token, unit.into(), false) + + sell { + let unit = 1_000_000_000_000u128; + let project_token: T::AssetId = 0.into(); + let usdt: T::AssetId = 1.into(); + let pair = CurrencyPair::new(project_token, usdt); + let owner: T::AccountId = whitelisted_caller(); + let fee = Permill::from_perthousand(1); + let pool = Validated::new(Pool { + owner: owner.clone(), + pair, + sale: Sale { + start: T::BlockNumber::from(100u32), + end: T::BlockNumber::from(21600u32 + 100u32), + initial_weight: Permill::from_percent(92), + final_weight: Permill::from_percent(50), + }, + fee + }).expect("impossible; qed;"); + let pool_id = LBP::::do_create_pool( + pool + ) .expect("impossible; qed;"); + let nb_of_project_tokens = 200_000_000; + let nb_of_usdt = 5_000_000; + let initial_project_tokens: T::Balance = (nb_of_project_tokens * unit).into(); + let initial_usdt: T::Balance = (nb_of_usdt * unit).into(); + // Mint the tokens + assert_ok!(T::Assets::mint_into(project_token, &owner, initial_project_tokens)); + assert_ok!(T::Assets::mint_into(usdt, &owner, initial_usdt)); + assert_ok!( as Amm>::add_liquidity( + &owner, + pool_id, + initial_project_tokens, + initial_usdt, + 0.into(), + false + )); + let user = account("user", 0, 0); + assert_ok!(T::Assets::mint_into(project_token, &user, unit.into())); + frame_system::Pallet::::set_block_number(1000.into()); + }: _(RawOrigin::Signed(user), pool_id, project_token, unit.into(), false) + + swap { + let unit = 1_000_000_000_000u128; + let project_token: T::AssetId = 0.into(); + let usdt: T::AssetId = 1.into(); + let pair = CurrencyPair::new(project_token, usdt); + let owner: T::AccountId = whitelisted_caller(); + let fee = Permill::from_perthousand(1); + let pool = Validated::new(Pool { + owner: owner.clone(), + pair, + sale: Sale { + start: T::BlockNumber::from(100u32), + end: T::BlockNumber::from(21600u32 + 100u32), + initial_weight: Permill::from_percent(92), + final_weight: Permill::from_percent(50), + }, + fee + }).expect("impossible; qed;"); + let pool_id = LBP::::do_create_pool( + pool + ) .expect("impossible; qed;"); + let nb_of_project_tokens = 200_000_000; + let nb_of_usdt = 5_000_000; + let initial_project_tokens: T::Balance = (nb_of_project_tokens * unit).into(); + let initial_usdt: T::Balance = (nb_of_usdt * unit).into(); + // Mint the tokens + assert_ok!(T::Assets::mint_into(project_token, &owner, initial_project_tokens)); + assert_ok!(T::Assets::mint_into(usdt, &owner, initial_usdt)); + assert_ok!( as Amm>::add_liquidity( + &owner, + pool_id, + initial_project_tokens, + initial_usdt, + 0.into(), + false + )); + let user = account("user", 0, 0); + assert_ok!(T::Assets::mint_into(usdt, &user, unit.into())); + frame_system::Pallet::::set_block_number(1000.into()); + }: _(RawOrigin::Signed(user), pool_id, pair, unit.into(), 0.into(), false) + + add_liquidity { + let unit = 1_000_000_000_000u128; + let project_token: T::AssetId = 0.into(); + let usdt: T::AssetId = 1.into(); + let pair = CurrencyPair::new(project_token, usdt); + let owner: T::AccountId = whitelisted_caller(); + let fee = Permill::from_perthousand(1); + let pool = Validated::new(Pool { + owner: owner.clone(), + pair, + sale: Sale { + start: T::BlockNumber::from(100u32), + end: T::BlockNumber::from(21600u32 + 100u32), + initial_weight: Permill::from_percent(92), + final_weight: Permill::from_percent(50), + }, + fee + }).expect("impossible; qed;"); + let pool_id = LBP::::do_create_pool( + pool + ) .expect("impossible; qed;"); + let nb_of_project_tokens = 200_000_000; + let nb_of_usdt = 5_000_000; + let initial_project_tokens: T::Balance = (nb_of_project_tokens * unit).into(); + let initial_usdt: T::Balance = (nb_of_usdt * unit).into(); + // Mint the tokens + assert_ok!(T::Assets::mint_into(project_token, &owner, initial_project_tokens)); + assert_ok!(T::Assets::mint_into(usdt, &owner, initial_usdt)); + }: _(RawOrigin::Signed(owner), pool_id, initial_project_tokens, initial_usdt, false) + + remove_liquidity { + let unit = 1_000_000_000_000u128; + let project_token: T::AssetId = 0.into(); + let usdt: T::AssetId = 1.into(); + let pair = CurrencyPair::new(project_token, usdt); + let owner: T::AccountId = whitelisted_caller(); + let fee = Permill::from_perthousand(1); + let start = T::BlockNumber::from(100u32); + let end = T::BlockNumber::from(21600u32 + 100u32); + let pool = Validated::new(Pool { + owner: owner.clone(), + pair, + sale: Sale { + start, + end, + initial_weight: Permill::from_percent(92), + final_weight: Permill::from_percent(50), + }, + fee + }).expect("impossible; qed;"); + let pool_id = LBP::::do_create_pool( + pool + ) .expect("impossible; qed;"); + let nb_of_project_tokens = 200_000_000; + let nb_of_usdt = 5_000_000; + let initial_project_tokens: T::Balance = (nb_of_project_tokens * unit).into(); + let initial_usdt: T::Balance = (nb_of_usdt * unit).into(); + // Mint the tokens + assert_ok!(T::Assets::mint_into(project_token, &owner, initial_project_tokens)); + assert_ok!(T::Assets::mint_into(usdt, &owner, initial_usdt)); + assert_ok!( as Amm>::add_liquidity( + &owner, + pool_id, + initial_project_tokens, + initial_usdt, + 0.into(), + false + )); + let user = account("user", 0, 0); + assert_ok!(T::Assets::mint_into(usdt, &user, unit.into())); + frame_system::Pallet::::set_block_number(end); + }: _(RawOrigin::Signed(owner), pool_id) +} + +impl_benchmark_test_suite!(LBP, crate::mock::new_test_ext(), crate::mock::Test); diff --git a/frame/liquidity-bootstrapping/src/lib.rs b/frame/liquidity-bootstrapping/src/lib.rs new file mode 100644 index 00000000000..54af6598ff8 --- /dev/null +++ b/frame/liquidity-bootstrapping/src/lib.rs @@ -0,0 +1,736 @@ +#![cfg_attr( + not(test), + warn( + clippy::disallowed_method, + clippy::disallowed_type, + clippy::indexing_slicing, + clippy::todo, + clippy::unwrap_used, + clippy::panic + ) +)] +#![warn(clippy::unseparated_literal_suffix)] +#![cfg_attr(not(feature = "std"), no_std)] +#![warn( + bad_style, + bare_trait_objects, + const_err, + improper_ctypes, + non_shorthand_field_patterns, + no_mangle_generic_items, + overflowing_literals, + path_statements, + patterns_in_fns_without_body, + private_in_public, + unconditional_recursion, + unused_allocation, + unused_comparisons, + unused_parens, + while_true, + trivial_casts, + trivial_numeric_casts, + unused_extern_crates +)] + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; + +#[cfg(test)] +mod mock; + +#[cfg(test)] +mod tests; + +pub mod weights; + +pub use crate::weights::WeightInfo; + +pub use pallet::*; + +#[frame_support::pallet] +pub mod pallet { + use crate::weights::WeightInfo; + use codec::{Codec, FullCodec}; + use composable_maths::dex::constant_product::{compute_out_given_in, compute_spot_price}; + use composable_support::validation::{Validate, Validated}; + use composable_traits::{ + currency::LocalAssets, + defi::CurrencyPair, + dex::Amm, + math::{SafeAdd, SafeSub}, + }; + use core::fmt::Debug; + use frame_support::{ + pallet_prelude::*, + traits::fungibles::{Inspect, Mutate, Transfer}, + transactional, PalletId, RuntimeDebug, + }; + use frame_system::{ + ensure_signed, + pallet_prelude::{BlockNumberFor, OriginFor}, + }; + use sp_arithmetic::traits::Saturating; + use sp_runtime::{ + traits::{ + AccountIdConversion, BlockNumberProvider, CheckedMul, CheckedSub, Convert, One, Zero, + }, + ArithmeticError, Permill, + }; + + #[derive(Copy, Clone, PartialEq, Eq)] + pub enum SaleState { + NotStarted, + Ongoing, + Ended, + } + + #[derive(RuntimeDebug, Encode, Decode, MaxEncodedLen, Copy, Clone, PartialEq, Eq, TypeInfo)] + pub struct Sale { + /// Block at which the sale start. + pub start: BlockNumber, + /// Block at which the sale stop. + pub end: BlockNumber, + /// Initial weight of the base asset of the current pair. + pub initial_weight: Permill, + /// Final weight of the base asset of the current pair. + pub final_weight: Permill, + } + + impl + Ord + Copy + Saturating + SafeAdd + SafeSub> Sale { + pub(crate) fn current_weights( + &self, + current_block: BlockNumber, + ) -> Result<(Permill, Permill), DispatchError> { + /* NOTE(hussein-aitlahcen): currently only linear + + Linearly decrease the base asset initial_weight to final_weight. + Quote asset weight is simple 1-base_asset_weight + + Assuming final_weight < initial_weight + current_weight = initial_weight - (current - start) / (end - start) * (initial_weight - final_weight) + = initial_weight - normalized_current / sale_duration * weight_range + = initial_weight - point_in_sale * weight_range + */ + let normalized_current_block = current_block.safe_sub(&self.start)?; + let point_in_sale = Permill::from_rational( + normalized_current_block.try_into().map_err(|_| ArithmeticError::Overflow)?, + self.duration().try_into().map_err(|_| ArithmeticError::Overflow)?, + ); + let weight_range = self + .initial_weight + .checked_sub(&self.final_weight) + .ok_or(ArithmeticError::Underflow)?; + let current_base_weight = self + .initial_weight + .checked_sub( + &point_in_sale.checked_mul(&weight_range).ok_or(ArithmeticError::Overflow)?, + ) + .ok_or(ArithmeticError::Underflow)?; + let current_quote_weight = Permill::one() + .checked_sub(¤t_base_weight) + .ok_or(ArithmeticError::Underflow)?; + Ok((current_base_weight, current_quote_weight)) + } + } + + impl Sale { + pub(crate) fn duration(&self) -> BlockNumber { + // NOTE(hussein-aitlahcen): end > start as previously checked by PoolIsValid. + self.end.saturating_sub(self.start) + } + } + + impl Sale { + pub(crate) fn state(&self, current_block: BlockNumber) -> SaleState { + if current_block < self.start { + SaleState::NotStarted + } else if current_block >= self.end { + SaleState::Ended + } else { + SaleState::Ongoing + } + } + } + + #[derive(RuntimeDebug, Encode, Decode, MaxEncodedLen, Copy, Clone, PartialEq, Eq, TypeInfo)] + pub struct Pool { + /// Owner of the pool + pub owner: AccountId, + /// Asset pair of the pool along their weight. + /// Base asset is the project token. + /// Quote asset is the collateral token. + pub pair: CurrencyPair, + /// Sale period of the LBP. + pub sale: Sale, + /// Trading fees. + pub fee: Permill, + } + + #[derive(Copy, Clone, Encode, Decode, MaxEncodedLen, PartialEq, Eq, TypeInfo)] + pub struct PoolIsValid(PhantomData); + + impl Validate, PoolIsValid> for PoolIsValid { + fn validate(input: PoolOf) -> Result, &'static str> { + if input.pair.base == input.pair.quote { + return Err("Pair elements must be distinct.") + } + + if input.sale.end <= input.sale.start { + return Err("Sale end must be after start.") + } + + if input.sale.duration() < T::MinSaleDuration::get() { + return Err("Sale duration must be greater than minimum duration.") + } + + if input.sale.duration() > T::MaxSaleDuration::get() { + return Err("Sale duration must not exceed maximum duration.") + } + + if input.sale.initial_weight < input.sale.final_weight { + return Err("Initial weight must be greater than final weight.") + } + + if input.sale.initial_weight > T::MaxInitialWeight::get() { + return Err("Initial weight must not exceed the defined maximum.") + } + + if input.sale.final_weight < T::MinFinalWeight::get() { + return Err("Final weight must not be lower than the defined minimum.") + } + + Ok(input) + } + } + + type AssetIdOf = ::AssetId; + type BalanceOf = ::Balance; + type AccountIdOf = ::AccountId; + type PoolIdOf = ::PoolId; + type PoolOf = Pool, BlockNumberFor, AssetIdOf>; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// Pool with specified id `T::PoolId` was created successfully by `T::AccountId`. + PoolCreated { + /// Id of newly created pool. + pool_id: T::PoolId, + /// Owner of the pool. + owner: T::AccountId, + }, + /// The sale ended, the funds repatriated and the pool deleted. + PoolDeleted { + /// Pool that was removed. + pool_id: T::PoolId, + /// Amount of base asset repatriated. + base_amount: T::Balance, + /// Amount of quote asset repatriated. + quote_amount: T::Balance, + }, + /// Liquidity added into the pool `T::PoolId`. + LiquidityAdded { + /// Pool id to which liquidity added. + pool_id: T::PoolId, + /// Amount of base asset deposited. + base_amount: T::Balance, + /// Amount of quote asset deposited. + quote_amount: T::Balance, + }, + /// Token exchange happened. + Swapped { + /// Pool id on which exchange done. + pool_id: T::PoolId, + /// Account id who exchanged token. + who: T::AccountId, + /// Id of asset used as input. + base_asset: T::AssetId, + /// Id of asset used as output. + quote_asset: T::AssetId, + /// Amount of base asset received. + base_amount: T::Balance, + /// Amount of quote asset provided. + quote_amount: T::Balance, + }, + } + + #[pallet::error] + pub enum Error { + PoolNotFound, + PairMismatch, + MustBeOwner, + InvalidSaleState, + InvalidAmount, + CannotRespectMinimumRequested, + } + + #[pallet::config] + pub trait Config: frame_system::Config { + #[allow(missing_docs)] + type Event: From> + IsType<::Event>; + + /// Type representing the unique ID of an asset. + type AssetId: FullCodec + + MaxEncodedLen + + Eq + + PartialEq + + Copy + + Clone + + MaybeSerializeDeserialize + + Debug + + Default + + TypeInfo + + Ord; + + /// Type representing the Balance of an account. + type Balance: Default + + Parameter + + Codec + + MaxEncodedLen + + Copy + + Ord + + Zero + + SafeAdd + + SafeSub; + + /// An isomorphism: Balance<->u128 + type Convert: Convert> + Convert, u128>; + + /// Dependency allowing this pallet to transfer funds from one account to another. + type Assets: Transfer, Balance = BalanceOf, AssetId = AssetIdOf> + + Mutate, Balance = BalanceOf, AssetId = AssetIdOf> + + Inspect, Balance = BalanceOf, AssetId = AssetIdOf>; + + /// Type representing the unique ID of a pool. + type PoolId: FullCodec + + MaxEncodedLen + + Default + + Debug + + TypeInfo + + Eq + + PartialEq + + Ord + + Copy + + Zero + + One + + SafeAdd + + SafeSub; + + type LocalAssets: LocalAssets>; + + #[pallet::constant] + type PalletId: Get; + + /// Minimum duration for a sale. + #[pallet::constant] + type MinSaleDuration: Get>; + + /// Maximum duration for a sale. + #[pallet::constant] + type MaxSaleDuration: Get>; + + /// Maximum initial weight. + #[pallet::constant] + type MaxInitialWeight: Get; + + /// Minimum final weight. + #[pallet::constant] + type MinFinalWeight: Get; + + /// The origin allowed to create new pools. + type AdminOrigin: EnsureOrigin; + + type WeightInfo: WeightInfo; + } + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); + + #[pallet::type_value] + pub fn PoolCountOnEmpty() -> T::PoolId { + Zero::zero() + } + + #[pallet::storage] + #[pallet::getter(fn pool_count)] + #[allow(clippy::disallowed_type)] + pub type PoolCount = StorageValue<_, T::PoolId, ValueQuery, PoolCountOnEmpty>; + + #[pallet::storage] + #[pallet::getter(fn pools)] + pub type Pools = StorageMap<_, Blake2_128Concat, T::PoolId, PoolOf>; + + #[pallet::call] + impl Pallet { + /// Create a new pool. + /// + /// Emits `PoolCreated` event when successful. + #[pallet::weight(T::WeightInfo::create())] + pub fn create( + origin: OriginFor, + pool: Validated, PoolIsValid>, + ) -> DispatchResult { + let _ = T::AdminOrigin::ensure_origin(origin)?; + let _ = Self::do_create_pool(pool)?; + Ok(()) + } + + /// Execute a buy order on a pool. + /// + /// Emits `Swapped` event when successful. + #[pallet::weight(T::WeightInfo::buy())] + pub fn buy( + origin: OriginFor, + pool_id: PoolIdOf, + asset_id: AssetIdOf, + amount: BalanceOf, + keep_alive: bool, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = ::buy(&who, pool_id, asset_id, amount, keep_alive)?; + Ok(()) + } + + /// Execute a sell order on a pool. + /// + /// Emits `Swapped` event when successful. + #[pallet::weight(T::WeightInfo::sell())] + pub fn sell( + origin: OriginFor, + pool_id: PoolIdOf, + asset_id: AssetIdOf, + amount: BalanceOf, + keep_alive: bool, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = ::sell(&who, pool_id, asset_id, amount, keep_alive)?; + Ok(()) + } + + /// Execute a specific swap operation. + /// + /// Buy operation if the pair is the original pool pair (A/B). + /// Sell operation if the pair is the original pool pair swapped (B/A). + /// + /// The `quote_amount` is always the quote asset amount (A/B => B), (B/A => A). + /// + /// Emits `Swapped` event when successful. + #[pallet::weight(T::WeightInfo::swap())] + pub fn swap( + origin: OriginFor, + pool_id: PoolIdOf, + pair: CurrencyPair, + quote_amount: BalanceOf, + min_receive: BalanceOf, + keep_alive: bool, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = ::exchange( + &who, + pool_id, + pair, + quote_amount, + min_receive, + keep_alive, + )?; + Ok(()) + } + + /// Add liquidity to an LBP pool. + /// + /// Only possible before the sale started. + /// + /// Emits `LiquidityAdded` event when successful. + #[pallet::weight(T::WeightInfo::add_liquidity())] + pub fn add_liquidity( + origin: OriginFor, + pool_id: PoolIdOf, + base_amount: BalanceOf, + quote_amount: BalanceOf, + keep_alive: bool, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = ::add_liquidity( + &who, + pool_id, + base_amount, + quote_amount, + BalanceOf::::zero(), + keep_alive, + )?; + Ok(()) + } + + /// Withdraw the remaining liquidity and destroy the pool. + /// + /// Emits `PoolDeleted` event when successful. + #[pallet::weight(T::WeightInfo::remove_liquidity())] + pub fn remove_liquidity(origin: OriginFor, pool_id: PoolIdOf) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = ::remove_liquidity( + &who, + pool_id, + BalanceOf::::zero(), + BalanceOf::::zero(), + BalanceOf::::zero(), + )?; + Ok(()) + } + } + + impl Pallet { + pub(crate) fn do_create_pool( + pool: Validated, PoolIsValid>, + ) -> Result { + let pool_id = + PoolCount::::try_mutate(|pool_count| -> Result { + let pool_id = *pool_count; + Pools::::insert(pool_id, pool.clone().value()); + *pool_count = pool_id.safe_add(&T::PoolId::one())?; + Ok(pool_id) + })?; + + Self::deposit_event(Event::PoolCreated { pool_id, owner: pool.owner.clone() }); + + Ok(pool_id) + } + + pub(crate) fn get_pool_ensuring_sale_state( + pool_id: T::PoolId, + current_block: BlockNumberFor, + expected_sale_state: SaleState, + ) -> Result, DispatchError> { + let pool = Self::get_pool(pool_id)?; + ensure!( + pool.sale.state(current_block) == expected_sale_state, + Error::::InvalidSaleState + ); + Ok(pool) + } + + pub(crate) fn get_pool(pool_id: T::PoolId) -> Result, DispatchError> { + Pools::::get(pool_id).ok_or_else(|| Error::::PoolNotFound.into()) + } + + pub(crate) fn account_id(pool_id: &T::PoolId) -> T::AccountId { + T::PalletId::get().into_sub_account(pool_id) + } + + #[allow(dead_code)] + pub(crate) fn do_spot_price( + pool_id: T::PoolId, + pair: CurrencyPair>, + current_block: BlockNumberFor, + ) -> Result, DispatchError> { + let pool = + Self::get_pool_ensuring_sale_state(pool_id, current_block, SaleState::Ongoing)?; + ensure!(pair == pool.pair, Error::::PairMismatch); + + let weights = pool.sale.current_weights(current_block)?; + + let (wo, wi) = + if pair.base == pool.pair.base { weights } else { (weights.1, weights.0) }; + + let pool_account = Self::account_id(&pool_id); + let bi = T::Convert::convert(T::Assets::balance(pair.quote, &pool_account)); + let bo = T::Convert::convert(T::Assets::balance(pair.base, &pool_account)); + let base_unit = T::LocalAssets::unit::(pair.base)?; + + let spot_price = compute_spot_price(wi, wo, bi, bo, base_unit)?; + + Ok(T::Convert::convert(spot_price)) + } + + pub(crate) fn do_get_exchange( + pool_id: T::PoolId, + pair: CurrencyPair>, + current_block: BlockNumberFor, + quote_amount: BalanceOf, + apply_fees: bool, + ) -> Result<(BalanceOf, BalanceOf), DispatchError> { + let pool = + Self::get_pool_ensuring_sale_state(pool_id, current_block, SaleState::Ongoing)?; + + ensure!(pair == pool.pair, Error::::PairMismatch); + ensure!(!quote_amount.is_zero(), Error::::InvalidAmount); + + let weights = pool.sale.current_weights(current_block)?; + + let (wo, wi) = + if pair.base == pool.pair.base { weights } else { (weights.1, weights.0) }; + + let pool_account = Self::account_id(&pool_id); + let ai = T::Convert::convert(quote_amount); + let (ai_minus_fees, fees) = if apply_fees { + let fees = pool.fee.mul_floor(ai); + // Safe as fees is a fraction of ai + (ai - fees, fees) + } else { + (ai, 0) + }; + let bi = T::Convert::convert(T::Assets::balance(pair.quote, &pool_account)); + let bo = T::Convert::convert(T::Assets::balance(pair.base, &pool_account)); + + let base_amount = compute_out_given_in(wi, wo, bi, bo, ai_minus_fees)?; + + Ok((T::Convert::convert(fees), T::Convert::convert(base_amount))) + } + } + + impl Amm for Pallet { + type AssetId = AssetIdOf; + type Balance = BalanceOf; + type AccountId = AccountIdOf; + type PoolId = PoolIdOf; + + fn pool_exists(pool_id: Self::PoolId) -> bool { + Pools::::contains_key(pool_id) + } + + fn currency_pair( + pool_id: Self::PoolId, + ) -> Result, DispatchError> { + Ok(Self::get_pool(pool_id)?.pair) + } + + fn get_exchange_value( + pool_id: Self::PoolId, + asset_id: Self::AssetId, + amount: Self::Balance, + ) -> Result { + let pool = Self::get_pool(pool_id)?; + let pair = if asset_id == pool.pair.base { pool.pair.swap() } else { pool.pair }; + let current_block = frame_system::Pallet::::current_block_number(); + let (_, base_amount) = + Self::do_get_exchange(pool_id, pair, current_block, amount, false)?; + Ok(base_amount) + } + + #[transactional] + fn buy( + who: &Self::AccountId, + pool_id: Self::PoolId, + asset_id: Self::AssetId, + amount: Self::Balance, + keep_alive: bool, + ) -> Result { + let pool = Self::get_pool(pool_id)?; + let pair = if asset_id == pool.pair.base { pool.pair } else { pool.pair.swap() }; + let quote_amount = Self::get_exchange_value(pool_id, asset_id, amount)?; + ::exchange( + who, + pool_id, + pair, + quote_amount, + T::Balance::zero(), + keep_alive, + ) + } + + #[transactional] + fn sell( + who: &Self::AccountId, + pool_id: Self::PoolId, + asset_id: Self::AssetId, + amount: Self::Balance, + keep_alive: bool, + ) -> Result { + let pool = Self::get_pool(pool_id)?; + let pair = if asset_id == pool.pair.base { pool.pair.swap() } else { pool.pair }; + ::exchange(who, pool_id, pair, amount, T::Balance::zero(), keep_alive) + } + + #[transactional] + fn add_liquidity( + who: &Self::AccountId, + pool_id: Self::PoolId, + base_amount: Self::Balance, + quote_amount: Self::Balance, + _: Self::Balance, + keep_alive: bool, + ) -> Result<(), DispatchError> { + let current_block = frame_system::Pallet::::current_block_number(); + let pool = + Self::get_pool_ensuring_sale_state(pool_id, current_block, SaleState::NotStarted)?; + + ensure!(pool.owner == *who, Error::::MustBeOwner); + ensure!(!base_amount.is_zero() && !quote_amount.is_zero(), Error::::InvalidAmount); + + // NOTE(hussein-aitlahcen): as we only allow the owner to provide liquidity, we don't + // mint any LP. + let pool_account = Self::account_id(&pool_id); + T::Assets::transfer(pool.pair.base, who, &pool_account, base_amount, keep_alive)?; + T::Assets::transfer(pool.pair.quote, who, &pool_account, quote_amount, keep_alive)?; + + Self::deposit_event(Event::LiquidityAdded { pool_id, base_amount, quote_amount }); + + Ok(()) + } + + #[transactional] + fn remove_liquidity( + who: &Self::AccountId, + pool_id: Self::PoolId, + _: Self::Balance, + _: Self::Balance, + _: Self::Balance, + ) -> Result<(), DispatchError> { + let current_block = frame_system::Pallet::::current_block_number(); + let pool = + Self::get_pool_ensuring_sale_state(pool_id, current_block, SaleState::Ended)?; + + ensure!(pool.owner == *who, Error::::MustBeOwner); + + let pool_account = Self::account_id(&pool_id); + + let repatriate = |a| -> Result, DispatchError> { + let a_balance = T::Assets::balance(a, &pool_account); + // NOTE(hussein-aitlahcen): not need to keep the pool account alive. + T::Assets::transfer(a, &pool_account, who, a_balance, false)?; + Ok(a_balance) + }; + + let base_amount = repatriate(pool.pair.base)?; + let quote_amount = repatriate(pool.pair.quote)?; + + Pools::::remove(pool_id); + + Self::deposit_event(Event::PoolDeleted { pool_id, base_amount, quote_amount }); + + Ok(()) + } + + #[transactional] + fn exchange( + who: &Self::AccountId, + pool_id: Self::PoolId, + pair: CurrencyPair, + quote_amount: Self::Balance, + min_receive: Self::Balance, + keep_alive: bool, + ) -> Result { + let current_block = frame_system::Pallet::::current_block_number(); + let (_, base_amount) = + Self::do_get_exchange(pool_id, pair, current_block, quote_amount, true)?; + + ensure!(base_amount >= min_receive, Error::::CannotRespectMinimumRequested); + + let pool_account = Self::account_id(&pool_id); + T::Assets::transfer(pair.quote, who, &pool_account, quote_amount, keep_alive)?; + // NOTE(hussein-aitlance): no need to keep alive the pool account + T::Assets::transfer(pair.base, &pool_account, who, base_amount, false)?; + + Self::deposit_event(Event::Swapped { + pool_id, + who: who.clone(), + base_asset: pair.base, + quote_asset: pair.quote, + base_amount, + quote_amount, + }); + + Ok(base_amount) + } + } +} diff --git a/frame/liquidity-bootstrapping/src/mock.rs b/frame/liquidity-bootstrapping/src/mock.rs new file mode 100644 index 00000000000..f54a5903ee0 --- /dev/null +++ b/frame/liquidity-bootstrapping/src/mock.rs @@ -0,0 +1,135 @@ +use crate as pallet_liquidity_bootstrapping; +use frame_support::{parameter_types, traits::Everything, PalletId}; +use frame_system as system; +use orml_traits::parameter_type_with_key; +use sp_arithmetic::traits::Zero; +use sp_core::H256; +use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, ConvertInto, IdentityLookup}, + Permill, +}; +use system::EnsureRoot; + +pub type AccountId = u128; +pub type AssetId = u128; +pub type Balance = u128; +pub type Amount = i128; +pub type PoolId = u32; +pub type BlockNumber = u64; + +#[allow(dead_code)] +pub static ALICE: AccountId = 1; +#[allow(dead_code)] +pub static BOB: AccountId = 2; +#[allow(dead_code)] +pub static CHARLIE: AccountId = 3; + +#[allow(dead_code)] +pub const PROJECT_TOKEN: AssetId = 0; +#[allow(dead_code)] +pub const USDT: AssetId = 1; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +// Configure a mock runtime to test the pallet. +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Tokens: orml_tokens::{Pallet, Call, Storage, Config, Event}, + CurrencyFactory: pallet_currency_factory::{Pallet, Storage, Event}, + LBP: pallet_liquidity_bootstrapping::{Pallet, Storage, Event}, + } +); + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const SS58Prefix: u8 = 42; +} + +impl system::Config for Test { + type BaseCallFilter = Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type Origin = Origin; + type Call = Call; + type Index = u64; + type BlockNumber = BlockNumber; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = SS58Prefix; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +parameter_type_with_key! { + pub ExistentialDeposits: |_currency_id: AssetId| -> Balance { + Zero::zero() + }; +} + +impl orml_tokens::Config for Test { + type Event = Event; + type Balance = Balance; + type Amount = Amount; + type CurrencyId = AssetId; + type WeightInfo = (); + type ExistentialDeposits = ExistentialDeposits; + type OnDust = (); + type MaxLocks = (); + type DustRemovalWhitelist = Everything; +} + +impl pallet_currency_factory::Config for Test { + type Event = Event; + type AssetId = AssetId; + type AddOrigin = EnsureRoot; + type ReserveOrigin = EnsureRoot; + type WeightInfo = (); +} + +parameter_types! { + pub LBPId: PalletId = PalletId(*b"pall_lbp"); + pub MinSaleDuration: BlockNumber = 3600 / 12; + pub MaxSaleDuration: BlockNumber = 30 * 24 * 3600 / 12; + pub MaxInitialWeight: Permill = Permill::from_percent(95); + pub MinFinalWeight: Permill = Permill::from_percent(5); +} + +impl pallet_liquidity_bootstrapping::Config for Test { + type Event = Event; + type AssetId = AssetId; + type Balance = Balance; + type Convert = ConvertInto; + type Assets = Tokens; + type PoolId = PoolId; + type LocalAssets = CurrencyFactory; + type PalletId = LBPId; + type MinSaleDuration = MinSaleDuration; + type MaxSaleDuration = MaxSaleDuration; + type MaxInitialWeight = MaxInitialWeight; + type MinFinalWeight = MinFinalWeight; + type WeightInfo = (); + type AdminOrigin = EnsureRoot; +} + +pub fn new_test_ext() -> sp_io::TestExternalities { + system::GenesisConfig::default().build_storage::().unwrap().into() +} diff --git a/frame/liquidity-bootstrapping/src/tests.rs b/frame/liquidity-bootstrapping/src/tests.rs new file mode 100644 index 00000000000..9b080343444 --- /dev/null +++ b/frame/liquidity-bootstrapping/src/tests.rs @@ -0,0 +1,633 @@ +use crate::{mock::*, *}; +use composable_support::validation::Validated; +use composable_tests_helpers::test::helper::default_acceptable_computation_error; +use composable_traits::defi::CurrencyPair; +use frame_support::{ + assert_noop, assert_ok, + traits::fungibles::{Inspect, Mutate}, +}; +use sp_runtime::{DispatchError, Permill}; + +fn valid_pool() -> Validated, PoolIsValid> { + let pair = CurrencyPair::new(PROJECT_TOKEN, USDT); + let owner = ALICE; + let duration = MaxSaleDuration::get(); + let start = 0; + let end = start + duration; + let initial_weight = MaxInitialWeight::get(); + let final_weight = MinFinalWeight::get(); + let fee = Permill::from_perthousand(1); + Validated::new(Pool { + owner, + pair, + sale: Sale { start, end, initial_weight, final_weight }, + fee, + }) + .expect("impossible; qed;") +} + +fn with_pool( + owner: AccountId, + sale_duration: BlockNumber, + initial_weight: Permill, + final_weight: Permill, + fee: Permill, + f: impl FnOnce(PoolId, &Pool, &dyn Fn(BlockNumber), &dyn Fn()) -> T, +) -> T { + let random_start = 0xDEADC0DE; + let pair = CurrencyPair::new(PROJECT_TOKEN, USDT); + let end = random_start + sale_duration; + let pool = Validated::<_, PoolIsValid>::new(Pool { + owner, + pair, + sale: Sale { start: random_start, end, initial_weight, final_weight }, + fee, + }) + .expect("impossible; qed;"); + new_test_ext().execute_with(|| -> T { + // Actually create the pool. + assert_ok!(LBP::create(Origin::root(), pool)); + + // Will always start to 0. + let pool_id = 0; + + // Relative to sale start. + let set_block = |x: BlockNumber| { + System::set_block_number(random_start + x); + }; + + // Forward to sale end. + let end_sale = || { + set_block(sale_duration + 1); + }; + + f(pool_id, &pool, &set_block, &end_sale) + }) +} + +fn within_sale_with_liquidity( + owner: AccountId, + sale_duration: BlockNumber, + initial_weight: Permill, + final_weight: Permill, + fee: Permill, + initial_project_tokens: Balance, + initial_usdt: Balance, + f: impl FnOnce(PoolId, &Pool, &dyn Fn(BlockNumber), &dyn Fn()) -> T, +) -> T { + with_pool( + owner, + sale_duration, + initial_weight, + final_weight, + fee, + |pool_id, pool, set_block, end_sale| -> T { + assert_ok!(Tokens::mint_into(PROJECT_TOKEN, &owner, initial_project_tokens)); + assert_ok!(Tokens::mint_into(USDT, &owner, initial_usdt)); + + // Add initial liquidity. + assert_ok!(LBP::add_liquidity( + Origin::signed(owner), + pool_id, + initial_project_tokens, + initial_usdt, + false + )); + + // Actually start the sale. + set_block(0); + + f(pool_id, pool, set_block, end_sale) + }, + ) +} + +mod create { + use super::*; + + #[test] + fn arbitrary_user_cant_create() { + new_test_ext().execute_with(|| { + assert_noop!( + LBP::create(Origin::signed(ALICE), valid_pool()), + DispatchError::BadOrigin + ); + }); + } + + #[test] + fn admin_can_create() { + new_test_ext().execute_with(|| { + assert_ok!(LBP::create(Origin::root(), valid_pool())); + }); + } +} + +mod sell { + use super::*; + + #[test] + fn can_sell_one_to_one() { + /* 50% weight = constant product, no fees. + */ + let unit = 1_000_000_000_000; + let initial_project_tokens = 1_000_000 * unit; + let initial_usdt = 1_000_000 * unit; + let sale_duration = MaxSaleDuration::get(); + let initial_weight = Permill::one() / 2; + let final_weight = Permill::one() / 2; + let fee = Permill::zero(); + within_sale_with_liquidity( + ALICE, + sale_duration, + initial_weight, + final_weight, + fee, + initial_project_tokens, + initial_usdt, + |pool_id, pool, _, _| { + // Buy project token + assert_ok!(Tokens::mint_into(USDT, &BOB, unit)); + assert_ok!(LBP::sell(Origin::signed(BOB), pool_id, pool.pair.quote, unit, false)); + assert_ok!(default_acceptable_computation_error( + Tokens::balance(PROJECT_TOKEN, &BOB), + unit + )); + }, + ) + } +} + +mod buy { + use super::*; + + #[test] + fn can_buy_one_to_one() { + /* 50% weight = constant product, no fees. + */ + let unit = 1_000_000_000_000; + let initial_project_tokens = 1_000_000 * unit; + let initial_usdt = 1_000_000 * unit; + let sale_duration = MaxSaleDuration::get(); + let initial_weight = Permill::one() / 2; + let final_weight = Permill::one() / 2; + let fee = Permill::zero(); + within_sale_with_liquidity( + ALICE, + sale_duration, + initial_weight, + final_weight, + fee, + initial_project_tokens, + initial_usdt, + |pool_id, pool, _, _| { + // Buy project token + assert_ok!(Tokens::mint_into(USDT, &BOB, unit)); + assert_ok!(LBP::buy(Origin::signed(BOB), pool_id, pool.pair.base, unit, false)); + assert_ok!(default_acceptable_computation_error( + Tokens::balance(PROJECT_TOKEN, &BOB), + unit + )); + }, + ) + } +} + +mod remove_liquidity { + use super::*; + + #[test] + fn cannot_remove_before_sale_end() { + let owner = ALICE; + let sale_duration = MaxSaleDuration::get(); + let initial_weight = Permill::one() / 2; + let final_weight = Permill::one() / 2; + let fee = Permill::zero(); + let unit = 1_000_000_000_000; + let initial_project_tokens = 1_000_000 * unit; + let initial_usdt = 1_000_000 * unit; + with_pool(owner, sale_duration, initial_weight, final_weight, fee, |pool_id, _, _, _| { + assert_ok!(Tokens::mint_into(PROJECT_TOKEN, &owner, initial_project_tokens)); + assert_ok!(Tokens::mint_into(USDT, &owner, initial_usdt)); + assert_noop!( + LBP::remove_liquidity(Origin::signed(owner), pool_id,), + Error::::InvalidSaleState + ); + }); + } + + #[test] + fn can_remove_after_sale_end() { + let owner = ALICE; + let sale_duration = MaxSaleDuration::get(); + let initial_weight = Permill::one() / 2; + let final_weight = Permill::one() / 2; + let fee = Permill::zero(); + let unit = 1_000_000_000_000; + let initial_project_tokens = 1_000_000 * unit; + let initial_usdt = 1_000_000 * unit; + with_pool( + owner, + sale_duration, + initial_weight, + final_weight, + fee, + |pool_id, _, _, end_sale| { + assert_ok!(Tokens::mint_into(PROJECT_TOKEN, &owner, initial_project_tokens)); + assert_ok!(Tokens::mint_into(USDT, &owner, initial_usdt)); + end_sale(); + assert_ok!(LBP::remove_liquidity(Origin::signed(owner), pool_id,),); + assert_eq!(Tokens::balance(PROJECT_TOKEN, &owner), initial_project_tokens); + assert_eq!(Tokens::balance(USDT, &owner), initial_usdt); + }, + ); + } +} + +mod add_liquidity { + use super::*; + + #[test] + fn can_add_liquidity_before_sale() { + let owner = ALICE; + let sale_duration = MaxSaleDuration::get(); + let initial_weight = Permill::one() / 2; + let final_weight = Permill::one() / 2; + let fee = Permill::zero(); + let unit = 1_000_000_000_000; + let initial_project_tokens = 1_000_000 * unit; + let initial_usdt = 1_000_000 * unit; + with_pool(owner, sale_duration, initial_weight, final_weight, fee, |pool_id, _, _, _| { + assert_ok!(Tokens::mint_into(PROJECT_TOKEN, &owner, initial_project_tokens)); + assert_ok!(Tokens::mint_into(USDT, &owner, initial_usdt)); + assert_ok!(LBP::add_liquidity( + Origin::signed(owner), + pool_id, + initial_project_tokens, + initial_usdt, + false + )); + }); + } + + #[test] + fn cannot_add_liquidity_after_sale_started() { + let owner = ALICE; + let sale_duration = MaxSaleDuration::get(); + let initial_weight = Permill::one() / 2; + let final_weight = Permill::one() / 2; + let fee = Permill::zero(); + let unit = 1_000_000_000_000; + let initial_project_tokens = 1_000_000 * unit; + let initial_usdt = 1_000_000 * unit; + with_pool( + owner, + sale_duration, + initial_weight, + final_weight, + fee, + |pool_id, _, set_sale_block, _| { + assert_ok!(Tokens::mint_into(PROJECT_TOKEN, &owner, initial_project_tokens)); + assert_ok!(Tokens::mint_into(USDT, &owner, initial_usdt)); + set_sale_block(0); + assert_noop!( + LBP::add_liquidity( + Origin::signed(owner), + pool_id, + initial_project_tokens, + initial_usdt, + false + ), + Error::::InvalidSaleState + ); + }, + ); + } +} + +mod invalid_pool { + use super::*; + + #[test] + fn final_weight_below_minimum() { + new_test_ext().execute_with(|| { + let pair = CurrencyPair::new(PROJECT_TOKEN, USDT); + let owner = ALICE; + let duration = MaxSaleDuration::get() - 1; + let start = 0; + let end = start + duration; + let initial_weight = MaxInitialWeight::get(); + let final_weight = MinFinalWeight::get() - Permill::from_parts(1); + let fee = Permill::from_perthousand(1); + assert!(Validated::<_, PoolIsValid>::new(Pool { + owner, + pair, + sale: Sale { start, end, initial_weight, final_weight }, + fee, + }) + .is_err()); + }); + } + + #[test] + fn initial_weight_above_maximum() { + new_test_ext().execute_with(|| { + let pair = CurrencyPair::new(PROJECT_TOKEN, USDT); + let owner = ALICE; + let duration = MaxSaleDuration::get() - 1; + let start = 0; + let end = start + duration; + let initial_weight = MaxInitialWeight::get() + Permill::from_parts(1); + let final_weight = MinFinalWeight::get(); + let fee = Permill::from_perthousand(1); + assert!(Validated::<_, PoolIsValid>::new(Pool { + owner, + pair, + sale: Sale { start, end, initial_weight, final_weight }, + fee, + }) + .is_err()); + }); + } + + #[test] + fn final_weight_above_initial_weight() { + new_test_ext().execute_with(|| { + let pair = CurrencyPair::new(PROJECT_TOKEN, USDT); + let owner = ALICE; + let duration = MaxSaleDuration::get() - 1; + let start = 0; + let end = start + duration; + let initial_weight = MinFinalWeight::get(); + let final_weight = MaxInitialWeight::get(); + let fee = Permill::from_perthousand(1); + assert!(Validated::<_, PoolIsValid>::new(Pool { + owner, + pair, + sale: Sale { start, end, initial_weight, final_weight }, + fee, + }) + .is_err()); + }); + } + + #[test] + fn end_before_start() { + new_test_ext().execute_with(|| { + let pair = CurrencyPair::new(PROJECT_TOKEN, USDT); + let owner = ALICE; + let start = 1; + let end = 0; + let initial_weight = MaxInitialWeight::get(); + let final_weight = MinFinalWeight::get(); + let fee = Permill::from_perthousand(1); + assert!(Validated::<_, PoolIsValid>::new(Pool { + owner, + pair, + sale: Sale { start, end, initial_weight, final_weight }, + fee, + }) + .is_err()); + }); + } + + #[test] + fn above_maximum_sale_duration() { + new_test_ext().execute_with(|| { + let pair = CurrencyPair::new(PROJECT_TOKEN, USDT); + let owner = ALICE; + let duration = MaxSaleDuration::get() + 1; + let start = 0; + let end = start + duration; + let initial_weight = MaxInitialWeight::get(); + let final_weight = MinFinalWeight::get(); + let fee = Permill::from_perthousand(1); + assert!(Validated::<_, PoolIsValid>::new(Pool { + owner, + pair, + sale: Sale { start, end, initial_weight, final_weight }, + fee, + }) + .is_err()); + }); + } + + #[test] + fn below_minimum_sale_duration() { + new_test_ext().execute_with(|| { + let pair = CurrencyPair::new(PROJECT_TOKEN, USDT); + let owner = ALICE; + let duration = MinSaleDuration::get() - 1; + let start = 0; + let end = start + duration; + let initial_weight = MaxInitialWeight::get(); + let final_weight = MinFinalWeight::get(); + let fee = Permill::from_perthousand(1); + assert!(Validated::<_, PoolIsValid>::new(Pool { + owner, + pair, + sale: Sale { start, end, initial_weight, final_weight }, + fee, + }) + .is_err()); + }); + } +} + +#[cfg(feature = "visualization")] +mod visualization { + use super::*; + + #[test] + fn plot() { + new_test_ext().execute_with(|| { + let pair = CurrencyPair::new(PROJECT_TOKEN, USDT); + let owner = ALICE; + let two_days = 48 * 3600 / 12; + let window = 100; + let pool = Pool { + owner, + pair, + sale: Sale { + start: window, + end: two_days + window, + initial_weight: Permill::from_percent(92), + final_weight: Permill::from_percent(50), + }, + fee: Permill::from_perthousand(1), + }; + let pool_id = LBP::do_create_pool(Validated::new(pool).expect("impossible; qed;")) + .expect("impossible; qed;"); + + let unit = 1_000_000_000_000; + let initial_project_tokens = 100_000_000 * unit; + let initial_usdt = 1_000_000 * unit; + + assert_ok!(Tokens::mint_into(PROJECT_TOKEN, &ALICE, initial_project_tokens)); + assert_ok!(Tokens::mint_into(USDT, &ALICE, initial_usdt)); + + assert_ok!(LBP::add_liquidity( + &ALICE, + pool_id, + initial_project_tokens, + initial_usdt, + 0, + false + )); + + { + let points = (pool.sale.start..pool.sale.end) + .map(|block| { + ( + block, + LBP::do_spot_price(pool_id, pool.pair, block).expect("impossible; qed;") + as f64 / unit as f64, + ) + }) + .collect::>(); + let max_amount = points.iter().copied().fold(f64::NAN, |x, (_, y)| f64::max(x, y)); + + use plotters::prelude::*; + let area = BitMapBackend::new("./plots/lbp_spot_price.png", (1024, 768)) + .into_drawing_area(); + area.fill(&WHITE).unwrap(); + + let mut chart = ChartBuilder::on(&area) + .caption("Spot price", ("Arial", 50).into_font()) + .margin(100u32) + .x_label_area_size(30u32) + .y_label_area_size(30u32) + .build_cartesian_2d(pool.sale.start..pool.sale.end, 0f64..max_amount) + .unwrap(); + + chart.configure_mesh().draw().unwrap(); + chart + .draw_series(LineSeries::new(points, &RED)) + .unwrap() + .label("base") + .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED)); + chart + .configure_series_labels() + .background_style(&WHITE.mix(0.8)) + .border_style(&BLACK) + .draw() + .unwrap(); + } + + { + use plotters::prelude::*; + + let plot_swap = |pair, swap_amount, name, caption| { + let points = (pool.sale.start..pool.sale.end) + .map(|block| { + let (fees, base_amount) = + LBP::do_get_exchange(pool_id, pair, block, swap_amount, true) + .expect("impossible; qed;"); + (block, fees / unit, base_amount / unit) + }) + .collect::>(); + let amounts = + points.clone().iter().copied().map(|(x, _, y)| (x, y)).collect::>(); + let amounts_with_fees = + points.into_iter().map(|(x, y, z)| (x, y + z)).collect::>(); + + let max_amount = + amounts_with_fees.iter().copied().map(|(_, x)| x).max().unwrap(); + + let area = BitMapBackend::new(name, (1024, 768)).into_drawing_area(); + area.fill(&WHITE).unwrap(); + + let mut chart = ChartBuilder::on(&area) + .caption(caption, ("Arial", 50).into_font()) + .margin(100u32) + .x_label_area_size(30u32) + .y_label_area_size(30u32) + .build_cartesian_2d(pool.sale.start..pool.sale.end, 0..max_amount) + .unwrap(); + + chart.configure_mesh().draw().unwrap(); + chart + .draw_series(LineSeries::new(amounts, &BLUE)) + .unwrap() + .label("Received tokens fees applied") + .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &BLUE)); + chart + .draw_series(LineSeries::new(amounts_with_fees, &RED)) + .unwrap() + .label("Received tokens fees not applied") + .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED)); + chart + .configure_series_labels() + .background_style(&WHITE.mix(0.8)) + .border_style(&BLACK) + .draw() + .unwrap(); + }; + + let buy_amount = 500; + plot_swap( + pair, + buy_amount * unit, + "./plots/lbp_buy_project.png", + format!("Buy project tokens with {} USDT", buy_amount), + ); + let sell_amount = 100_000; + plot_swap( + pair.swap(), + sell_amount * unit, + "./plots/lbp_sell_project.png", + format!("Sell {} project tokens", sell_amount), + ); + } + + { + use plotters::prelude::*; + let area = + BitMapBackend::new("./plots/lbp_weights.png", (1024, 768)).into_drawing_area(); + area.fill(&WHITE).unwrap(); + + let mut chart = ChartBuilder::on(&area) + .caption("y = weight", ("Arial", 50).into_font()) + .margin(100u32) + .x_label_area_size(30u32) + .y_label_area_size(30u32) + .build_cartesian_2d( + pool.sale.start..pool.sale.end, + 0..Permill::one().deconstruct(), + ) + .unwrap(); + + let points = (pool.sale.start..pool.sale.end).map(|block| { + (block, pool.sale.current_weights(block).expect("impossible; qed;")) + }); + + chart.configure_mesh().draw().unwrap(); + chart + .draw_series(LineSeries::new( + points + .clone() + .map(|(block, (base_weight, _))| (block, base_weight.deconstruct())), + &RED, + )) + .unwrap() + .label("base") + .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED)); + chart + .draw_series(LineSeries::new( + points + .map(|(block, (_, quote_weight))| (block, quote_weight.deconstruct())), + &BLUE, + )) + .unwrap() + .label("quote") + .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &BLUE)); + chart + .configure_series_labels() + .background_style(&WHITE.mix(0.8)) + .border_style(&BLACK) + .draw() + .unwrap(); + } + }); + } +} diff --git a/frame/liquidity-bootstrapping/src/weights.rs b/frame/liquidity-bootstrapping/src/weights.rs new file mode 100644 index 00000000000..17bb0a4be1b --- /dev/null +++ b/frame/liquidity-bootstrapping/src/weights.rs @@ -0,0 +1,43 @@ +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(clippy::unnecessary_cast)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +pub trait WeightInfo { + fn create() -> Weight; + fn buy() -> Weight; + fn sell() -> Weight; + fn swap() -> Weight; + fn add_liquidity() -> Weight; + fn remove_liquidity() -> Weight; +} + +// For backwards compatibility and tests +impl WeightInfo for () { + fn create() -> Weight { + 10_000 + } + + fn buy() -> Weight { + 10_000 + } + + fn sell() -> Weight { + 10_000 + } + + fn swap() -> Weight { + 10_000 + } + + fn add_liquidity() -> Weight { + 10_000 + } + + fn remove_liquidity() -> Weight { + 10_000 + } +} diff --git a/frame/mosaic/Cargo.toml b/frame/mosaic/Cargo.toml index 80f4aca0386..0c37d8de6f8 100644 --- a/frame/mosaic/Cargo.toml +++ b/frame/mosaic/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "pallet-mosaic" -version = "0.1.0" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" +homepage = "https://composable.finance" +name = "pallet-mosaic" +version = "0.1.0" [[bin]] name = "plot" @@ -24,48 +24,51 @@ version = "2.0.0" [dependencies] composable-traits = { path = "../composable-traits", default-features = false } -frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.16" } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +composable-support = { path = "../composable-support", default-features = false } log = { version = "0.4.14", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } num-traits = { version = "0.2.14", default-features = false } -plotters = {version = "0.3.1", optional = true} +plotters = { version = "0.3.1", optional = true } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } [dev-dependencies] -proptest = "0.9.6" -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false} -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -composable-tests-helpers = { path = "../composable-tests-helpers", default-features = false } +composable-tests-helpers = { path = "../composable-tests-helpers" } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +proptest = "1.0" [features] default = ["std"] std = [ - "codec/std", - "log/std", - "composable-traits/std", - "scale-info/std", - "frame-support/std", - "frame-system/std", - "sp-runtime/std", - "sp-io/std", - "sp-core/std", - "sp-std/std", - "xcm/std", - "num-traits/std", + "codec/std", + "log/std", + "composable-traits/std", + "scale-info/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-io/std", + "sp-core/std", + "sp-std/std", + "xcm/std", + "num-traits/std", ] runtime-benchmarks = [ - "frame-benchmarking", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", ] visualization = ["plotters"] diff --git a/frame/mosaic/src/benchmarking.rs b/frame/mosaic/src/benchmarking.rs index 971f39236dd..f44aff65a3f 100644 --- a/frame/mosaic/src/benchmarking.rs +++ b/frame/mosaic/src/benchmarking.rs @@ -1,20 +1,21 @@ use super::*; use crate::{decay::*, Pallet as Mosaic}; +use composable_support::validation::Validated; use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller}; use frame_support::{ assert_ok, traits::{fungibles::Mutate, Get}, }; use frame_system::RawOrigin; - +const MIN_TRANSFER_SIZE: u128 = 1_000_000_000_000; const MAX_TRANSFER_SIZE: u128 = 100_000_000_000_000_000; const BUDGET_AMOUNT: u128 = 100_000_000_000_000_000_000; const TRANSFER_AMOUNT: u128 = 100_000_000_000_000; benchmarks! { where_clause { - where T::BlockNumber: From, T::NetworkId: From, BalanceOf: From, AssetIdOf: From, + where T::RemoteAssetId: From<[u8; 20]>, T::BlockNumber: From, T::NetworkId: From, BalanceOf: From, AssetIdOf: From, T::BudgetPenaltyDecayer: From, T::BlockNumber>> } @@ -27,7 +28,7 @@ benchmarks! { assert_ok!(Mosaic::::set_relayer(RawOrigin::Root.into(), relayer.clone())); let new_relayer = account("new_relayer", 0, 0); - }: _(RawOrigin::Signed(relayer), new_relayer, 42.into()) + }: _(RawOrigin::Signed(relayer), new_relayer, Validated::new(42.into()).unwrap()) set_network { let relayer: T::AccountId = whitelisted_caller(); @@ -36,6 +37,7 @@ benchmarks! { let network_id: T::NetworkId = 1.into(); let network_info = NetworkInfo { enabled: true, + min_transfer_size: MIN_TRANSFER_SIZE.into(), max_transfer_size: MAX_TRANSFER_SIZE.into(), }; @@ -55,11 +57,15 @@ benchmarks! { let network_id: T::NetworkId = 1.into(); let network_info = NetworkInfo { enabled: true, + min_transfer_size: MIN_TRANSFER_SIZE.into(), max_transfer_size: MAX_TRANSFER_SIZE.into(), }; assert_ok!(Mosaic::::set_network(RawOrigin::Signed(relayer).into(), network_id.clone(), network_info)); let asset_id: AssetIdOf = 1.into(); + let remote_asset_id: RemoteAssetIdOf = [0xFFu8; 20].into(); + assert_ok!(Mosaic::::update_asset_mapping(RawOrigin::Root.into(), asset_id, network_id.clone(), Some(remote_asset_id.clone()))); + let budget_amount: BalanceOf = BUDGET_AMOUNT.into(); let decayer: BudgetPenaltyDecayer, T::BlockNumber> = BudgetPenaltyDecayer::linear(5.into()); @@ -79,11 +85,15 @@ benchmarks! { let network_id: T::NetworkId = 1.into(); let network_info = NetworkInfo { enabled: true, + min_transfer_size: MIN_TRANSFER_SIZE.into(), max_transfer_size: MAX_TRANSFER_SIZE.into(), }; assert_ok!(Mosaic::::set_network(RawOrigin::Signed(relayer.clone()).into(), network_id.clone(), network_info)); let asset_id: AssetIdOf = 1.into(); + let remote_asset_id: RemoteAssetIdOf = [0xFFu8; 20].into(); + assert_ok!(Mosaic::::update_asset_mapping(RawOrigin::Root.into(), asset_id, network_id.clone(), Some(remote_asset_id.clone()))); + let budget_amount: BalanceOf = BUDGET_AMOUNT.into(); let decayer: BudgetPenaltyDecayer, T::BlockNumber> = BudgetPenaltyDecayer::linear(5.into()); @@ -94,8 +104,8 @@ benchmarks! { let transfer_amount: BalanceOf = TRANSFER_AMOUNT.into(); assert_ok!(T::Assets::mint_into(asset_id, &alice, transfer_amount)); - assert_ok!(Mosaic::::transfer_to(RawOrigin::Signed(alice.clone()).into(), network_id, asset_id, address, transfer_amount, false)); - }: _(RawOrigin::Signed(relayer), alice, asset_id, transfer_amount) + assert_ok!(Mosaic::::transfer_to(RawOrigin::Signed(alice.clone()).into(), network_id.clone(), asset_id, address, transfer_amount, false)); + }: _(RawOrigin::Signed(relayer), alice, network_id.clone(), remote_asset_id.clone(), transfer_amount) claim_stale_to { let relayer: T::AccountId = whitelisted_caller(); @@ -104,11 +114,15 @@ benchmarks! { let network_id: T::NetworkId = 1.into(); let network_info = NetworkInfo { enabled: true, + min_transfer_size: MIN_TRANSFER_SIZE.into(), max_transfer_size: MAX_TRANSFER_SIZE.into(), }; assert_ok!(Mosaic::::set_network(RawOrigin::Signed(relayer.clone()).into(), network_id.clone(), network_info)); let asset_id: AssetIdOf = 1.into(); + let remote_asset_id: RemoteAssetIdOf = [0xFFu8; 20].into(); + assert_ok!(Mosaic::::update_asset_mapping(RawOrigin::Root.into(), asset_id, network_id.clone(), Some(remote_asset_id.clone()))); + let budget_amount: BalanceOf = BUDGET_AMOUNT.into(); let decayer: BudgetPenaltyDecayer, T::BlockNumber> = BudgetPenaltyDecayer::linear(5.into()); @@ -130,11 +144,15 @@ benchmarks! { let network_id: T::NetworkId = 1.into(); let network_info = NetworkInfo { enabled: true, + min_transfer_size: MIN_TRANSFER_SIZE.into(), max_transfer_size: MAX_TRANSFER_SIZE.into(), }; assert_ok!(Mosaic::::set_network(RawOrigin::Signed(relayer.clone()).into(), network_id.clone(), network_info)); let asset_id: AssetIdOf = 1.into(); + let remote_asset_id: RemoteAssetIdOf = [0xFFu8; 20].into(); + assert_ok!(Mosaic::::update_asset_mapping(RawOrigin::Root.into(), asset_id, network_id.clone(), Some(remote_asset_id.clone()))); + let budget_amount: BalanceOf = BUDGET_AMOUNT.into(); let decayer: BudgetPenaltyDecayer, T::BlockNumber> = BudgetPenaltyDecayer::linear(5.into()); @@ -147,13 +165,13 @@ benchmarks! { assert_ok!(T::Assets::mint_into(asset_id, &alice, transfer_amount)); assert_ok!(Mosaic::::transfer_to(RawOrigin::Signed(alice.clone()).into(), network_id.clone(), asset_id, address, transfer_amount, false)); - assert_ok!(Mosaic::::accept_transfer(RawOrigin::Signed(relayer.clone()).into(), alice.clone(), asset_id, transfer_amount)); + assert_ok!(Mosaic::::accept_transfer(RawOrigin::Signed(relayer.clone()).into(), alice.clone(), network_id.clone(), remote_asset_id.clone(), transfer_amount)); let current_block = frame_system::Pallet::::block_number(); let tx_id = generate_id::(&alice, &network_id, &asset_id, &address, &transfer_amount, ¤t_block); - }: _(RawOrigin::Signed(relayer), asset_id, alice.clone(), transfer_amount, T::MinimumTimeLockPeriod::get(), tx_id) + }: _(RawOrigin::Signed(relayer), network_id.clone(), remote_asset_id.clone(), alice.clone(), transfer_amount, T::MinimumTimeLockPeriod::get(), tx_id) set_timelock_duration { - }: _(RawOrigin::Root, 100.into()) + }: _(RawOrigin::Root, Validated::new(100.into()).unwrap()) rescind_timelocked_mint { let relayer: T::AccountId = whitelisted_caller(); @@ -162,11 +180,15 @@ benchmarks! { let network_id: T::NetworkId = 1.into(); let network_info = NetworkInfo { enabled: true, + min_transfer_size: MIN_TRANSFER_SIZE.into(), max_transfer_size: MAX_TRANSFER_SIZE.into(), }; assert_ok!(Mosaic::::set_network(RawOrigin::Signed(relayer.clone()).into(), network_id.clone(), network_info)); let asset_id: AssetIdOf = 1.into(); + let remote_asset_id: RemoteAssetIdOf = [0xFFu8; 20].into(); + assert_ok!(Mosaic::::update_asset_mapping(RawOrigin::Root.into(), asset_id, network_id.clone(), Some(remote_asset_id.clone()))); + let budget_amount: BalanceOf = BUDGET_AMOUNT.into(); let decayer: BudgetPenaltyDecayer, T::BlockNumber> = BudgetPenaltyDecayer::linear(5.into()); @@ -179,12 +201,12 @@ benchmarks! { assert_ok!(T::Assets::mint_into(asset_id, &alice, transfer_amount)); assert_ok!(Mosaic::::transfer_to(RawOrigin::Signed(alice.clone()).into(), network_id.clone(), asset_id, address, transfer_amount, false)); - assert_ok!(Mosaic::::accept_transfer(RawOrigin::Signed(relayer.clone()).into(), alice.clone(), asset_id, transfer_amount)); + assert_ok!(Mosaic::::accept_transfer(RawOrigin::Signed(relayer.clone()).into(), alice.clone(), network_id.clone(), remote_asset_id.clone(), transfer_amount)); let current_block = frame_system::Pallet::::block_number(); let tx_id = generate_id::(&alice, &network_id, &asset_id, &address, &transfer_amount, ¤t_block); - assert_ok!(Mosaic::::timelocked_mint(RawOrigin::Signed(relayer.clone()).into(), asset_id, alice.clone(), transfer_amount, T::MinimumTimeLockPeriod::get(), tx_id)); - }: _(RawOrigin::Signed(relayer), asset_id, alice.clone(), transfer_amount) + assert_ok!(Mosaic::::timelocked_mint(RawOrigin::Signed(relayer.clone()).into(), network_id.clone(), remote_asset_id.clone(), alice.clone(), transfer_amount, T::MinimumTimeLockPeriod::get(), tx_id)); + }: _(RawOrigin::Signed(relayer), network_id.clone(), remote_asset_id.clone(), alice.clone(), transfer_amount) claim_to { @@ -194,11 +216,15 @@ benchmarks! { let network_id: T::NetworkId = 1.into(); let network_info = NetworkInfo { enabled: true, + min_transfer_size: MIN_TRANSFER_SIZE.into(), max_transfer_size: MAX_TRANSFER_SIZE.into(), }; assert_ok!(Mosaic::::set_network(RawOrigin::Signed(relayer.clone()).into(), network_id.clone(), network_info)); let asset_id: AssetIdOf = 1.into(); + let remote_asset_id: RemoteAssetIdOf = [0xFFu8; 20].into(); + assert_ok!(Mosaic::::update_asset_mapping(RawOrigin::Root.into(), asset_id, network_id.clone(), Some(remote_asset_id.clone()))); + let budget_amount: BalanceOf = BUDGET_AMOUNT.into(); let decayer: BudgetPenaltyDecayer, T::BlockNumber> = BudgetPenaltyDecayer::linear(5.into()); @@ -211,13 +237,29 @@ benchmarks! { assert_ok!(T::Assets::mint_into(asset_id, &alice, transfer_amount)); assert_ok!(Mosaic::::transfer_to(RawOrigin::Signed(alice.clone()).into(), network_id.clone(), asset_id, address, transfer_amount, false)); - assert_ok!(Mosaic::::accept_transfer(RawOrigin::Signed(relayer.clone()).into(), alice.clone(), asset_id, transfer_amount)); + assert_ok!(Mosaic::::accept_transfer(RawOrigin::Signed(relayer.clone()).into(), alice.clone(), network_id.clone(), remote_asset_id.clone(), transfer_amount)); let current_block = frame_system::Pallet::::block_number(); let tx_id = generate_id::(&alice, &network_id, &asset_id, &address, &transfer_amount, ¤t_block); - assert_ok!(Mosaic::::timelocked_mint(RawOrigin::Signed(relayer.clone()).into(), asset_id, alice.clone(), transfer_amount, T::MinimumTimeLockPeriod::get(), tx_id)); + assert_ok!(Mosaic::::timelocked_mint(RawOrigin::Signed(relayer.clone()).into(), network_id.clone(), remote_asset_id.clone(), alice.clone(), transfer_amount, T::MinimumTimeLockPeriod::get(), tx_id)); frame_system::Pallet::::set_block_number(T::MinimumTimeLockPeriod::get() + 1.into()); }: _(RawOrigin::Signed(alice.clone()), asset_id, alice.clone()) + + update_asset_mapping { + let relayer: T::AccountId = whitelisted_caller(); + assert_ok!(Mosaic::::set_relayer(RawOrigin::Root.into(), relayer.clone())); + + let network_id: T::NetworkId = 1.into(); + let network_info = NetworkInfo { + enabled: true, + min_transfer_size: MIN_TRANSFER_SIZE.into(), + max_transfer_size: MAX_TRANSFER_SIZE.into(), + }; + + assert_ok!(Mosaic::::set_network(RawOrigin::Signed(relayer.clone()).into(), network_id.clone(), network_info)); + let asset_id: AssetIdOf = 1.into(); + let remote_asset_id: T::RemoteAssetId = [0xFFu8; 20].into(); + }: _(RawOrigin::Root, asset_id, network_id.clone(), Some(remote_asset_id.clone())) } impl_benchmark_test_suite!(Mosaic, crate::mock::new_test_ext(), crate::mock::Test,); diff --git a/frame/mosaic/src/lib.rs b/frame/mosaic/src/lib.rs index 995e0492b63..a67e90da369 100644 --- a/frame/mosaic/src/lib.rs +++ b/frame/mosaic/src/lib.rs @@ -8,11 +8,14 @@ mod decay; mod relayer; +mod validation; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; pub mod weights; +pub use crate::weights::WeightInfo; + pub use decay::{BudgetPenaltyDecayer, Decayer}; pub use pallet::*; @@ -28,10 +31,12 @@ pub mod pallet { use crate::{ decay::Decayer, relayer::{RelayerConfig, StaleRelayer}, + validation::{ValidTTL, ValidTimeLockPeriod}, weights::WeightInfo, }; use codec::FullCodec; - use composable_traits::math::SafeArithmetic; + use composable_support::validation::Validated; + use composable_traits::math::SafeAdd; use frame_support::{ dispatch::DispatchResultWithPostInfo, pallet_prelude::*, @@ -53,19 +58,25 @@ pub mod pallet { pub(crate) type BlockNumberOf = ::BlockNumber; pub(crate) type AssetIdOf = <::Assets as Inspect>>::AssetId; pub(crate) type NetworkIdOf = ::NetworkId; + pub(crate) type RemoteAssetIdOf = ::RemoteAssetId; #[pallet::config] pub trait Config: frame_system::Config { type Event: From> + IsType<::Event>; type PalletId: Get; + type Assets: Mutate> + Transfer>; + /// The minimum time to live before a relayer account rotation. #[pallet::constant] type MinimumTTL: Get>; + + /// The minimum period for which we lock outgoing/incoming funds. #[pallet::constant] type MinimumTimeLockPeriod: Get>; + /// The budget penalty decayer. type BudgetPenaltyDecayer: Decayer, BlockNumberOf> + Clone + Encode @@ -75,24 +86,38 @@ pub mod pallet { + TypeInfo + PartialEq; + /// A type representing a network ID. type NetworkId: FullCodec + MaxEncodedLen + TypeInfo + Clone + Debug + PartialEq; + /// A type representing a remote asset ID. + type RemoteAssetId: FullCodec + MaxEncodedLen + TypeInfo + Clone + Debug + PartialEq; + /// Origin capable of setting the relayer. Inteded to be RootOrHalfCouncil, as it is also /// used as the origin capable of stopping attackers. type ControlOrigin: EnsureOrigin; + /// Weight implementation used for extrinsics. type WeightInfo: WeightInfo; } #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(_); + /// Convenience identifiers emitted by the pallet for relayer bookkeeping. + pub type Id = H256; + + /// Raw ethereum addresses. + pub type EthereumAddress = [u8; 20]; + + /// Transaction type. pub enum TransactionType { Incoming, Outgoing, } + /// The information required for an assets to be transferred between chains. #[derive(Clone, Debug, Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq)] pub struct AssetInfo { pub last_mint_block: BlockNumber, @@ -101,9 +126,11 @@ pub mod pallet { pub penalty_decayer: Decayer, } + /// The network informations, used for rate limitting. #[derive(Clone, Debug, Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq)] pub struct NetworkInfo { pub enabled: bool, + pub min_transfer_size: Balance, pub max_transfer_size: Balance, } @@ -138,7 +165,7 @@ pub mod pallet { #[pallet::getter(fn asset_infos)] pub type AssetsInfo = StorageMap< _, - Twox64Concat, + Blake2_128Concat, AssetIdOf, AssetInfo, BalanceOf, T::BudgetPenaltyDecayer>, OptionQuery, @@ -147,15 +174,17 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn network_infos)] pub type NetworkInfos = - StorageMap<_, Twox64Concat, NetworkIdOf, NetworkInfo>, OptionQuery>; + StorageMap<_, Blake2_128Concat, NetworkIdOf, NetworkInfo>, OptionQuery>; #[pallet::storage] #[pallet::getter(fn time_lock_period)] + #[allow(clippy::disallowed_type)] pub type TimeLockPeriod = StorageValue<_, BlockNumberOf, ValueQuery, TimeLockPeriodOnEmpty>; #[pallet::storage] #[pallet::getter(fn nonce)] + #[allow(clippy::disallowed_type)] pub type Nonce = StorageValue<_, u128, ValueQuery>; #[pallet::type_value] @@ -168,9 +197,9 @@ pub mod pallet { #[pallet::getter(fn outgoing_transactions)] pub type OutgoingTransactions = StorageDoubleMap< _, - Twox64Concat, + Blake2_128Concat, AccountIdOf, - Twox64Concat, + Blake2_128Concat, AssetIdOf, (BalanceOf, BlockNumberFor), OptionQuery, @@ -181,14 +210,38 @@ pub mod pallet { #[pallet::getter(fn incoming_transactions)] pub type IncomingTransactions = StorageDoubleMap< _, - Twox64Concat, + Blake2_128Concat, AccountIdOf, - Twox64Concat, + Blake2_128Concat, AssetIdOf, (BalanceOf, BlockNumberFor), OptionQuery, >; + #[pallet::storage] + #[pallet::getter(fn local_to_remote_asset)] + pub type LocalToRemoteAsset = StorageDoubleMap< + _, + Blake2_128Concat, + AssetIdOf, + Blake2_128Concat, + NetworkIdOf, + RemoteAssetIdOf, + OptionQuery, + >; + + #[pallet::storage] + #[pallet::getter(fn remote_to_local_asset)] + pub type RemoteToLocalAsset = StorageDoubleMap< + _, + Blake2_128Concat, + RemoteAssetIdOf, + Blake2_128Concat, + NetworkIdOf, + AssetIdOf, + OptionQuery, + >; + #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { @@ -207,13 +260,27 @@ pub mod pallet { TransferOut { id: Id, to: EthereumAddress, - amount: BalanceOf, + asset_id: AssetIdOf, network_id: NetworkIdOf, + remote_asset_id: RemoteAssetIdOf, + amount: BalanceOf, }, /// User claimed outgoing tx that was not (yet) picked up by the relayer - StaleTxClaimed { to: AccountIdOf, by: AccountIdOf, amount: BalanceOf }, + StaleTxClaimed { + to: AccountIdOf, + by: AccountIdOf, + asset_id: AssetIdOf, + amount: BalanceOf, + }, /// An incoming tx is created and waiting for the user to claim. - TransferInto { to: AccountIdOf, amount: BalanceOf, asset_id: AssetIdOf, id: Id }, + TransferInto { + id: Id, + to: AccountIdOf, + network_id: NetworkIdOf, + remote_asset_id: RemoteAssetIdOf, + asset_id: AssetIdOf, + amount: BalanceOf, + }, /// When we have finality issues occur on the Ethereum chain, /// we burn the locked `IncomingTransaction` for which we know that it is invalid. TransferIntoRescined { @@ -225,10 +292,18 @@ pub mod pallet { PartialTransferAccepted { from: AccountIdOf, asset_id: AssetIdOf, + network_id: NetworkIdOf, + remote_asset_id: RemoteAssetIdOf, amount: BalanceOf, }, /// The relayer accepted the user's `OutgoingTransaction`. - TransferAccepted { from: AccountIdOf, asset_id: AssetIdOf, amount: BalanceOf }, + TransferAccepted { + from: AccountIdOf, + asset_id: AssetIdOf, + network_id: NetworkIdOf, + remote_asset_id: RemoteAssetIdOf, + amount: BalanceOf, + }, /// The user claims his `IncomingTransaction` and unlocks the locked amount. TransferClaimed { by: AccountIdOf, @@ -236,6 +311,24 @@ pub mod pallet { asset_id: AssetIdOf, amount: BalanceOf, }, + /// An asset mapping has been created. + AssetMappingCreated { + asset_id: AssetIdOf, + network_id: NetworkIdOf, + remote_asset_id: RemoteAssetIdOf, + }, + /// An existing asset mapping has been updated. + AssetMappingUpdated { + asset_id: AssetIdOf, + network_id: NetworkIdOf, + remote_asset_id: RemoteAssetIdOf, + }, + /// An existing asset mapping has been deleted. + AssetMappingDeleted { + asset_id: AssetIdOf, + network_id: NetworkIdOf, + remote_asset_id: RemoteAssetIdOf, + }, } #[pallet::error] @@ -250,10 +343,12 @@ pub mod pallet { NoStaleTransactions, InsufficientBudget, ExceedsMaxTransferSize, + BelowMinTransferSize, NoClaimableTx, TxStillLocked, NoOutgoingTx, AmountMismatch, + AssetNotMapped, } #[pallet::call] @@ -281,9 +376,9 @@ pub mod pallet { pub fn rotate_relayer( origin: OriginFor, new: T::AccountId, - ttl: T::BlockNumber, + validated_ttl: Validated>, ) -> DispatchResultWithPostInfo { - ensure!(ttl > T::MinimumTTL::get(), Error::::BadTTL); + let ttl = validated_ttl.value(); let (relayer, current_block) = Self::ensure_relayer(origin)?; let ttl = current_block.saturating_add(ttl); let relayer = relayer.rotate(new.clone(), ttl); @@ -365,10 +460,12 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { let caller = ensure_signed(origin)?; ensure!(AssetsInfo::::contains_key(asset_id), Error::::UnsupportedAsset); + let remote_asset_id = Self::get_remote_mapping(asset_id, network_id.clone())?; let network_info = NetworkInfos::::get(network_id.clone()).ok_or(Error::::UnsupportedNetwork)?; ensure!(network_info.enabled, Error::::NetworkDisabled); ensure!(network_info.max_transfer_size >= amount, Error::::ExceedsMaxTransferSize); + ensure!(network_info.min_transfer_size <= amount, Error::::BelowMinTransferSize); T::Assets::transfer( asset_id, @@ -398,7 +495,14 @@ pub mod pallet { )?; let id = generate_id::(&caller, &network_id, &asset_id, &address, &amount, &now); - Self::deposit_event(Event::::TransferOut { to: address, amount, network_id, id }); + Self::deposit_event(Event::::TransferOut { + id, + to: address, + amount, + asset_id, + network_id, + remote_asset_id, + }); Ok(().into()) } @@ -419,10 +523,12 @@ pub mod pallet { pub fn accept_transfer( origin: OriginFor, from: AccountIdOf, - asset_id: AssetIdOf, + network_id: NetworkIdOf, + remote_asset_id: RemoteAssetIdOf, amount: BalanceOf, ) -> DispatchResultWithPostInfo { Self::ensure_relayer(origin)?; + let asset_id = Self::get_local_mapping(remote_asset_id.clone(), network_id.clone())?; OutgoingTransactions::::try_mutate_exists::<_, _, _, DispatchError, _>( from.clone(), asset_id, @@ -441,6 +547,8 @@ pub mod pallet { *maybe_tx = None; Self::deposit_event(Event::::TransferAccepted { from, + network_id, + remote_asset_id, asset_id, amount, }); @@ -450,6 +558,8 @@ pub mod pallet { *maybe_tx = Some((new_balance, lock_period)); Self::deposit_event(Event::::PartialTransferAccepted { from, + network_id, + remote_asset_id, asset_id, amount, }); @@ -500,7 +610,12 @@ pub mod pallet { }?; *prev = None; - Self::deposit_event(Event::::StaleTxClaimed { to, by: caller, amount }); + Self::deposit_event(Event::::StaleTxClaimed { + to, + asset_id, + by: caller, + amount, + }); Ok(()) }, )?; @@ -512,13 +627,15 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::timelocked_mint())] pub fn timelocked_mint( origin: OriginFor, - asset_id: AssetIdOf, + network_id: NetworkIdOf, + remote_asset_id: RemoteAssetIdOf, to: AccountIdOf, amount: BalanceOf, lock_time: BlockNumberOf, id: Id, ) -> DispatchResultWithPostInfo { let (_caller, current_block) = Self::ensure_relayer(origin)?; + let asset_id = Self::get_local_mapping(remote_asset_id.clone(), network_id.clone())?; AssetsInfo::::try_mutate_exists::<_, _, DispatchError, _>(asset_id, |info| { let AssetInfo { last_mint_block, penalty, budget, penalty_decayer } = @@ -554,7 +671,14 @@ pub mod pallet { penalty_decayer, }); - Self::deposit_event(Event::::TransferInto { to, asset_id, amount, id }); + Self::deposit_event(Event::::TransferInto { + id, + to, + network_id, + remote_asset_id, + asset_id, + amount, + }); Ok(()) })?; @@ -564,11 +688,11 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::set_timelock_duration())] pub fn set_timelock_duration( origin: OriginFor, - period: BlockNumberOf, + period: Validated, ValidTimeLockPeriod>, ) -> DispatchResultWithPostInfo { + let validated_period = period.value(); T::ControlOrigin::ensure_origin(origin)?; - ensure!(period > T::MinimumTimeLockPeriod::get(), Error::::BadTimelockPeriod); - TimeLockPeriod::::set(period); + TimeLockPeriod::::set(validated_period); Ok(().into()) } @@ -578,11 +702,13 @@ pub mod pallet { #[transactional] pub fn rescind_timelocked_mint( origin: OriginFor, - asset_id: AssetIdOf, + network_id: NetworkIdOf, + remote_asset_id: RemoteAssetIdOf, account: AccountIdOf, untrusted_amount: BalanceOf, ) -> DispatchResultWithPostInfo { Self::ensure_relayer(origin)?; + let asset_id = Self::get_local_mapping(remote_asset_id.clone(), network_id.clone())?; IncomingTransactions::::try_mutate_exists::<_, _, _, DispatchError, _>( account.clone(), @@ -648,6 +774,79 @@ pub mod pallet { )?; Ok(().into()) } + + /// Update a network asset mapping. + /// + /// The caller must be `ControlOrigin`. + /// + /// Possibly emits one of: + /// - `AssetMappingCreated` + /// - `AssetMappingDeleted` + /// - `AssetMappingUpdated` + #[pallet::weight(T::WeightInfo::update_asset_mapping())] + pub fn update_asset_mapping( + origin: OriginFor, + asset_id: AssetIdOf, + network_id: NetworkIdOf, + remote_asset_id: Option>, + ) -> DispatchResultWithPostInfo { + T::ControlOrigin::ensure_origin(origin)?; + let _ = + NetworkInfos::::get(network_id.clone()).ok_or(Error::::UnsupportedNetwork)?; + let entry = LocalToRemoteAsset::::try_get(asset_id, network_id.clone()).ok(); + match (entry, remote_asset_id) { + // remove an non-existent entry. + (None, None) => {}, + // insert a new entry. + (None, Some(remote_asset_id)) => { + LocalToRemoteAsset::::insert( + asset_id, + network_id.clone(), + remote_asset_id.clone(), + ); + RemoteToLocalAsset::::insert( + remote_asset_id.clone(), + network_id.clone(), + asset_id, + ); + Self::deposit_event(Event::::AssetMappingCreated { + asset_id, + network_id, + remote_asset_id, + }); + }, + // remove an existing entry. + (Some(remote_asset_id), None) => { + LocalToRemoteAsset::::remove(asset_id, network_id.clone()); + RemoteToLocalAsset::::remove(remote_asset_id.clone(), network_id.clone()); + Self::deposit_event(Event::::AssetMappingDeleted { + asset_id, + network_id, + remote_asset_id, + }); + }, + // update an existing entry + (Some(old_remote_asset_id), Some(new_remote_asset_id)) => { + LocalToRemoteAsset::::insert( + asset_id, + network_id.clone(), + new_remote_asset_id.clone(), + ); + RemoteToLocalAsset::::remove(old_remote_asset_id, network_id.clone()); + RemoteToLocalAsset::::insert( + new_remote_asset_id.clone(), + network_id.clone(), + asset_id, + ); + Self::deposit_event(Event::::AssetMappingUpdated { + asset_id, + network_id, + remote_asset_id: new_remote_asset_id, + }); + }, + } + Ok(().into()) + } } #[pallet::extra_constants] @@ -659,12 +858,13 @@ pub mod pallet { impl Pallet { /// AccountId of the pallet, used to store all funds before actually moving them. - pub fn sub_account_id(sub_account: SubAccount) -> AccountIdOf { + pub(crate) fn sub_account_id(sub_account: SubAccount) -> AccountIdOf { T::PalletId::get().into_sub_account(sub_account.to_id()) } /// Queries storage, returning the account_id of the current relayer. - pub fn relayer_account_id() -> Result, DispatchError> { + #[allow(dead_code)] + pub(crate) fn relayer_account_id() -> Result, DispatchError> { let current_block = >::block_number(); Ok(Relayer::::get() .ok_or(Error::::RelayerNotSet)? @@ -686,13 +886,23 @@ pub mod pallet { ensure!(relayer.is_relayer(&acc), DispatchError::BadOrigin); Ok((relayer, current_block)) } - } - /// Convenience identifiers emitted by the pallet for relayer bookkeeping. - pub type Id = H256; + pub(crate) fn get_local_mapping( + remote_asset_id: RemoteAssetIdOf, + network_id: NetworkIdOf, + ) -> Result, Error> { + RemoteToLocalAsset::::try_get(remote_asset_id, network_id) + .map_err(|_| Error::::AssetNotMapped) + } - /// Raw ethereum addresses. - pub type EthereumAddress = [u8; 20]; + pub(crate) fn get_remote_mapping( + asset_id: AssetIdOf, + network_id: NetworkIdOf, + ) -> Result, Error> { + LocalToRemoteAsset::::try_get(asset_id, network_id) + .map_err(|_| Error::::AssetNotMapped) + } + } /// Uses Keccak256 to generate an identifier for pub(crate) fn generate_id( diff --git a/frame/mosaic/src/mock.rs b/frame/mosaic/src/mock.rs index d2fd7eacc77..ae5bc011a2e 100644 --- a/frame/mosaic/src/mock.rs +++ b/frame/mosaic/src/mock.rs @@ -21,6 +21,7 @@ pub type NetworkId = u32; pub type Balance = u128; pub type Amount = i128; pub type AssetId = u128; +pub type RemoteAssetId = [u8; 20]; type Block = frame_system::mocking::MockBlock; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; @@ -106,6 +107,7 @@ impl pallet_mosaic::Config for Test { type MinimumTimeLockPeriod = MinimumTimeLockPeriod; type BudgetPenaltyDecayer = pallet_mosaic::BudgetPenaltyDecayer; type NetworkId = NetworkId; + type RemoteAssetId = RemoteAssetId; type ControlOrigin = EnsureRoot; type WeightInfo = (); } diff --git a/frame/mosaic/src/tests.rs b/frame/mosaic/src/tests.rs index 6ad953f3bf3..43aabf96ee6 100644 --- a/frame/mosaic/src/tests.rs +++ b/frame/mosaic/src/tests.rs @@ -30,6 +30,7 @@ /// For every test, make sure that you check wether the funds moved to the correct (sub) /// accounts. use crate::{decay::*, mock::*, *}; +use composable_support::validation::{Validate, Validated}; use composable_tests_helpers::{prop_assert_noop, prop_assert_ok}; use frame_support::{ assert_err, assert_noop, assert_ok, @@ -53,6 +54,9 @@ pub trait OriginExt { } const BUDGET: Balance = 10000; +const NETWORK_ID: NetworkId = 1; +const ASSET_ID: AssetId = 1; +const REMOTE_ASSET_ID: RemoteAssetId = [1u8; 20]; impl OriginExt for Origin {} @@ -140,7 +144,6 @@ mod set_relayer { assert_noop!(Mosaic::set_relayer(Origin::none(), ALICE), DispatchError::BadOrigin); }) } - #[test] fn alice_cannot_set_relayer() { new_test_ext().execute_with(|| { @@ -162,13 +165,14 @@ mod rotate_relayer { let current_block = System::block_number(); assert_ok!(Mosaic::set_relayer(Origin::root(), RELAYER)); - // first rotation - assert_ok!(Mosaic::rotate_relayer(Origin::relayer(), BOB, ttl)); + //first rotation + let validated_ttl = Validated::new(ttl).unwrap(); + assert_ok!(Mosaic::rotate_relayer(Origin::relayer(), BOB, validated_ttl)); System::set_block_number(current_block + ttl); assert_eq!(Mosaic::relayer_account_id(), Ok(BOB)); // second rotation - assert_ok!(Mosaic::rotate_relayer(Origin::signed(BOB), CHARLIE, ttl)); + assert_ok!(Mosaic::rotate_relayer(Origin::signed(BOB), CHARLIE, validated_ttl)); System::set_block_number(current_block + 2 * ttl); assert_eq!(Mosaic::relayer_account_id(), Ok(CHARLIE)); }) @@ -180,7 +184,8 @@ mod rotate_relayer { let ttl = 500; let current_block = System::block_number(); assert_ok!(Mosaic::set_relayer(Origin::root(), RELAYER)); - assert_ok!(Mosaic::rotate_relayer(Origin::relayer(), BOB, ttl)); + let validated_ttl = Validated::new(ttl).unwrap(); + assert_ok!(Mosaic::rotate_relayer(Origin::relayer(), BOB, validated_ttl)); System::set_block_number(current_block + ttl - 1); // just before the ttl assert_eq!(Mosaic::relayer_account_id(), Ok(RELAYER)); // not BOB }) @@ -189,7 +194,7 @@ mod rotate_relayer { #[test] fn arbitrary_account_cannot_rotate_relayer() { new_test_ext().execute_with(|| { - let ttl = 500; + let ttl = Validated::new(500).unwrap(); assert_ok!(Mosaic::set_relayer(Origin::root(), RELAYER)); assert_noop!( Mosaic::rotate_relayer(Origin::signed(ALICE), BOB, ttl), @@ -201,7 +206,7 @@ mod rotate_relayer { #[test] fn none_cannot_rotate_relayer() { new_test_ext().execute_with(|| { - let ttl = 500; + let ttl = Validated::new(500).unwrap(); assert_ok!(Mosaic::set_relayer(Origin::root(), RELAYER)); assert_noop!( Mosaic::rotate_relayer(Origin::none(), BOB, ttl), @@ -217,7 +222,8 @@ mod set_network { #[test] fn relayer_can_set_network() { let network_id = 3; - let network_info = NetworkInfo { enabled: false, max_transfer_size: 100000 }; + let network_info = + NetworkInfo { enabled: false, min_transfer_size: 1, max_transfer_size: 100000 }; new_test_ext().execute_with(|| { assert_ok!(Mosaic::set_relayer(Origin::root(), RELAYER)); @@ -229,7 +235,8 @@ mod set_network { #[test] fn root_cannot_set_network() { let network_id = 3; - let network_info = NetworkInfo { enabled: false, max_transfer_size: 100000 }; + let network_info = + NetworkInfo { enabled: false, min_transfer_size: 1, max_transfer_size: 100000 }; new_test_ext().execute_with(|| { assert_ok!(Mosaic::set_relayer(Origin::root(), RELAYER)); @@ -243,7 +250,8 @@ mod set_network { #[test] fn none_cannot_set_network() { let network_id = 3; - let network_info = NetworkInfo { enabled: false, max_transfer_size: 100000 }; + let network_info = + NetworkInfo { enabled: false, min_transfer_size: 1, max_transfer_size: 100000 }; new_test_ext().execute_with(|| { assert_ok!(Mosaic::set_relayer(Origin::root(), RELAYER)); @@ -381,284 +389,40 @@ fn incoming_outgoing_accounts_are_isolated() { fn initialize() { System::set_block_number(1); - Mosaic::set_relayer(Origin::root(), RELAYER).expect("root may call set_relayer"); - Mosaic::set_network( + assert_ok!(Mosaic::set_relayer(Origin::root(), RELAYER)); + assert_ok!(Mosaic::set_network( Origin::relayer(), 1, - NetworkInfo { enabled: true, max_transfer_size: 100000 }, - ) - .expect("relayer may set network info"); - Mosaic::set_budget(Origin::root(), 1, BUDGET, BudgetPenaltyDecayer::linear(10)) - .expect("root may set budget"); + NetworkInfo { enabled: true, min_transfer_size: 1, max_transfer_size: 100000 }, + )); + assert_ok!(Mosaic::set_budget(Origin::root(), 1, BUDGET, BudgetPenaltyDecayer::linear(10))); + assert_ok!(Mosaic::update_asset_mapping( + Origin::root(), + ASSET_ID, + NETWORK_ID, + Some(REMOTE_ASSET_ID) + )); } -fn do_timelocked_mint(to: AccountId, asset_id: AssetId, amount: Balance, lock_time: u64) { +fn do_timelocked_mint(to: AccountId, amount: Balance, lock_time: u64) { let initial_block = System::block_number(); - Mosaic::timelocked_mint(Origin::relayer(), asset_id, to, amount, lock_time, Default::default()) - .expect("relayer should be able to mint"); + assert_ok!(Mosaic::timelocked_mint( + Origin::relayer(), + NETWORK_ID, + REMOTE_ASSET_ID, + to, + amount, + lock_time, + Default::default() + )); assert_eq!( - Mosaic::incoming_transactions(to, asset_id), + Mosaic::incoming_transactions(to, ASSET_ID), Some((amount, initial_block + lock_time)) ); } -mod transfers { - use super::*; - - #[test] - fn transfer_to() { - new_test_ext().execute_with(|| { - initialize(); - do_transfer_to(); - }) - } - - #[test] - fn accept_transfer() { - new_test_ext().execute_with(|| { - initialize(); - do_transfer_to(); - Mosaic::accept_transfer(Origin::relayer(), ALICE, 1, 100) - .expect("accepting transfer should work"); - }) - } - - #[test] - fn cannot_accept_transfer_larger_than_balance() { - new_test_ext().execute_with(|| { - initialize(); - do_transfer_to(); - assert_noop!( - Mosaic::accept_transfer(Origin::relayer(), ALICE, 1, 101), - Error::::AmountMismatch - ); - }) - } - - #[test] - fn claim_stale_to() { - new_test_ext().execute_with(|| { - initialize(); - do_transfer_to(); - let current_block = System::block_number(); - System::set_block_number(current_block + Mosaic::timelock_period() + 1); - Mosaic::claim_stale_to(Origin::signed(ALICE), 1, ALICE) - .expect("claiming an outgoing transaction should work after the timelock period"); - }) - } - - #[test] - fn cannot_claim_stale_to_early() { - new_test_ext().execute_with(|| { - initialize(); - do_transfer_to(); - let current_block = System::block_number(); - System::set_block_number(current_block + Mosaic::timelock_period() - 1); - assert_noop!( - Mosaic::claim_stale_to(Origin::signed(ALICE), 1, ALICE), - Error::::TxStillLocked - ); - }) - } - - #[test] - fn cannot_claim_after_relayer_accepts_transfer() { - new_test_ext().execute_with(|| { - initialize(); - do_transfer_to(); - assert_ok!(Mosaic::accept_transfer(Origin::relayer(), ALICE, 1, 100)); - let current_block = System::block_number(); - System::set_block_number(current_block + Mosaic::timelock_period() + 1); - assert_noop!( - Mosaic::claim_stale_to(Origin::signed(ALICE), 1, ALICE), - Error::::NoStaleTransactions - ); - }) - } - - #[test] - fn relayer_cannot_accept_transfer_after_claim() { - new_test_ext().execute_with(|| { - initialize(); - do_transfer_to(); - let current_block = System::block_number(); - System::set_block_number(current_block + Mosaic::timelock_period() + 1); - assert_ok!(Mosaic::claim_stale_to(Origin::signed(ALICE), 1, ALICE)); - assert_noop!( - Mosaic::accept_transfer(Origin::relayer(), ALICE, 1, 100), - Error::::NoOutgoingTx - ); - }) - } - - #[test] - fn can_claim_stale_after_partial_accept_transfer() { - new_test_ext().execute_with(|| { - initialize(); - do_transfer_to(); - let current_block = System::block_number(); - System::set_block_number(current_block + Mosaic::timelock_period() + 1); - assert_ok!(Mosaic::accept_transfer(Origin::relayer(), ALICE, 1, 20)); - // System::set_block_number(current_block + Mosaic::timelock_period() + 1); - assert_ok!(Mosaic::claim_stale_to(Origin::signed(ALICE), 1, ALICE)); - }) - } - - #[test] - fn transfer_to_exceeds_max_transfer_size() { - ExtBuilder { balances: Default::default() }.build().execute_with(|| { - let max_transfer_size = 100000; - - assert_ok!(Mosaic::set_relayer(Origin::root(), RELAYER)); - - let network_id = 1; - assert_ok!(Mosaic::set_network( - Origin::relayer(), - network_id, - NetworkInfo { enabled: true, max_transfer_size }, - )); - - let asset_id: u128 = 1; - assert_ok!(Mosaic::set_budget( - Origin::root(), - asset_id, - 10000, - BudgetPenaltyDecayer::linear(10) - )); - - // We exceed the max transfer size - let amount = max_transfer_size + 1; - assert_ok!(Tokens::mint_into(asset_id, &ALICE, amount)); - assert_noop!( - Mosaic::transfer_to( - Origin::signed(ALICE), - network_id, - asset_id, - [0; 20], - amount, - true - ), - Error::::ExceedsMaxTransferSize - ); - }) - } - - #[test] - fn transfer_to_move_funds_to_outgoing() { - ExtBuilder { balances: Default::default() }.build().execute_with(|| { - initialize(); - - let amount = 100; - let network_id = 1; - let asset_id: u128 = 1; - - assert_ok!(Tokens::mint_into(asset_id, &ALICE, amount)); - let account_balance = || Tokens::balance(asset_id, &ALICE); - let outgoing_balance = || { - Tokens::balance(asset_id, &Mosaic::sub_account_id(SubAccount::new_outgoing(ALICE))) - }; - assert_eq!(account_balance(), amount); - assert_eq!(outgoing_balance(), 0); - assert_ok!(Mosaic::transfer_to( - Origin::signed(ALICE), - network_id, - asset_id, - [0; 20], - amount, - true - )); - assert_eq!(account_balance(), 0); - assert_eq!(outgoing_balance(), amount); - }) - } - - #[test] - fn transfer_to_unsupported_asset() { - ExtBuilder { balances: Default::default() }.build().execute_with(|| { - assert_ok!(Mosaic::set_relayer(Origin::root(), RELAYER)); - assert_ok!(Mosaic::set_network( - Origin::relayer(), - 1, - NetworkInfo { enabled: true, max_transfer_size: 100000 }, - )); - - // We don't register the asset - - let amount = 100; - let network_id = 1; - let asset_id: u128 = 1; - - assert_ok!(Tokens::mint_into(asset_id, &ALICE, amount)); - assert_noop!( - Mosaic::transfer_to( - Origin::signed(ALICE), - network_id, - asset_id, - [0; 20], - amount, - true - ), - Error::::UnsupportedAsset - ); - }) - } - - fn do_transfer_to() { - let ethereum_address = [0; 20]; - let amount = 100; - let network_id = 1; - let asset_id: u128 = 1; - - Mosaic::transfer_to( - Origin::signed(ALICE), - network_id, - asset_id, - ethereum_address, - amount, - true, - ) - .expect("transfer_to should work"); - assert_eq!( - Mosaic::outgoing_transactions(&ALICE, 1), - Some((100, MinimumTimeLockPeriod::get() + System::block_number())) - ); - - // normally we don't unit test events being emitted, but in this case it is very crucial for - // the relayer to observe the events. - - // When a transfer is made, the nonce is incremented. However, nonce is one of the - // dependencies for `generate_id`, we want to check if the events match, so we decrement the - // nonce and increment it back when we're done - // TODO: this is a hack, cfr: CU-1ubrf2y - Nonce::::mutate(|nonce| { - *nonce = nonce.wrapping_sub(1); - *nonce - }); - - let id = generate_id::( - &ALICE, - &network_id, - &asset_id, - ðereum_address, - &amount, - &System::block_number(), - ); - Nonce::::mutate(|nonce| { - *nonce = nonce.wrapping_add(1); - *nonce - }); - - System::assert_last_event(mock::Event::Mosaic(crate::Event::TransferOut { - id, - to: ethereum_address, - amount, - network_id, - })); - } -} - mod timelocked_mint { use super::*; @@ -666,7 +430,7 @@ mod timelocked_mint { fn timelocked_mint() { new_test_ext().execute_with(|| { initialize(); - do_timelocked_mint(ALICE, 1, 50, 10); + do_timelocked_mint(ALICE, 50, 10); }) } @@ -674,11 +438,18 @@ mod timelocked_mint { fn cannot_mint_unsupported_assets() { new_test_ext().execute_with(|| { initialize(); - let unsupported_asset_id: u128 = 42; + let unsupported_remote_asset_id: RemoteAssetId = [0xFFu8; 20]; + assert_ok!(Mosaic::update_asset_mapping( + Origin::root(), + 0xCAFEBABE, + NETWORK_ID, + Some(unsupported_remote_asset_id) + )); assert_noop!( Mosaic::timelocked_mint( Origin::relayer(), - unsupported_asset_id, + NETWORK_ID, + unsupported_remote_asset_id, ALICE, 50, 10, @@ -694,7 +465,15 @@ mod timelocked_mint { new_test_ext().execute_with(|| { initialize(); assert_noop!( - Mosaic::timelocked_mint(Origin::relayer(), 1, ALICE, 10001, 10, Default::default()), + Mosaic::timelocked_mint( + Origin::relayer(), + NETWORK_ID, + REMOTE_ASSET_ID, + ALICE, + 10001, + 10, + Default::default() + ), Error::::InsufficientBudget ); }) @@ -707,7 +486,8 @@ mod timelocked_mint { assert_noop!( Mosaic::timelocked_mint( Origin::signed(ALICE), - 1, + NETWORK_ID, + REMOTE_ASSET_ID, ALICE, 50, 10, @@ -723,7 +503,15 @@ mod timelocked_mint { new_test_ext().execute_with(|| { initialize(); assert_noop!( - Mosaic::timelocked_mint(Origin::none(), 1, ALICE, 50, 10, Default::default()), + Mosaic::timelocked_mint( + Origin::none(), + NETWORK_ID, + REMOTE_ASSET_ID, + ALICE, + 50, + 10, + Default::default() + ), DispatchError::BadOrigin ); }) @@ -735,15 +523,15 @@ mod timelocked_mint { initialize(); let amount = 50; let lock_time = 10; - Mosaic::timelocked_mint( + assert_ok!(Mosaic::timelocked_mint( Origin::relayer(), - 1, + NETWORK_ID, + REMOTE_ASSET_ID, ALICE, amount, lock_time, Default::default(), - ) - .expect("timelocked_mint should work"); + )); assert_eq!( Mosaic::incoming_transactions(ALICE, 1), Some((amount, lock_time + System::block_number())) @@ -758,15 +546,15 @@ mod timelocked_mint { let amount = 50; let lock_time = 10; - Mosaic::timelocked_mint( + assert_ok!(Mosaic::timelocked_mint( Origin::relayer(), - 1, + NETWORK_ID, + REMOTE_ASSET_ID, ALICE, amount, lock_time, Default::default(), - ) - .expect("timelocked_mint should work"); + )); assert_eq!( Mosaic::incoming_transactions(ALICE, 1), Some((amount, lock_time + System::block_number())) @@ -775,15 +563,15 @@ mod timelocked_mint { let amount_2 = 100; let new_lock_time = 20; - Mosaic::timelocked_mint( + assert_ok!(Mosaic::timelocked_mint( Origin::relayer(), - 1, + NETWORK_ID, + REMOTE_ASSET_ID, ALICE, amount_2, new_lock_time, Default::default(), - ) - .expect("timelocked_mint should work"); + )); assert_eq!( Mosaic::incoming_transactions(ALICE, 1), @@ -797,19 +585,29 @@ mod timelocked_mint { new_test_ext().execute_with(|| { initialize(); let lock_time = 10; - do_timelocked_mint(ALICE, 1, 50, lock_time); + do_timelocked_mint(ALICE, 50, lock_time); let initial_block = System::block_number(); - Mosaic::rescind_timelocked_mint(Origin::relayer(), 1, ALICE, 40) - .expect("relayer should be able to rescind transactions"); + assert_ok!(Mosaic::rescind_timelocked_mint( + Origin::relayer(), + NETWORK_ID, + REMOTE_ASSET_ID, + ALICE, + 40 + )); assert_eq!( Mosaic::incoming_transactions(ALICE, 1), Some((10, initial_block + lock_time)) ); let transfer_amount = 9; - Mosaic::rescind_timelocked_mint(Origin::relayer(), 1, ALICE, transfer_amount) - .expect("relayer should be able to rescind transactions"); + assert_ok!(Mosaic::rescind_timelocked_mint( + Origin::relayer(), + NETWORK_ID, + REMOTE_ASSET_ID, + ALICE, + transfer_amount + )); assert_eq!(Mosaic::incoming_transactions(ALICE, 1), Some((1, 11))); }) } @@ -821,9 +619,11 @@ mod timelocked_mint { fn can_mint_up_to_the_penalised_budget( account_a in account_id(), decay in 1..100u128, // todo, - max_transfer_size in 1..10_000_000u128, + min_transfer_size in 1..10_000_000u128, + max_transfer_size in 10_000_000u128..100_000_000u128, asset_id in 1..100u128, network_id in 1..100u32, + remote_asset_id in any::(), start_block in 1..10_000u64, (budget, first_part, second_part) in budget_with_split(), ) { @@ -835,18 +635,19 @@ mod timelocked_mint { prop_assert_ok!(Mosaic::set_network( Origin::relayer(), network_id, - NetworkInfo { enabled: true, max_transfer_size }, + NetworkInfo { enabled: true, min_transfer_size, max_transfer_size }, ), "relayer may set network info"); prop_assert_ok!(Mosaic::set_budget(Origin::root(), asset_id, budget, BudgetPenaltyDecayer::linear(decay)), "root may set budget"); + prop_assert_ok!(Mosaic::update_asset_mapping(Origin::root(), asset_id, network_id, Some(remote_asset_id))); // We've split the budget in two parts. Both within the budget prop_assert_eq!(budget, first_part + second_part); // When mint the first part of the budget, it should be fine. - prop_assert_ok!(Mosaic::timelocked_mint(Origin::relayer(), asset_id, account_a, first_part, 0, Default::default())); + prop_assert_ok!(Mosaic::timelocked_mint(Origin::relayer(), network_id, remote_asset_id, account_a, first_part, 0, Default::default())); // The new penalised_budget should be budget - first_part. // Whenwe mint the second part of the budget, it should be fine because it matches the penalised_budget. - prop_assert_ok!(Mosaic::timelocked_mint(Origin::relayer(), asset_id, account_a, second_part, 0, Default::default())); + prop_assert_ok!(Mosaic::timelocked_mint(Origin::relayer(), network_id, remote_asset_id, account_a, second_part, 0, Default::default())); Ok(()) })?; @@ -856,9 +657,11 @@ mod timelocked_mint { fn cannot_mint_more_than_the_penalised_budget( account_a in account_id(), decay in 1..100u128, // todo, - max_transfer_size in 1..10_000_000u128, + min_transfer_size in 1..10_000_000u128, + max_transfer_size in 10_000_000u128..100_000_000u128, asset_id in 1..100u128, network_id in 1..100u32, + remote_asset_id in any::(), start_block in 1..10_000u64, (budget, first_part, second_part) in budget_with_split(), ) { @@ -870,20 +673,21 @@ mod timelocked_mint { prop_assert_ok!(Mosaic::set_network( Origin::relayer(), network_id, - NetworkInfo { enabled: true, max_transfer_size }, + NetworkInfo { enabled: true, min_transfer_size, max_transfer_size }, ), "relayer may set network info"); prop_assert_ok!(Mosaic::set_budget(Origin::root(), asset_id, budget, BudgetPenaltyDecayer::linear(decay)), "root may set budget"); + prop_assert_ok!(Mosaic::update_asset_mapping(Origin::root(), asset_id, network_id, Some(remote_asset_id))); // We've split the budget in two parts. Both within the budget prop_assert_eq!(budget, first_part + second_part); // When mint the first part of the budget, it should be fine. - prop_assert_ok!(Mosaic::timelocked_mint(Origin::relayer(), asset_id, account_a, first_part, 0, Default::default())); + prop_assert_ok!(Mosaic::timelocked_mint(Origin::relayer(), network_id, remote_asset_id, account_a, first_part, 0, Default::default())); // The new penalised_budget should be budget - first_part. // When we mint the second part of the budget, it should be fine because it matches the penalised_budget. - prop_assert_ok!(Mosaic::timelocked_mint(Origin::relayer(), asset_id, account_a, second_part, 0, Default::default())); + prop_assert_ok!(Mosaic::timelocked_mint(Origin::relayer(), network_id, remote_asset_id, account_a, second_part, 0, Default::default())); // When we mint more than the penalised budget, it should fail. - prop_assert_noop!(Mosaic::timelocked_mint(Origin::relayer(), asset_id, account_a, 1, 0, Default::default()), Error::::InsufficientBudget); + prop_assert_noop!(Mosaic::timelocked_mint(Origin::relayer(), network_id, remote_asset_id, account_a, 1, 0, Default::default()), Error::::InsufficientBudget); Ok(()) })?; } @@ -892,9 +696,11 @@ mod timelocked_mint { fn should_be_able_to_mint_again_after_waiting_for_penalty_to_decay( account_a in account_id(), decay_factor in 1..100u128, // todo, - max_transfer_size in 1..10_000_000u128, + min_transfer_size in 1..10_000_000u128, + max_transfer_size in 10_000_000u128..100_000_000u128, asset_id in 1..100u128, network_id in 1..100u32, + remote_asset_id in any::(), start_block in 1..10_000u64, (budget, first_part, second_part) in budget_with_split(), iteration_count in 2..10u64, @@ -912,9 +718,10 @@ mod timelocked_mint { prop_assert_ok!(Mosaic::set_network( Origin::relayer(), network_id, - NetworkInfo { enabled: true, max_transfer_size }, + NetworkInfo { enabled: true, min_transfer_size, max_transfer_size }, ), "relayer may set network info"); prop_assert_ok!(Mosaic::set_budget(Origin::root(), asset_id, budget, budget_penalty_decayer.clone()), "root may set budget"); + prop_assert_ok!(Mosaic::update_asset_mapping(Origin::root(), asset_id, network_id, Some(remote_asset_id))); // We've split the budget in two parts. Both within the budget @@ -928,14 +735,14 @@ mod timelocked_mint { for _ in 0..iteration_count { // When mint the first part of the budget, it should be fine. - prop_assert_ok!(Mosaic::timelocked_mint(Origin::relayer(), asset_id, account_a, first_part, 0, Default::default())); + prop_assert_ok!(Mosaic::timelocked_mint(Origin::relayer(), network_id, remote_asset_id, account_a, first_part, 0, Default::default())); // The new penalised_budget should be budget - first_part. // When we mint the second part of the budget, it should be fine because it matches the penalised_budget. - prop_assert_ok!(Mosaic::timelocked_mint(Origin::relayer(), asset_id, account_a, second_part, 0, Default::default())); + prop_assert_ok!(Mosaic::timelocked_mint(Origin::relayer(), network_id, remote_asset_id, account_a, second_part, 0, Default::default())); // When we mint more than the penalised budget, it should fail. - prop_assert_noop!(Mosaic::timelocked_mint(Origin::relayer(), asset_id, account_a, 1, 0, Default::default()), Error::::InsufficientBudget); + prop_assert_noop!(Mosaic::timelocked_mint(Origin::relayer(), network_id, remote_asset_id, account_a, 1, 0, Default::default()), Error::::InsufficientBudget); // We wait until the budget has recovered @@ -956,7 +763,13 @@ mod rescind_timelocked_mint { new_test_ext().execute_with(|| { initialize(); assert_noop!( - Mosaic::rescind_timelocked_mint(Origin::relayer(), 1, ALICE, 50), + Mosaic::rescind_timelocked_mint( + Origin::relayer(), + NETWORK_ID, + REMOTE_ASSET_ID, + ALICE, + 50 + ), Error::::NoClaimableTx ); }) @@ -967,9 +780,22 @@ mod rescind_timelocked_mint { new_test_ext().execute_with(|| { initialize(); let lock_time = 10; - do_timelocked_mint(ALICE, 1, 50, lock_time); + do_timelocked_mint(ALICE, 50, lock_time); + let another_remote_asset_id = [0xFFu8; 20]; + assert_ok!(Mosaic::update_asset_mapping( + Origin::root(), + 0xCAFEBABE, + NETWORK_ID, + Some(another_remote_asset_id) + )); assert_noop!( - Mosaic::rescind_timelocked_mint(Origin::relayer(), 2, ALICE, 50), + Mosaic::rescind_timelocked_mint( + Origin::relayer(), + NETWORK_ID, + another_remote_asset_id, + ALICE, + 50 + ), Error::::NoClaimableTx ); }) @@ -980,9 +806,15 @@ mod rescind_timelocked_mint { new_test_ext().execute_with(|| { initialize(); let lock_time = 10; - do_timelocked_mint(ALICE, 1, 50, lock_time); + do_timelocked_mint(ALICE, 50, lock_time); assert_noop!( - Mosaic::rescind_timelocked_mint(Origin::relayer(), 1, BOB, 50), + Mosaic::rescind_timelocked_mint( + Origin::relayer(), + NETWORK_ID, + REMOTE_ASSET_ID, + BOB, + 50 + ), Error::::NoClaimableTx ); }) @@ -994,9 +826,15 @@ mod rescind_timelocked_mint { initialize(); let lock_time = 10; let amount = 50; - do_timelocked_mint(ALICE, 1, amount, lock_time); + do_timelocked_mint(ALICE, amount, lock_time); assert_noop!( - Mosaic::rescind_timelocked_mint(Origin::relayer(), 1, ALICE, amount + 1), + Mosaic::rescind_timelocked_mint( + Origin::relayer(), + NETWORK_ID, + REMOTE_ASSET_ID, + ALICE, + amount + 1 + ), TokenError::NoFunds ); }) @@ -1008,27 +846,32 @@ mod rescind_timelocked_mint { initialize(); let lock_time = 10; let start_amount = 50; - do_timelocked_mint(ALICE, 1, start_amount, lock_time); + do_timelocked_mint(ALICE, start_amount, lock_time); assert_eq!( Mosaic::incoming_transactions(ALICE, 1), Some((start_amount, lock_time + System::block_number())) ); let rescind_amount = 9; - Mosaic::rescind_timelocked_mint(Origin::relayer(), 1, ALICE, rescind_amount) - .expect("relayer should be able to rescind transactions"); + assert_ok!(Mosaic::rescind_timelocked_mint( + Origin::relayer(), + NETWORK_ID, + REMOTE_ASSET_ID, + ALICE, + rescind_amount + )); assert_eq!( Mosaic::incoming_transactions(ALICE, 1), Some((start_amount - rescind_amount, lock_time + System::block_number())) ); - Mosaic::rescind_timelocked_mint( + assert_ok!(Mosaic::rescind_timelocked_mint( Origin::relayer(), - 1, + NETWORK_ID, + REMOTE_ASSET_ID, ALICE, start_amount - rescind_amount, - ) - .expect("relayer should be able to rescind transactions"); + )); assert_eq!(Mosaic::incoming_transactions(ALICE, 1), None); }) @@ -1041,8 +884,10 @@ mod set_timelock_duration { #[test] fn set_timelock_duration() { new_test_ext().execute_with(|| { - Mosaic::set_timelock_duration(Origin::root(), MinimumTimeLockPeriod::get() + 1) - .expect("root may set the timelock period"); + assert_ok!(Mosaic::set_timelock_duration( + Origin::root(), + Validated::new(MinimumTimeLockPeriod::get() + 1).unwrap() + )); }) } @@ -1052,7 +897,7 @@ mod set_timelock_duration { assert_noop!( Mosaic::set_timelock_duration( Origin::signed(ALICE), - MinimumTimeLockPeriod::get() + 1 + Validated::new(MinimumTimeLockPeriod::get() + 1).unwrap() ), DispatchError::BadOrigin ); @@ -1063,31 +908,14 @@ mod set_timelock_duration { fn set_timelock_duration_with_origin_none() { new_test_ext().execute_with(|| { assert_noop!( - Mosaic::set_timelock_duration(Origin::none(), MinimumTimeLockPeriod::get() + 1), + Mosaic::set_timelock_duration( + Origin::none(), + Validated::new(MinimumTimeLockPeriod::get() + 1).unwrap() + ), DispatchError::BadOrigin ); }) } - - #[test] - fn set_timelock_duration_with_invalid_period() { - new_test_ext().execute_with(|| { - assert_noop!( - Mosaic::set_timelock_duration(Origin::root(), 0), - Error::::BadTimelockPeriod - ); - }) - } - - #[test] - fn set_timelock_duration_with_invalid_period_2() { - new_test_ext().execute_with(|| { - assert_noop!( - Mosaic::set_timelock_duration(Origin::root(), MinimumTimeLockPeriod::get() - 1), - Error::::BadTimelockPeriod - ); - }) - } } mod transfer_to { @@ -1106,8 +934,13 @@ mod transfer_to { new_test_ext().execute_with(|| { initialize(); do_transfer_to(); - Mosaic::accept_transfer(Origin::relayer(), ALICE, 1, 100) - .expect("accepting transfer should work"); + assert_ok!(Mosaic::accept_transfer( + Origin::relayer(), + ALICE, + NETWORK_ID, + REMOTE_ASSET_ID, + 100 + )); }) } @@ -1117,7 +950,7 @@ mod transfer_to { initialize(); do_transfer_to(); assert_noop!( - Mosaic::accept_transfer(Origin::relayer(), ALICE, 1, 101), + Mosaic::accept_transfer(Origin::relayer(), ALICE, NETWORK_ID, REMOTE_ASSET_ID, 101), Error::::AmountMismatch ); }) @@ -1130,8 +963,7 @@ mod transfer_to { do_transfer_to(); let current_block = System::block_number(); System::set_block_number(current_block + Mosaic::timelock_period() + 1); - Mosaic::claim_stale_to(Origin::signed(ALICE), 1, ALICE) - .expect("claiming an outgoing transaction should work after the timelock period"); + assert_ok!(Mosaic::claim_stale_to(Origin::signed(ALICE), 1, ALICE)); }) } @@ -1154,7 +986,13 @@ mod transfer_to { new_test_ext().execute_with(|| { initialize(); do_transfer_to(); - assert_ok!(Mosaic::accept_transfer(Origin::relayer(), ALICE, 1, 100)); + assert_ok!(Mosaic::accept_transfer( + Origin::relayer(), + ALICE, + NETWORK_ID, + REMOTE_ASSET_ID, + 100 + )); let current_block = System::block_number(); System::set_block_number(current_block + Mosaic::timelock_period() + 1); assert_noop!( @@ -1173,7 +1011,7 @@ mod transfer_to { System::set_block_number(current_block + Mosaic::timelock_period() + 1); assert_ok!(Mosaic::claim_stale_to(Origin::signed(ALICE), 1, ALICE)); assert_noop!( - Mosaic::accept_transfer(Origin::relayer(), ALICE, 1, 100), + Mosaic::accept_transfer(Origin::relayer(), ALICE, NETWORK_ID, REMOTE_ASSET_ID, 100), Error::::NoOutgoingTx ); }) @@ -1186,15 +1024,69 @@ mod transfer_to { do_transfer_to(); let current_block = System::block_number(); System::set_block_number(current_block + Mosaic::timelock_period() + 1); - assert_ok!(Mosaic::accept_transfer(Origin::relayer(), ALICE, 1, 20)); + assert_ok!(Mosaic::accept_transfer( + Origin::relayer(), + ALICE, + NETWORK_ID, + REMOTE_ASSET_ID, + 20 + )); // System::set_block_number(current_block + Mosaic::timelock_period() + 1); assert_ok!(Mosaic::claim_stale_to(Origin::signed(ALICE), 1, ALICE)); }) } + #[test] + fn transfer_to_below_min_transfer_size() { + ExtBuilder { balances: Default::default() }.build().execute_with(|| { + let min_transfer_size = 1000; + let max_transfer_size = 100000; + + assert_ok!(Mosaic::set_relayer(Origin::root(), RELAYER)); + + let network_id = 1; + assert_ok!(Mosaic::set_network( + Origin::relayer(), + network_id, + NetworkInfo { enabled: true, min_transfer_size, max_transfer_size }, + )); + + let asset_id: u128 = 1; + assert_ok!(Mosaic::set_budget( + Origin::root(), + asset_id, + 10000, + BudgetPenaltyDecayer::linear(10) + )); + + let remote_asset_id = [0xFFu8; 20]; + assert_ok!(Mosaic::update_asset_mapping( + Origin::root(), + asset_id, + network_id, + Some(remote_asset_id) + )); + + let amount = min_transfer_size - 1; + assert_ok!(Tokens::mint_into(asset_id, &ALICE, amount)); + assert_noop!( + Mosaic::transfer_to( + Origin::signed(ALICE), + network_id, + asset_id, + [0; 20], + amount, + true + ), + Error::::BelowMinTransferSize + ); + }) + } + #[test] fn transfer_to_exceeds_max_transfer_size() { ExtBuilder { balances: Default::default() }.build().execute_with(|| { + let min_transfer_size = 1; let max_transfer_size = 100000; assert_ok!(Mosaic::set_relayer(Origin::root(), RELAYER)); @@ -1203,7 +1095,7 @@ mod transfer_to { assert_ok!(Mosaic::set_network( Origin::relayer(), network_id, - NetworkInfo { enabled: true, max_transfer_size }, + NetworkInfo { enabled: true, min_transfer_size, max_transfer_size }, )); let asset_id: u128 = 1; @@ -1214,6 +1106,14 @@ mod transfer_to { BudgetPenaltyDecayer::linear(10) )); + let remote_asset_id = [0xFFu8; 20]; + assert_ok!(Mosaic::update_asset_mapping( + Origin::root(), + asset_id, + network_id, + Some(remote_asset_id) + )); + // We exceed the max transfer size let amount = max_transfer_size + 1; assert_ok!(Tokens::mint_into(asset_id, &ALICE, amount)); @@ -1267,7 +1167,7 @@ mod transfer_to { assert_ok!(Mosaic::set_network( Origin::relayer(), 1, - NetworkInfo { enabled: true, max_transfer_size: 100000 }, + NetworkInfo { enabled: true, min_transfer_size: 1, max_transfer_size: 100000 }, )); // We don't register the asset @@ -1294,20 +1194,17 @@ mod transfer_to { fn do_transfer_to() { let ethereum_address = [0; 20]; let amount = 100; - let network_id = 1; - let asset_id: u128 = 1; - Mosaic::transfer_to( + assert_ok!(Mosaic::transfer_to( Origin::signed(ALICE), - network_id, - asset_id, + NETWORK_ID, + ASSET_ID, ethereum_address, amount, true, - ) - .expect("transfer_to should work"); + )); assert_eq!( - Mosaic::outgoing_transactions(&ALICE, 1), + Mosaic::outgoing_transactions(&ALICE, ASSET_ID), Some((100, MinimumTimeLockPeriod::get() + System::block_number())) ); @@ -1325,8 +1222,8 @@ mod transfer_to { let id = generate_id::( &ALICE, - &network_id, - &asset_id, + &NETWORK_ID, + &ASSET_ID, ðereum_address, &amount, &System::block_number(), @@ -1339,8 +1236,10 @@ mod transfer_to { System::assert_last_event(mock::Event::Mosaic(crate::Event::TransferOut { id, to: ethereum_address, + asset_id: ASSET_ID, + network_id: NETWORK_ID, + remote_asset_id: REMOTE_ASSET_ID, amount, - network_id, })); } } @@ -1349,30 +1248,19 @@ mod accept_transfer { use super::*; #[test] - fn cannot_mint_unsupported_assets() { + fn cannot_mint_more_than_budget() { new_test_ext().execute_with(|| { initialize(); - let unsupported_asset_id: u128 = 42; assert_noop!( Mosaic::timelocked_mint( Origin::relayer(), - unsupported_asset_id, + NETWORK_ID, + REMOTE_ASSET_ID, ALICE, - 50, + 10001, 10, Default::default() ), - Error::::UnsupportedAsset - ); - }) - } - - #[test] - fn cannot_mint_more_than_budget() { - new_test_ext().execute_with(|| { - initialize(); - assert_noop!( - Mosaic::timelocked_mint(Origin::relayer(), 1, ALICE, 10001, 10, Default::default()), Error::::InsufficientBudget ); }) @@ -1383,36 +1271,106 @@ mod accept_transfer { new_test_ext().execute_with(|| { initialize(); let lock_time = 10; - do_timelocked_mint(ALICE, 1, 50, lock_time); + do_timelocked_mint(ALICE, 50, lock_time); let initial_block = System::block_number(); - Mosaic::rescind_timelocked_mint(Origin::relayer(), 1, ALICE, 40) - .expect("relayer should be able to rescind transactions"); + assert_ok!(Mosaic::rescind_timelocked_mint( + Origin::relayer(), + NETWORK_ID, + REMOTE_ASSET_ID, + ALICE, + 40 + )); assert_eq!( Mosaic::incoming_transactions(ALICE, 1), Some((10, initial_block + lock_time)) ); let transfer_amount = 9; - Mosaic::rescind_timelocked_mint(Origin::relayer(), 1, ALICE, transfer_amount) - .expect("relayer should be able to rescind transactions"); + assert_ok!(Mosaic::rescind_timelocked_mint( + Origin::relayer(), + NETWORK_ID, + REMOTE_ASSET_ID, + ALICE, + transfer_amount + )); assert_eq!(Mosaic::incoming_transactions(ALICE, 1), Some((1, 11))); }) } } -#[test] -fn claim_to() { - new_test_ext().execute_with(|| { - initialize(); - let lock_time = 10; - do_timelocked_mint(ALICE, 1, 50, lock_time); - let current_block = System::block_number(); - Mosaic::claim_to(Origin::alice(), 1, ALICE).expect_err( - "received funds should only be claimable after waiting for the relayer mandated time", +mod claim_to { + use super::*; + + #[test] + fn claim_to() { + new_test_ext().execute_with(|| { + initialize(); + let lock_time = 10; + do_timelocked_mint(ALICE, 50, lock_time); + let current_block = System::block_number(); + assert_noop!(Mosaic::claim_to(Origin::alice(), 1, ALICE), Error::::TxStillLocked); + System::set_block_number(current_block + lock_time + 1); + assert_ok!(Mosaic::claim_to(Origin::alice(), 1, ALICE)); + }) + } +} + +#[cfg(test)] +mod test_validation { + use super::*; + use composable_support::validation::Validate; + use frame_support::assert_ok; + use validation::{ValidTTL, ValidTimeLockPeriod}; + + #[test] + fn set_ttl_with_invalid_period() { + assert!( as Validate>>::validate( + 0_u64 + ) + .is_err()); + } + + #[test] + fn set_ttl_with_invalid_period_3() { + assert!( as Validate>>::validate( + MinimumTTL::get() - 1 + ) + .is_err()); + } + + #[test] + fn set_ttl_period_3() { + assert_ok!( + as Validate>>::validate( + MinimumTTL::get() + 1 + ) ); - System::set_block_number(current_block + lock_time + 1); - Mosaic::claim_to(Origin::alice(), 1, ALICE) - .expect("received funds should be claimable after time has passed"); - }) + } + + #[test] + fn set_timelock_duration_with_invalid_period() { + assert!( as Validate< + BlockNumber, + ValidTimeLockPeriod, + >>::validate(0_u64) + .is_err()); + } + + #[test] + fn set_timelock_duration_with_invalid_period_2() { + assert!( as Validate< + BlockNumber, + ValidTimeLockPeriod, + >>::validate(MinimumTimeLockPeriod::get() - 1) + .is_err()); + } + + #[test] + fn set_timelock_duration_with_invalid_period_3() { + assert_ok!( as Validate< + BlockNumber, + ValidTimeLockPeriod, + >>::validate(MinimumTimeLockPeriod::get() + 1)); + } } diff --git a/frame/mosaic/src/validation.rs b/frame/mosaic/src/validation.rs new file mode 100644 index 00000000000..a45fb0061f8 --- /dev/null +++ b/frame/mosaic/src/validation.rs @@ -0,0 +1,54 @@ +use composable_support::validation::Validate; +use frame_support::{pallet_prelude::*, traits::Get}; + +#[derive(Debug, Decode)] +pub struct ValidTTL { + _marker: PhantomData, +} + +impl Copy for ValidTTL {} + +impl Clone for ValidTTL { + fn clone(&self) -> Self { + *self + } +} + +#[derive(Debug, Decode)] +pub struct ValidTimeLockPeriod { + _marker: PhantomData, +} + +impl Copy for ValidTimeLockPeriod {} + +impl Clone for ValidTimeLockPeriod { + fn clone(&self) -> Self { + *self + } +} + +impl Validate> for ValidTTL +where + MinimumTTL: Get, +{ + fn validate(input: TTL) -> Result { + if input <= MinimumTTL::get() { + return Err("TTL_BELOW_MINIMUM") + } + Ok(input) + } +} + +impl + Validate> + for ValidTimeLockPeriod +where + MinimumTimeLockPeriod: Get, +{ + fn validate(input: TimeLockPeriod) -> Result { + if input <= MinimumTimeLockPeriod::get() { + return Err("TIME_LOCK_PERIOD_BELOW_MINIMUM") + } + Ok(input) + } +} diff --git a/frame/mosaic/src/weights.rs b/frame/mosaic/src/weights.rs index 174027f35f8..b0407e06f9d 100644 --- a/frame/mosaic/src/weights.rs +++ b/frame/mosaic/src/weights.rs @@ -18,51 +18,56 @@ pub trait WeightInfo { fn set_timelock_duration() -> Weight; fn rescind_timelocked_mint() -> Weight; fn claim_to() -> Weight; + fn update_asset_mapping() -> Weight; } // For backwards compatibility and tests impl WeightInfo for () { - fn set_relayer() -> Weight { - 10_000 as Weight - } + fn set_relayer() -> Weight { + 10_000 as Weight + } - fn rotate_relayer() -> Weight { - 10_000 as Weight - } + fn rotate_relayer() -> Weight { + 10_000 as Weight + } - fn set_network() -> Weight { - 10_000 as Weight - } + fn set_network() -> Weight { + 10_000 as Weight + } - fn set_budget() -> Weight { - 10_000 as Weight - } + fn set_budget() -> Weight { + 10_000 as Weight + } - fn transfer_to() -> Weight { - 10_000 as Weight - } + fn transfer_to() -> Weight { + 10_000 as Weight + } - fn accept_transfer() -> Weight { - 10_000 as Weight - } + fn accept_transfer() -> Weight { + 10_000 as Weight + } - fn claim_stale_to() -> Weight { - 10_000 as Weight - } + fn claim_stale_to() -> Weight { + 10_000 as Weight + } - fn timelocked_mint() -> Weight { - 10_000 as Weight - } + fn timelocked_mint() -> Weight { + 10_000 as Weight + } - fn set_timelock_duration() -> Weight { - 10_000 as Weight - } + fn set_timelock_duration() -> Weight { + 10_000 as Weight + } - fn rescind_timelocked_mint() -> Weight { - 10_000 as Weight - } + fn rescind_timelocked_mint() -> Weight { + 10_000 as Weight + } - fn claim_to() -> Weight { - 10_000 as Weight - } + fn claim_to() -> Weight { + 10_000 as Weight + } + + fn update_asset_mapping() -> Weight { + 10_000 as Weight + } } diff --git a/frame/oracle/Cargo.toml b/frame/oracle/Cargo.toml index 1fee981e595..73a054d7cf3 100644 --- a/frame/oracle/Cargo.toml +++ b/frame/oracle/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "pallet-oracle" -version = "1.0.0" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" +homepage = "https://composable.finance" +name = "pallet-oracle" +version = "1.0.0" [package.metadata.docs.rs] @@ -17,46 +17,51 @@ package = "parity-scale-codec" version = "2.0.0" [dependencies] -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -log = { version = "0.4.14", default-features = false } lite-json = { version = "0.1", default-features = false } -serde_json = { version = "1.0.45", default-features = false, features = ["alloc"] } +log = { version = "0.4.14", default-features = false } +serde_json = { version = "1.0.45", default-features = false, features = [ + "alloc", +] } -frame-benchmarking = { default-features = false, optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.16' } +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +composable-support = { path = "../composable-support", default-features = false } composable-traits = { path = "../composable-traits", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } [dev-dependencies] -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } parking_lot = "0.11.2" serde = "1.0.130" -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } [features] default = ["std"] std = [ - "codec/std", - "log/std", - "lite-json/std", - "frame-support/std", - "frame-system/std", - "sp-runtime/std", - "sp-io/std", - "sp-core/std", - "sp-std/std", - "scale-info/std", + "codec/std", + "log/std", + "lite-json/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-io/std", + "sp-core/std", + "sp-std/std", + "scale-info/std", ] runtime-benchmarks = [ - 'frame-benchmarking', - 'frame-support/runtime-benchmarks', - 'frame-system/runtime-benchmarks', + 'frame-benchmarking', + 'frame-support/runtime-benchmarks', + 'frame-system/runtime-benchmarks', ] diff --git a/frame/oracle/src/benchmarking.rs b/frame/oracle/src/benchmarking.rs index d33b46d79ef..2bf51c82eed 100644 --- a/frame/oracle/src/benchmarking.rs +++ b/frame/oracle/src/benchmarking.rs @@ -1,7 +1,10 @@ use super::*; +use crate::validation::ValidBlockInterval; #[allow(unused)] use crate::Pallet as Oracle; +use composable_support::validation::Validated; +use composable_traits::oracle::Price; use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller}; use frame_support::{ assert_ok, @@ -10,6 +13,7 @@ use frame_support::{ }; use frame_system::{EventRecord, RawOrigin}; use sp_runtime::{DispatchResult, Percent}; + use sp_std::{prelude::*, vec}; pub type BalanceOf = @@ -37,10 +41,10 @@ benchmarks! { add_asset_and_info { let caller = T::AddOracle::successful_origin(); let asset_id = 1; - let threshold = Percent::from_percent(80); - let min_answers = 3; - let max_answers = 5; - let block_interval: T::BlockNumber = 5u32.into(); + let threshold = Validated::new(Percent::from_percent(80)).unwrap(); + let min_answers = Validated::new(3).unwrap(); + let max_answers = Validated::new(5).unwrap(); + let block_interval = Validated::>::new(T::StalePrice::get() + 1u32.into()).unwrap(); let reward: BalanceOf = T::Currency::minimum_balance(); let slash: BalanceOf = T::Currency::minimum_balance(); @@ -50,7 +54,7 @@ benchmarks! { ); } verify { - assert_last_event::(Event::AssetInfoChange(asset_id.into(), threshold, min_answers, max_answers, block_interval, reward, slash).into()); + assert_last_event::(Event::AssetInfoChange(asset_id.into(), *threshold, *min_answers, *max_answers, *block_interval, reward, slash).into()); } set_signer { @@ -141,7 +145,7 @@ benchmarks! { threshold: Percent::from_percent(80), min_answers: 1, max_answers: p, - block_interval: 5u32.into(), + block_interval: T::StalePrice::get(), reward: T::Currency::minimum_balance(), slash: T::Currency::minimum_balance() }; @@ -167,7 +171,7 @@ benchmarks! { threshold: Percent::from_percent(80), min_answers: 1, max_answers: p, - block_interval: 5u32.into(), + block_interval: T::StalePrice::get(), reward: T::Currency::minimum_balance(), slash: T::Currency::minimum_balance() }; diff --git a/frame/oracle/src/lib.rs b/frame/oracle/src/lib.rs index 5dfb21f3036..510f7d7c8ce 100644 --- a/frame/oracle/src/lib.rs +++ b/frame/oracle/src/lib.rs @@ -15,6 +15,8 @@ #![allow(clippy::too_many_arguments)] pub use pallet::*; +mod validation; + #[cfg(test)] mod mock; @@ -27,12 +29,14 @@ pub mod weights; #[frame_support::pallet] pub mod pallet { + use crate::validation::{ValidBlockInterval, ValidMaxAnswer, ValidMinAnswers, ValidThreshhold}; pub use crate::weights::WeightInfo; use codec::{Codec, FullCodec}; + use composable_support::validation::Validated; use composable_traits::{ currency::LocalAssets, - math::SafeArithmetic, - oracle::{Oracle, Price as LastPrice}, + math::SafeDiv, + oracle::{Oracle, Price}, }; use core::ops::{Div, Mul}; use frame_support::{ @@ -53,7 +57,6 @@ pub mod pallet { pallet_prelude::*, Config as SystemConfig, }; - use lite_json::json::JsonValue; use scale_info::TypeInfo; use sp_core::crypto::KeyTypeId; @@ -169,14 +172,6 @@ pub mod pallet { pub who: AccountId, } - // block timestamped value - #[derive(Encode, Decode, MaxEncodedLen, Default, Debug, PartialEq, TypeInfo, Clone)] - pub struct Price { - /// value - pub price: PriceValue, - pub block: BlockNumber, - } - #[derive(Encode, Decode, MaxEncodedLen, Default, Debug, PartialEq, Clone, TypeInfo)] pub struct AssetInfo { pub threshold: Percent, @@ -384,11 +379,12 @@ pub mod pallet { type AssetId = T::AssetId; type Timestamp = ::BlockNumber; type LocalAssets = T::LocalAssets; + type MaxAnswerBound = T::MaxAnswerBound; fn get_price( asset_id: Self::AssetId, amount: Self::Balance, - ) -> Result, DispatchError> { + ) -> Result, DispatchError> { let Price { price, block } = Prices::::try_get(asset_id).map_err(|_| Error::::PriceNotFound)?; let unit = 10_u128 @@ -399,7 +395,7 @@ pub mod pallet { let price = price .try_into() .map_err(|_| DispatchError::Arithmetic(ArithmeticError::Overflow))?; - Ok(LastPrice { price, block }) + Ok(Price { price, block }) } fn get_twap( @@ -420,6 +416,7 @@ pub mod pallet { Self::get_price(pair.quote, (10 ^ T::LocalAssets::decimals(pair.base)?).into())? .price .into(); + let base = FixedU128::saturating_from_integer(base); let quote = FixedU128::saturating_from_integer(quote); Ok(base.safe_div("e)?) @@ -436,6 +433,7 @@ pub mod pallet { // so we need 2_500 asset amount to pay for 10 normalized let unit = 10 ^ (T::LocalAssets::decimals(asset_id))?; let price_asset_for_unit: u128 = Self::get_price(asset_id, unit.into())?.price.into(); + let amount: u128 = amount.into(); let result = multiply_by_rational(amount, unit as u128, price_asset_for_unit)?; let result: u64 = result @@ -463,25 +461,30 @@ pub mod pallet { pub fn add_asset_and_info( origin: OriginFor, asset_id: T::AssetId, - threshold: Percent, - min_answers: u32, - max_answers: u32, - block_interval: T::BlockNumber, + threshold: Validated, + min_answers: Validated, + max_answers: Validated>, + block_interval: Validated>, reward: BalanceOf, slash: BalanceOf, ) -> DispatchResultWithPostInfo { T::AddOracle::ensure_origin(origin)?; - ensure!(min_answers > 0, Error::::InvalidMinAnswers); - ensure!(max_answers >= min_answers, Error::::MaxAnswersLessThanMinAnswers); - ensure!(threshold < Percent::from_percent(100), Error::::ExceedThreshold); - ensure!(max_answers <= T::MaxAnswerBound::get(), Error::::ExceedMaxAnswers); - ensure!(block_interval > T::StalePrice::get(), Error::::BlockIntervalLength); + + ensure!(*max_answers >= *min_answers, Error::::MaxAnswersLessThanMinAnswers); + ensure!( AssetsCount::::get() < T::MaxAssetsCount::get(), Error::::ExceedAssetsCount ); - let asset_info = - AssetInfo { threshold, min_answers, max_answers, block_interval, reward, slash }; + + let asset_info = AssetInfo { + threshold: *threshold, + min_answers: *min_answers, + max_answers: *max_answers, + block_interval: *block_interval, + reward, + slash, + }; let current_asset_info = Self::asset_info(asset_id); if current_asset_info.is_none() { @@ -491,10 +494,10 @@ pub mod pallet { AssetsInfo::::insert(asset_id, asset_info); Self::deposit_event(Event::AssetInfoChange( asset_id, - threshold, - min_answers, - max_answers, - block_interval, + *threshold, + *min_answers, + *max_answers, + *block_interval, reward, slash, )); diff --git a/frame/oracle/src/mock.rs b/frame/oracle/src/mock.rs index bab2132f1de..1748dd0846f 100644 --- a/frame/oracle/src/mock.rs +++ b/frame/oracle/src/mock.rs @@ -29,6 +29,10 @@ frame_support::construct_runtime!( } ); +pub type BlockNumber = u64; + +// pub type StalePrice = Get; + parameter_types! { pub const BlockHashCount: u64 = 250; pub const SS58Prefix: u8 = 42; diff --git a/frame/oracle/src/tests.rs b/frame/oracle/src/tests.rs index 93c3a4b565c..4e6074dff0e 100644 --- a/frame/oracle/src/tests.rs +++ b/frame/oracle/src/tests.rs @@ -1,9 +1,9 @@ use crate::{ mock::{AccountId, Call, Extrinsic, *}, - AssetInfo, Error, PrePrice, Price, Withdraw, *, + AssetInfo, Error, PrePrice, Withdraw, *, }; use codec::Decode; -use composable_traits::defi::CurrencyPair; +use composable_traits::{defi::CurrencyPair, oracle::Price}; use frame_support::{ assert_noop, assert_ok, traits::{Currency, OnInitialize}, @@ -20,6 +20,9 @@ use sp_runtime::{ }; use std::sync::Arc; +use crate::validation::{ValidBlockInterval, ValidMaxAnswer, ValidMinAnswers, ValidThreshhold}; +use composable_support::validation::{Validate, Validated}; +use core::{fmt, marker::PhantomData}; #[test] fn add_asset_and_info() { new_test_ext().execute_with(|| { @@ -31,15 +34,14 @@ fn add_asset_and_info() { const REWARD: u64 = 5; const SLASH: u64 = 5; - // passes let account_2 = get_account_2(); assert_ok!(Oracle::add_asset_and_info( Origin::signed(account_2), ASSET_ID, - THRESHOLD, - MIN_ANSWERS, - MAX_ANSWERS, - BLOCK_INTERVAL, + Validated::new(THRESHOLD).unwrap(), + Validated::new(MIN_ANSWERS).unwrap(), + Validated::new(MAX_ANSWERS).unwrap(), + Validated::>::new(BLOCK_INTERVAL).unwrap(), REWARD, SLASH )); @@ -48,10 +50,10 @@ fn add_asset_and_info() { assert_ok!(Oracle::add_asset_and_info( Origin::signed(account_2), ASSET_ID, - THRESHOLD, - MIN_ANSWERS, - MAX_ANSWERS, - BLOCK_INTERVAL, + Validated::new(THRESHOLD).unwrap(), + Validated::new(MIN_ANSWERS).unwrap(), + Validated::new(MAX_ANSWERS).unwrap(), + Validated::>::new(BLOCK_INTERVAL).unwrap(), REWARD, SLASH )); @@ -60,10 +62,10 @@ fn add_asset_and_info() { assert_ok!(Oracle::add_asset_and_info( Origin::signed(account_2), ASSET_ID + 1, - THRESHOLD, - MIN_ANSWERS, - MAX_ANSWERS, - BLOCK_INTERVAL, + Validated::new(THRESHOLD).unwrap(), + Validated::new(MIN_ANSWERS).unwrap(), + Validated::new(MAX_ANSWERS).unwrap(), + Validated::>::new(BLOCK_INTERVAL).unwrap(), REWARD, SLASH )); @@ -76,6 +78,7 @@ fn add_asset_and_info() { reward: REWARD, slash: SLASH, }; + // id now activated and count incremented assert_eq!(Oracle::asset_info(1), Some(asset_info)); assert_eq!(Oracle::assets_count(), 2); @@ -86,10 +89,11 @@ fn add_asset_and_info() { Oracle::add_asset_and_info( Origin::signed(account_1), ASSET_ID, - THRESHOLD, - MAX_ANSWERS, - MAX_ANSWERS, - BLOCK_INTERVAL, + Validated::new(THRESHOLD).unwrap(), + Validated::new(MIN_ANSWERS).unwrap(), + Validated::new(MAX_ANSWERS).unwrap(), + Validated::>::new(BLOCK_INTERVAL) + .unwrap(), REWARD, SLASH ), @@ -100,85 +104,31 @@ fn add_asset_and_info() { Oracle::add_asset_and_info( Origin::signed(account_2), ASSET_ID, - THRESHOLD, - MAX_ANSWERS, - MIN_ANSWERS, - BLOCK_INTERVAL, - REWARD, - SLASH - ), - Error::::MaxAnswersLessThanMinAnswers - ); - - assert_noop!( - Oracle::add_asset_and_info( - Origin::signed(account_2), - ASSET_ID, - Percent::from_percent(100), - MIN_ANSWERS, - MAX_ANSWERS, - BLOCK_INTERVAL, - REWARD, - SLASH - ), - Error::::ExceedThreshold - ); - - assert_noop!( - Oracle::add_asset_and_info( - Origin::signed(account_2), - ASSET_ID, - THRESHOLD, - MIN_ANSWERS, - MAX_ANSWERS + 1, - BLOCK_INTERVAL, - REWARD, - SLASH - ), - Error::::ExceedMaxAnswers - ); - - assert_noop!( - Oracle::add_asset_and_info( - Origin::signed(account_2), - ASSET_ID, - THRESHOLD, - 0, - MAX_ANSWERS, - BLOCK_INTERVAL, + Validated::new(THRESHOLD).unwrap(), + Validated::new(MIN_ANSWERS).unwrap(), + Validated::new(MAX_ANSWERS).unwrap(), + Validated::>::new(BLOCK_INTERVAL) + .unwrap(), REWARD, SLASH ), - Error::::InvalidMinAnswers + Error::::ExceedAssetsCount ); assert_noop!( Oracle::add_asset_and_info( Origin::signed(account_2), ASSET_ID + 2, - THRESHOLD, - MIN_ANSWERS, - MAX_ANSWERS, - BLOCK_INTERVAL, + Validated::new(THRESHOLD).unwrap(), + Validated::new(MIN_ANSWERS).unwrap(), + Validated::new(MAX_ANSWERS).unwrap(), + Validated::>::new(BLOCK_INTERVAL) + .unwrap(), REWARD, SLASH ), Error::::ExceedAssetsCount ); - - assert_noop!( - Oracle::add_asset_and_info( - Origin::signed(account_2), - ASSET_ID, - THRESHOLD, - MIN_ANSWERS, - MAX_ANSWERS, - BLOCK_INTERVAL - 4, - REWARD, - SLASH - ), - Error::::BlockIntervalLength - ); }); } @@ -300,10 +250,10 @@ fn add_price() { assert_ok!(Oracle::add_asset_and_info( Origin::signed(account_2), 0, - Percent::from_percent(80), - 3, - 3, - 5, + Validated::new(Percent::from_percent(80)).unwrap(), + Validated::new(3).unwrap(), + Validated::new(3).unwrap(), + Validated::>::new(5).unwrap(), 5, 5 )); @@ -389,10 +339,10 @@ fn check_request() { assert_ok!(Oracle::add_asset_and_info( Origin::signed(account_2), 0, - Percent::from_percent(80), - 3, - 5, - 5, + Validated::new(Percent::from_percent(80)).unwrap(), + Validated::new(3).unwrap(), + Validated::new(5).unwrap(), + Validated::>::new(5).unwrap(), 5, 5 )); @@ -415,10 +365,10 @@ fn is_requested() { assert_ok!(Oracle::add_asset_and_info( Origin::signed(account_2), 0, - Percent::from_percent(80), - 3, - 5, - 5, + Validated::new(Percent::from_percent(80)).unwrap(), + Validated::new(3).unwrap(), + Validated::new(5).unwrap(), + Validated::>::new(5).unwrap(), 5, 5 )); @@ -467,10 +417,10 @@ fn test_payout_slash() { assert_ok!(Oracle::add_asset_and_info( Origin::signed(account_2), 0, - Percent::from_percent(80), - 3, - 5, - 5, + Validated::new(Percent::from_percent(80)).unwrap(), + Validated::new(3).unwrap(), + Validated::new(5).unwrap(), + Validated::>::new(5).unwrap(), 5, 5 )); @@ -502,10 +452,10 @@ fn test_payout_slash() { assert_ok!(Oracle::add_asset_and_info( Origin::signed(account_2), 0, - Percent::from_percent(90), - 3, - 5, - 5, + Validated::new(Percent::from_percent(90)).unwrap(), + Validated::new(3).unwrap(), + Validated::new(5).unwrap(), + Validated::>::new(5).unwrap(), 4, 5 )); @@ -541,10 +491,10 @@ fn on_init() { assert_ok!(Oracle::add_asset_and_info( Origin::signed(account_2), 0, - Percent::from_percent(80), - 3, - 5, - 5, + Validated::new(Percent::from_percent(80)).unwrap(), + Validated::new(3).unwrap(), + Validated::new(5).unwrap(), + Validated::>::new(5).unwrap(), 5, 5 )); @@ -583,10 +533,10 @@ fn historic_pricing() { assert_ok!(Oracle::add_asset_and_info( Origin::signed(account_2), 0, - Percent::from_percent(80), - 3, - 5, - 5, + Validated::new(Percent::from_percent(80)).unwrap(), + Validated::new(3).unwrap(), + Validated::new(5).unwrap(), + Validated::>::new(5).unwrap(), 5, 5 )); @@ -644,6 +594,7 @@ fn price_of_amount() { assert_eq!(total_price.price, value * amount) }); } + #[test] fn ratio_human_case() { new_test_ext().execute_with(|| { @@ -702,10 +653,10 @@ fn get_twap() { assert_ok!(Oracle::add_asset_and_info( Origin::signed(account_2), 0, - Percent::from_percent(80), - 3, - 5, - 5, + Validated::new(Percent::from_percent(80)).unwrap(), + Validated::new(3).unwrap(), + Validated::new(5).unwrap(), + Validated::>::new(5).unwrap(), 5, 5 )); @@ -736,10 +687,10 @@ fn on_init_prune_scenerios() { assert_ok!(Oracle::add_asset_and_info( Origin::signed(account_2), 0, - Percent::from_percent(80), - 3, - 5, - 5, + Validated::new(Percent::from_percent(80)).unwrap(), + Validated::new(3).unwrap(), + Validated::new(5).unwrap(), + Validated::>::new(5).unwrap(), 5, 5 )); @@ -796,10 +747,10 @@ fn on_init_over_max_answers() { assert_ok!(Oracle::add_asset_and_info( Origin::signed(account_2), 0, - Percent::from_percent(80), - 1, - 2, - 5, + Validated::new(Percent::from_percent(80)).unwrap(), + Validated::new(1).unwrap(), + Validated::new(2).unwrap(), + Validated::>::new(5).unwrap(), 5, 5 )); @@ -898,10 +849,10 @@ fn should_submit_signed_transaction_on_chain() { assert_ok!(Oracle::add_asset_and_info( Origin::signed(account_2), 0, - Percent::from_percent(80), - 3, - 3, - 5, + Validated::new(Percent::from_percent(80)).unwrap(), + Validated::new(3).unwrap(), + Validated::new(5).unwrap(), + Validated::>::new(5).unwrap(), 5, 5 )); @@ -928,10 +879,10 @@ fn should_check_oracles_submitted_price() { assert_ok!(Oracle::add_asset_and_info( Origin::signed(account_2), 0, - Percent::from_percent(80), - 3, - 3, - 5, + Validated::new(Percent::from_percent(80)).unwrap(), + Validated::new(3).unwrap(), + Validated::new(5).unwrap(), + Validated::>::new(5).unwrap(), 5, 5 )); @@ -1037,3 +988,89 @@ fn offchain_worker_env( (t, pool_state) } + +#[cfg(test)] +mod test { + use super::*; + use composable_support::validation::Validate; + use frame_support::assert_ok; + use mock::Test; + use validation::{ValidBlockInterval, ValidMaxAnswer, ValidMinAnswers, ValidThreshhold}; + + #[test] + fn test_threshold_valid_case() { + assert_ok!(>::validate( + Percent::from_percent(99) + )); + } + + #[test] + fn test_threshold_invalid_case() { + assert!(>::validate( + Percent::from_percent(100) + ) + .is_err()); + + assert!(>::validate( + Percent::from_percent(110) + ) + .is_err()); + } + + #[test] + fn test_threshold() { + assert!(>::validate( + Percent::from_percent(100) + ) + .is_err()); + + assert!(>::validate( + Percent::from_percent(110) + ) + .is_err()); + } + + #[test] + fn test_max_answer_valid_case() { + assert_ok!( as Validate< + u32, + ValidMaxAnswer, + >>::validate(2_u32)); + } + + #[test] + fn test_max_answer_invalid_case() { + assert!( as Validate< + u32, + ValidMaxAnswer, + >>::validate(10_u32) + .is_err()); + } + + #[test] + fn test_min_answer_valid_case() { + assert!(>::validate(0_u32).is_err()); + } + + #[test] + fn test_min_answer_invalid_case() { + assert_ok!(>::validate(1_u32)); + } + + #[test] + fn test_block_interval_valid_case() { + assert_ok!( as Validate< + BlockNumber, + ValidBlockInterval, + >>::validate(100_u64)); + } + + #[test] + fn test_block_interval_invalid_case() { + assert!( as Validate< + BlockNumber, + ValidBlockInterval, + >>::validate(2_u64) + .is_err()); + } +} diff --git a/frame/oracle/src/validation.rs b/frame/oracle/src/validation.rs new file mode 100644 index 00000000000..ef46de50422 --- /dev/null +++ b/frame/oracle/src/validation.rs @@ -0,0 +1,103 @@ +use composable_support::validation::Validate; +use frame_support::{pallet_prelude::*, traits::Get}; +use scale_info::TypeInfo; +use sp_runtime::{traits::Zero, Percent}; + +#[derive(Debug, Decode, Copy, Clone, PartialEq, TypeInfo)] +pub struct ValidMinAnswers; + +#[derive(Debug, Copy, Clone, Decode, PartialEq, TypeInfo)] +pub struct ValidThreshhold; + +#[derive(Debug, Decode)] +pub struct ValidMaxAnswer { + pub m: PhantomData, +} + +impl Copy for ValidMaxAnswer {} + +impl Clone for ValidMaxAnswer { + fn clone(&self) -> Self { + *self + } +} + +#[derive(Debug, Decode)] +pub struct ValidBlockInterval { + pub m: PhantomData, +} + +impl Copy for ValidBlockInterval {} + +impl Clone for ValidBlockInterval { + fn clone(&self) -> Self { + *self + } +} + +#[derive(Debug, Decode)] +pub struct ValidAssetId { + u: PhantomData, +} + +impl Copy for ValidAssetId {} + +impl Clone for ValidAssetId { + fn clone(&self) -> Self { + *self + } +} + +#[derive(Debug, Decode)] +pub struct IsRequested; + +impl Validate + for ValidMinAnswers +{ + fn validate(input: MinAnswer) -> Result { + if input <= MinAnswer::zero() { + return Err("INVALID_MIN_ANSWERS") + } + + Ok(input) + } +} + +impl Validate for ValidThreshhold { + fn validate(input: Percent) -> Result { + if input >= Percent::from_percent(100) { + return Err("INVALID_THRESHOLD") + } + + Ok(input) + } +} + +impl + Validate> for ValidMaxAnswer +where + MaxAnswerBound: Get, +{ + fn validate(input: MaxAnswer) -> Result { + if input > MaxAnswerBound::get() { + return Err("INVALID_MAX_ANSWER") + } + + Ok(input) + } +} + +impl Validate> + for ValidBlockInterval +where + StalePrice: Get, + ValidBlockInterval: Decode, +{ + fn validate(input: BlockInterval) -> Result { + if input <= StalePrice::get() { + return Err("INVALID_BLOCK_INTERVAL_LENGTH") + } + + Ok(input) + } +} diff --git a/frame/pablo/Cargo.toml b/frame/pablo/Cargo.toml new file mode 100644 index 00000000000..ce5bb3cb852 --- /dev/null +++ b/frame/pablo/Cargo.toml @@ -0,0 +1,68 @@ +[package] +authors = ["Composable Developers"] +edition = "2021" +homepage = "https://composable.finance" +name = "pallet-pablo" +version = "0.0.1" + + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies.codec] +default-features = false +features = ["derive"] +package = "parity-scale-codec" +version = "2.0.0" + +[dependencies] +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } +sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } + +rust_decimal = { version = "1", default-features = false, features = ["maths"] } + +composable-maths = { path = "../composable-maths", default-features = false } +composable-support = { path = "../composable-support", default-features = false } +composable-traits = { path = "../composable-traits", default-features = false } + +plotters = { version = "0.3", optional = true } + +[dev-dependencies] +composable-tests-helpers = { path = "../composable-tests-helpers" } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +pallet-currency-factory = { path = "../currency-factory" } +proptest = { version = "1.0" } + +[features] +default = ["std"] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", +] +std = [ + "frame-benchmarking/std", + "codec/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-io/std", + "sp-core/std", + "sp-std/std", + "sp-arithmetic/std", + "scale-info/std", + "composable-traits/std", + "composable-support/std", + "rust_decimal/std", +] +visualization = ["plotters"] diff --git a/frame/pablo/plots/lbp/lbp_buy_project.png b/frame/pablo/plots/lbp/lbp_buy_project.png new file mode 100644 index 0000000000000000000000000000000000000000..0629b9b6e443abb29e573f77ccb922e3fcb8e72b GIT binary patch literal 47978 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�Fs)W{2cgcvv+wh0-IQmbyL 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 literal 0 HcmV?d00001 diff --git a/frame/pablo/plots/lbp/lbp_sell_project.png b/frame/pablo/plots/lbp/lbp_sell_project.png new file mode 100644 index 0000000000000000000000000000000000000000..4ac62f9f7e44e4082e96b1b36c99c28ba2bf97bf GIT binary patch literal 46521 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 YcB@$c8NhLZQH6dL1cyq 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 M`mO6?*O+_#Kix3efB*mh literal 0 HcmV?d00001 diff --git a/frame/pablo/plots/lbp/lbp_weights.png b/frame/pablo/plots/lbp/lbp_weights.png new file mode 100644 index 0000000000000000000000000000000000000000..244833c6666cfa9deffd8fc94ed35d71bc3e1a08 GIT binary patch literal 40290 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 ZXEuI2O}Od(<~C5q@O1TaS?83{1OTemiOK)~ literal 0 HcmV?d00001 diff --git a/frame/pablo/plots/stable_swap/curve_base.png b/frame/pablo/plots/stable_swap/curve_base.png new file mode 100644 index 0000000000000000000000000000000000000000..cf7b0fae9ee2d3755711aff64f0498765884e97e GIT binary patch literal 54926 zcmeFaXIPZi_CAby)FcFn$0LX|4Jt7-E1;A)iARZ|l4ztz84&>uNEHEr8Djw(5K%!v zm>7aY5e68fGlL?%iG?C%Xagd>GsBd3?HN!&1_u3qct8BE>s;5#$ zy4U5O_v?s!wel+=At907KmG53kkG&29~TIHF(3YGYvsAaLPF(-cK`2(U)}C@)Ow_M zxtO+k&6mpR-xV>hH2CR;gS#)aoLm^JQ}lGfZK+rHr9#f1%DV95x2J;kZaZ!rn)j3W z*EMx(js9>8esfs$_did_xo7TJYk2)n0E4)$lXQzx-`f#pU9e=X^SAR2O>Fb1ojE4*D$NA zo81-eug#z`L-1MFl*^-|6wWA~uEL>-vg<|J4YKUjyr*;8@hp`Vwj8EUPTb6Gwd}6c zuGIFJmcd9gIZ4EvB=0pvfS<2B&D)br%m(}7h`!OR=M3>;L zMb+!i=4ubc>A5{!CNq+`xX-9Dq*jkJpyzD;w#1d(uhs3Yr|t3fo{u*C`8tdJNv*b- z-ATVWyK$~&r768RlAIQMw)f-FVb9WGCY`|9cGj?@ zD`U8>=1ym9))J3w1+yozTZau!dz37aispUjm!+@1+mwtRpI(vCl^vQL&77ZVS6D82 zHYP3F-?LfH-=n69+;@w}9P#IG$OL?2B2fp=$e5t>NaZ+AA(OgB4iH$!b;d!oGX{L9gtS8@xyB zhRHS9KbUXqQrp&%zgCVd9^ItMbn&wyyOqyl{xzIZ>LrG!^;a%Z74qB-_8&witrSxr z^(r!`aDu39`&}DLe;3uUFdez5;`w`F{%8kDRJOo7;`Q6@0T>1H-x))1+L4*5EBZfQ zZea4{U4I(6JxzPyo@noC?kTDArYhcXY2Ga#I#5Vq7II2C{hYgwITD`gDq?aX4VBIM*q@qynQY#0Wdci7%H3#Hxa zfA_3(sdeHlky5h{e#9q5eW2GL?^(RZaUY%$iD!gk7~z~=3_BOLfK8!0q{wUcUdA#T z#p$Z~EInM`4Ly%HFAcxF>+tkT`7pOe0;`J9TOSc*R?yy-E90RU^*eU-F}CUYEonTn z7vC$6|GmMce#eC;X-wpc&Rs|D%ySvi+*caqA8}2%nG+d{RY)a0|QRp+VZQ2nNkpa$Q`{1jC zDVTp%MiZSAXvE)o#W4fz6n4AGDyf*Exc_czxov@Cx8m8bn`*K#wi~OXMTBhrvrb#l zrcyVZNmIdY_G16b?JKX5ELkhBQlH^8DvQmcaE2qnBNep1ptlk@SWY`W>+#3P)GkU%d8vDr=)im(JWOwsw`ysS19ZDuMWRy zecnY9ry?nHccbSDbCL+fXpe~9KD2l4gNy!bKRwteP8mUd)TlB8PIhzF!nitGHN7p8 zz;?zAJ9{SAWPy)sk4f{>5*qfo*c2|yI!+$$+4t6iGVGD^oXu>-aF9QFeqQF;!unD? zyWf>ET6=v*g^9BW^&nj@kQkHEM9cyNF62*YxQ0C z|5uSJ^RGuu^qu(n#kl(2dT0Jk`6|jiW;bQ%F_8r>5Od`C5fWAsTiJ2$w(nO8wP`gp z&w*?yda*sOKN7=gljZcv z;#uw3QtP%F=Th2^L_Ma#Xg38zQBmH|pB;O*k<_lL7#+4f(eIf5vqSGlCEMF04blw) zDwAxf3+@GQ4O?p zEl-te2_oeuM>1^P9AK|66st0=)^AnsdUWleSnD$G75o5liliuXlbP&b)KXcs)|k;M z&*W8t!nb-Q!n?a^)Bp*A~_!^ zE0xoca{L!jI__oDQ;h7Axcf%214dPFR4%Kf`86+;Fx%zUBuUL%dq~^FkIrsXVK?>- zN^?Fo+r$VCJCqJ>pJnqO=mWwJ>F{2B~FyPY(4VY09$-bW;i*Q zPI{6mLJ1NPEm@&`Ef)F8h()6xK66CR|i3wD(yuLmO}^9ecfZdUKc8n|S3agK0MO#zsX( z;!NHSnWwQRY;ls(mhxTuD)tXXob2dE?dCo5Hhb7n4d-ZGV7zXP#W8XOh^>0hWf|A? z1wtGbEE=TIbZxWS74o}7#4~NW*a9DKi7cPTwuudDx=gR;tgRyW76ppCsXOhKd>sQr z66qbj)G8!?+ep1{b#$8Fv3Ui4e)0?SzQn5Lt+=BY{K6ML+u4hw^vLi*9B~cMn4Yn~A~)8IzYiSDn5S3kL6HOl9aRA0v-s ztFV2kBO=;Tl^qqTX{)q5Vzaa%e5kJ?^fcH?j&9d!GH8f8JbV>1@O+2SmRNOxngD6J3ZMWXaFnKBK+K)`TH@C#c=FNpCy$uB@E$>JEr1Ofs%%i%x z9&feuo{K6q7Uqv^=%-5_`aPDGRaQ%z=ho#+D7?5u+hm!+#T3<|Low*0re$$PWI0Xk zX2Yp)XHhv2-kWQ$QT|ob-c-7C7}q@y4H8Gf}U%JHWx};b{uklj=$tI; ztxo^FaVxj{=IUzL1Bd}Mbputr+H{9a7-|O$+xzntL%hFO>+KJUI&kTD#2ssh_&V(S z!qR2s8^PNv;AsXpOE>QtSSTFhC80#_(JvzowcZiS_0p?cntPZ=xa-GKI0FRsOB?Ly z;V|1Q-EYP%A0HoF8~$%9X~^UXMo;^$_-4!BI8@FsM~Q=1bn}isBAx%Z6*)XSJqS+^ zrP4#$wy}0hF}u?GYYkangeYl)%}d}@3|R+J-oU+pO+|=y90*e0!u@UE-*7JZ)xgb2 zO-pz4q?!e?BmXTg$m+AJd+PW_B8NTN@72DUKrh;-R{PA0oaF`k(iB+wZ;q1A$Xgvu zD)kBn>zM+1YbYX~6~)39ZhAm&vrOdukbN`{W^%3vT^VC zY``ue9G2pIiB}JA&%-hzu#Hy~RnW!6oG+{F3J&@leY??(-g~?N$2aQ!~r(MMGLnM$#E5AuLo!!^!yhu-Z@Bg@^je6qS8SD2x-PI4Z-3wJ{w-GeK*O$#4lpC@H3QW zj@Bu(KgY zDJ}5V3ADhEpm-QUHw(F3AK^w(!ct8Ry%f`(-ai718z4?asry;sYLmK_9mtVaZ&SB$ zTl3WFs_2C9(eA1+&cuohzL2b|oYLHt#HQ5lP#knKV!Gm5U6V12Qgpwk-S>v?`lZSGP0Z$&z;IDqj_xL@OsZx(C!%p=o#^PEh6H0#fU`?5e< zzf-X|Wyi?*CEMS=iz2q{*<6wBehebP>YmZVDXUsE6sTBPdY(?7Ws#Yw9LI$Xneam5 z8i(kv22s4aELznXBW5-M&!(rZ%#^K7s~c3-mO4}0ZkBs03=j;gXK%LWPu|6BoV6tR zVHGB7tK?a0%_a${8x>N94n3>mgcuN9pY~2mpLax>)Kcm&awa*iU^7@_5*+vwcd_jU z35-{?AT0YI9jz-mm!cvu>?TY}ofDnlq*k=zp=CHLQ^_M~REZ4X|$;8vl>wSw0 zeFh*)iqu?C!MsSjlZ8Dd7GG#@-dakKZ|>M0u-h^J&f|5&yx!oiiA}w$^1+qYmOPQz zu~hZ2r-MRMw_Fsy@l>&oX@yb+O3js&?Rvd}g_(<`95Ny4;DiYuf!IdNa9tm(L&V-~ zfp}8#qDA56ELUc4E@??JEzsC-u`}y3W#6-4(GB(u$x?lQIeby^B3aQly{|yQ-N6zv z4ic47p42B2&>ckWm8Sk~J&%Q866tQY#fujgkqwc^MdG>tzh^> z%A+H$u>BSaW|;fw_7#ekQW8pi(i=+`x{*V04Z_$X(WSCWsjhUze4?{k_IcuO#qmeB zZNM(aW_>|{e~fBcv2_GC@5=gicOje%;vc>A((6q{6vQW4{ z8_s^c&n(CN?GD+3)3gW`ul0ES^x!A5!dGR!4v`&_Vea1KDz-&2dPHwT3q_^PK|ieYUmvhHlqw1UzsJ7Q@F{~EmEVl?b>n-=GM{;m*5u1G0QgIhukD1@~+cY{+ks~ z|6C)n32i9JG4%GuRrr+sn!W!UGB7b{5xpV4xAG=Jjo8n9w6`$xUtTpE_%`rw9a*m} zrFVP)P+-cNB;q@5u!Y|S&^JBt3SvuFnoH*ss_$5b<@;>N$qn;exLrZlFW<&!?;m<1 z5Rx9hcz(0@x3-BR_4+vmCGQC6wzlC$|5s=u2v)n;?al!NCeNoZ?o3m)Xq0)^vWmY6 z1AohV!KK!s-I+wiRVUfEj!FohNtw4wKZ$6<*tmnzr$BkCrVGggE&D`dXiid=q<#8z zQ6IOHp}KvZSxs!)LdtjIh4kO(`}5B~OEM>?dj+zoD-K)PkX6OhJgKInRaV((i zCg6ns9V?Yf>?F<*mE8{sPN67#nwO+TjC=`GPSsmt$75Snt6`MGqG)_L$m8j7wx0 zOG;K;iLGipZyW=$zZwxrIki72{+9Apwn9AzP(@F4Z9Ly0N?YhCgOyNda)o#mWdmt& zKV#_mdgMaWuBW)O-G|OMf5B`u+0;z(R9_jif?k@^Uk`B!oS)6ERu&phw&vNyq~ zYTcz*o@^xRXf`fYz-yrRB!A)lC51t(JRR+S3pJ^g9K2NeqE&l%Tg)(I?}S#Tmh&Y@*xpV|UN6jVjyL{j1)uk3A_MY{OgMQTHcySjdj9NZP^lwOE>>8N9Gp%5d0r zgCwQu4cEU_|7Vd7ggMsUl+kwf&i2%3eTbI2LgdN*%EWtghwX8jtbQmGo^KM@lvTEF zG}{%G<V8m_tbv z)(@g*o+F^Nr-5U{n*65#{)Yb~{)~Qv`;VzgzrsuL{?ShOwdC2|1IRVz>*2uN4ATJu z!LkeS`Jvf6SL~KBUt@VpYz^(E#P0P*or*sdd?B}9?%Hp;OX1&NxPJ4x(H}PtTCIsV z_L#H^{{7$AHUu=ig(@SROfx3az}fn^7ZgwyEZucr*NWZi^7amIMz=P1A zu=?S^{yW!i2D~mghaTi4Z_LVCrWWa%`ubO$jCpx*Rh0cEvD?T)HR#&kcQ?tcUmF#= zko$rce(6;ImiyzIHVFqf6|>?|T$j?B@SM54P5OeW zBu`M23vz+W??$ObJZA`@II)kGR~sk zdh$nYdiu|4Dc*8O+*!DLo8_(pd-OGg1Nu(KvqaU;R=b;e6mPBZQ|&%$^Tsphz!l@1 zUP#J=G-^`^7p;;leS=$gB=PXB0|o7i1zyS;5!G%^rBNKSI{#T2+Q4moerFc^K~xh8 zf4wQ-K$v!O*&4a^kwri4$^Q-B7B))4{8tS>?neK8t?1l`wcb_|7<0})p>B^o^SA|C z`P{N!?1lOU7ad7J@AT3~Gx(Tbrs5i3raKxX?xJx=Gx!Lyq)*)%vHU7wX1h{@nDoh= zU|LIeIY~*Qm6AM*Th?Ry_}bq!zcBoi^M5K>zd7JQ{2MS=?&81plY7duWw6`vPgkII z7`p^f!_oqj{t3K(Go;jTk7J=aV_#-GY;}`SHBqQYzwoC$?yUdH?AtWa%+T*XZo0G~ zU=utv4-U!LkHxO4w>so3cB1bryvX~bac04W!%A}NX>B_MddxYaM`i#x8O_|%n`BxD!3aIV~{yd&^7M* zF#gcFG5ZPKTYQw3iqF^?#B||0jss0^1K}y!szNNHP%%8HKsti+_jv&fO4ur{kJ>{o z6!prJ@@*zcny;a?Yz{n7v&oNbaP}B@j$BeAcHZr1*wa47?*iGV9LezT<*s+-YXdb` z@?1<=o_gvwuq>>-(5@)UH4&O#dEvWvO>$V%o$b@riaF)1!u)Wai(65v>SvcR_tV#8 ztge<8O!+fj=OwbSFXZS3TnE%Hl6f3#>t>{=`<7XaykM}Z?*;Zzcsb@xH1DIXGo!dC zIBwoswRxr7HSedEJ>De9!`y9Y#va6smf*2NWv6YiK3k~?9#jb5=Wl(IGJk_Hvh%?O zf;?_%V#2eUsw)={zQ1HX#j4VMm58G!tnz;am&#kHPcd=Vc-C-hNl6Rw=6i?u39jz% z=DtIm!SbJ`UX7JP10iRv!G>slFI-Q}YC~6PeIA~)(ynOUWjAixxMi`A;GT6WA5st^ zAwO=05#ZRh6htg0I^hbG~iMw+1RKpIw!PQ$KDl&h7Bp+(7n@s7mJNyh(y? z36>$+d9?k|lr8rc`7h;5H*{HcednbUG@BnuV5(AWh$-IH?)eMK#{!Uk3ElN}5;~MG z4WWYUscAF1{A?At-}OYjlx^1ZE98)nP5xdFVW>Qk@TOmA0)AGz4o_ioU5yja7FamwuH z2hKIV@veIDql2|`pjuM?#oZ```n209IimuP4%GVZcUC7+9kN6K1sF&KN&qv@NmzTUQ0C)!IhQ;RttI33$eH&3mNBk4Q7_wyp`_vVpUv#37W-m6^} zcs*nw=+v_}hxJ|yA`e6W{v@Qb(8Mu&xu#P`T&@h%?ib6r)i09S)|V%jqGy2h8cf&o z1z&*j5CQUsy5DUL883@oSS~ld{XVVXIRd4mc_WBp09olUDmf&hLIevy==qXoVd)Xz zr|DE~WZg+B)mH3M>&eTPClq<50+*=8>$e1fBdxwA=KVqJ9ci~G2KVC|0FaJG<0UzA zKX62%u&j5eHo`(w3ifC>zBgN(q)<OnfP|_GfVKcmjYlAedUgd_td(2X+m>(sFlXAU4QmeFwqHCRFTSQHXu$A9f zCWQ8>*gC7=U4a5o6R{dzMpuKmJg=azUBbRagcCC$D6yf6_zcqc;g@=tP*XX=_TFd9 zL^V1##B|x$FE!g+uWfp|%CcX3>&o{QyD7PtFd^aMnnU;-$N#<0aV^&xAAa3woALO{ z_BRKn+Dzl3`iD_5+>#`z*&07&twLcs$!r^`Kd+Kpe-21A-91^N)^swU)FPTshX$@~ zE>Z6<+6+j4X_a1YR1p+oQMMHzpVI>O!3^1J{57R$HVxB5VVBwMn{sOOYlN7U{;U-q zXHm5f%0bxtb|KBDJ|-jz(53XY(QeB5sUP+C)pn|J%nfy|bNA@Z819G^dnK^Nip54m za7utRywet?Q{$;P&t{{O=iNS>F>eJokRDj=zfR&q{`&E9(mIbS1hQ+MtB34{=;TA{ zmG5{8-p5n$=j2qyGO!tn66O{VD{+%$?vIV7vHl{N7lDfBR$KaSe_jG69f7GZojE@f ziABk_aq3X8O|og#p2Su8AI?V#{aVC-lCCv@p((qjx&d{>7p`@k{z8#>G0qZ%LXU%``+^%7KOGLR5t z15j=@29JEogHp651KDfzSGCKYTt8ve-lwD!Qi+J}w*fQffg2_3x;;9#Rw!B(q7Zi6 zNIoN#XpN6p`=%sNOa=wGlQ63}hfa4zqBzTS{Tx*fLKgEG+Zbb+^@5;JR4b3)Ht{2O zt(fyk_+Ir9J6C@tikPSQv^fO_OKjapDyAC!SzbPiaze8wzSw81zH5Agyr+`Mk&a`1 z$6Y?h%+{xzT7BBOJzDuy*~4i*RbZ&$FjhI5jlp+5ZjX(CwD$ly!&8G;fe%r%T#!D; zWCZI|dl&$|$-a>b20pi+ABLQx#vW?f+L@f=7QGmEO1Ea>eSlBKEo(wxHpj$nWst70 ziZauA^Oh2;D;qu>qd8kxg8mX+{Nap03=3QSV?GV2D`;|e{FanH$3pkgAzK`vZ6CR8 zfsx14`Q~kU&gG(Mm1h8oo`65|&hlIgKCk;svs}vN^eR`g4bGYWPnMl*;7B4328#5Z z{q&Fgy6EVMK@5%11LpG4_X%d@P9*EN1V-yq4#VleWRP<%{)N_3d=z5U7YEF*o0Lrk z`{%gWb|s45gzmIH7P-GU`2GY`dF)~hr~XTEE|+S07JOgeo2qxqpI(x(`GD=u_40Dh zEjen)@{blNFW9zkLYaXV+rar1EHUrSG%CWfUVgug@)?UQz3D1gcE7>GwB|F@zKg{I z0euNwv8Z%-?cbX9$0it%8X@jxW1u6zOqO#&KW_o(soJ?$anY-Jk;M=YeQzCilLwd2 z#gZ(m6a)1+eXXM}7>iAQjym;(td595b_6Nixf_eKO8$NB2{ zSm8l$`%iok;*>a}4t(aknis+NPHPe4u`-%uNH(wbH3mI#6#hG>;)5^v6ZeF^ryQrK z%BQ?EqdHGf>=RZ$rJ8h`!icP{Ji`m}6RSyvDxa`swYRg`qt4dW{gjICV~yf#dDWKF z7GjOZxfR5@*~EJ5C$8dlVu~!EW|ciW@IBusZya17GgDh3sM#P))JdmJBb9$`YYS;b zU0+%YiyWShy~$gw&7@WCTevn>Y^@lPY$?TBccco^uAaSIu5t(1MisX!2#+AFpjo2|FOgEOsI3owjeByZsyVXI8H~M{rsF>v0xB|a&R_e zR*Vwm_nBPcaX4W*sKU!DR~;`rDWpAGRT{sY0|bCPFXd7SYE;^J*1~UF3$WwruUq(Q z4UIJUV|p?d07!9NM<(AZ75Y(H1qCUbJjEb7wqqrJcnMYQt9P2Yg-Uo2xP0C?NeZ1o ztr3XgV&|GxjmYDOvZrYZEju_iy|w=V5Z7%0sW5k>{I0WKn|`e8<=P;VP2C5>#{i=~ z&&nCl2)`n@8HjA}3GcA!YTT4}I16l(Uf_E&UWN^AQ5E8_fT@I#vmihkpdZS!E2Xus z3ecL-mJoYwpzW*n&0$QdSf-uGjPWKB+r-;DDXMx)1whCDuQ-Up1bpj~>MU{pp~d)-5O(pG*-E3TibP zra&)13mdv2N)En59S?dK)~VCJnofGx|Lm13Q<2@*r^x0;Sg_Y~o*;_}^{@yⅇYtzLzQpka;05s+*?DF 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 ai+hr2O^3_|$}sq6x_jSO8Gk)|_P+r)v$;P2 literal 0 HcmV?d00001 diff --git a/frame/pablo/plots/stable_swap/curve_graph.png b/frame/pablo/plots/stable_swap/curve_graph.png new file mode 100644 index 0000000000000000000000000000000000000000..a3c674105bb7d181f7309b2eb96f99c248928e98 GIT binary patch literal 58012 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�l06aM(Z+BxkooYj& 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 literal 0 HcmV?d00001 diff --git a/frame/pablo/src/common_test_functions.rs b/frame/pablo/src/common_test_functions.rs new file mode 100644 index 00000000000..2f691ef8d81 --- /dev/null +++ b/frame/pablo/src/common_test_functions.rs @@ -0,0 +1,68 @@ +use crate::{ + mock::{Pablo, *}, + PoolConfiguration::{ConstantProduct, LiquidityBootstrapping, StableSwap}, + PoolInitConfiguration, +}; +use frame_support::{ + assert_ok, + traits::fungibles::{Inspect, Mutate}, +}; + +/// `expected_lp_check` takes base_amount, quote_amount and lp_tokens in order and returns +/// true if lp_tokens are expected for given base_amount, quote_amount. +pub fn common_add_remove_lp( + init_config: PoolInitConfiguration, + init_base_amount: Balance, + init_quote_amount: Balance, + base_amount: Balance, + quote_amount: Balance, + expected_lp_check: impl Fn(Balance, Balance, Balance) -> bool, +) { + let pool_id = Pablo::do_create_pool(&ALICE, init_config.clone()).expect("pool creation failed"); + let pair = match init_config { + PoolInitConfiguration::StableSwap { pair, .. } => pair, + PoolInitConfiguration::ConstantProduct { pair, .. } => pair, + PoolInitConfiguration::LiquidityBootstrapping(pool) => pool.pair, + }; + // Mint the tokens + assert_ok!(Tokens::mint_into(pair.base, &ALICE, init_base_amount)); + assert_ok!(Tokens::mint_into(pair.quote, &ALICE, init_quote_amount)); + + // Add the liquidity + assert_ok!(Pablo::add_liquidity( + Origin::signed(ALICE), + pool_id, + init_base_amount, + init_quote_amount, + 0, + false + )); + + let pool = Pablo::pools(pool_id).expect("pool not found"); + let lp_token = match pool { + StableSwap(pool) => pool.lp_token, + ConstantProduct(pool) => pool.lp_token, + LiquidityBootstrapping(_) => panic!("Not implemented"), + }; + // Mint the tokens + assert_ok!(Tokens::mint_into(pair.base, &BOB, base_amount)); + assert_ok!(Tokens::mint_into(pair.quote, &BOB, quote_amount)); + + let lp = Tokens::balance(lp_token, &BOB); + assert_eq!(lp, 0_u128); + // Add the liquidity + assert_ok!(Pablo::add_liquidity( + Origin::signed(BOB), + pool_id, + base_amount, + quote_amount, + 0, + false + )); + let lp = Tokens::balance(lp_token, &BOB); + assert!(expected_lp_check(base_amount, quote_amount, lp)); + assert_ok!(Pablo::remove_liquidity(Origin::signed(BOB), pool_id, lp, 0, 0)); + let lp = Tokens::balance(lp_token, &BOB); + // all lp tokens must have been burnt + assert_eq!(lp, 0_u128); +} diff --git a/frame/pablo/src/lib.rs b/frame/pablo/src/lib.rs new file mode 100644 index 00000000000..d2ab7770b24 --- /dev/null +++ b/frame/pablo/src/lib.rs @@ -0,0 +1,866 @@ +#![cfg_attr( + not(test), + warn( + clippy::disallowed_method, + clippy::disallowed_type, + clippy::indexing_slicing, + clippy::todo, + clippy::unwrap_used, + clippy::panic + ) +)] +#![warn(clippy::unseparated_literal_suffix)] +#![cfg_attr(not(feature = "std"), no_std)] +#![warn( + bad_style, + bare_trait_objects, + const_err, + improper_ctypes, + non_shorthand_field_patterns, + no_mangle_generic_items, + overflowing_literals, + path_statements, + patterns_in_fns_without_body, + private_in_public, + unconditional_recursion, + unused_allocation, + unused_comparisons, + unused_parens, + while_true, + trivial_casts, + trivial_numeric_casts, + unused_extern_crates +)] +#![allow(dead_code)] // TODO: remove when most of the work is completed. + +pub use pallet::*; + +#[cfg(test)] +mod common_test_functions; +#[cfg(test)] +mod liquidity_bootstrapping_tests; +#[cfg(test)] +mod mock; +#[cfg(test)] +mod stable_swap_tests; +#[cfg(test)] +mod uniswap_tests; + +mod liquidity_bootstrapping; +mod stable_swap; +mod uniswap; + +#[frame_support::pallet] +pub mod pallet { + use crate::{stable_swap::StableSwap, uniswap::Uniswap, PoolConfiguration::ConstantProduct}; + use codec::{Codec, FullCodec}; + use composable_traits::{ + currency::CurrencyFactory, + defi::CurrencyPair, + dex::{Amm, ConstantProductPoolInfo, StableSwapPoolInfo}, + math::{SafeAdd, SafeSub}, + }; + use core::fmt::Debug; + use frame_support::{ + pallet_prelude::*, + traits::fungibles::{Inspect, Mutate, Transfer}, + transactional, PalletId, RuntimeDebug, + }; + + use crate::liquidity_bootstrapping::LiquidityBootstrapping; + use composable_support::validation::Validated; + use composable_traits::{currency::LocalAssets, dex::LiquidityBootstrappingPoolInfo}; + use frame_system::{ + ensure_signed, + pallet_prelude::{BlockNumberFor, OriginFor}, + }; + use sp_runtime::{ + traits::{AccountIdConversion, BlockNumberProvider, Convert, One, Zero}, + Permill, + }; + + #[derive(RuntimeDebug, Encode, Decode, MaxEncodedLen, Clone, PartialEq, Eq, TypeInfo)] + pub enum PoolInitConfiguration { + StableSwap { + // TODO consider adding the owner here to allow a third party owner + pair: CurrencyPair, + amplification_coefficient: u16, + fee: Permill, + protocol_fee: Permill, + }, + ConstantProduct { + // TODO consider adding the owner here to allow a third party owner + pair: CurrencyPair, + fee: Permill, + owner_fee: Permill, + }, + LiquidityBootstrapping(LiquidityBootstrappingPoolInfo), + } + + #[derive(RuntimeDebug, Encode, Decode, MaxEncodedLen, Clone, PartialEq, Eq, TypeInfo)] + pub enum PoolConfiguration { + StableSwap(StableSwapPoolInfo), + ConstantProduct(ConstantProductPoolInfo), + LiquidityBootstrapping(LiquidityBootstrappingPoolInfo), + } + + pub(crate) type AssetIdOf = ::AssetId; + pub(crate) type BalanceOf = ::Balance; + pub(crate) type AccountIdOf = ::AccountId; + pub(crate) type LiquidityBootstrappingPoolInfoOf = LiquidityBootstrappingPoolInfo< + ::AccountId, + ::AssetId, + ::BlockNumber, + >; + type PoolIdOf = ::PoolId; + type PoolConfigurationOf = PoolConfiguration< + ::AccountId, + ::AssetId, + ::BlockNumber, + >; + type PoolInitConfigurationOf = PoolInitConfiguration< + ::AccountId, + ::AssetId, + ::BlockNumber, + >; + // TODO refactor event publishing with cu-23v2y3n + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// Pool with specified id `T::PoolId` was created successfully by `T::AccountId`. + PoolCreated { + /// Id of newly created pool. + pool_id: T::PoolId, + /// Owner of the pool. + owner: T::AccountId, + }, + /// The sale ended, the funds repatriated and the pool deleted. + PoolDeleted { + /// Pool that was removed. + pool_id: T::PoolId, + /// Amount of base asset repatriated. + base_amount: T::Balance, + /// Amount of quote asset repatriated. + quote_amount: T::Balance, + }, + + /// Liquidity added into the pool `T::PoolId`. + LiquidityAdded { + /// Account id who added liquidity. + who: T::AccountId, + /// Pool id to which liquidity added. + pool_id: T::PoolId, + /// Amount of base asset deposited. + base_amount: T::Balance, + /// Amount of quote asset deposited. + quote_amount: T::Balance, + /// Amount of minted lp. + minted_lp: T::Balance, + }, + /// Liquidity removed from pool `T::PoolId` by `T::AccountId` in balanced way. + LiquidityRemoved { + /// Account id who removed liquidity. + who: T::AccountId, + /// Pool id to which liquidity added. + pool_id: T::PoolId, + /// Amount of base asset removed from pool. + base_amount: T::Balance, + /// Amount of quote asset removed from pool. + quote_amount: T::Balance, + /// Updated lp token supply. + total_issuance: T::Balance, + }, + /// Token exchange happened. + Swapped { + /// Pool id on which exchange done. + pool_id: T::PoolId, + /// Account id who exchanged token. + who: T::AccountId, + /// Id of asset used as input. + base_asset: T::AssetId, + /// Id of asset used as output. + quote_asset: T::AssetId, + /// Amount of base asset received. + base_amount: T::Balance, + /// Amount of quote asset provided. + quote_amount: T::Balance, + /// Charged fees. + fee: T::Balance, + }, + } + + #[pallet::error] + pub enum Error { + PoolNotFound, + PoolConfigurationNotSupported, + PairMismatch, + MustBeOwner, + InvalidSaleState, + InvalidAmount, + CannotRespectMinimumRequested, + AssetAmountMustBePositiveNumber, + InvalidPair, + InvalidFees, + AmpFactorMustBeGreaterThanZero, + + // ConstantProduct Specific: Possibly rename + MissingAmount, + } + + #[pallet::config] + pub trait Config: frame_system::Config { + #[allow(missing_docs)] + type Event: From> + IsType<::Event>; + + /// Type representing the unique ID of an asset. + type AssetId: FullCodec + + MaxEncodedLen + + Eq + + PartialEq + + Copy + + Clone + + MaybeSerializeDeserialize + + Debug + + Default + + TypeInfo + + Ord; + + /// Type representing the Balance of an account. + type Balance: Default + + Parameter + + Codec + + MaxEncodedLen + + Copy + + Ord + + Zero + + SafeAdd + + SafeSub; + + /// An isomorphism: Balance<->u128 + type Convert: Convert> + Convert, u128>; + + /// Factory to create new lp-token. + type CurrencyFactory: CurrencyFactory<::AssetId>; + + /// Dependency allowing this pallet to transfer funds from one account to another. + type Assets: Transfer, Balance = BalanceOf, AssetId = AssetIdOf> + + Mutate, Balance = BalanceOf, AssetId = AssetIdOf> + + Inspect, Balance = BalanceOf, AssetId = AssetIdOf>; + + /// Type representing the unique ID of a pool. + type PoolId: FullCodec + + MaxEncodedLen + + Default + + Debug + + TypeInfo + + Eq + + PartialEq + + Ord + + Copy + + Zero + + One + + SafeAdd + + SafeSub; + + #[pallet::constant] + type PalletId: Get; + + // Used for spot price calculation for LBP + type LocalAssets: LocalAssets>; + + /// Minimum duration for a sale. + #[pallet::constant] + type LbpMinSaleDuration: Get>; + + /// Maximum duration for a sale. + #[pallet::constant] + type LbpMaxSaleDuration: Get>; + + /// Maximum initial weight. + #[pallet::constant] + type LbpMaxInitialWeight: Get; + + /// Minimum final weight. + #[pallet::constant] + type LbpMinFinalWeight: Get; + } + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); + + #[pallet::type_value] + pub fn PoolCountOnEmpty() -> T::PoolId { + Zero::zero() + } + + #[pallet::storage] + #[pallet::getter(fn pool_count)] + #[allow(clippy::disallowed_type)] + pub type PoolCount = StorageValue<_, T::PoolId, ValueQuery, PoolCountOnEmpty>; + + #[pallet::storage] + #[pallet::getter(fn pools)] + pub type Pools = StorageMap<_, Blake2_128Concat, T::PoolId, PoolConfigurationOf>; + + #[pallet::call] + impl Pallet { + /// Create a new pool. + /// + /// Emits `PoolCreated` event when successful. + // TODO: enable weight + #[pallet::weight(10_000)] + pub fn create(origin: OriginFor, pool: PoolInitConfigurationOf) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = Self::do_create_pool(&who, pool)?; + Ok(()) + } + + /// Execute a buy order on pool. + /// + /// Emits `Swapped` event when successful. + #[pallet::weight(10_000)] + pub fn buy( + origin: OriginFor, + pool_id: T::PoolId, + asset_id: T::AssetId, + amount: T::Balance, + keep_alive: bool, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = ::buy(&who, pool_id, asset_id, amount, keep_alive)?; + Ok(()) + } + + /// Execute a sell order on pool. + /// + /// Emits `Swapped` event when successful. + #[pallet::weight(10_000)] + pub fn sell( + origin: OriginFor, + pool_id: T::PoolId, + asset_id: T::AssetId, + amount: T::Balance, + keep_alive: bool, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = ::sell(&who, pool_id, asset_id, amount, keep_alive)?; + Ok(()) + } + + /// Execute a specific swap operation. + /// + /// The `quote_amount` is always the quote asset amount (A/B => B), (B/A => A). + /// + /// Emits `Swapped` event when successful. + #[pallet::weight(10_000)] + pub fn swap( + origin: OriginFor, + pool_id: T::PoolId, + pair: CurrencyPair, + quote_amount: T::Balance, + min_receive: T::Balance, + keep_alive: bool, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = ::exchange( + &who, + pool_id, + pair, + quote_amount, + min_receive, + keep_alive, + )?; + Ok(()) + } + + /// Add liquidity to a stable-swap pool. + /// + /// Emits `LiquidityAdded` event when successful. + #[pallet::weight(10_000)] + pub fn add_liquidity( + origin: OriginFor, + pool_id: T::PoolId, + base_amount: T::Balance, + quote_amount: T::Balance, + min_mint_amount: T::Balance, + keep_alive: bool, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = ::add_liquidity( + &who, + pool_id, + base_amount, + quote_amount, + min_mint_amount, + keep_alive, + )?; + Ok(()) + } + + /// Remove liquidity from stable-swap pool. + /// + /// Emits `LiquidityRemoved` event when successful. + #[pallet::weight(10_000)] + pub fn remove_liquidity( + origin: OriginFor, + pool_id: T::PoolId, + lp_amount: T::Balance, + min_base_amount: T::Balance, + min_quote_amount: T::Balance, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = ::remove_liquidity( + &who, + pool_id, + lp_amount, + min_base_amount, + min_quote_amount, + )?; + Ok(()) + } + } + + impl Pallet { + #[transactional] + pub(crate) fn do_create_pool( + who: &T::AccountId, + init_config: PoolInitConfigurationOf, + ) -> Result { + match init_config { + PoolInitConfiguration::StableSwap { + pair, + amplification_coefficient, + fee, + protocol_fee, + } => { + let pool_id = StableSwap::::do_create_pool( + &who, + pair, + amplification_coefficient, + fee, + protocol_fee, + )?; + Self::deposit_event(Event::PoolCreated { owner: who.clone(), pool_id }); + + Ok(pool_id) + }, + PoolInitConfiguration::ConstantProduct { pair, fee, owner_fee } => { + let pool_id = Uniswap::::do_create_pool(&who, pair, fee, owner_fee)?; + Self::deposit_event(Event::PoolCreated { owner: who.clone(), pool_id }); + Ok(pool_id) + }, + PoolInitConfiguration::LiquidityBootstrapping(pool_config) => { + let validated_pool_config = Validated::new(pool_config)?; + let pool_id = + LiquidityBootstrapping::::do_create_pool(validated_pool_config)?; + Self::deposit_event(Event::PoolCreated { owner: who.clone(), pool_id }); + Ok(pool_id) + }, + } + } + + pub(crate) fn get_pool( + pool_id: T::PoolId, + ) -> Result, DispatchError> { + Pools::::get(pool_id).ok_or_else(|| Error::::PoolNotFound.into()) + } + + pub(crate) fn account_id(pool_id: &T::PoolId) -> T::AccountId { + T::PalletId::get().into_sub_account(pool_id) + } + } + + impl Amm for Pallet { + type AssetId = T::AssetId; + type Balance = T::Balance; + type AccountId = T::AccountId; + type PoolId = T::PoolId; + + fn pool_exists(pool_id: Self::PoolId) -> bool { + Pools::::contains_key(pool_id) + } + + fn currency_pair( + pool_id: Self::PoolId, + ) -> Result, DispatchError> { + let pool = Self::get_pool(pool_id)?; + match pool { + PoolConfiguration::StableSwap(stable_swap_pool_info) => + Ok(stable_swap_pool_info.pair), + ConstantProduct(constant_product_pool_info) => Ok(constant_product_pool_info.pair), + PoolConfiguration::LiquidityBootstrapping(liquidity_bootstrapping_pool_info) => + Ok(liquidity_bootstrapping_pool_info.pair), + } + } + + fn get_exchange_value( + pool_id: Self::PoolId, + asset_id: Self::AssetId, + amount: Self::Balance, + ) -> Result { + let pool = Self::get_pool(pool_id)?; + let pool_account = Self::account_id(&pool_id); + match pool { + PoolConfiguration::StableSwap(stable_swap_pool_info) => + StableSwap::::get_exchange_value( + &stable_swap_pool_info, + &pool_account, + asset_id, + amount, + ), + ConstantProduct(constant_product_pool_info) => Uniswap::::get_exchange_value( + &constant_product_pool_info, + &pool_account, + asset_id, + amount, + ), + PoolConfiguration::LiquidityBootstrapping(liquidity_bootstrapping_pool_info) => + LiquidityBootstrapping::::get_exchange_value( + liquidity_bootstrapping_pool_info, + pool_account, + asset_id, + amount, + ), + } + } + + #[transactional] + fn add_liquidity( + who: &Self::AccountId, + pool_id: Self::PoolId, + base_amount: Self::Balance, + quote_amount: Self::Balance, + min_mint_amount: Self::Balance, + keep_alive: bool, + ) -> Result<(), DispatchError> { + let pool = Self::get_pool(pool_id)?; + let pool_account = Self::account_id(&pool_id); + match pool { + PoolConfiguration::StableSwap(stable_swap_pool_info) => { + let mint_amount = StableSwap::::add_liquidity( + who, + stable_swap_pool_info, + pool_account, + base_amount, + quote_amount, + min_mint_amount, + keep_alive, + )?; + Self::deposit_event(Event::::LiquidityAdded { + who: who.clone(), + pool_id, + base_amount, + quote_amount, + minted_lp: mint_amount, + }); + }, + ConstantProduct(constant_product_pool_info) => { + let mint_amount = Uniswap::::add_liquidity( + who, + constant_product_pool_info, + pool_account, + base_amount, + quote_amount, + min_mint_amount, + keep_alive, + )?; + Self::deposit_event(Event::::LiquidityAdded { + who: who.clone(), + pool_id, + base_amount, + quote_amount, + minted_lp: mint_amount, + }); + }, + PoolConfiguration::LiquidityBootstrapping(liquidity_bootstrapping_pool_info) => { + LiquidityBootstrapping::::add_liquidity( + who, + liquidity_bootstrapping_pool_info, + pool_account, + base_amount, + quote_amount, + min_mint_amount, + keep_alive, + )?; + Self::deposit_event(Event::::LiquidityAdded { + who: who.clone(), + pool_id, + base_amount, + quote_amount, + minted_lp: T::Balance::zero(), + }); + }, + } + // TODO refactor event publishing with cu-23v2y3n + Ok(()) + } + + #[transactional] + fn remove_liquidity( + who: &Self::AccountId, + pool_id: Self::PoolId, + lp_amount: Self::Balance, + min_base_amount: Self::Balance, + min_quote_amount: Self::Balance, + ) -> Result<(), DispatchError> { + let pool = Self::get_pool(pool_id)?; + let pool_account = Self::account_id(&pool_id); + match pool { + PoolConfiguration::StableSwap(stable_swap_pool_info) => { + let (base_amount, quote_amount, updated_lp) = + StableSwap::::remove_liquidity( + who, + stable_swap_pool_info, + pool_account, + lp_amount, + min_base_amount, + min_quote_amount, + )?; + Self::deposit_event(Event::::LiquidityRemoved { + pool_id, + who: who.clone(), + base_amount, + quote_amount, + total_issuance: updated_lp, + }); + }, + ConstantProduct(constant_product_pool_info) => { + let (base_amount, quote_amount, updated_lp) = Uniswap::::remove_liquidity( + who, + constant_product_pool_info, + pool_account, + lp_amount, + min_base_amount, + min_quote_amount, + )?; + Self::deposit_event(Event::::LiquidityRemoved { + pool_id, + who: who.clone(), + base_amount, + quote_amount, + total_issuance: updated_lp, + }); + }, + PoolConfiguration::LiquidityBootstrapping(liquidity_bootstrapping_pool_info) => { + let (base_amount, quote_amount) = + LiquidityBootstrapping::::remove_liquidity( + who, + pool_id, + liquidity_bootstrapping_pool_info, + pool_account, + lp_amount, + min_base_amount, + min_quote_amount, + )?; + Self::deposit_event(Event::PoolDeleted { pool_id, base_amount, quote_amount }); + }, + } + Ok(()) + } + + #[transactional] + fn exchange( + who: &Self::AccountId, + pool_id: Self::PoolId, + pair: CurrencyPair, + quote_amount: Self::Balance, + min_receive: Self::Balance, + keep_alive: bool, + ) -> Result { + let pool = Self::get_pool(pool_id)?; + let pool_account = Self::account_id(&pool_id); + match pool { + PoolConfiguration::StableSwap(pool) => { + // /!\ NOTE(hussein-aitlahcen): after this check, do not use pool.pair as the + // provided pair might have been swapped + ensure!(pair == pool.pair, Error::::PairMismatch); + let (base_amount_excluding_fees, quote_amount, lp_fees, protocol_fees) = + StableSwap::::do_compute_swap(&pool, &pool_account, quote_amount, true)?; + + ensure!( + base_amount_excluding_fees >= min_receive, + Error::::CannotRespectMinimumRequested + ); + T::Assets::transfer(pair.quote, who, &pool_account, quote_amount, keep_alive)?; + + // NOTE(hussein-aitlance): no need to keep alive the pool account + T::Assets::transfer( + pair.base, + &pool_account, + &pool.owner, + protocol_fees, + false, + )?; + T::Assets::transfer( + pair.base, + &pool_account, + who, + base_amount_excluding_fees, + false, + )?; + Self::deposit_event(Event::::Swapped { + pool_id, + who: who.clone(), + base_asset: pair.base, + quote_asset: pair.quote, + base_amount: base_amount_excluding_fees, + quote_amount, + fee: lp_fees.safe_add(&protocol_fees)?, + }); + + Ok(base_amount_excluding_fees) + }, + ConstantProduct(constant_product_pool_info) => { + let (base_amount, quote_amount_excluding_fees, lp_fees, owner_fees) = + Uniswap::::do_compute_swap( + &constant_product_pool_info, + &pool_account, + pair, + quote_amount, + true, + )?; + let total_fees = lp_fees.safe_add(&owner_fees)?; + let quote_amount_including_fees = + quote_amount_excluding_fees.safe_add(&total_fees)?; + + ensure!(base_amount >= min_receive, Error::::CannotRespectMinimumRequested); + + T::Assets::transfer( + pair.quote, + who, + &pool_account, + quote_amount_including_fees, + keep_alive, + )?; + // NOTE(hussein-aitlance): no need to keep alive the pool account + T::Assets::transfer( + pair.quote, + &pool_account, + &constant_product_pool_info.owner, + owner_fees, + false, + )?; + T::Assets::transfer(pair.base, &pool_account, who, base_amount, false)?; + + Self::deposit_event(Event::::Swapped { + pool_id, + who: who.clone(), + base_asset: pair.base, + quote_asset: pair.quote, + base_amount, + quote_amount: quote_amount_excluding_fees, + fee: total_fees, + }); + + Ok(base_amount) + }, + PoolConfiguration::LiquidityBootstrapping(liquidity_bootstrapping_pool_info) => { + let current_block = frame_system::Pallet::::current_block_number(); + let (fees, base_amount) = LiquidityBootstrapping::::do_get_exchange( + liquidity_bootstrapping_pool_info, + &pool_account, + pair, + current_block, + quote_amount, + true, + )?; + + ensure!(base_amount >= min_receive, Error::::CannotRespectMinimumRequested); + + T::Assets::transfer(pair.quote, who, &pool_account, quote_amount, keep_alive)?; + // NOTE(hussein-aitlance): no need to keep alive the pool account + T::Assets::transfer(pair.base, &pool_account, who, base_amount, false)?; + Self::deposit_event(Event::::Swapped { + pool_id, + who: who.clone(), + base_asset: pair.base, + quote_asset: pair.quote, + base_amount, + quote_amount, + fee: fees, + }); + Ok(base_amount) + }, + } + + // TODO refactor event publishing with cu-23v2y3n + } + + #[transactional] + fn buy( + who: &Self::AccountId, + pool_id: Self::PoolId, + asset_id: Self::AssetId, + amount: Self::Balance, + keep_alive: bool, + ) -> Result { + let pool = Self::get_pool(pool_id)?; + match pool { + PoolConfiguration::StableSwap(pool) => { + let pair = + if asset_id == pool.pair.base { pool.pair } else { pool.pair.swap() }; + // Since when buying asset user can't executed exchange as he don't know how + // much amount of token he has to trade-in to get expected buy tokens. + // So we compute price assuming user wants to sell instead of buy. + // And then do exchange computed amount with token indices flipped. + let dx = Self::get_exchange_value(pool_id, asset_id, amount)?; + Self::exchange(who, pool_id, pair, dx, T::Balance::zero(), keep_alive)?; + Ok(amount) + }, + ConstantProduct(constant_product_pool) => { + let pair = if asset_id == constant_product_pool.pair.base { + constant_product_pool.pair + } else { + constant_product_pool.pair.swap() + }; + let quote_amount = Self::get_exchange_value(pool_id, asset_id, amount)?; + Self::exchange(who, pool_id, pair, quote_amount, T::Balance::zero(), keep_alive) + }, + PoolConfiguration::LiquidityBootstrapping(liquidity_bootstrapping_pool_info) => { + let pair = if asset_id == liquidity_bootstrapping_pool_info.pair.base { + liquidity_bootstrapping_pool_info.pair + } else { + liquidity_bootstrapping_pool_info.pair.swap() + }; + let quote_amount = Self::get_exchange_value(pool_id, asset_id, amount)?; + Self::exchange(who, pool_id, pair, quote_amount, T::Balance::zero(), keep_alive) + }, + } + } + + #[transactional] + fn sell( + who: &Self::AccountId, + pool_id: Self::PoolId, + asset_id: Self::AssetId, + amount: Self::Balance, + keep_alive: bool, + ) -> Result { + let pool = Self::get_pool(pool_id)?; + match pool { + PoolConfiguration::StableSwap(pool) => { + let pair = + if asset_id == pool.pair.base { pool.pair.swap() } else { pool.pair }; + Self::exchange(who, pool_id, pair, amount, Self::Balance::zero(), keep_alive) + }, + ConstantProduct(constant_product_pool) => { + let pair = if asset_id == constant_product_pool.pair.base { + constant_product_pool.pair.swap() + } else { + constant_product_pool.pair + }; + Self::exchange(who, pool_id, pair, amount, T::Balance::zero(), keep_alive) + }, + PoolConfiguration::LiquidityBootstrapping(liquidity_bootstrapping_pool_info) => { + let pair = if asset_id == liquidity_bootstrapping_pool_info.pair.base { + liquidity_bootstrapping_pool_info.pair.swap() + } else { + liquidity_bootstrapping_pool_info.pair + }; + Self::exchange(who, pool_id, pair, amount, T::Balance::zero(), keep_alive) + }, + } + } + } +} diff --git a/frame/pablo/src/liquidity_bootstrapping.rs b/frame/pablo/src/liquidity_bootstrapping.rs new file mode 100644 index 00000000000..028b3ed7899 --- /dev/null +++ b/frame/pablo/src/liquidity_bootstrapping.rs @@ -0,0 +1,209 @@ +use crate::{ + AccountIdOf, AssetIdOf, BalanceOf, Config, Error, LiquidityBootstrappingPoolInfoOf, + PoolConfiguration, PoolCount, Pools, +}; +use composable_maths::dex::constant_product::{compute_out_given_in, compute_spot_price}; +use composable_support::validation::{Validate, Validated}; +use composable_traits::{currency::LocalAssets, defi::CurrencyPair, dex::SaleState, math::SafeAdd}; +use frame_support::{ + pallet_prelude::*, + traits::fungibles::{Inspect, Transfer}, + transactional, +}; +use frame_system::pallet_prelude::BlockNumberFor; +use sp_runtime::traits::{BlockNumberProvider, Convert, One, Zero}; +use std::marker::PhantomData; + +#[derive(Copy, Clone, Encode, Decode, MaxEncodedLen, PartialEq, Eq, TypeInfo)] +pub struct PoolIsValid(PhantomData); + +impl Validate, PoolIsValid> for PoolIsValid { + fn validate( + input: LiquidityBootstrappingPoolInfoOf, + ) -> Result, &'static str> { + if input.pair.base == input.pair.quote { + return Err("Pair elements must be distinct.") + } + + if input.sale.end <= input.sale.start { + return Err("Sale end must be after start.") + } + + if input.sale.duration() < T::LbpMinSaleDuration::get() { + return Err("Sale duration must be greater than minimum duration.") + } + + if input.sale.duration() > T::LbpMaxSaleDuration::get() { + return Err("Sale duration must not exceed maximum duration.") + } + + if input.sale.initial_weight < input.sale.final_weight { + return Err("Initial weight must be greater than final weight.") + } + + if input.sale.initial_weight > T::LbpMaxInitialWeight::get() { + return Err("Initial weight must not exceed the defined maximum.") + } + + if input.sale.final_weight < T::LbpMinFinalWeight::get() { + return Err("Final weight must not be lower than the defined minimum.") + } + + Ok(input) + } +} + +pub(crate) struct LiquidityBootstrapping(PhantomData); + +impl LiquidityBootstrapping { + pub(crate) fn do_create_pool( + pool: Validated, PoolIsValid>, + ) -> Result { + let pool_id = + PoolCount::::try_mutate(|pool_count| -> Result { + let pool_id = *pool_count; + Pools::::insert( + pool_id, + PoolConfiguration::LiquidityBootstrapping(pool.clone().value()), + ); + *pool_count = pool_id.safe_add(&T::PoolId::one())?; + Ok(pool_id) + })?; + + Ok(pool_id) + } + + fn ensure_sale_state( + pool: &LiquidityBootstrappingPoolInfoOf, + current_block: BlockNumberFor, + expected_sale_state: SaleState, + ) -> Result<(), DispatchError> { + ensure!( + pool.sale.state(current_block) == expected_sale_state, + Error::::InvalidSaleState + ); + Ok(()) + } + + #[allow(dead_code)] + pub(crate) fn do_spot_price( + pool: LiquidityBootstrappingPoolInfoOf, + pool_account: AccountIdOf, + pair: CurrencyPair>, + current_block: BlockNumberFor, + ) -> Result, DispatchError> { + Self::ensure_sale_state(&pool, current_block, SaleState::Ongoing)?; + ensure!(pair == pool.pair, Error::::PairMismatch); + + let weights = pool.sale.current_weights(current_block)?; + + let (wo, wi) = if pair.base == pool.pair.base { weights } else { (weights.1, weights.0) }; + + let bi = T::Convert::convert(T::Assets::balance(pair.quote, &pool_account)); + let bo = T::Convert::convert(T::Assets::balance(pair.base, &pool_account)); + let base_unit = T::LocalAssets::unit::(pair.base)?; + + let spot_price = compute_spot_price(wi, wo, bi, bo, base_unit)?; + + Ok(T::Convert::convert(spot_price)) + } + + pub(crate) fn do_get_exchange( + pool: LiquidityBootstrappingPoolInfoOf, + pool_account: &AccountIdOf, + pair: CurrencyPair>, + current_block: BlockNumberFor, + quote_amount: BalanceOf, + apply_fees: bool, + ) -> Result<(BalanceOf, BalanceOf), DispatchError> { + Self::ensure_sale_state(&pool, current_block, SaleState::Ongoing)?; + + ensure!(pair == pool.pair, Error::::PairMismatch); + ensure!(!quote_amount.is_zero(), Error::::InvalidAmount); + + let weights = pool.sale.current_weights(current_block)?; + + let (wo, wi) = if pair.base == pool.pair.base { weights } else { (weights.1, weights.0) }; + + let ai = T::Convert::convert(quote_amount); + let (ai_minus_fees, fees) = if apply_fees { + let fees = pool.fee.mul_floor(ai); + // Safe as fees is a fraction of ai + (ai - fees, fees) + } else { + (ai, 0) + }; + let bi = T::Convert::convert(T::Assets::balance(pair.quote, &pool_account)); + let bo = T::Convert::convert(T::Assets::balance(pair.base, &pool_account)); + + let base_amount = compute_out_given_in(wi, wo, bi, bo, ai_minus_fees)?; + + Ok((T::Convert::convert(fees), T::Convert::convert(base_amount))) + } + + pub(crate) fn get_exchange_value( + pool: LiquidityBootstrappingPoolInfoOf, + pool_account: AccountIdOf, + asset_id: T::AssetId, + amount: T::Balance, + ) -> Result { + let pair = if asset_id == pool.pair.base { pool.pair.swap() } else { pool.pair }; + let current_block = frame_system::Pallet::::current_block_number(); + let (_, base_amount) = + Self::do_get_exchange(pool, &pool_account, pair, current_block, amount, false)?; + Ok(base_amount) + } + + #[transactional] + pub(crate) fn add_liquidity( + who: &T::AccountId, + pool: LiquidityBootstrappingPoolInfoOf, + pool_account: AccountIdOf, + base_amount: T::Balance, + quote_amount: T::Balance, + _: T::Balance, + keep_alive: bool, + ) -> Result<(), DispatchError> { + let current_block = frame_system::Pallet::::current_block_number(); + Self::ensure_sale_state(&pool, current_block, SaleState::NotStarted)?; + + ensure!(pool.owner == *who, Error::::MustBeOwner); + ensure!(!base_amount.is_zero() && !quote_amount.is_zero(), Error::::InvalidAmount); + + // NOTE(hussein-aitlahcen): as we only allow the owner to provide liquidity, we don't + // mint any LP. + T::Assets::transfer(pool.pair.base, who, &pool_account, base_amount, keep_alive)?; + T::Assets::transfer(pool.pair.quote, who, &pool_account, quote_amount, keep_alive)?; + + Ok(()) + } + + #[transactional] + pub(crate) fn remove_liquidity( + who: &T::AccountId, + pool_id: T::PoolId, + pool: LiquidityBootstrappingPoolInfoOf, + pool_account: AccountIdOf, + _: T::Balance, + _: T::Balance, + _: T::Balance, + ) -> Result<(BalanceOf, BalanceOf), DispatchError> { + let current_block = frame_system::Pallet::::current_block_number(); + Self::ensure_sale_state(&pool, current_block, SaleState::Ended)?; + + ensure!(pool.owner == *who, Error::::MustBeOwner); + + let repatriate = |a| -> Result, DispatchError> { + let a_balance = T::Assets::balance(a, &pool_account); + // NOTE(hussein-aitlahcen): not need to keep the pool account alive. + T::Assets::transfer(a, &pool_account, who, a_balance, false)?; + Ok(a_balance) + }; + + let base_amount = repatriate(pool.pair.base)?; + let quote_amount = repatriate(pool.pair.quote)?; + + Pools::::remove(pool_id); + Ok((base_amount, quote_amount)) + } +} diff --git a/frame/pablo/src/liquidity_bootstrapping_tests.rs b/frame/pablo/src/liquidity_bootstrapping_tests.rs new file mode 100644 index 00000000000..9a11b796e74 --- /dev/null +++ b/frame/pablo/src/liquidity_bootstrapping_tests.rs @@ -0,0 +1,673 @@ +use crate::{ + liquidity_bootstrapping::PoolIsValid, + mock::{Pablo, *}, + Error, PoolInitConfiguration, +}; +use composable_support::validation::Validated; +use composable_tests_helpers::test::helper::default_acceptable_computation_error; +use composable_traits::{ + defi::CurrencyPair, + dex::{LiquidityBootstrappingPoolInfo, Sale}, +}; +use frame_support::{ + assert_noop, assert_ok, + traits::fungibles::{Inspect, Mutate}, +}; +use sp_runtime::Permill; + +fn valid_pool( +) -> Validated, PoolIsValid> { + let pair = CurrencyPair::new(PROJECT_TOKEN, USDT); + let owner = ALICE; + let duration = MaxSaleDuration::get(); + let start = 0; + let end = start + duration; + let initial_weight = MaxInitialWeight::get(); + let final_weight = MinFinalWeight::get(); + let fee = Permill::from_perthousand(1); + Validated::new(LiquidityBootstrappingPoolInfo { + owner, + pair, + sale: Sale { start, end, initial_weight, final_weight }, + fee, + }) + .expect("impossible; qed;") +} + +fn with_pool( + owner: AccountId, + sale_duration: BlockNumber, + initial_weight: Permill, + final_weight: Permill, + fee: Permill, + f: impl FnOnce( + PoolId, + &LiquidityBootstrappingPoolInfo, + &dyn Fn(BlockNumber), + &dyn Fn(), + ) -> T, +) -> T { + let random_start = 0xDEADC0DE; + let pair = CurrencyPair::new(PROJECT_TOKEN, USDT); + let end = random_start + sale_duration; + let pool = Validated::<_, PoolIsValid>::new(LiquidityBootstrappingPoolInfo { + owner, + pair, + sale: Sale { start: random_start, end, initial_weight, final_weight }, + fee, + }) + .expect("impossible; qed;"); + new_test_ext().execute_with(|| -> T { + // Actually create the pool. + assert_ok!(Pablo::create( + Origin::signed(ALICE), + PoolInitConfiguration::LiquidityBootstrapping(pool.value()) + )); + + // Will always start to 0. + let pool_id = 0; + + // Relative to sale start. + let set_block = |x: BlockNumber| { + System::set_block_number(random_start + x); + }; + + // Forward to sale end. + let end_sale = || { + set_block(sale_duration + 1); + }; + + f(pool_id, &pool, &set_block, &end_sale) + }) +} + +fn within_sale_with_liquidity( + owner: AccountId, + sale_duration: BlockNumber, + initial_weight: Permill, + final_weight: Permill, + fee: Permill, + initial_project_tokens: Balance, + initial_usdt: Balance, + f: impl FnOnce( + PoolId, + &LiquidityBootstrappingPoolInfo, + &dyn Fn(BlockNumber), + &dyn Fn(), + ) -> T, +) -> T { + with_pool( + owner, + sale_duration, + initial_weight, + final_weight, + fee, + |pool_id, pool, set_block, end_sale| -> T { + assert_ok!(Tokens::mint_into(PROJECT_TOKEN, &owner, initial_project_tokens)); + assert_ok!(Tokens::mint_into(USDT, &owner, initial_usdt)); + + // Add initial liquidity. + assert_ok!(Pablo::add_liquidity( + Origin::signed(owner), + pool_id, + initial_project_tokens, + initial_usdt, + 0_u128, + false + )); + + // Actually start the sale. + set_block(0); + + f(pool_id, pool, set_block, end_sale) + }, + ) +} + +mod create { + use super::*; + + #[test] + fn arbitrary_user_can_create() { + new_test_ext().execute_with(|| { + assert_ok!(Pablo::create( + Origin::signed(ALICE), + PoolInitConfiguration::LiquidityBootstrapping(valid_pool().value()) + ),); + }); + } + + // TODO enable with cu-23v3155 + // #[test] + // fn admin_can_create() { + // new_test_ext().execute_with(|| { + // assert_ok!(Pablo::create(Origin::root(), + // PoolInitConfiguration::LiquidityBootstrapping(valid_pool().value()))); }); + // } +} + +mod sell { + use super::*; + + #[test] + fn can_sell_one_to_one() { + /* 50% weight = constant product, no fees. + */ + let unit = 1_000_000_000_000; + let initial_project_tokens = 1_000_000 * unit; + let initial_usdt = 1_000_000 * unit; + let sale_duration = MaxSaleDuration::get(); + let initial_weight = Permill::one() / 2; + let final_weight = Permill::one() / 2; + let fee = Permill::zero(); + within_sale_with_liquidity( + ALICE, + sale_duration, + initial_weight, + final_weight, + fee, + initial_project_tokens, + initial_usdt, + |pool_id, pool, _, _| { + // Buy project token + assert_ok!(Tokens::mint_into(USDT, &BOB, unit)); + assert_ok!(Pablo::sell(Origin::signed(BOB), pool_id, pool.pair.quote, unit, false)); + assert_ok!(default_acceptable_computation_error( + Tokens::balance(PROJECT_TOKEN, &BOB), + unit + )); + }, + ) + } +} + +mod buy { + use super::*; + + #[test] + fn can_buy_one_to_one() { + /* 50% weight = constant product, no fees. + */ + let unit = 1_000_000_000_000; + let initial_project_tokens = 1_000_000 * unit; + let initial_usdt = 1_000_000 * unit; + let sale_duration = MaxSaleDuration::get(); + let initial_weight = Permill::one() / 2; + let final_weight = Permill::one() / 2; + let fee = Permill::zero(); + within_sale_with_liquidity( + ALICE, + sale_duration, + initial_weight, + final_weight, + fee, + initial_project_tokens, + initial_usdt, + |pool_id, pool, _, _| { + // Buy project token + assert_ok!(Tokens::mint_into(USDT, &BOB, unit)); + assert_ok!(Pablo::buy(Origin::signed(BOB), pool_id, pool.pair.base, unit, false)); + assert_ok!(default_acceptable_computation_error( + Tokens::balance(PROJECT_TOKEN, &BOB), + unit + )); + }, + ) + } +} + +mod remove_liquidity { + use super::*; + + #[test] + fn cannot_remove_before_sale_end() { + let owner = ALICE; + let sale_duration = MaxSaleDuration::get(); + let initial_weight = Permill::one() / 2; + let final_weight = Permill::one() / 2; + let fee = Permill::zero(); + let unit = 1_000_000_000_000; + let initial_project_tokens = 1_000_000 * unit; + let initial_usdt = 1_000_000 * unit; + with_pool(owner, sale_duration, initial_weight, final_weight, fee, |pool_id, _, _, _| { + assert_ok!(Tokens::mint_into(PROJECT_TOKEN, &owner, initial_project_tokens)); + assert_ok!(Tokens::mint_into(USDT, &owner, initial_usdt)); + assert_noop!( + Pablo::remove_liquidity(Origin::signed(owner), pool_id, 0, 0, 0), + Error::::InvalidSaleState + ); + }); + } + + #[test] + fn can_remove_after_sale_end() { + let owner = ALICE; + let sale_duration = MaxSaleDuration::get(); + let initial_weight = Permill::one() / 2; + let final_weight = Permill::one() / 2; + let fee = Permill::zero(); + let unit = 1_000_000_000_000; + let initial_project_tokens = 1_000_000 * unit; + let initial_usdt = 1_000_000 * unit; + with_pool( + owner, + sale_duration, + initial_weight, + final_weight, + fee, + |pool_id, _, _, end_sale| { + assert_ok!(Tokens::mint_into(PROJECT_TOKEN, &owner, initial_project_tokens)); + assert_ok!(Tokens::mint_into(USDT, &owner, initial_usdt)); + end_sale(); + assert_ok!(Pablo::remove_liquidity(Origin::signed(owner), pool_id, 0, 0, 0)); + assert_eq!(Tokens::balance(PROJECT_TOKEN, &owner), initial_project_tokens); + assert_eq!(Tokens::balance(USDT, &owner), initial_usdt); + }, + ); + } +} + +mod add_liquidity { + use super::*; + + #[test] + fn can_add_liquidity_before_sale() { + let owner = ALICE; + let sale_duration = MaxSaleDuration::get(); + let initial_weight = Permill::one() / 2; + let final_weight = Permill::one() / 2; + let fee = Permill::zero(); + let unit = 1_000_000_000_000; + let initial_project_tokens = 1_000_000 * unit; + let initial_usdt = 1_000_000 * unit; + with_pool(owner, sale_duration, initial_weight, final_weight, fee, |pool_id, _, _, _| { + assert_ok!(Tokens::mint_into(PROJECT_TOKEN, &owner, initial_project_tokens)); + assert_ok!(Tokens::mint_into(USDT, &owner, initial_usdt)); + assert_ok!(Pablo::add_liquidity( + Origin::signed(owner), + pool_id, + initial_project_tokens, + initial_usdt, + 0_128, + false + )); + }); + } + + #[test] + fn cannot_add_liquidity_after_sale_started() { + let owner = ALICE; + let sale_duration = MaxSaleDuration::get(); + let initial_weight = Permill::one() / 2; + let final_weight = Permill::one() / 2; + let fee = Permill::zero(); + let unit = 1_000_000_000_000; + let initial_project_tokens = 1_000_000 * unit; + let initial_usdt = 1_000_000 * unit; + with_pool( + owner, + sale_duration, + initial_weight, + final_weight, + fee, + |pool_id, _, set_sale_block, _| { + assert_ok!(Tokens::mint_into(PROJECT_TOKEN, &owner, initial_project_tokens)); + assert_ok!(Tokens::mint_into(USDT, &owner, initial_usdt)); + set_sale_block(0); + assert_noop!( + Pablo::add_liquidity( + Origin::signed(owner), + pool_id, + initial_project_tokens, + initial_usdt, + 0_128, + false + ), + Error::::InvalidSaleState + ); + }, + ); + } +} + +mod invalid_pool { + use super::*; + + #[test] + fn final_weight_below_minimum() { + new_test_ext().execute_with(|| { + let pair = CurrencyPair::new(PROJECT_TOKEN, USDT); + let owner = ALICE; + let duration = MaxSaleDuration::get() - 1; + let start = 0; + let end = start + duration; + let initial_weight = MaxInitialWeight::get(); + let final_weight = MinFinalWeight::get() - Permill::from_parts(1); + let fee = Permill::from_perthousand(1); + assert!(Validated::<_, PoolIsValid>::new(LiquidityBootstrappingPoolInfo { + owner, + pair, + sale: Sale { start, end, initial_weight, final_weight }, + fee, + }) + .is_err()); + }); + } + + #[test] + fn initial_weight_above_maximum() { + new_test_ext().execute_with(|| { + let pair = CurrencyPair::new(PROJECT_TOKEN, USDT); + let owner = ALICE; + let duration = MaxSaleDuration::get() - 1; + let start = 0; + let end = start + duration; + let initial_weight = MaxInitialWeight::get() + Permill::from_parts(1); + let final_weight = MinFinalWeight::get(); + let fee = Permill::from_perthousand(1); + assert!(Validated::<_, PoolIsValid>::new(LiquidityBootstrappingPoolInfo { + owner, + pair, + sale: Sale { start, end, initial_weight, final_weight }, + fee, + }) + .is_err()); + }); + } + + #[test] + fn final_weight_above_initial_weight() { + new_test_ext().execute_with(|| { + let pair = CurrencyPair::new(PROJECT_TOKEN, USDT); + let owner = ALICE; + let duration = MaxSaleDuration::get() - 1; + let start = 0; + let end = start + duration; + let initial_weight = MinFinalWeight::get(); + let final_weight = MaxInitialWeight::get(); + let fee = Permill::from_perthousand(1); + assert!(Validated::<_, PoolIsValid>::new(LiquidityBootstrappingPoolInfo { + owner, + pair, + sale: Sale { start, end, initial_weight, final_weight }, + fee, + }) + .is_err()); + }); + } + + #[test] + fn end_before_start() { + new_test_ext().execute_with(|| { + let pair = CurrencyPair::new(PROJECT_TOKEN, USDT); + let owner = ALICE; + let start = 1; + let end = 0; + let initial_weight = MaxInitialWeight::get(); + let final_weight = MinFinalWeight::get(); + let fee = Permill::from_perthousand(1); + assert!(Validated::<_, PoolIsValid>::new(LiquidityBootstrappingPoolInfo { + owner, + pair, + sale: Sale { start, end, initial_weight, final_weight }, + fee, + }) + .is_err()); + }); + } + + #[test] + fn above_maximum_sale_duration() { + new_test_ext().execute_with(|| { + let pair = CurrencyPair::new(PROJECT_TOKEN, USDT); + let owner = ALICE; + let duration = MaxSaleDuration::get() + 1; + let start = 0; + let end = start + duration; + let initial_weight = MaxInitialWeight::get(); + let final_weight = MinFinalWeight::get(); + let fee = Permill::from_perthousand(1); + assert!(Validated::<_, PoolIsValid>::new(LiquidityBootstrappingPoolInfo { + owner, + pair, + sale: Sale { start, end, initial_weight, final_weight }, + fee, + }) + .is_err()); + }); + } + + #[test] + fn below_minimum_sale_duration() { + new_test_ext().execute_with(|| { + let pair = CurrencyPair::new(PROJECT_TOKEN, USDT); + let owner = ALICE; + let duration = MinSaleDuration::get() - 1; + let start = 0; + let end = start + duration; + let initial_weight = MaxInitialWeight::get(); + let final_weight = MinFinalWeight::get(); + let fee = Permill::from_perthousand(1); + assert!(Validated::<_, PoolIsValid>::new(LiquidityBootstrappingPoolInfo { + owner, + pair, + sale: Sale { start, end, initial_weight, final_weight }, + fee, + }) + .is_err()); + }); + } +} + +#[cfg(feature = "visualization")] +mod visualization { + use super::*; + use crate::liquidity_bootstrapping::LiquidityBootstrapping; + + #[test] + fn plot() { + new_test_ext().execute_with(|| { + let pair = CurrencyPair::new(PROJECT_TOKEN, USDT); + let owner = ALICE; + let two_days = 48 * 3600 / 12; + let window = 100; + let pool = LiquidityBootstrappingPoolInfo { + owner, + pair, + sale: Sale { + start: window, + end: two_days + window, + initial_weight: Permill::from_percent(92), + final_weight: Permill::from_percent(50), + }, + fee: Permill::from_perthousand(1), + }; + let pool_id = + Pablo::do_create_pool(&owner, PoolInitConfiguration::LiquidityBootstrapping(pool)) + .expect("impossible; qed;"); + + let unit = 1_000_000_000_000; + let initial_project_tokens = 100_000_000 * unit; + let initial_usdt = 1_000_000 * unit; + + assert_ok!(Tokens::mint_into(PROJECT_TOKEN, &ALICE, initial_project_tokens)); + assert_ok!(Tokens::mint_into(USDT, &ALICE, initial_usdt)); + assert_ok!(Pablo::add_liquidity( + Origin::signed(ALICE), + pool_id, + initial_project_tokens, + initial_usdt, + 0, + false + )); + let pool_account = Pablo::account_id(&pool_id); + + { + let points = (pool.sale.start..pool.sale.end) + .map(|block| { + ( + block, + LiquidityBootstrapping::::do_spot_price( + pool, + pool_account, + pool.pair, + block, + ) + .expect("impossible; qed;") as f64 / + unit as f64, + ) + }) + .collect::>(); + let max_amount = points.iter().copied().fold(f64::NAN, |x, (_, y)| f64::max(x, y)); + + use plotters::prelude::*; + let area = BitMapBackend::new("./plots/lbp/lbp_spot_price.png", (1024, 768)) + .into_drawing_area(); + area.fill(&WHITE).unwrap(); + + let mut chart = ChartBuilder::on(&area) + .caption("Spot price", ("Arial", 50).into_font()) + .margin(100u32) + .x_label_area_size(30u32) + .y_label_area_size(30u32) + .build_cartesian_2d(pool.sale.start..pool.sale.end, 0f64..max_amount) + .unwrap(); + + chart.configure_mesh().draw().unwrap(); + chart + .draw_series(LineSeries::new(points, &RED)) + .unwrap() + .label("base") + .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED)); + chart + .configure_series_labels() + .background_style(&WHITE.mix(0.8)) + .border_style(&BLACK) + .draw() + .unwrap(); + } + + { + use plotters::prelude::*; + + let plot_swap = |pair, swap_amount, name, caption| { + let points = (pool.sale.start..pool.sale.end) + .map(|block| { + let (fees, base_amount) = + LiquidityBootstrapping::::do_get_exchange( + pool, + &pool_account, + pair, + block, + swap_amount, + true, + ) + .expect("impossible; qed;"); + (block, fees / unit, base_amount / unit) + }) + .collect::>(); + let amounts = + points.clone().iter().copied().map(|(x, _, y)| (x, y)).collect::>(); + let amounts_with_fees = + points.into_iter().map(|(x, y, z)| (x, y + z)).collect::>(); + + let max_amount = + amounts_with_fees.iter().copied().map(|(_, x)| x).max().unwrap(); + + let area = BitMapBackend::new(name, (1024, 768)).into_drawing_area(); + area.fill(&WHITE).unwrap(); + + let mut chart = ChartBuilder::on(&area) + .caption(caption, ("Arial", 50).into_font()) + .margin(100u32) + .x_label_area_size(30u32) + .y_label_area_size(30u32) + .build_cartesian_2d(pool.sale.start..pool.sale.end, 0..max_amount) + .unwrap(); + + chart.configure_mesh().draw().unwrap(); + chart + .draw_series(LineSeries::new(amounts, &BLUE)) + .unwrap() + .label("Received tokens fees applied") + .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &BLUE)); + chart + .draw_series(LineSeries::new(amounts_with_fees, &RED)) + .unwrap() + .label("Received tokens fees not applied") + .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED)); + chart + .configure_series_labels() + .background_style(&WHITE.mix(0.8)) + .border_style(&BLACK) + .draw() + .unwrap(); + }; + + let buy_amount = 500; + plot_swap( + pair, + buy_amount * unit, + "./plots/lbp/lbp_buy_project.png", + format!("Buy project tokens with {} USDT", buy_amount), + ); + let sell_amount = 100_000; + plot_swap( + pair.swap(), + sell_amount * unit, + "./plots/lbp/lbp_sell_project.png", + format!("Sell {} project tokens", sell_amount), + ); + } + + { + use plotters::prelude::*; + let area = BitMapBackend::new("./plots/lbp/lbp_weights.png", (1024, 768)) + .into_drawing_area(); + area.fill(&WHITE).unwrap(); + + let mut chart = ChartBuilder::on(&area) + .caption("y = weight", ("Arial", 50).into_font()) + .margin(100u32) + .x_label_area_size(30u32) + .y_label_area_size(30u32) + .build_cartesian_2d( + pool.sale.start..pool.sale.end, + 0..Permill::one().deconstruct(), + ) + .unwrap(); + + let points = (pool.sale.start..pool.sale.end).map(|block| { + (block, pool.sale.current_weights(block).expect("impossible; qed;")) + }); + + chart.configure_mesh().draw().unwrap(); + chart + .draw_series(LineSeries::new( + points + .clone() + .map(|(block, (base_weight, _))| (block, base_weight.deconstruct())), + &RED, + )) + .unwrap() + .label("base") + .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED)); + chart + .draw_series(LineSeries::new( + points + .map(|(block, (_, quote_weight))| (block, quote_weight.deconstruct())), + &BLUE, + )) + .unwrap() + .label("quote") + .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &BLUE)); + chart + .configure_series_labels() + .background_style(&WHITE.mix(0.8)) + .border_style(&BLACK) + .draw() + .unwrap(); + } + }); + } +} diff --git a/frame/pablo/src/mock.rs b/frame/pablo/src/mock.rs new file mode 100644 index 00000000000..f3a6e2012ca --- /dev/null +++ b/frame/pablo/src/mock.rs @@ -0,0 +1,142 @@ +use crate as pablo; +use frame_support::{parameter_types, traits::Everything, PalletId}; +use frame_system as system; +use orml_traits::parameter_type_with_key; + +use sp_arithmetic::traits::Zero; +use sp_core::H256; +use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, ConvertInto, IdentityLookup}, + Permill, +}; +use system::EnsureRoot; + +pub type CurrencyId = u128; +pub type BlockNumber = u64; + +pub const BTC: AssetId = 0; +pub const USDT: CurrencyId = 2; +pub const USDC: CurrencyId = 4; +pub const PROJECT_TOKEN: AssetId = 1; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +// Configure a mock runtime to test the pallet. +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Pablo: pablo::{Pallet, Call, Storage, Event}, + LpTokenFactory: pallet_currency_factory::{Pallet, Storage, Event}, + Tokens: orml_tokens::{Pallet, Call, Storage, Config, Event}, + } +); + +impl pallet_currency_factory::Config for Test { + type Event = Event; + type AssetId = CurrencyId; + type AddOrigin = EnsureRoot; + type ReserveOrigin = EnsureRoot; + type WeightInfo = (); +} + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const SS58Prefix: u8 = 42; +} + +pub type AccountId = u128; + +#[allow(dead_code)] +pub static ALICE: AccountId = 1; +#[allow(dead_code)] +pub static BOB: AccountId = 2; +#[allow(dead_code)] +pub static CHARLIE: AccountId = 3; +#[allow(dead_code)] +pub static CURVE_ADMIN_FEE_ACC_ID: AccountId = 4; + +impl system::Config for Test { + type BaseCallFilter = Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type Origin = Origin; + type Call = Call; + type Index = u64; + type BlockNumber = BlockNumber; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = SS58Prefix; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +pub type Balance = u128; +pub type AssetId = u128; +pub type Amount = i128; +pub type PoolId = u128; + +parameter_type_with_key! { + pub ExistentialDeposits: |_currency_id: AssetId| -> Balance { + Zero::zero() + }; +} + +impl orml_tokens::Config for Test { + type Event = Event; + type Balance = Balance; + type Amount = Amount; + type CurrencyId = AssetId; + type WeightInfo = (); + type ExistentialDeposits = ExistentialDeposits; + type OnDust = (); + type MaxLocks = (); + type DustRemovalWhitelist = Everything; +} + +parameter_types! { + pub Precision: u128 = 100_u128; + pub TestPalletID : PalletId = PalletId(*b"pablo_pa"); + pub MinSaleDuration: BlockNumber = 3600 / 12; + pub MaxSaleDuration: BlockNumber = 30 * 24 * 3600 / 12; + pub MaxInitialWeight: Permill = Permill::from_percent(95); + pub MinFinalWeight: Permill = Permill::from_percent(5); +} + +impl pablo::Config for Test { + type Event = Event; + type AssetId = AssetId; + type Balance = Balance; + type CurrencyFactory = LpTokenFactory; + type Assets = Tokens; + type Convert = ConvertInto; + type PoolId = PoolId; + type PalletId = TestPalletID; + type LocalAssets = LpTokenFactory; + type LbpMinSaleDuration = MinSaleDuration; + type LbpMaxSaleDuration = MaxSaleDuration; + type LbpMaxInitialWeight = MaxInitialWeight; + type LbpMinFinalWeight = MinFinalWeight; +} + +// Build genesis storage according to the mock runtime. +pub fn new_test_ext() -> sp_io::TestExternalities { + system::GenesisConfig::default().build_storage::().unwrap().into() +} diff --git a/frame/pablo/src/stable_swap.rs b/frame/pablo/src/stable_swap.rs new file mode 100644 index 00000000000..f3b10d86b67 --- /dev/null +++ b/frame/pablo/src/stable_swap.rs @@ -0,0 +1,266 @@ +use std::marker::PhantomData; + +use crate::{Config, Error, PoolConfiguration, PoolCount, Pools}; +use composable_maths::dex::stable_swap::{compute_base, compute_d}; +use composable_traits::{ + currency::{CurrencyFactory, RangeId}, + defi::CurrencyPair, + dex::StableSwapPoolInfo, + math::{safe_multiply_by_rational, SafeAdd, SafeSub}, +}; +use frame_support::{ + pallet_prelude::*, + traits::fungibles::{Inspect, Mutate, Transfer}, +}; +use sp_runtime::{ + traits::{CheckedAdd, Convert, One, Zero}, + ArithmeticError, DispatchError, Permill, +}; + +use sp_std::ops::Mul; + +pub(crate) struct StableSwap(PhantomData); + +impl StableSwap { + pub fn do_create_pool( + who: &T::AccountId, + pair: CurrencyPair, + amp_coeff: u16, + fee: Permill, + protocol_fee: Permill, + ) -> Result { + ensure!(amp_coeff > 0, Error::::AmpFactorMustBeGreaterThanZero); + ensure!(pair.base != pair.quote, Error::::InvalidPair); + + let total_fees = fee.checked_add(&protocol_fee).ok_or(ArithmeticError::Overflow)?; + ensure!(total_fees < Permill::one(), Error::::InvalidFees); + + let lp_token = T::CurrencyFactory::create(RangeId::LP_TOKENS)?; + // Add new pool + let pool_id = + PoolCount::::try_mutate(|pool_count| -> Result { + let pool_id = *pool_count; + + Pools::::insert( + pool_id, + PoolConfiguration::StableSwap(StableSwapPoolInfo { + owner: who.clone(), + pair, + lp_token, + amplification_coefficient: amp_coeff, + fee, + protocol_fee, + }), + ); + *pool_count = pool_id.safe_add(&T::PoolId::one())?; + Ok(pool_id) + })?; + + Ok(pool_id) + } + + fn get_invariant( + base_asset_aum: T::Balance, + quote_asset_aum: T::Balance, + amp_coeff: T::Balance, + ) -> Result { + let d = compute_d( + T::Convert::convert(base_asset_aum), + T::Convert::convert(quote_asset_aum), + T::Convert::convert(amp_coeff), + )?; + + Ok(T::Convert::convert(d)) + } + + pub fn get_exchange_value( + pool: &StableSwapPoolInfo, + pool_account: &T::AccountId, + asset_id: T::AssetId, + amount: T::Balance, + ) -> Result { + let pair = if asset_id == pool.pair.base { pool.pair } else { pool.pair.swap() }; + let pool_base_aum = T::Assets::balance(pair.base, pool_account); + let pool_quote_aum = T::Assets::balance(pair.quote, pool_account); + let amp = T::Convert::convert(pool.amplification_coefficient.into()); + let d = Self::get_invariant(pool_base_aum, pool_quote_aum, amp)?; + let new_quote_amount = pool_quote_aum.safe_add(&amount)?; + let new_base_amount = T::Convert::convert(compute_base( + T::Convert::convert(new_quote_amount), + T::Convert::convert(amp), + T::Convert::convert(d), + )?); + let exchange_value = pool_base_aum.safe_sub(&new_base_amount)?; + Ok(exchange_value) + } + + fn abs_difference( + new_balance: T::Balance, + old_balance: T::Balance, + ) -> Result { + let difference = if old_balance > new_balance { + old_balance.safe_sub(&new_balance) + } else { + new_balance.safe_sub(&old_balance) + }?; + Ok(difference) + } + + pub fn do_compute_swap( + pool: &StableSwapPoolInfo, + pool_account: &T::AccountId, + quote_amount: T::Balance, + apply_fees: bool, + ) -> Result<(T::Balance, T::Balance, T::Balance, T::Balance), DispatchError> { + let base_amount = + Self::get_exchange_value(pool, pool_account, pool.pair.base, quote_amount)?; + let base_amount_u: u128 = T::Convert::convert(base_amount); + + let (lp_fee, protocol_fee) = if apply_fees { + let lp_fee = pool.fee.mul_floor(base_amount_u); + // protocol_fee is computed based on lp_fee + let protocol_fee = pool.protocol_fee.mul_floor(lp_fee); + let lp_fee = T::Convert::convert(lp_fee); + let protocol_fee = T::Convert::convert(protocol_fee); + (lp_fee, protocol_fee) + } else { + (T::Balance::zero(), T::Balance::zero()) + }; + + let base_amount_excluding_fees = base_amount.safe_sub(&lp_fee)?; + Ok((base_amount_excluding_fees, quote_amount, lp_fee, protocol_fee)) + } + + pub fn add_liquidity( + who: &T::AccountId, + pool: StableSwapPoolInfo, + pool_account: T::AccountId, + base_amount: T::Balance, + quote_amount: T::Balance, + min_mint_amount: T::Balance, + keep_alive: bool, + ) -> Result { + let zero = T::Balance::zero(); + ensure!(base_amount > zero, Error::::AssetAmountMustBePositiveNumber); + ensure!(quote_amount > zero, Error::::AssetAmountMustBePositiveNumber); + // pool supports only 2 assets + let pool_base_aum = T::Assets::balance(pool.pair.base, &pool_account); + let pool_quote_aum = T::Assets::balance(pool.pair.quote, &pool_account); + + let lp_issued = T::Assets::total_issuance(pool.lp_token); + let amp = T::Convert::convert(pool.amplification_coefficient.into()); + let d0 = Self::get_invariant(pool_base_aum, pool_quote_aum, amp)?; + let new_base_amount = pool_base_aum.safe_add(&base_amount)?; + let new_quote_amount = pool_quote_aum.safe_add("e_amount)?; + let d1 = Self::get_invariant(new_base_amount, new_quote_amount, amp)?; + ensure!(d1 > d0, Error::::AssetAmountMustBePositiveNumber); + + let (mint_amount, base_protocol_fee, quote_protocol_fee) = if lp_issued > zero { + // Deposit x + withdraw y sould charge about same + // fees as a swap. Otherwise, one could exchange w/o paying fees. + // And this formula leads to exactly that equality + // fee = pool.fee * n_coins / (4 * (n_coins - 1)) + // pool supports only two coins. + let share: Permill = Permill::from_rational(2_u32, 4_u32); + let fee = pool.fee.mul(share); + + let ideal_base_balance = T::Convert::convert(safe_multiply_by_rational( + T::Convert::convert(d1), + T::Convert::convert(pool_base_aum), + T::Convert::convert(d0), + )?); + let ideal_quote_balance = T::Convert::convert(safe_multiply_by_rational( + T::Convert::convert(d1), + T::Convert::convert(pool_quote_aum), + T::Convert::convert(d0), + )?); + + let base_difference = Self::abs_difference(ideal_base_balance, new_base_amount)?; + let quote_difference = Self::abs_difference(ideal_quote_balance, new_quote_amount)?; + + let base_fee = fee.mul_floor(T::Convert::convert(base_difference)); + let quote_fee = fee.mul_floor(T::Convert::convert(quote_difference)); + let base_protocol_fee = T::Convert::convert(pool.protocol_fee.mul_floor(base_fee)); + let quote_protocol_fee = T::Convert::convert(pool.protocol_fee.mul_floor(quote_fee)); + let base_fee = T::Convert::convert(base_fee); + let quote_fee = T::Convert::convert(quote_fee); + let new_base_balance = new_base_amount.safe_sub(&base_fee)?; + let new_quote_balance = new_quote_amount.safe_sub("e_fee)?; + + let d2 = Self::get_invariant(new_base_balance, new_quote_balance, amp)?; + let mint_amount = T::Convert::convert(safe_multiply_by_rational( + T::Convert::convert(lp_issued), + T::Convert::convert(d2.safe_sub(&d0)?), + T::Convert::convert(d0), + )?); + (mint_amount, base_protocol_fee, quote_protocol_fee) + } else { + (d1, T::Balance::zero(), T::Balance::zero()) + }; + + ensure!(mint_amount >= min_mint_amount, Error::::CannotRespectMinimumRequested); + + T::Assets::transfer(pool.pair.base, who, &pool_account, base_amount, keep_alive)?; + T::Assets::transfer(pool.pair.quote, who, &pool_account, quote_amount, keep_alive)?; + // owner's fee is transferred upfront. + T::Assets::transfer( + pool.pair.base, + &pool_account, + &pool.owner, + base_protocol_fee, + keep_alive, + )?; + T::Assets::transfer( + pool.pair.quote, + &pool_account, + &pool.owner, + quote_protocol_fee, + keep_alive, + )?; + T::Assets::mint_into(pool.lp_token, who, mint_amount)?; + Ok(mint_amount) + } + + pub fn remove_liquidity( + who: &T::AccountId, + pool: StableSwapPoolInfo, + pool_account: T::AccountId, + lp_amount: T::Balance, + min_base_amount: T::Balance, + min_quote_amount: T::Balance, + ) -> Result< + ( + T::Balance, /* base_amount */ + T::Balance, /* quote_amount */ + T::Balance, /* updated_lp */ + ), + DispatchError, + > { + let pool_base_aum = T::Assets::balance(pool.pair.base, &pool_account); + let pool_quote_aum = T::Assets::balance(pool.pair.quote, &pool_account); + let lp_issued = T::Assets::total_issuance(pool.lp_token); + let base_amount = T::Convert::convert(safe_multiply_by_rational( + T::Convert::convert(lp_amount), + T::Convert::convert(pool_base_aum), + T::Convert::convert(lp_issued), + )?); + let quote_amount = T::Convert::convert(safe_multiply_by_rational( + T::Convert::convert(lp_amount), + T::Convert::convert(pool_quote_aum), + T::Convert::convert(lp_issued), + )?); + + ensure!( + base_amount >= min_base_amount && quote_amount >= min_quote_amount, + Error::::CannotRespectMinimumRequested + ); + + let total_issuance = lp_issued.safe_sub(&lp_amount)?; + + // NOTE(hussein-aitlance): no need to keep alive the pool account + T::Assets::transfer(pool.pair.base, &pool_account, who, base_amount, false)?; + T::Assets::transfer(pool.pair.quote, &pool_account, who, quote_amount, false)?; + T::Assets::burn_from(pool.lp_token, who, lp_amount)?; + Ok((base_amount, quote_amount, total_issuance)) + } +} diff --git a/frame/pablo/src/stable_swap_tests.rs b/frame/pablo/src/stable_swap_tests.rs new file mode 100644 index 00000000000..c399fe3f27b --- /dev/null +++ b/frame/pablo/src/stable_swap_tests.rs @@ -0,0 +1,883 @@ +#![allow(unreachable_patterns)] // TODO: remove this when there are more pool configurations added. + +use crate::{ + common_test_functions::*, + mock::{Pablo, *}, + PoolConfiguration::StableSwap, + PoolInitConfiguration, +}; +use composable_tests_helpers::{ + prop_assert_ok, + test::helper::{acceptable_computation_error, default_acceptable_computation_error}, +}; +use composable_traits::{defi::CurrencyPair, dex::Amm}; +use frame_support::{ + assert_noop, assert_ok, + traits::fungibles::{Inspect, Mutate}, +}; +use proptest::prelude::*; +use sp_runtime::{Permill, TokenError}; + +fn create_stable_swap_pool( + base_asset: AssetId, + quote_asset: AssetId, + base_amount: Balance, + quote_amount: Balance, + amplification_factor: u16, + lp_fee: Permill, + protocol_fee: Permill, +) -> PoolId { + let pool_init_config = PoolInitConfiguration::StableSwap { + pair: CurrencyPair::new(base_asset, quote_asset), + amplification_coefficient: amplification_factor, + fee: lp_fee, + protocol_fee, + }; + let pool_id = Pablo::do_create_pool(&ALICE, pool_init_config).expect("pool creation failed"); + // Mint the tokens + assert_ok!(Tokens::mint_into(base_asset, &ALICE, base_amount)); + assert_ok!(Tokens::mint_into(quote_asset, &ALICE, quote_amount)); + + // Add the liquidity + assert_ok!(Pablo::add_liquidity( + Origin::signed(ALICE), + pool_id, + base_amount, + quote_amount, + 0, + false + )); + pool_id +} + +#[test] +fn test_amp_zero_pool_creation_failure() { + new_test_ext().execute_with(|| { + let pool_init_config = PoolInitConfiguration::StableSwap { + pair: CurrencyPair::new(USDC, USDT), + amplification_coefficient: 0_u16, + fee: Permill::zero(), + protocol_fee: Permill::zero(), + }; + assert_noop!( + Pablo::do_create_pool(&ALICE, pool_init_config), + crate::Error::::AmpFactorMustBeGreaterThanZero + ); + }); +} + +#[test] +fn test_dex_demo() { + new_test_ext().execute_with(|| { + let pool_init_config = PoolInitConfiguration::StableSwap { + pair: CurrencyPair::new(USDC, USDT), + amplification_coefficient: 100_u16, + fee: Permill::zero(), + protocol_fee: Permill::zero(), + }; + let pool_id = + Pablo::do_create_pool(&ALICE, pool_init_config).expect("pool creation failed"); + let pool = Pablo::pools(pool_id).expect("pool not found"); + let pool = match pool { + StableSwap(pool) => pool, + _ => panic!("expected stable_swap pool"), + }; + + let unit = 1_000_000_000_000_u128; + let usdc_price = 1 * unit; + + let nb_of_usdc = 1_000_000_000; + let usdt_price = 1 * unit; + + let nb_of_usdt = 1_000_000_000; + + // 10^9 USDC/10^9 USDT + let initial_usdc = nb_of_usdc * usdc_price; + let initial_usdt = nb_of_usdt * usdt_price; + + // Mint the tokens + assert_ok!(Tokens::mint_into(USDC, &ALICE, initial_usdc)); + assert_ok!(Tokens::mint_into(USDT, &ALICE, initial_usdt)); + + // Add the liquidity + assert_ok!(Pablo::add_liquidity( + Origin::signed(ALICE), + pool_id, + initial_usdc, + initial_usdt, + 0, + false + )); + + let precision = 100; + let epsilon = 1; + // 1 unit of usdc == 1 unit of usdt + let ratio = ::get_exchange_value(pool_id, USDC, unit) + .expect("get_exchange_value failed"); + assert_ok!(acceptable_computation_error(ratio, unit, precision, epsilon)); + + let swap_usdc = 100_u128 * unit; + assert_ok!(Tokens::mint_into(USDC, &BOB, swap_usdc)); + // mint 1 USDT, after selling 100 USDC we get 99 USDT so to buy 100 USDC we need 100 USDT + assert_ok!(Tokens::mint_into(USDT, &BOB, unit)); + + Pablo::sell(Origin::signed(BOB), pool_id, USDC, swap_usdc, false).expect("sell failed"); + + Pablo::buy(Origin::signed(BOB), pool_id, USDC, swap_usdc, false).expect("buy failed"); + + let bob_usdc = Tokens::balance(USDC, &BOB); + + assert_ok!(acceptable_computation_error( + bob_usdc.into(), + swap_usdc.into(), + precision, + epsilon + )); + let lp = Tokens::balance(pool.lp_token, &ALICE); + assert_ok!(Pablo::remove_liquidity(Origin::signed(ALICE), pool_id, lp, 0, 0)); + + // Alice should get back a different amount of tokens. + let alice_usdc = Tokens::balance(USDC, &ALICE); + let alice_usdt = Tokens::balance(USDT, &ALICE); + assert_ok!(default_acceptable_computation_error(alice_usdc.into(), initial_usdc.into())); + assert_ok!(default_acceptable_computation_error(alice_usdt.into(), initial_usdt.into())); + }); +} + +//- test lp mint/burn +#[test] +fn add_remove_lp() { + new_test_ext().execute_with(|| { + let pool_init_config = PoolInitConfiguration::StableSwap { + pair: CurrencyPair::new(USDC, USDT), + amplification_coefficient: 10_u16, + fee: Permill::zero(), + protocol_fee: Permill::zero(), + }; + let unit = 1_000_000_000_000_u128; + let initial_usdt = 1_000_000_000_000_u128 * unit; + let initial_usdc = 1_000_000_000_000_u128 * unit; + let usdc_amount = 1000 * unit; + let usdt_amount = 1000 * unit; + let expected_lp_check = |base_amount: Balance, + quote_amount: Balance, + lp: Balance| + -> bool { base_amount + quote_amount == lp }; + common_add_remove_lp( + pool_init_config, + initial_usdc, + initial_usdt, + usdc_amount, + usdt_amount, + expected_lp_check, + ); + }); +} + +// +// - add liquidity which creates imbalance in pool +#[test] +fn add_lp_imbalanced() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_usdt = 1_000_000_000_000_u128 * unit; + let initial_usdc = 1_000_000_000_000_u128 * unit; + let pool_id = create_stable_swap_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::from_float(0.05), // 5% lp fee. + Permill::from_float(0.10), // 10% of lp fee goes to owner + ); + let pool = Pablo::pools(pool_id).expect("pool not found"); + let pool = match pool { + StableSwap(pool) => pool, + _ => panic!("expected stable_swap pool"), + }; + let bob_usdc = 1000 * unit; + let bob_usdt = 1000 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDC, &BOB, bob_usdc)); + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + + let lp = Tokens::balance(pool.lp_token, &BOB); + assert_eq!(lp, 0_u128); + // Add the liquidity in balanced way + assert_ok!(Pablo::add_liquidity( + Origin::signed(BOB), + pool_id, + bob_usdc, + bob_usdt, + 0, + false + )); + let lp = Tokens::balance(pool.lp_token, &BOB); + // must have received some lp tokens + assert!(lp == bob_usdt + bob_usdc); + // there must not be any fee charged. simple way is to check owner (ALICE) has not got any + // tokens as owner fee. + let alice_usdc = Tokens::balance(USDC, &ALICE); + let alice_usdt = Tokens::balance(USDT, &ALICE); + assert!(alice_usdt == 0); + assert!(alice_usdc == 0); + + let bob_usdc = 100000 * unit; + let bob_usdt = 5000 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDC, &BOB, bob_usdc)); + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + // Add the liquidity in imbalanced way + assert_ok!(Pablo::add_liquidity( + Origin::signed(BOB), + pool_id, + bob_usdc, + bob_usdt, + 0, + false + )); + // there must fee charged. simple way is to check owner (ALICE) has got + // tokens as owner fee. + let alice_usdc = Tokens::balance(USDC, &ALICE); + let alice_usdt = Tokens::balance(USDT, &ALICE); + assert!(alice_usdt != 0); + assert!(alice_usdc != 0); + }); +} + +// test add liquidity with min_mint_amount +#[test] +fn add_lp_with_min_mint_amount_success() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_usdt = 1_000_000_000_000_u128 * unit; + let initial_usdc = 1_000_000_000_000_u128 * unit; + let pool_id = create_stable_swap_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::zero(), + Permill::zero(), + ); + let pool = Pablo::pools(pool_id).expect("pool not found"); + let pool = match pool { + StableSwap(pool) => pool, + _ => panic!("expected stable_swap pool"), + }; + let bob_usdc = 1000 * unit; + let bob_usdt = 1000 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDC, &BOB, bob_usdc)); + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + + let lp = Tokens::balance(pool.lp_token, &BOB); + assert_eq!(lp, 0_u128); + let expected_min_value = bob_usdt + bob_usdc; + // Add the liquidity in balanced way + assert_ok!(Pablo::add_liquidity( + Origin::signed(BOB), + pool_id, + bob_usdc, + bob_usdt, + expected_min_value, + false + )); + let lp = Tokens::balance(pool.lp_token, &BOB); + // must have received some lp tokens + assert!(lp == bob_usdc + bob_usdt); + + let bob_usdc = 1000 * unit; + let bob_usdt = 900 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDC, &BOB, bob_usdc)); + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + // Add the liquidity in imbalanced way, but have expected_min_value higher + assert_noop!( + Pablo::add_liquidity( + Origin::signed(BOB), + pool_id, + bob_usdc, + bob_usdt, + expected_min_value, + false + ), + crate::Error::::CannotRespectMinimumRequested + ); + }); +} + +// test add liquidity with min_mint_amount +#[test] +fn add_lp_with_min_mint_amount_fail() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_usdt = 1_000_000_000_000_u128 * unit; + let initial_usdc = 1_000_000_000_000_u128 * unit; + let pool_id = create_stable_swap_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::zero(), + Permill::zero(), + ); + + let bob_usdc = 1000 * unit; + let bob_usdt = 900 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDC, &BOB, bob_usdc)); + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + let expected_min_value = bob_usdt + bob_usdc + 1_u128; + // Add the liquidity in imbalanced way, but have expected_min_value higher + assert_noop!( + Pablo::add_liquidity( + Origin::signed(BOB), + pool_id, + bob_usdc, + bob_usdt, + expected_min_value, + false + ), + crate::Error::::CannotRespectMinimumRequested + ); + }); +} + +// +// - test error if trying to remove > lp than we have +#[test] +fn remove_lp_failure() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_usdt = 1_000_000_000_000_u128 * unit; + let initial_usdc = 1_000_000_000_000_u128 * unit; + let pool_id = create_stable_swap_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::zero(), + Permill::zero(), + ); + let pool = Pablo::pools(pool_id).expect("pool not found"); + let pool = match pool { + StableSwap(pool) => pool, + _ => panic!("expected stable_swap pool"), + }; + let bob_usdc = 1000 * unit; + let bob_usdt = 1000 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDC, &BOB, bob_usdc)); + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + + // Add the liquidity + assert_ok!(Pablo::add_liquidity( + Origin::signed(BOB), + pool_id, + bob_usdc, + bob_usdt, + 0, + false + )); + let lp = Tokens::balance(pool.lp_token, &BOB); + assert_noop!( + Pablo::remove_liquidity(Origin::signed(BOB), pool_id, lp + 1, 0, 0), + TokenError::NoFunds + ); + let min_expected_usdt = 1001 * unit; + let min_expected_usdc = 1001 * unit; + assert_noop!( + Pablo::remove_liquidity( + Origin::signed(BOB), + pool_id, + lp, + min_expected_usdc, + min_expected_usdt + ), + crate::Error::::CannotRespectMinimumRequested + ); + }); +} + +// +// - test exchange failure +#[test] +fn exchange_failure() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_usdt = 1_000_000_u128 * unit; + let initial_usdc = 1_000_000_u128 * unit; + let pool_id = create_stable_swap_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::zero(), + Permill::zero(), + ); + let bob_usdc = 1000 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDC, &BOB, bob_usdc)); + + let exchange_usdc = 1001 * unit; + assert_noop!( + Pablo::swap( + Origin::signed(BOB), + pool_id, + CurrencyPair::new(USDT, USDC), + exchange_usdc, + 0, + false + ), + orml_tokens::Error::::BalanceTooLow + ); + let exchange_value = 1000 * unit; + let expected_value = 1001 * unit; + assert_noop!( + Pablo::swap( + Origin::signed(BOB), + pool_id, + CurrencyPair::new(USDT, USDC), + exchange_value, + expected_value, + false + ), + crate::Error::::CannotRespectMinimumRequested + ); + }); +} + +// +// - test lp fees +#[test] +fn lp_fee() { + new_test_ext().execute_with(|| { + let precision = 100; + let epsilon = 1; + let unit = 1_000_000_000_000_u128; + let initial_usdt = 1_000_000_000_000_u128 * unit; + let initial_usdc = 1_000_000_000_000_u128 * unit; + let lp_fee = Permill::from_float(0.05); + let pool_id = create_stable_swap_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + lp_fee, + Permill::zero(), + ); + let bob_usdt = 1000 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + + assert_ok!(Pablo::sell(Origin::signed(BOB), pool_id, USDT, bob_usdt, false)); + let usdc_balance = Tokens::balance(USDC, &BOB); + // received usdc should bob_usdt - lp_fee + assert_ok!(acceptable_computation_error( + usdc_balance, + bob_usdt - lp_fee.mul_ceil(bob_usdt), + precision, + epsilon + )); + }); +} + +// +// - test protocol fees +#[test] +fn protocol_fee() { + new_test_ext().execute_with(|| { + let precision = 100; + let epsilon = 1; + let unit = 1_000_000_000_000_u128; + let initial_usdt = 1_000_000_000_000_u128 * unit; + let initial_usdc = 1_000_000_000_000_u128 * unit; + let lp_fee = Permill::from_float(0.05); + let protocol_fee = Permill::from_float(0.01); // 10% of lp fees goes to pool owner + let pool_id = create_stable_swap_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + lp_fee, + protocol_fee, + ); + let bob_usdt = 1000 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + assert_ok!(Pablo::sell(Origin::signed(BOB), pool_id, USDT, bob_usdt, false)); + let usdc_balance = Tokens::balance(USDC, &BOB); + // received usdc should bob_usdt - lp_fee + assert_ok!(acceptable_computation_error( + usdc_balance, + bob_usdt - lp_fee.mul_floor(bob_usdt), + precision, + epsilon + )); + // from lp_fee 1 % (as per protocol_fee) goes to pool owner (ALICE) + let alice_usdc_bal = Tokens::balance(USDC, &ALICE); + assert_ok!(acceptable_computation_error( + alice_usdc_bal, + protocol_fee.mul_floor(lp_fee.mul_floor(bob_usdt)), + precision, + epsilon + )); + }); +} + +// +// - test high slippage scenario +// trying to exchange a large value, will result in high_slippage scenario +// there should be substential difference between expected exchange value and received amount. +#[test] +fn high_slippage() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_usdt = 1_000_000_000_000_u128 * unit; + let initial_usdc = 1_000_000_000_000_u128 * unit; + let pool_id = create_stable_swap_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::zero(), + Permill::zero(), + ); + let bob_usdt = 1_000_000_000_00_u128 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + + assert_ok!(Pablo::sell(Origin::signed(BOB), pool_id, USDT, bob_usdt, false)); + let usdc_balance = Tokens::balance(USDC, &BOB); + assert!((bob_usdt - usdc_balance) > 5_u128); + }); +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(10000))] + #[test] + fn add_remove_liquidity_proptest( + usdc_balance in 1..u32::MAX, + usdt_balance in 1..u32::MAX, + ) { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let usdt_balance = usdt_balance as u128 * unit; + let usdc_balance = usdc_balance as u128 * unit; + let initial_usdt = u64::MAX as u128 * unit; + let initial_usdc = u64::MAX as u128 * unit; + let pool_id = create_stable_swap_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::zero(), + Permill::zero(), + ); + let pool = Pablo::pools(pool_id).expect("pool not found"); + let pool = match pool { + StableSwap(pool) => pool, + _ => panic!("expected stable_swap pool"), + }; + prop_assert_ok!(Tokens::mint_into(USDT, &BOB, usdt_balance)); + prop_assert_ok!(Tokens::mint_into(USDC, &BOB, usdc_balance)); + prop_assert_ok!(Pablo::add_liquidity( + Origin::signed(BOB), + pool_id, + usdc_balance, + usdt_balance, + 0, + false + )); + let lp = Tokens::balance(pool.lp_token, &BOB); + let expected_lp = usdt_balance + usdc_balance; + prop_assert_ok!(default_acceptable_computation_error(lp, expected_lp)); + prop_assert_ok!(Pablo::remove_liquidity( + Origin::signed(BOB), + pool_id, + lp, + 0, + 0, + )); + let bob_usdc = Tokens::balance(USDC, &BOB); + let bob_usdt = Tokens::balance(USDT, &BOB); + prop_assert_ok!(default_acceptable_computation_error(usdc_balance + usdt_balance, bob_usdc + + bob_usdt)); Ok(()) + })?; + } + + #[test] + fn buy_sell_proptest( + value in 1..u32::MAX, + ) { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_usdt = u64::MAX as u128 * unit; + let initial_usdc = u64::MAX as u128 * unit; + let value = value as u128 * unit; + let pool_id = create_stable_swap_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::zero(), + Permill::zero(), + ); + prop_assert_ok!(Tokens::mint_into(USDT, &BOB, value)); + prop_assert_ok!(Pablo::sell(Origin::signed(BOB), pool_id, USDT, value, false)); + // mint 1 extra USDC so that original amount of USDT can be buy back even with small slippage + prop_assert_ok!(Tokens::mint_into(USDC, &BOB, unit)); + prop_assert_ok!(Pablo::buy(Origin::signed(BOB), pool_id, USDT, value, false)); + let bob_usdt = Tokens::balance(USDT, &BOB); + prop_assert_ok!(default_acceptable_computation_error(bob_usdt, value)); + Ok(()) + })?; + } + + #[test] + fn swap_proptest( + value in 1..u32::MAX, + ) { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_usdt = u64::MAX as u128 * unit; + let initial_usdc = u64::MAX as u128 * unit; + let value = value as u128 * unit; + let pool_id = create_stable_swap_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::from_float(0.025), + Permill::zero(), + ); + let pool = Pablo::pools(pool_id).expect("pool not found"); + let pool = match pool { + StableSwap(pool) => pool, + _ => panic!("expected stable_swap pool"), + }; + prop_assert_ok!(Tokens::mint_into(USDT, &BOB, value)); + prop_assert_ok!(Pablo::swap(Origin::signed(BOB), pool_id, CurrencyPair::new(USDC, USDT), + value, 0, false)); let bob_usdc = Tokens::balance(USDC, &BOB); + let expected_usdc = value - pool.fee.mul_floor(value); + prop_assert_ok!(default_acceptable_computation_error(bob_usdc, expected_usdc)); + Ok(()) + })?; + } +} + +#[cfg(feature = "visualization")] +#[test] +fn get_base_graph() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_usdt = 100000_u128 * unit; + let initial_usdc = 100000_u128 * unit; + let pool_id = create_stable_swap_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::zero(), + Permill::zero(), + ); + + let start_quote = 0; + let end_quote = 120000; + let points = (start_quote..end_quote) + .map(|quote| { + ( + quote, + ::get_exchange_value(pool_id, USDC, quote * unit) + .expect("get_exchange_value not found") as f64 / + unit as f64, + ) + }) + .collect::>(); + let max_amount = points.iter().copied().fold(f64::NAN, |x, (_, y)| f64::max(x, y)); + + use plotters::prelude::*; + let area = BitMapBackend::new("./plots/stable_swap/curve_base.png", (1024, 768)) + .into_drawing_area(); + area.fill(&WHITE).unwrap(); + + let mut chart = ChartBuilder::on(&area) + .caption("Curve price, pool has 100000 USDC 100000 USDT", ("Arial", 25).into_font()) + .margin(100u32) + .x_label_area_size(30u32) + .y_label_area_size(30u32) + .build_cartesian_2d(start_quote..end_quote, 0f64..max_amount) + .unwrap(); + + chart + .configure_mesh() + .y_desc("base amount") + .x_desc("quote amount") + .draw() + .unwrap(); + chart.draw_series(LineSeries::new(points, &RED)).unwrap(); + chart + .configure_series_labels() + .background_style(&WHITE.mix(0.8)) + .border_style(&BLACK) + .draw() + .unwrap(); + }); +} + +#[cfg(feature = "visualization")] +#[test] +fn slippage_graph() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_usdt = 1000000_u128 * unit; + let initial_usdc = 1000000_u128 * unit; + let pool_id = create_stable_swap_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 100_u16, + Permill::zero(), + Permill::zero(), + ); + + let start_quote = 0; + let end_quote = 120000; + let points = (start_quote..end_quote) + .map(|quote| { + let quote = quote * unit; + let base = ::get_exchange_value(pool_id, USDC, quote) + .expect("get_exchange_value failed"); + let slippage = if base <= quote { quote - base } else { base }; + (quote / unit, slippage as f64 / unit as f64) + }) + .collect::>(); + let max_amount = points.iter().copied().fold(f64::NAN, |x, (_, y)| f64::max(x, y)); + + use plotters::prelude::*; + let area = BitMapBackend::new("./plots/stable_swap/curve_slippage.png", (1024, 768)) + .into_drawing_area(); + area.fill(&WHITE).unwrap(); + + let mut chart = ChartBuilder::on(&area) + .caption("Curve price, pool has 100000 USDC 100000 USDT", ("Arial", 25).into_font()) + .margin(100u32) + .x_label_area_size(30u32) + .y_label_area_size(30u32) + .build_cartesian_2d(start_quote..end_quote, 0f64..max_amount) + .unwrap(); + + chart.configure_mesh().y_desc("slippage").x_desc("quote amount").draw().unwrap(); + chart.draw_series(LineSeries::new(points, &RED)).unwrap(); + chart + .configure_series_labels() + .background_style(&WHITE.mix(0.8)) + .border_style(&BLACK) + .draw() + .unwrap(); + }); +} + +#[cfg(feature = "visualization")] +#[test] +fn curve_graph() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_usdt = 5_u128 * unit; + let initial_usdc = initial_usdt; + let pool_id = create_stable_swap_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 5_u16, + Permill::zero(), + Permill::zero(), + ); + let window = 15u128; + let max_base = (initial_usdt + window * unit) as f64 / unit as f64; + let max_quote = max_base; + let pool_account = Pablo::account_id(&pool_id); + let range: Vec = (0..window).collect(); + + let points1 = range + .iter() + .map(|_| { + let amount = unit; + let _ = Tokens::mint_into(USDC, &BOB, amount).expect("mint failed"); + let _base = + ::sell(&BOB, pool_id, USDC, amount, true).expect("sell failed"); + let pool_sell_asset_balance = + Tokens::balance(USDC, &pool_account) as f64 / unit as f64; + let pool_buy_asset_balance = + Tokens::balance(USDT, &pool_account) as f64 / unit as f64; + (pool_buy_asset_balance, pool_sell_asset_balance) + }) + .collect::>(); + let pool_id = create_stable_swap_pool( + USDC, + USDT, + initial_usdc, + initial_usdt, + 5_u16, + Permill::zero(), + Permill::zero(), + ); + let pool_account = Pablo::account_id(&pool_id); + let points2 = range + .iter() + .map(|_| { + let amount = unit; + let _ = Tokens::mint_into(USDT, &BOB, amount).expect("mint failed"); + let _base = + ::sell(&BOB, pool_id, USDT, amount, true).expect("sell failed"); + let pool_sell_asset_balance = + Tokens::balance(USDC, &pool_account) as f64 / unit as f64; + let pool_buy_asset_balance = + Tokens::balance(USDT, &pool_account) as f64 / unit as f64; + (pool_buy_asset_balance, pool_sell_asset_balance) + }) + .collect::>(); + let points: Vec<_> = points1.into_iter().rev().chain(points2.into_iter()).collect(); + use plotters::prelude::*; + let area = BitMapBackend::new("./plots/stable_swap/curve_graph.png", (1024, 768)) + .into_drawing_area(); + area.fill(&WHITE).unwrap(); + + let mut chart = ChartBuilder::on(&area) + .caption("Curve price, pool has 1000 USDC 1000 USDT", ("Arial", 25).into_font()) + .margin(100u32) + .x_label_area_size(30u32) + .y_label_area_size(30u32) + .build_cartesian_2d(0f64..max_base, 0f64..max_quote) + .unwrap(); + + chart + .configure_mesh() + .y_desc("quote amount") + .x_desc("base amount") + .draw() + .unwrap(); + chart.draw_series(LineSeries::new(points, &RED)).unwrap(); + chart + .configure_series_labels() + .background_style(&WHITE.mix(0.8)) + .border_style(&BLACK) + .draw() + .unwrap(); + }); +} diff --git a/frame/pablo/src/uniswap.rs b/frame/pablo/src/uniswap.rs new file mode 100644 index 00000000000..bf8aa936bc5 --- /dev/null +++ b/frame/pablo/src/uniswap.rs @@ -0,0 +1,195 @@ +use crate::{Config, Error, PoolConfiguration, PoolCount, Pools}; +use composable_maths::dex::constant_product::{ + compute_deposit_lp, compute_in_given_out, compute_out_given_in, +}; +use composable_traits::{ + currency::{CurrencyFactory, RangeId}, + defi::CurrencyPair, + dex::ConstantProductPoolInfo, + math::{safe_multiply_by_rational, SafeAdd, SafeSub}, +}; +use frame_support::{ + pallet_prelude::*, + traits::fungibles::{Inspect, Mutate, Transfer}, + transactional, +}; +use sp_runtime::{ + traits::{CheckedAdd, Convert, One, Zero}, + ArithmeticError, Permill, +}; + +// Uniswap +pub(crate) struct Uniswap(PhantomData); + +impl Uniswap { + #[transactional] + pub(crate) fn do_create_pool( + who: &T::AccountId, + pair: CurrencyPair, + fee: Permill, + owner_fee: Permill, + ) -> Result { + // NOTE(hussein-aitlahcen): do we allow such pair? + ensure!(pair.base != pair.quote, Error::::InvalidPair); + + let total_fees = fee.checked_add(&owner_fee).ok_or(ArithmeticError::Overflow)?; + ensure!(total_fees < Permill::one(), Error::::InvalidFees); + + let lp_token = T::CurrencyFactory::create(RangeId::LP_TOKENS)?; + + // Add new pool + let pool_id = + PoolCount::::try_mutate(|pool_count| -> Result { + let pool_id = *pool_count; + Pools::::insert( + pool_id, + PoolConfiguration::ConstantProduct(ConstantProductPoolInfo { + owner: who.clone(), + pair, + lp_token, + fee, + owner_fee, + }), + ); + *pool_count = pool_id.safe_add(&T::PoolId::one())?; + Ok(pool_id) + })?; + + Ok(pool_id) + } + + pub(crate) fn get_exchange_value( + pool: &ConstantProductPoolInfo, + pool_account: &T::AccountId, + asset_id: T::AssetId, + amount: T::Balance, + ) -> Result { + let amount = T::Convert::convert(amount); + let half_weight = Permill::from_percent(50); + let pool_base_aum = T::Convert::convert(T::Assets::balance(pool.pair.base, pool_account)); + let pool_quote_aum = T::Convert::convert(T::Assets::balance(pool.pair.quote, pool_account)); + let exchange_amount = if asset_id == pool.pair.quote { + compute_out_given_in(half_weight, half_weight, pool_quote_aum, pool_base_aum, amount) + } else { + compute_in_given_out(half_weight, half_weight, pool_quote_aum, pool_base_aum, amount) + }?; + Ok(T::Convert::convert(exchange_amount)) + } + + #[transactional] + pub(crate) fn add_liquidity( + who: &T::AccountId, + pool: ConstantProductPoolInfo, + pool_account: T::AccountId, + base_amount: T::Balance, + quote_amount: T::Balance, + min_mint_amount: T::Balance, + keep_alive: bool, + ) -> Result { + ensure!(base_amount > T::Balance::zero(), Error::::InvalidAmount); + let pool_base_aum = T::Convert::convert(T::Assets::balance(pool.pair.base, &pool_account)); + let pool_quote_aum = + T::Convert::convert(T::Assets::balance(pool.pair.quote, &pool_account)); + + let lp_total_issuance = T::Convert::convert(T::Assets::total_issuance(pool.lp_token)); + let (quote_amount, lp_token_to_mint) = compute_deposit_lp( + lp_total_issuance, + T::Convert::convert(base_amount), + T::Convert::convert(quote_amount), + pool_base_aum, + pool_quote_aum, + )?; + let quote_amount = T::Convert::convert(quote_amount); + let lp_token_to_mint = T::Convert::convert(lp_token_to_mint); + + ensure!(quote_amount > T::Balance::zero(), Error::::InvalidAmount); + ensure!(lp_token_to_mint >= min_mint_amount, Error::::CannotRespectMinimumRequested); + + T::Assets::transfer(pool.pair.base, who, &pool_account, base_amount, keep_alive)?; + T::Assets::transfer(pool.pair.quote, who, &pool_account, quote_amount, keep_alive)?; + T::Assets::mint_into(pool.lp_token, who, lp_token_to_mint)?; + Ok(lp_token_to_mint) + } + + #[transactional] + pub(crate) fn remove_liquidity( + who: &T::AccountId, + pool: ConstantProductPoolInfo, + pool_account: T::AccountId, + lp_amount: T::Balance, + min_base_amount: T::Balance, + min_quote_amount: T::Balance, + ) -> Result<(T::Balance, T::Balance, T::Balance), DispatchError> { + let pool_base_aum = T::Convert::convert(T::Assets::balance(pool.pair.base, &pool_account)); + let pool_quote_aum = + T::Convert::convert(T::Assets::balance(pool.pair.quote, &pool_account)); + let lp_issued = T::Assets::total_issuance(pool.lp_token); + + let base_amount = T::Convert::convert(safe_multiply_by_rational( + T::Convert::convert(lp_amount), + pool_base_aum, + T::Convert::convert(lp_issued), + )?); + let quote_amount = T::Convert::convert(safe_multiply_by_rational( + T::Convert::convert(lp_amount), + pool_quote_aum, + T::Convert::convert(lp_issued), + )?); + + ensure!( + base_amount >= min_base_amount && quote_amount >= min_quote_amount, + Error::::CannotRespectMinimumRequested + ); + + // NOTE(hussein-aitlance): no need to keep alive the pool account + T::Assets::transfer(pool.pair.base, &pool_account, who, base_amount, false)?; + T::Assets::transfer(pool.pair.quote, &pool_account, who, quote_amount, false)?; + T::Assets::burn_from(pool.lp_token, who, lp_amount)?; + + Ok((base_amount, quote_amount, lp_issued.safe_sub(&lp_amount)?)) + } + + pub(crate) fn do_compute_swap( + pool: &ConstantProductPoolInfo, + pool_account: &T::AccountId, + pair: CurrencyPair, + quote_amount: T::Balance, + apply_fees: bool, + ) -> Result<(T::Balance, T::Balance, T::Balance, T::Balance), DispatchError> { + let pool_base_aum = T::Convert::convert(T::Assets::balance(pair.base, pool_account)); + let pool_quote_aum = T::Convert::convert(T::Assets::balance(pair.quote, pool_account)); + let quote_amount = T::Convert::convert(quote_amount); + + // https://uniswap.org/whitepaper.pdf + // 3.2.1 + // we do not inflate the lp for the owner fees + // cut is done before enforcing the invariant + let (lp_fee, owner_fee) = if apply_fees { + let lp_fee = pool.fee.mul_floor(quote_amount); + let owner_fee = pool.owner_fee.mul_floor(quote_amount); + (lp_fee, owner_fee) + } else { + (0, 0) + }; + + let quote_amount_excluding_fees = quote_amount.safe_sub(&lp_fee)?.safe_sub(&owner_fee)?; + + let half_weight = Permill::from_percent(50); + let base_amount = compute_out_given_in( + half_weight, + half_weight, + pool_quote_aum, + pool_base_aum, + quote_amount_excluding_fees, + )?; + + ensure!(base_amount > 0 && quote_amount_excluding_fees > 0, Error::::InvalidAmount); + + Ok(( + T::Convert::convert(base_amount), + T::Convert::convert(quote_amount_excluding_fees), + T::Convert::convert(lp_fee), + T::Convert::convert(owner_fee), + )) + } +} diff --git a/frame/pablo/src/uniswap_tests.rs b/frame/pablo/src/uniswap_tests.rs new file mode 100644 index 00000000000..fcfb9319910 --- /dev/null +++ b/frame/pablo/src/uniswap_tests.rs @@ -0,0 +1,408 @@ +use crate::{ + common_test_functions::*, + mock::{Pablo, *}, + PoolConfiguration::ConstantProduct, + PoolInitConfiguration, +}; +use composable_tests_helpers::{ + prop_assert_ok, + test::helper::{acceptable_computation_error, default_acceptable_computation_error}, +}; +use composable_traits::{ + defi::CurrencyPair, + dex::{Amm, ConstantProductPoolInfo}, + math::safe_multiply_by_rational, +}; +use frame_support::{ + assert_err, assert_ok, + traits::fungibles::{Inspect, Mutate}, +}; +use proptest::prelude::*; +use sp_runtime::{traits::IntegerSquareRoot, Permill, TokenError}; + +fn create_pool( + base_asset: AssetId, + quote_asset: AssetId, + base_amount: Balance, + quote_amount: Balance, + lp_fee: Permill, + protocol_fee: Permill, +) -> PoolId { + let pool_init_config = PoolInitConfiguration::ConstantProduct { + pair: CurrencyPair::new(base_asset, quote_asset), + fee: lp_fee, + owner_fee: protocol_fee, + }; + let pool_id = Pablo::do_create_pool(&ALICE, pool_init_config).expect("pool creation failed"); + + // Mint the tokens + assert_ok!(Tokens::mint_into(base_asset, &ALICE, base_amount)); + assert_ok!(Tokens::mint_into(quote_asset, &ALICE, quote_amount)); + + // Add the liquidity + assert_ok!(::add_liquidity(&ALICE, pool_id, base_amount, quote_amount, 0, false)); + pool_id +} + +fn get_pool(pool_id: PoolId) -> ConstantProductPoolInfo { + match Pablo::pools(pool_id).expect("pool not found") { + ConstantProduct(pool) => pool, + _ => panic!("expected stable_swap pool"), + } +} + +#[test] +fn test() { + new_test_ext().execute_with(|| { + let pool_init_config = PoolInitConfiguration::ConstantProduct { + pair: CurrencyPair::new(BTC, USDT), + fee: Permill::zero(), + owner_fee: Permill::zero(), + }; + let pool_id = + Pablo::do_create_pool(&ALICE, pool_init_config).expect("pool creation failed"); + + let pool = get_pool(pool_id); + + let current_product = |a| { + let balance_btc = Tokens::balance(BTC, &a); + let balance_usdt = Tokens::balance(USDT, &a); + balance_btc * balance_usdt + }; + let current_pool_product = || current_product(Pablo::account_id(&pool_id)); + + let unit = 1_000_000_000_000; + + let btc_price = 45_000; + + let nb_of_btc = 100; + + // 100 BTC/4.5M USDT + let initial_btc = nb_of_btc * unit; + let initial_usdt = nb_of_btc * btc_price * unit; + + // Mint the tokens + assert_ok!(Tokens::mint_into(BTC, &ALICE, initial_btc)); + assert_ok!(Tokens::mint_into(USDT, &ALICE, initial_usdt)); + + let initial_user_invariant = current_product(ALICE); + + // Add the liquidity + assert_ok!(::add_liquidity( + &ALICE, + pool_id, + initial_btc, + initial_usdt, + 0, + false + )); + + // 1 unit of btc = 45k + some unit of usdt + let ratio = ::get_exchange_value(pool_id, BTC, unit) + .expect("get_exchange_value failed"); + assert!(ratio > (initial_usdt / initial_btc) * unit); + + let initial_pool_invariant = current_pool_product(); + + assert_eq!(initial_user_invariant, initial_pool_invariant); + + // swap a btc + let swap_btc = unit; + assert_ok!(Tokens::mint_into(BTC, &BOB, swap_btc)); + + ::sell(&BOB, pool_id, BTC, swap_btc, false).expect("sell failed"); + + let new_pool_invariant = current_pool_product(); + assert_ok!(default_acceptable_computation_error( + initial_pool_invariant, + new_pool_invariant + )); + + ::buy(&BOB, pool_id, BTC, swap_btc, false).expect("buy failed"); + + let precision = 100; + let epsilon = 5; + let bob_btc = Tokens::balance(BTC, &BOB); + assert_ok!(acceptable_computation_error(bob_btc, swap_btc, precision, epsilon)); + + let new_pool_invariant = current_pool_product(); + assert_ok!(default_acceptable_computation_error( + initial_pool_invariant, + new_pool_invariant + )); + + let lp = Tokens::balance(pool.lp_token, &ALICE); + assert_ok!(::remove_liquidity(&ALICE, pool_id, lp, 0, 0)); + + // Alice should get back a different amount of tokens. + let alice_btc = Tokens::balance(BTC, &ALICE); + let alice_usdt = Tokens::balance(USDT, &ALICE); + assert_ok!(default_acceptable_computation_error(alice_btc, initial_btc)); + assert_ok!(default_acceptable_computation_error(alice_usdt, initial_usdt)); + }); +} + +//- test lp mint/burn +#[test] +fn add_remove_lp() { + new_test_ext().execute_with(|| { + let pool_init_config = PoolInitConfiguration::ConstantProduct { + pair: CurrencyPair::new(BTC, USDT), + fee: Permill::zero(), + owner_fee: Permill::zero(), + }; + let unit = 1_000_000_000_000_u128; + let initial_btc = 1_00_u128 * unit; + let btc_price = 45_000_u128; + let initial_usdt = initial_btc * btc_price; + let btc_amount = 10 * unit; + let usdt_amount = btc_amount * btc_price; + let expected_lp_check = + |_base_amount: Balance, _quote_amount: Balance, lp: Balance| -> bool { lp > 0_u128 }; + common_add_remove_lp( + pool_init_config, + initial_btc, + initial_usdt, + btc_amount, + usdt_amount, + expected_lp_check, + ); + }); +} + +// +// - test error if trying to remove > lp than we have +#[test] +fn remove_lp_failure() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_btc = 1_00_u128 * unit; + let btc_price = 45_000_u128; + let initial_usdt = initial_btc * btc_price; + let pool_id = + create_pool(BTC, USDT, initial_btc, initial_usdt, Permill::zero(), Permill::zero()); + let pool = get_pool(pool_id); + let bob_btc = 10 * unit; + let bob_usdt = bob_btc * btc_price; + // Mint the tokens + assert_ok!(Tokens::mint_into(BTC, &BOB, bob_btc)); + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + + // Add the liquidity + assert_ok!(::add_liquidity(&BOB, pool_id, bob_btc, bob_usdt, 0, false)); + let lp = Tokens::balance(pool.lp_token, &BOB); + assert_err!( + ::remove_liquidity(&BOB, pool_id, lp + 1, 0, 0), + TokenError::NoFunds + ); + let min_expected_btc = (bob_btc + 1) * unit; + let min_expected_usdt = (bob_usdt + 1) * unit; + assert_err!( + ::remove_liquidity( + &BOB, + pool_id, + lp, + min_expected_btc, + min_expected_usdt + ), + crate::Error::::CannotRespectMinimumRequested + ); + }); +} + +// +// - test exchange failure +#[test] +fn exchange_failure() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_btc = 1_00_u128 * unit; + let btc_price = 45_000_u128; + let initial_usdt = initial_btc * btc_price; + let pool_id = + create_pool(BTC, USDT, initial_btc, initial_usdt, Permill::zero(), Permill::zero()); + let bob_btc = 10 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(BTC, &BOB, bob_btc)); + + let exchange_btc = 100_u128 * unit; + assert_err!( + ::exchange( + &BOB, + pool_id, + CurrencyPair::new(USDT, BTC), + exchange_btc, + 0, + false + ), + orml_tokens::Error::::BalanceTooLow + ); + let exchange_value = 10 * unit; + let expected_value = exchange_value * btc_price + 1; + assert_err!( + ::exchange( + &BOB, + pool_id, + CurrencyPair::new(USDT, BTC), + exchange_value, + expected_value, + false + ), + crate::Error::::CannotRespectMinimumRequested + ); + }); +} + +// +// - test high slippage scenario +// trying to exchange a large value, will result in high_slippage scenario +// there should be substantial difference between expected exchange value and received amount. +#[test] +fn high_slippage() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_btc = 1_00_u128 * unit; + let btc_price = 45_000_u128; + let initial_usdt = initial_btc * btc_price; + let pool_id = + create_pool(BTC, USDT, initial_btc, initial_usdt, Permill::zero(), Permill::zero()); + let bob_btc = 99_u128 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(BTC, &BOB, bob_btc)); + + assert_ok!(::sell(&BOB, pool_id, BTC, bob_btc, false)); + let usdt_balance = Tokens::balance(USDT, &BOB); + let idea_usdt_balance = bob_btc * btc_price; + assert!((idea_usdt_balance - usdt_balance) > 5_u128); + }); +} + +// +// - test protocol_fee and owner_fee +#[test] +fn fees() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_btc = 1_00_u128 * unit; + let btc_price = 45_000_u128; + let initial_usdt = initial_btc * btc_price; + let fee = Permill::from_float(0.05); + let protocol_fee = Permill::from_float(0.01); + let total_fee = fee + protocol_fee; + let pool_id = create_pool(BTC, USDT, initial_btc, initial_usdt, fee, protocol_fee); + let bob_usdt = 45_000_u128 * unit; + let quote_usdt = bob_usdt - total_fee.mul_floor(bob_usdt); + let expected_btc_value = ::get_exchange_value(pool_id, USDT, quote_usdt) + .expect("get_exchange_value failed"); + // Mint the tokens + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + + assert_ok!(::sell(&BOB, pool_id, USDT, bob_usdt, false)); + let btc_balance = Tokens::balance(BTC, &BOB); + assert_ok!(default_acceptable_computation_error(expected_btc_value, btc_balance)); + }); +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(10000))] + #[test] + fn buy_sell_proptest( + btc_value in 1..u32::MAX, + ) { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_btc = 1_000_000_000_000_u128 * unit; + let btc_price = 45_000_u128; + let initial_usdt = initial_btc * btc_price; + let btc_value = btc_value as u128 * unit; + let usdt_value = btc_value * btc_price; + let pool_id = create_pool( + BTC, + USDT, + initial_btc, + initial_usdt, + Permill::zero(), + Permill::zero(), + ); + prop_assert_ok!(Tokens::mint_into(USDT, &BOB, usdt_value)); + prop_assert_ok!(Pablo::sell(Origin::signed(BOB), pool_id, USDT, usdt_value, false)); + let bob_btc = Tokens::balance(BTC, &BOB); + // mint extra BTC equal to slippage so that original amount of USDT can be buy back + prop_assert_ok!(Tokens::mint_into(BTC, &BOB, btc_value - bob_btc)); + prop_assert_ok!(Pablo::buy(Origin::signed(BOB), pool_id, USDT, usdt_value, false)); + let bob_usdt = Tokens::balance(USDT, &BOB); + let slippage = usdt_value - bob_usdt; + let slippage_percentage = slippage as f64 * 100.0_f64 / usdt_value as f64; + prop_assert!(slippage_percentage < 1.0_f64); + Ok(()) + })?; + } + + #[test] + fn add_remove_liquidity_proptest( + btc_value in 1..u32::MAX, + ) { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_btc = 1_000_000_000_000_u128 * unit; + let btc_price = 45_000_u128; + let initial_usdt = initial_btc * btc_price; + let btc_value = btc_value as u128 * unit; + let usdt_value = btc_value * btc_price; + let pool_id = create_pool( + BTC, + USDT, + initial_btc, + initial_usdt, + Permill::zero(), + Permill::zero(), + ); + let pool = get_pool(pool_id); + prop_assert_ok!(Tokens::mint_into(USDT, &BOB, usdt_value)); + prop_assert_ok!(Tokens::mint_into(BTC, &BOB, btc_value)); + prop_assert_ok!(Pablo::add_liquidity(Origin::signed(BOB), pool_id, btc_value, usdt_value, 0, false)); + let term1 = initial_usdt.integer_sqrt_checked().expect("integer_sqrt failed"); + let term2 = initial_btc.integer_sqrt_checked().expect("integer_sqrt failed"); + let expected_lp_tokens = safe_multiply_by_rational(term1, btc_value, term2).expect("multiply_by_rational failed"); + let lp_token = Tokens::balance(pool.lp_token, &BOB); + prop_assert_ok!(default_acceptable_computation_error(expected_lp_tokens, lp_token)); + prop_assert_ok!(Pablo::remove_liquidity(Origin::signed(BOB), pool_id, lp_token, 0, 0)); + let btc_value_redeemed = Tokens::balance(BTC, &BOB); + let usdt_value_redeemed = Tokens::balance(USDT, &BOB); + prop_assert_ok!(default_acceptable_computation_error(btc_value_redeemed, btc_value)); + prop_assert_ok!(default_acceptable_computation_error(usdt_value_redeemed, usdt_value)); + Ok(()) + })?; + } + + #[test] + fn swap_proptest( + usdt_value in 1..u32::MAX, + ) { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_btc = 1_000_000_000_000_u128 * unit; + let btc_price = 45_000_u128; + let initial_usdt = initial_btc * btc_price; + let usdt_value = usdt_value as u128 * unit; + let pool_id = create_pool( + BTC, + USDT, + initial_btc, + initial_usdt, + Permill::from_float(0.025), + Permill::zero(), + ); + let pool = get_pool(pool_id); + prop_assert_ok!(Tokens::mint_into(USDT, &BOB, usdt_value)); + prop_assert_ok!(Pablo::swap(Origin::signed(BOB), pool_id, CurrencyPair::new(BTC, USDT), usdt_value, 0, false)); + let usdt_value_after_fee = usdt_value - pool.fee.mul_floor(usdt_value); + let ratio = initial_btc as f64 / initial_usdt as f64; + let expected_btc_value = ratio * usdt_value_after_fee as f64; + let expected_btc_value = expected_btc_value as u128; + let bob_btc = Tokens::balance(BTC, &BOB); + prop_assert_ok!(default_acceptable_computation_error(bob_btc, expected_btc_value)); + Ok(()) + })?; +} +} diff --git a/frame/ping/Cargo.toml b/frame/ping/Cargo.toml index 4fd01071ff0..f13687fa7c2 100644 --- a/frame/ping/Cargo.toml +++ b/frame/ping/Cargo.toml @@ -1,35 +1,39 @@ [package] authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" +homepage = "https://composable.finance" name = "pallet-ping" version = "0.1.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.3.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "2.3.0", default-features = false, features = [ + "derive", +] } +scale-info = { version = "1.0.0", default-features = false, features = [ + "derive", +] } serde = { version = "1.0.130", optional = true, features = ["derive"] } -sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.16" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.16" } -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.16" } -frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.16" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.17" } +frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.17" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.17" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.17" } -xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.16" } +xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.17" } -cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } +cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } [features] default = ["std"] std = [ - "codec/std", - "scale-info/std", - "serde", - "cumulus-primitives-core/std", - "sp-std/std", - "sp-runtime/std", - "frame-support/std", - "frame-system/std", + "codec/std", + "scale-info/std", + "serde", + "cumulus-primitives-core/std", + "sp-std/std", + "sp-runtime/std", + "frame-support/std", + "frame-system/std", ] diff --git a/frame/privilege/Cargo.toml b/frame/privilege/Cargo.toml index bd4ce74b05a..704e9dbc609 100644 --- a/frame/privilege/Cargo.toml +++ b/frame/privilege/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "pallet-privilege" -version = "0.0.1" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2018" +homepage = "https://composable.finance" +name = "pallet-privilege" +version = "0.0.1" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] @@ -15,34 +15,36 @@ package = "parity-scale-codec" version = "2.0.0" [dependencies] -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } +sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -composable-traits = { version = "0.0.1", path = "../composable-traits", default-features = false } bitflags = "1.3.2" +composable-traits = { version = "0.0.1", path = "../composable-traits", default-features = false } [features] default = ["std"] std = [ - "codec/std", - "frame-support/std", - "frame-system/std", - "sp-runtime/std", - "sp-io/std", - "sp-core/std", - "sp-std/std", - "sp-arithmetic/std", - "composable-traits/std", + "codec/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-io/std", + "sp-core/std", + "sp-std/std", + "sp-arithmetic/std", + "composable-traits/std", ] runtime-benchmarks = [ - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", ] diff --git a/frame/transaction-fee/Cargo.lock b/frame/transaction-fee/Cargo.lock new file mode 100644 index 00000000000..a4794ea2308 --- /dev/null +++ b/frame/transaction-fee/Cargo.lock @@ -0,0 +1,2655 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "addr2line" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom 0.2.4", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anyhow" +version = "1.0.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0" + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +dependencies = [ + "nodrop", +] + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + +[[package]] +name = "async-trait" +version = "0.1.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e121dee8023ce33ab248d9ce1493df03c3b38a659b240096fcbd7048ff9c31f" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base58" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitvec" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7774144344a4faa177370406a7ff5f1da24303817368584c6206c8303eb07848" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake2-rfc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" +dependencies = [ + "arrayvec 0.4.12", + "constant_time_eq", +] + +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array 0.12.4", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array 0.14.5", +] + +[[package]] +name = "block-buffer" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +dependencies = [ + "generic-array 0.14.5", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", +] + +[[package]] +name = "bumpalo" +version = "3.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" + +[[package]] +name = "byte-slice-cast" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d30c751592b77c499e7bce34d99d67c2c11bdc0574e9a488ddade14150a4698" + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "cc" +version = "1.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "winapi", +] + +[[package]] +name = "composable-support" +version = "0.0.1" +dependencies = [ + "frame-support", + "frame-system", + "is_sorted", + "parity-scale-codec", + "scale-info", +<<<<<<< HEAD +======= + "serde", +>>>>>>> main + "sorted-vec", + "sp-arithmetic", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "composable-traits" +version = "0.0.1" +dependencies = [ + "bitflags", + "composable-support", + "frame-support", + "frame-system", +<<<<<<< HEAD + "orml-traits", +======= +>>>>>>> main + "parity-scale-codec", + "scale-info", + "serde", + "sp-arithmetic", + "sp-runtime", + "sp-std", + "xcm", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "cpufeatures" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4600d695eb3f6ce1cd44e6e291adceb2cc3ab12f20a33777ecd0bf6eba34e06" +dependencies = [ + "generic-array 0.14.5", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array 0.14.5", + "subtle", +] + +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array 0.14.5", + "subtle", +] + +[[package]] +name = "curve25519-dalek" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b85542f99a2dfa2a1b8e192662741c9859a846b296bef1c92ef9b58b5a216" +dependencies = [ + "byteorder", + "digest 0.8.1", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn", +] + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.4", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array 0.14.5", +] + +[[package]] +name = "digest" +<<<<<<< HEAD +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b697d66081d42af4fba142d56918a3cb21dc8eb63372c6b85d14f44fb9c5979b" +dependencies = [ + "block-buffer 0.10.2", + "crypto-common", + "generic-array 0.14.5", +======= +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cb780dce4f9a8f5c087362b3a4595936b2019e7c8b30f2c3e9a7e94e6ae9837" +dependencies = [ + "block-buffer 0.10.2", + "crypto-common", +>>>>>>> main +] + +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + +[[package]] +name = "dyn-clonable" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e9232f0e607a262ceb9bd5141a3dfb3e4db6994b31989bbfd845878cba59fd4" +dependencies = [ + "dyn-clonable-impl", + "dyn-clone", +] + +[[package]] +name = "dyn-clonable-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dyn-clone" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf" + +[[package]] +name = "ed25519" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74e1069e39f1454367eb2de793ed062fac4c35c2934b76a81d90dd9abcd28816" +dependencies = [ + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek 3.2.0", + "ed25519", + "rand 0.7.3", + "serde", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "environmental" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b91989ae21441195d7d9b9993a2f9295c7e1a8c96255d8b729accddc124797" + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "fixed-hash" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" +dependencies = [ + "byteorder", +<<<<<<< HEAD + "rand 0.8.4", +======= + "rand 0.8.5", +>>>>>>> main + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "frame-metadata" +version = "14.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ed5e5c346de62ca5c184b4325a6600d1eaca210666e4606fe4e449574978d0" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "frame-support" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "bitflags", + "frame-metadata", + "frame-support-procedural", + "impl-trait-for-tuples", + "log", + "once_cell", + "parity-scale-codec", + "paste", + "scale-info", + "serde", + "smallvec", + "sp-arithmetic", + "sp-core", + "sp-core-hashing-proc-macro", + "sp-inherents", + "sp-io", + "sp-runtime", + "sp-staking", + "sp-state-machine", + "sp-std", + "sp-tracing", + "tt-call", +] + +[[package]] +name = "frame-support-procedural" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "Inflector", + "frame-support-procedural-tools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "frame-support-procedural-tools" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "frame-support-procedural-tools-derive", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "frame-support-procedural-tools-derive" +version = "3.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "frame-system" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "frame-support", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-version", +] + +[[package]] +name = "funty" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" + +[[package]] +name = "futures" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-executor" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", + "num_cpus", +] + +[[package]] +name = "futures-io" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" + +[[package]] +name = "futures-macro" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" + +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.10.2+wasi-snapshot-preview1", +] + +[[package]] +name = "gimli" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" + +[[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.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c21d40587b92fa6a6c6e3c1bdbf87d75511db5672f9c93175574b3a00df1758" +dependencies = [ + "ahash", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[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 0.8.0", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac 0.11.1", + "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 0.14.5", + "hmac 0.8.1", +] + +[[package]] +name = "impl-codec" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "161ebdfec3c8e3b52bf61c4f3550a1eea4f9579d10dc1b936f3171ebdcd6c443" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-serde" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits", +] + +[[package]] +name = "is_sorted" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357376465c37db3372ef6a00585d336ed3d0f11d4345eef77ebcb05865392b21" + +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + +[[package]] +name = "js-sys" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" +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" + +[[package]] +name = "libc" +<<<<<<< HEAD +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c" +======= +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06e509672465a0504304aa87f9f176f2b2b716ed8fb105ebe5c02dc6dce96a94" +>>>>>>> main + +[[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", +<<<<<<< HEAD + "rand 0.8.4", +======= + "rand 0.8.5", +>>>>>>> main + "serde", + "sha2 0.9.9", + "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 = "lock_api" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "matchers" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "memory-db" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d505169b746dacf02f7d14d8c80b34edfd8212159c63d23c977739a0d960c626" +dependencies = [ + "hash-db", + "hashbrown 0.11.2", + "parity-util-mem", +] + +[[package]] +name = "memory_units" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" + +[[package]] +name = "merlin" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e261cf0f8b3c42ded9f7d2bb59dea03aa52bc8a1cbc7482f9fc3fd1229d3b42" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.5.1", + "zeroize", +] + +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "num-bigint" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" +dependencies = [ + "autocfg", + "num-integer", + "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-rational" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" +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 = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "orml-tokens" +version = "0.4.1-dev" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?rev=aac79b3b31953381669a2ffa9b3e9bfe48e87f38#aac79b3b31953381669a2ffa9b3e9bfe48e87f38" +dependencies = [ + "frame-support", + "frame-system", + "orml-traits", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "orml-traits" +version = "0.4.1-dev" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?rev=aac79b3b31953381669a2ffa9b3e9bfe48e87f38#aac79b3b31953381669a2ffa9b3e9bfe48e87f38" +dependencies = [ + "frame-support", + "impl-trait-for-tuples", + "num-traits", + "orml-utilities", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", + "xcm", +] + +[[package]] +name = "orml-utilities" +version = "0.4.1-dev" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?rev=aac79b3b31953381669a2ffa9b3e9bfe48e87f38#aac79b3b31953381669a2ffa9b3e9bfe48e87f38" +dependencies = [ + "frame-support", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-transaction-fee" +version = "0.1.0" +dependencies = [ + "composable-traits", + "frame-support", + "frame-system", + "orml-tokens", + "orml-traits", + "pallet-transaction-payment-rpc-runtime-api", + "parity-scale-codec", + "primitives", + "scale-info", + "smallvec", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-transaction-payment" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "serde", + "smallvec", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-transaction-payment-rpc-runtime-api" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "pallet-transaction-payment", + "parity-scale-codec", + "sp-api", + "sp-runtime", +] + +[[package]] +name = "parity-scale-codec" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "373b1a4c1338d9cd3d1fa53b3a11bdab5ab6bd80a20f7f7becd76953ae2be909" +dependencies = [ + "arrayvec 0.7.2", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[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", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "parity-util-mem" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f4cb4e169446179cbc6b8b6320cc9fca49bd2e94e8db25f25f200a8ea774770" +dependencies = [ + "cfg-if", + "hashbrown 0.11.2", + "impl-trait-for-tuples", + "parity-util-mem-derive", + "parking_lot", + "primitive-types", + "winapi", +] + +[[package]] +name = "parity-util-mem-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" +dependencies = [ + "proc-macro2", + "syn", + "synstructure", +] + +[[package]] +name = "parity-wasm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be5e13c266502aadf83426d87d81a0f5d1ef45b8027f5a471c360abfe4bfae92" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "paste" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" + +[[package]] +name = "pbkdf2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd" +dependencies = [ + "crypto-mac 0.8.0", +] + +[[package]] +name = "pbkdf2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" +dependencies = [ + "crypto-mac 0.11.1", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "primitive-types" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-serde", + "scale-info", + "uint", +] + +[[package]] +name = "primitives" +version = "0.1.0" +dependencies = [ +<<<<<<< HEAD +======= + "composable-support", +>>>>>>> main + "composable-traits", + "parity-scale-codec", + "scale-info", + "serde", + "sp-runtime", +] + +[[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-macro2" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb" + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", +<<<<<<< HEAD + "rand_hc 0.2.0", +======= + "rand_hc", +>>>>>>> main + "rand_pcg", +] + +[[package]] +name = "rand" +<<<<<<< HEAD +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +======= +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +>>>>>>> main +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.3", +<<<<<<< HEAD + "rand_hc 0.3.1", +======= +>>>>>>> main +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.3", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom 0.2.4", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +<<<<<<< HEAD +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core 0.6.3", +] + +[[package]] +======= +>>>>>>> main +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "ref-cast" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300f2a835d808734ee295d45007adacb9ebb29dd3ae2424acfa17930cae541da" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c38e3aecd2b21cb3959637b883bb3714bc7e43f0268b9a29d3743ee3e55cdd2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + +[[package]] +name = "scale-info" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c55b744399c25532d63a0d2789b109df8d46fc93752d46b0782991a931a782f" +dependencies = [ + "bitvec", + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", + "serde", +] + +[[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", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "schnorrkel" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "021b403afe70d81eea68f6ea12f6b3c9588e5d536a94c3bf80f15e7faa267862" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "curve25519-dalek 2.1.3", + "getrandom 0.1.16", + "merlin", + "rand 0.7.3", + "rand_core 0.5.1", + "sha2 0.8.2", + "subtle", + "zeroize", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0486718e92ec9a68fbed73bb5ef687d71103b142595b406835649bebd33f72c7" + +[[package]] +name = "serde" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +<<<<<<< HEAD +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d23c1ba4cf0efd44be32017709280b32d1cea5c3f1275c3b6d9e8bc54f758085" +======= +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +>>>>>>> main +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + +[[package]] +name = "sha2" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec" +dependencies = [ + "cfg-if", + "cpufeatures", +<<<<<<< HEAD + "digest 0.10.1", +======= + "digest 0.10.2", +>>>>>>> main +] + +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "signature" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" + +[[package]] +name = "slab" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" + +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + +[[package]] +name = "sorted-vec" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4210e1a17d165a0c1d4a233af1e3b36fb21b1359042767a4d2c73554f5f8c2aa" + +[[package]] +name = "sp-api" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "hash-db", + "log", + "parity-scale-codec", + "sp-api-proc-macro", + "sp-core", + "sp-runtime", + "sp-state-machine", + "sp-std", + "sp-version", + "thiserror", +] + +[[package]] +name = "sp-api-proc-macro" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "blake2-rfc", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sp-application-crypto" +version = "4.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-std", +] + +[[package]] +name = "sp-arithmetic" +version = "4.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "integer-sqrt", + "num-traits", + "parity-scale-codec", + "scale-info", + "serde", + "sp-debug-derive", + "sp-std", + "static_assertions", +] + +[[package]] +name = "sp-core" +version = "4.1.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "base58", + "bitflags", + "blake2-rfc", + "byteorder", + "dyn-clonable", + "ed25519-dalek", + "futures", + "hash-db", + "hash256-std-hasher", + "hex", + "impl-serde", + "lazy_static", + "libsecp256k1", + "log", + "merlin", + "num-traits", + "parity-scale-codec", + "parity-util-mem", + "parking_lot", + "primitive-types", + "rand 0.7.3", + "regex", + "scale-info", + "schnorrkel", + "secrecy", + "serde", + "sha2 0.10.1", + "sp-core-hashing", + "sp-debug-derive", + "sp-externalities", + "sp-runtime-interface", + "sp-std", + "sp-storage", + "ss58-registry", + "substrate-bip39", + "thiserror", + "tiny-bip39", + "tiny-keccak", + "twox-hash", + "wasmi", + "zeroize", +] + +[[package]] +name = "sp-core-hashing" +version = "4.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "blake2-rfc", + "byteorder", + "sha2 0.10.1", + "sp-std", + "tiny-keccak", + "twox-hash", +] + +[[package]] +name = "sp-core-hashing-proc-macro" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "proc-macro2", + "quote", + "sp-core-hashing", + "syn", +] + +[[package]] +name = "sp-debug-derive" +version = "4.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sp-externalities" +version = "0.10.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "environmental", + "parity-scale-codec", + "sp-std", + "sp-storage", +] + +[[package]] +name = "sp-inherents" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "async-trait", + "impl-trait-for-tuples", + "parity-scale-codec", + "sp-core", + "sp-runtime", + "sp-std", + "thiserror", +] + +[[package]] +name = "sp-io" +version = "4.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "futures", + "hash-db", + "libsecp256k1", + "log", + "parity-scale-codec", + "parking_lot", + "sp-core", + "sp-externalities", + "sp-keystore", + "sp-runtime-interface", + "sp-state-machine", + "sp-std", + "sp-tracing", + "sp-trie", + "sp-wasm-interface", + "tracing", + "tracing-core", +] + +[[package]] +name = "sp-keystore" +version = "0.10.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "async-trait", + "derive_more", + "futures", + "merlin", + "parity-scale-codec", + "parking_lot", + "schnorrkel", + "sp-core", + "sp-externalities", +] + +[[package]] +name = "sp-panic-handler" +version = "4.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "backtrace", + "lazy_static", + "regex", +] + +[[package]] +name = "sp-runtime" +version = "4.1.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "either", + "hash256-std-hasher", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "parity-util-mem", + "paste", + "rand 0.7.3", + "scale-info", + "serde", + "sp-application-crypto", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-std", +] + +[[package]] +name = "sp-runtime-interface" +version = "4.1.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "impl-trait-for-tuples", + "parity-scale-codec", + "primitive-types", + "sp-externalities", + "sp-runtime-interface-proc-macro", + "sp-std", + "sp-storage", + "sp-tracing", + "sp-wasm-interface", + "static_assertions", +] + +[[package]] +name = "sp-runtime-interface-proc-macro" +version = "4.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "Inflector", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sp-staking" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "sp-state-machine" +version = "0.10.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "hash-db", + "log", + "num-traits", + "parity-scale-codec", + "parking_lot", + "rand 0.7.3", + "smallvec", + "sp-core", + "sp-externalities", + "sp-panic-handler", + "sp-std", + "sp-trie", + "thiserror", + "tracing", + "trie-db", + "trie-root", +] + +[[package]] +name = "sp-std" +version = "4.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" + +[[package]] +name = "sp-storage" +version = "4.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "ref-cast", + "serde", + "sp-debug-derive", + "sp-std", +] + +[[package]] +name = "sp-tracing" +version = "4.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "parity-scale-codec", + "sp-std", + "tracing", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "sp-trie" +version = "4.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "hash-db", + "memory-db", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-std", + "trie-db", + "trie-root", +] + +[[package]] +name = "sp-version" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "parity-wasm", + "scale-info", + "serde", + "sp-core-hashing-proc-macro", + "sp-runtime", + "sp-std", + "sp-version-proc-macro", + "thiserror", +] + +[[package]] +name = "sp-version-proc-macro" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "parity-scale-codec", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sp-wasm-interface" +version = "4.1.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.17#4aeb95f7f38fcd519e2628f32f79044a8fef99d5" +dependencies = [ + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "sp-std", + "wasmi", +] + +[[package]] +name = "ss58-registry" +<<<<<<< HEAD +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8319f44e20b42e5c11b88b1ad4130c35fe2974665a007b08b02322070177136a" +======= +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8cb4b9ce18beb6cb16ecad62d936245cef5212ddc8e094d7417a75e8d0e85f5" +>>>>>>> main +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "serde", + "serde_json", + "unicode-xid", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "substrate-bip39" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49eee6965196b32f882dd2ee85a92b1dbead41b04e53907f269de3b0dc04733c" +dependencies = [ + "hmac 0.11.0", + "pbkdf2 0.8.0", + "schnorrkel", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[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 = "thread_local" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tiny-bip39" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc59cb9dfc85bb312c3a78fd6aa8a8582e310b0fa885d5bb877f6dcc601839d" +dependencies = [ + "anyhow", + "hmac 0.8.1", + "once_cell", + "pbkdf2 0.4.0", + "rand 0.7.3", + "rustc-hash", + "sha2 0.9.9", + "thiserror", + "unicode-normalization", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinyvec" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + +[[package]] +name = "tracing" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d8d93354fe2a8e50d5953f5ae2e47a3fc2ef03292e7ea46e3cc38f549525fb9" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8276d9a4a3a558d7b7ad5303ad50b53d58264641b82914b7ada36bd762e7a716" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23" +dependencies = [ + "lazy_static", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-serde" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +dependencies = [ + "serde", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" +dependencies = [ + "ansi_term", + "chrono", + "lazy_static", + "matchers", + "regex", + "serde", + "serde_json", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", + "tracing-serde", +] + +[[package]] +name = "trie-db" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32d034c0d3db64b43c31de38e945f15b40cd4ca6d2dcfc26d4798ce8de4ab83" +dependencies = [ + "hash-db", + "hashbrown 0.12.0", + "log", + "rustc-hex", + "smallvec", +] + +[[package]] +name = "trie-root" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a36c5ca3911ed3c9a5416ee6c679042064b93fc637ded67e25f92e68d783891" +dependencies = [ + "hash-db", +] + +[[package]] +name = "tt-call" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e66dcbec4290c69dd03c57e76c2469ea5c7ce109c6dd4351c13055cf71ea055" + +[[package]] +name = "twox-hash" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee73e6e4924fe940354b8d4d98cad5231175d615cd855b758adc658c0aac6a0" +dependencies = [ + "cfg-if", +<<<<<<< HEAD + "rand 0.8.4", +======= + "rand 0.8.5", +>>>>>>> main + "static_assertions", +] + +[[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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f03af7ccf01dd611cc450a0d10dbc9b745770d096473e2faf0ca6e2d66d1e0" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[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.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" + +[[package]] +name = "wasmi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca00c5147c319a8ec91ec1a0edbec31e566ce2c9cc93b3f9bb86a9efd0eb795d" +dependencies = [ + "downcast-rs", + "libc", + "memory_units", + "num-rational", + "num-traits", + "parity-wasm", + "wasmi-validation", +] + +[[package]] +name = "wasmi-validation" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "165343ecd6c018fc09ebcae280752702c9a2ef3e6f8d02f1cfcbdb53ef6d7937" +dependencies = [ + "parity-wasm", +] + +[[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 = "wyz" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" + +[[package]] +name = "xcm" +version = "0.9.17" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.17#41ab002d7451766324a9f314fee11c9c53314350" +dependencies = [ + "derivative", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "scale-info", + "xcm-procedural", +] + +[[package]] +name = "xcm-procedural" +version = "0.1.0" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.17#41ab002d7451766324a9f314fee11c9c53314350" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zeroize" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c88870063c39ee00ec285a2f8d6a966e5b6fb2becc4e8dac77ed0d370ed6006" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81e8f13fef10b63c06356d65d416b070798ddabcadc10d3ece0c5be9b3c7eddb" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] diff --git a/frame/transaction-fee/Cargo.toml b/frame/transaction-fee/Cargo.toml index c30bdeb9f0d..2a101b8021b 100644 --- a/frame/transaction-fee/Cargo.toml +++ b/frame/transaction-fee/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "pallet-transaction-fee" -version = "0.1.0" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" +homepage = "https://composable.finance" +name = "pallet-transaction-fee" +version = "0.1.0" [package.metadata.docs.rs] @@ -11,33 +11,35 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -support = { package = "frame-support", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -system = { package = "frame-system", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -primitives = { path = "../../runtime/primitives", default-features = false } composable-traits = { path = "../composable-traits", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +primitives = { path = "../../runtime/primitives", default-features = false } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +support = { package = "frame-support", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +system = { package = "frame-system", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } [dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } smallvec = "1.6.1" -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } [features] default = ["std"] std = [ - "codec/std", - "support/std", - "system/std", - "sp-runtime/std", - "sp-io/std", - "composable-traits/std", - "primitives/std", - "pallet-transaction-payment-rpc-runtime-api/std", - "sp-std/std", - "scale-info/std", + "codec/std", + "support/std", + "system/std", + "sp-runtime/std", + "sp-io/std", + "composable-traits/std", + "primitives/std", + "pallet-transaction-payment-rpc-runtime-api/std", + "sp-std/std", + "scale-info/std", ] diff --git a/frame/uniswap-v2/Cargo.toml b/frame/uniswap-v2/Cargo.toml index 7128efada0e..534003d9bfc 100644 --- a/frame/uniswap-v2/Cargo.toml +++ b/frame/uniswap-v2/Cargo.toml @@ -1,17 +1,13 @@ [package] -name = "pallet-uniswap-v2" -version = "0.0.1" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" - +homepage = "https://composable.finance" +name = "pallet-uniswap-v2" +version = "0.0.1" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] -[package.metadata.cargo-udeps.ignore] -normal = ["pallet-vault"] - [dependencies.codec] default-features = false features = ["derive"] @@ -19,54 +15,53 @@ package = "parity-scale-codec" version = "2.0.0" [dependencies] -frame-benchmarking = { default-features = false, optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.16' } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } - -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -pallet-oracle = { default-features = false, optional = true, version = "1.0.0", path = "../oracle" } -pallet-vault = { default-features = false, version = "0.0.1", path = "../vault", optional = true } +sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +composable-maths = { path = "../composable-maths", default-features = false } +composable-traits = { path = "../composable-traits", default-features = false } log = { version = "0.4.14", default-features = false } num-traits = { version = "0.2.14", default-features = false } plotters = { version = "0.3.1", optional = true } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = '1', optional = true } -composable-traits = { default-features = false, version = "0.0.1", path = "../composable-traits" } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } +serde = { version = "1.0.130", optional = true } [dev-dependencies] -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -pallet-currency-factory = { version = "0.0.1", path = "../currency-factory" } +composable-tests-helpers = { path = "../composable-tests-helpers" } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +pallet-currency-factory = { path = "../currency-factory" } +proptest = { version = "1.0" } [features] default = ["std"] std = [ - "serde/std", - "codec/std", - "log/std", - "frame-support/std", - "frame-system/std", - "sp-runtime/std", - "sp-io/std", - "sp-core/std", - "sp-std/std", - "sp-arithmetic/std", - "pallet-vault/std", - "scale-info/std", + "serde/std", + "codec/std", + "log/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-io/std", + "sp-core/std", + "sp-std/std", + "sp-arithmetic/std", + "scale-info/std", ] runtime-benchmarks = [ - "frame-benchmarking", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "pallet-oracle/runtime-benchmarks", + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", ] visualization = ["plotters"] diff --git a/frame/uniswap-v2/src/benchmarking.rs b/frame/uniswap-v2/src/benchmarking.rs new file mode 100644 index 00000000000..8344ffccadf --- /dev/null +++ b/frame/uniswap-v2/src/benchmarking.rs @@ -0,0 +1,177 @@ +use super::*; +use crate::Pallet as Uni; +use composable_traits::{defi::CurrencyPair, dex::Amm}; +use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller}; +use frame_support::{ + assert_ok, + traits::fungibles::{Inspect, Mutate}, +}; +use frame_system::RawOrigin; +use sp_arithmetic::Permill; + +benchmarks! { + where_clause { where T::Balance: From, T::AssetId: From } + + create { + let btc: T::AssetId = 100.into(); + let usdt: T::AssetId = 101.into(); + let owner = whitelisted_caller(); + let pair = CurrencyPair::new(btc, usdt); + let fee = Permill::from_percent(1); + let owner_fee = Permill::from_percent(1); + }: _(RawOrigin::Signed(owner), pair, fee, owner_fee) + + add_liquidity { + let btc: T::AssetId = 100.into(); + let usdt: T::AssetId = 101.into(); + let owner = whitelisted_caller(); + let pool_id = Uni::::do_create_pool( + &owner, + CurrencyPair::new(btc, usdt), + Permill::from_percent(1), + Permill::from_percent(1), + ) .expect("impossible; qed;"); + let unit = 1_000_000_000_000; + let btc_price = 45_000; + let nb_of_btc = 100; + // 100 btc/4.5M usdt + let initial_btc: T::Balance = (nb_of_btc * unit).into(); + let initial_usdt: T::Balance = (nb_of_btc * btc_price * unit).into(); + // Mint the tokens + assert_ok!(T::Assets::mint_into(btc, &owner, initial_btc)); + assert_ok!(T::Assets::mint_into(usdt, &owner, initial_usdt)); + }: _(RawOrigin::Signed(owner), pool_id, initial_btc, initial_usdt, 0.into(), false) + + remove_liquidity { + let btc: T::AssetId = 100.into(); + let usdt: T::AssetId = 101.into(); + let owner = whitelisted_caller(); + let pool_id = Uni::::do_create_pool( + &owner, + CurrencyPair::new(btc, usdt), + Permill::from_percent(1), + Permill::from_percent(1), + ) .expect("impossible; qed;"); + let unit = 1_000_000_000_000; + let btc_price = 45_000; + let nb_of_btc = 100; + // 100 btc/4.5M usdt + let initial_btc: T::Balance = (nb_of_btc * unit).into(); + let initial_usdt: T::Balance = (nb_of_btc * btc_price * unit).into(); + // Mint the tokens + assert_ok!(T::Assets::mint_into(btc, &owner, initial_btc)); + assert_ok!(T::Assets::mint_into(usdt, &owner, initial_usdt)); + // Add the liquidity + assert_ok!( as Amm>::add_liquidity( + &owner, + pool_id, + initial_btc, + initial_usdt, + 0.into(), + false + )); + let pool_info = Uni::::get_pool(pool_id).expect("impossible; qed;"); + let lp_amount = T::Assets::balance(pool_info.lp_token, &owner); + }: _(RawOrigin::Signed(owner), pool_id, lp_amount, (0_u128).into(), (0_u128).into()) + + buy { + let btc: T::AssetId = 100.into(); + let usdt: T::AssetId = 101.into(); + let owner = whitelisted_caller(); + let pool_id = Uni::::do_create_pool( + &owner, + CurrencyPair::new(btc, usdt), + Permill::from_percent(1), + Permill::from_percent(1), + ) .expect("impossible; qed;"); + let unit = 1_000_000_000_000; + let btc_price = 45_000; + let nb_of_btc = 100; + // 100 btc/4.5M usdt + let initial_btc: T::Balance = (nb_of_btc * unit).into(); + let initial_usdt: T::Balance = (nb_of_btc * btc_price * unit).into(); + // Mint the tokens + assert_ok!(T::Assets::mint_into(btc, &owner, initial_btc)); + assert_ok!(T::Assets::mint_into(usdt, &owner, initial_usdt)); + // Add the liquidity + assert_ok!( as Amm>::add_liquidity( + &owner, + pool_id, + initial_btc, + initial_usdt, + 0.into(), + false + )); + let user = account("user", 0, 0); + let price = as Amm>::get_exchange_value(pool_id, btc, unit.into())?; + assert_ok!(T::Assets::mint_into(usdt, &user, price)); + // buy 1 btc + }: _(RawOrigin::Signed(user), pool_id, btc, unit.into(), false) + + sell { + let btc: T::AssetId = 100.into(); + let usdt: T::AssetId = 101.into(); + let owner = whitelisted_caller(); + let pool_id = Uni::::do_create_pool( + &owner, + CurrencyPair::new(btc, usdt), + Permill::from_percent(1), + Permill::from_percent(1), + ) .expect("impossible; qed;"); + let unit = 1_000_000_000_000; + let btc_price = 45_000; + let nb_of_btc = 100; + // 100 btc/4.5M usdt + let initial_btc: T::Balance = (nb_of_btc * unit).into(); + let initial_usdt: T::Balance = (nb_of_btc * btc_price * unit).into(); + // Mint the tokens + assert_ok!(T::Assets::mint_into(btc, &owner, initial_btc)); + assert_ok!(T::Assets::mint_into(usdt, &owner, initial_usdt)); + // Add the liquidity + assert_ok!( as Amm>::add_liquidity( + &owner, + pool_id, + initial_btc, + initial_usdt, + 0.into(), + false + )); + let user = account("user", 0, 0); + assert_ok!(T::Assets::mint_into(btc, &user, unit.into())); + }: _(RawOrigin::Signed(user), pool_id, btc, unit.into(), false) + + swap { + let btc: T::AssetId = 100.into(); + let usdt: T::AssetId = 101.into(); + let owner = whitelisted_caller(); + let pair = CurrencyPair::new(btc, usdt); + let pool_id = Uni::::do_create_pool( + &owner, + pair, + Permill::from_percent(1), + Permill::from_percent(1), + ) .expect("impossible; qed;"); + let unit = 1_000_000_000_000; + let btc_price = 45_000; + let nb_of_btc = 100; + // 100 btc/4.5M usdt + let initial_btc: T::Balance = (nb_of_btc * unit).into(); + let initial_usdt: T::Balance = (nb_of_btc * btc_price * unit).into(); + // Mint the tokens + assert_ok!(T::Assets::mint_into(btc, &owner, initial_btc)); + assert_ok!(T::Assets::mint_into(usdt, &owner, initial_usdt)); + // Add the liquidity + assert_ok!( as Amm>::add_liquidity( + &owner, + pool_id, + initial_btc, + initial_usdt, + 0.into(), + false + )); + let user = account("user", 0, 0); + assert_ok!(T::Assets::mint_into(btc, &user, unit.into())); + }: _(RawOrigin::Signed(user), pool_id, pair.swap(), unit.into(), 0.into(), false) +} + +impl_benchmark_test_suite!(Uni, crate::mock::new_test_ext(), crate::mock::Test); diff --git a/frame/uniswap-v2/src/lib.rs b/frame/uniswap-v2/src/lib.rs index b0a027b6c3f..afa2bd6dd29 100644 --- a/frame/uniswap-v2/src/lib.rs +++ b/frame/uniswap-v2/src/lib.rs @@ -4,10 +4,8 @@ warn( clippy::disallowed_method, clippy::disallowed_type, - // TODO: enable me after this crate is stablized. todo macros are still denied in the release pipeline, but for - // regular development allowed. - // clippy::indexing_slicing, - // clippy::todo, + clippy::indexing_slicing, + clippy::todo, clippy::unwrap_used, clippy::panic ) @@ -33,7 +31,6 @@ trivial_numeric_casts, unused_extern_crates )] -#![allow(clippy::all)] pub use pallet::*; @@ -43,32 +40,45 @@ mod mock; #[cfg(test)] mod tests; +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; +pub mod weights; +pub use crate::weights::WeightInfo; + #[frame_support::pallet] pub mod pallet { use codec::{Codec, FullCodec}; + use composable_maths::dex::constant_product::{ + compute_deposit_lp, compute_in_given_out, compute_out_given_in, + }; use composable_traits::{ - currency::CurrencyFactory, - defi::{CurrencyPair, LiftedFixedBalance}, - dex::{ConstantProductPoolInfo, CurveAmm}, + currency::{CurrencyFactory, RangeId}, + defi::CurrencyPair, + dex::{Amm, ConstantProductPoolInfo}, + math::{safe_multiply_by_rational, SafeAdd, SafeSub}, }; use frame_support::{ pallet_prelude::*, traits::fungibles::{Inspect, Mutate, Transfer}, - PalletId, + transactional, PalletId, }; + use frame_system::{ensure_signed, pallet_prelude::OriginFor}; use scale_info::TypeInfo; use sp_runtime::{ - traits::{ - AccountIdConversion, AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul, - CheckedSub, IntegerSquareRoot, One, Zero, - }, - FixedPointNumber, FixedPointOperand, FixedU128, Permill, + traits::{AccountIdConversion, CheckedAdd, Convert, One, Zero}, + ArithmeticError, Permill, }; - use sp_std::{collections::btree_set::BTreeSet, fmt::Debug, iter::FromIterator}; + use sp_std::fmt::Debug; + + use crate::weights::WeightInfo; + + type PoolOf = + ConstantProductPoolInfo<::AccountId, ::AssetId>; #[pallet::config] pub trait Config: frame_system::Config { type Event: From> + IsType<::Event>; + type AssetId: FullCodec + MaxEncodedLen + Eq @@ -79,29 +89,25 @@ pub mod pallet { + Default + TypeInfo + Ord; + type Balance: Default + Parameter + Codec + MaxEncodedLen + Copy - + Ord - + CheckedAdd - + CheckedSub - + CheckedMul - + AtLeast32BitUnsigned - + From // at least 64 bit + Zero - + One - + IntegerSquareRoot - + FixedPointOperand - + Into - + Into; // cannot do From, until LiftedFixedBalance integer part is larger than 128 - // bit + + Ord + + SafeAdd + + SafeSub; + + type Convert: Convert + Convert; + type CurrencyFactory: CurrencyFactory<::AssetId>; - type LpToken: Transfer::AssetId> + + type Assets: Transfer::AssetId> + Mutate::AssetId> + Inspect::AssetId>; - type Precision: Get; + type PoolId: FullCodec + MaxEncodedLen + Default @@ -111,11 +117,15 @@ pub mod pallet { + Ord + Copy + Debug - + CheckedAdd + + SafeAdd + + SafeSub + Zero + One; - type PoolTokenIndex: Copy + Debug + Eq + Into + From; + + #[pallet::constant] type PalletId: Get; + + type WeightInfo: WeightInfo; } #[pallet::pallet] @@ -132,6 +142,7 @@ pub mod pallet { pub fn PoolCountOnEmpty() -> T::PoolId { Zero::zero() } + /// Existing pools #[pallet::storage] #[pallet::getter(fn pools)] @@ -142,79 +153,15 @@ pub mod pallet { ConstantProductPoolInfo, >; - /// Pair of assets supported by the pool - #[pallet::storage] - #[pallet::getter(fn pool_assets)] - pub type PoolAssets = - StorageMap<_, Blake2_128Concat, T::PoolId, CurrencyPair>; - - /// Balance of asset for given pool excluding admin_fee - #[pallet::storage] - #[pallet::getter(fn pool_asset_balance)] - #[allow(clippy::disallowed_type)] - pub type PoolAssetBalance = StorageDoubleMap< - _, - Blake2_128Concat, - T::PoolId, - Blake2_128Concat, - T::AssetId, - T::Balance, - ValueQuery, - PoolAssetBalanceOnEmpty, - >; - - #[pallet::type_value] - pub fn PoolAssetBalanceOnEmpty() -> T::Balance { - Zero::zero() - } - - /// Balance of asset for given pool including admin_fee - #[pallet::storage] - #[pallet::getter(fn pool_asset_total_balance)] - #[allow(clippy::disallowed_type)] - pub type PoolAssetTotalBalance = StorageDoubleMap< - _, - Blake2_128Concat, - T::PoolId, - Blake2_128Concat, - T::AssetId, - T::Balance, - ValueQuery, - PoolAssetTotalBalanceOnEmpty, - >; - - #[pallet::type_value] - pub fn PoolAssetTotalBalanceOnEmpty() -> T::Balance { - Zero::zero() - } - - #[pallet::hooks] - impl Hooks for Pallet {} - #[pallet::error] pub enum Error { - /// Could not create new asset - AssetNotCreated, - /// Values in the storage are inconsistent - InconsistentStorage, - /// Not enough assets provided - NotEnoughAssets, - /// Some provided assets are not unique - DuplicateAssets, - /// Pool with specified id is not found + InvalidFees, + InvalidPair, PoolNotFound, - /// Error occurred while performing math calculations - Math, - /// Specified asset amount is wrong - AssetAmountMustBePositiveNumber, - /// Required amount of some token did not reached during adding or removing liquidity - RequiredAmountNotReached, - /// Source does not have required amount of coins to complete operation - InsufficientFunds, - /// Specified index is out of range - IndexOutOfRange, - /// The `AssetChecker` can use this error in case it can't provide better error - ExternalAssetCheckFailed, + InvalidAmount, + MissingAmount, + PairMismatch, + CannotRespectMinimumRequested, } #[pallet::event] @@ -222,645 +169,509 @@ pub mod pallet { pub enum Event { /// Pool with specified id `T::PoolId` was created successfully by `T::AccountId`. PoolCreated { - /// Account id of creator. - who: T::AccountId, /// Id of newly created pool. pool_id: T::PoolId, + /// Account id of creator. + who: T::AccountId, }, /// Liquidity added into the pool `T::PoolId` by `T::AccountId`. LiquidityAdded { - /// Account id who added liquidity. - who: T::AccountId, /// Pool id to which liquidity added. pool_id: T::PoolId, - /// Added token amounts. - token_amounts: Vec, - /// Charged fees. - fees: Vec, - /// Invariant after liquidity addition. - invariant: T::Balance, - /// Updated lp token supply. - token_supply: T::Balance, - /// Amount of minted lp tokens. - mint_amount: T::Balance, + /// Account id who added liquidity. + who: T::AccountId, + /// Amount of base asset deposited. + base_amount: T::Balance, + /// Amount of quote asset deposited. + quote_amount: T::Balance, + /// Amount of minted lp. + minted_lp: T::Balance, }, /// Liquidity removed from pool `T::PoolId` by `T::AccountId` in balanced way. LiquidityRemoved { - /// Account id who removed liquidity. - who: T::AccountId, /// Pool id to which liquidity added. pool_id: T::PoolId, - /// Removed token amounts. - token_amounts: Vec, - /// Charged fees. - fees: Vec, - /// Updated lp token supply. - token_supply: T::Balance, + /// Account id who removed liquidity. + who: T::AccountId, + /// Amount of base asset deposited. + base_amount: T::Balance, + /// Amount of quote asset deposited. + quote_amount: T::Balance, + /// New total LP issuance. + total_issuance: T::Balance, }, /// Token exchange happened. - TokenExchanged { + Swapped { /// Account id who exchanged token. who: T::AccountId, /// Pool id on which exchange done. pool_id: T::PoolId, - /// Index of sent token. - sent_token_index: T::PoolTokenIndex, - /// Amount of sent token. - sent_amount: T::Balance, - /// Index of received token. - received_token_index: T::PoolTokenIndex, - /// Amount of received token. - received_amount: T::Balance, + /// Id of asset used as input. + base_asset: T::AssetId, + /// Id of asset used as output. + quote_asset: T::AssetId, + /// Amount of base asset received. + base_amount: T::Balance, + /// Amount of quote asset provided. + quote_amount: T::Balance, /// Charged fees. fee: T::Balance, }, - - /// Withdraw admin fees `Vec` from pool `T::PoolId` by user `T::AccountId` - AdminFeesWithdrawn { - /// Account id which withdrew admin fee. - who: T::AccountId, - /// Pool id from which fee withdrew. - pool_id: T::PoolId, - /// Account id to which fee deposited. - admin_fee_account: T::AccountId, - /// Amounts of fees. - admin_fees: Vec, - }, } #[pallet::call] - impl Pallet {} + impl Pallet { + /// Create a new pool. + /// + /// Emits `PoolCreated` even when successful. + #[pallet::weight(T::WeightInfo::create())] + pub fn create( + origin: OriginFor, + pair: CurrencyPair, + fee: Permill, + owner_fee: Permill, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = Self::do_create_pool(&who, pair, fee, owner_fee)?; + Ok(()) + } - impl CurveAmm for Pallet { + /// Execute a buy order on a pool. + /// + /// The `base_amount` always represent the base asset amount (A/B => A). + /// + /// Emits `Swapped` event when successful. + #[pallet::weight(T::WeightInfo::buy())] + pub fn buy( + origin: OriginFor, + pool_id: T::PoolId, + asset_id: T::AssetId, + amount: T::Balance, + keep_alive: bool, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = ::buy(&who, pool_id, asset_id, amount, keep_alive)?; + Ok(()) + } + + /// Execute a sell order on a pool. + /// + /// The `base_amount` always represent the base asset amount (A/B => A). + /// + /// Emits `Swapped` event when successful. + #[pallet::weight(T::WeightInfo::sell())] + pub fn sell( + origin: OriginFor, + pool_id: T::PoolId, + asset_id: T::AssetId, + amount: T::Balance, + keep_alive: bool, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = ::sell(&who, pool_id, asset_id, amount, keep_alive)?; + Ok(()) + } + + /// Execute a specific swap operation. + /// + /// Buy operation if the pair is the original pool pair (A/B). + /// Sell operation if the pair is the original pool pair swapped (B/A). + /// + /// The `quote_amount` is always the quote asset amount (A/B => B), (B/A => A). + /// + /// Emits `Swapped` event when successful. + #[pallet::weight(T::WeightInfo::swap())] + pub fn swap( + origin: OriginFor, + pool_id: T::PoolId, + pair: CurrencyPair, + quote_amount: T::Balance, + min_receive: T::Balance, + keep_alive: bool, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = ::exchange( + &who, + pool_id, + pair, + quote_amount, + min_receive, + keep_alive, + )?; + Ok(()) + } + + /// Add liquidity to a constant_product pool. + /// + /// Emits `LiquidityAdded` event when successful. + #[pallet::weight(T::WeightInfo::add_liquidity())] + pub fn add_liquidity( + origin: OriginFor, + pool_id: T::PoolId, + base_amount: T::Balance, + quote_amount: T::Balance, + min_mint_amount: T::Balance, + keep_alive: bool, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = ::add_liquidity( + &who, + pool_id, + base_amount, + quote_amount, + min_mint_amount, + keep_alive, + )?; + Ok(()) + } + + /// Remove liquidity from constant_product pool. + /// + /// Emits `LiquidityRemoved` event when successful. + #[pallet::weight(T::WeightInfo::remove_liquidity())] + pub fn remove_liquidity( + origin: OriginFor, + pool_id: T::PoolId, + lp_amount: T::Balance, + min_base_amount: T::Balance, + min_quote_amount: T::Balance, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let _ = ::remove_liquidity( + &who, + pool_id, + lp_amount, + min_base_amount, + min_quote_amount, + )?; + Ok(()) + } + } + + impl Amm for Pallet { type AssetId = T::AssetId; type Balance = T::Balance; type AccountId = T::AccountId; type PoolId = T::PoolId; - type PoolTokenIndex = T::PoolTokenIndex; - fn pool_exists(pool_id: T::PoolId) -> bool { + fn pool_exists(pool_id: Self::PoolId) -> bool { Pools::::contains_key(pool_id) } - fn pool_count() -> T::PoolId { - PoolCount::::get() + fn currency_pair( + pool_id: Self::PoolId, + ) -> Result, DispatchError> { + let pool = Self::get_pool(pool_id)?; + Ok(pool.pair) } + fn get_exchange_value( + pool_id: Self::PoolId, + asset_id: Self::AssetId, + amount: Self::Balance, + ) -> Result { + let pool = Self::get_pool(pool_id)?; + let pool_account = Self::account_id(&pool_id); + let amount = T::Convert::convert(amount); + let half_weight = Permill::from_percent(50); + let pool_base_aum = + T::Convert::convert(T::Assets::balance(pool.pair.base, &pool_account)); + let pool_quote_aum = + T::Convert::convert(T::Assets::balance(pool.pair.quote, &pool_account)); + let exchange_amount = if asset_id == pool.pair.quote { + compute_out_given_in( + half_weight, + half_weight, + pool_quote_aum, + pool_base_aum, + amount, + ) + } else { + compute_in_given_out( + half_weight, + half_weight, + pool_quote_aum, + pool_base_aum, + amount, + ) + }?; + Ok(T::Convert::convert(exchange_amount)) + } + + #[transactional] fn add_liquidity( who: &Self::AccountId, - pool_id: T::PoolId, - amounts: Vec, + pool_id: Self::PoolId, + base_amount: Self::Balance, + quote_amount: Self::Balance, min_mint_amount: Self::Balance, + keep_alive: bool, ) -> Result<(), DispatchError> { - let zero = Self::Balance::zero(); - ensure!(amounts.len() == 2, Error::::IndexOutOfRange); - ensure!( - amounts.iter().all(|&x| x >= zero), - Error::::AssetAmountMustBePositiveNumber - ); - - let pool = Self::get_pool_info(pool_id).ok_or(Error::::PoolNotFound)?; - let pool_lp_asset = pool.lp_token; - let assets_pair = PoolAssets::::get(pool_id).ok_or(Error::::PoolNotFound)?; - let assets = assets_pair.as_slice(); - let mut balances = Vec::new(); - for asset_id in assets { - balances.push(PoolAssetBalance::::get(pool_id, asset_id)); - } - - let n_coins = assets.len(); - - ensure!(n_coins == balances.len(), Error::::InconsistentStorage); - - ensure!(n_coins == amounts.len(), Error::::IndexOutOfRange); - - let old_balances: Vec = balances - .iter() - .map(|b| { - let b_u: u128 = (*b).into(); - FixedU128::saturating_from_integer(b_u) - }) - .collect(); - let old_balance_a = old_balances.get(0).ok_or(Error::::IndexOutOfRange)?; - let old_balance_b = old_balances.get(1).ok_or(Error::::IndexOutOfRange)?; - let amount_a_u: u128 = (*amounts.get(0).ok_or(Error::::IndexOutOfRange)?).into(); - let amount_b_u: u128 = (*amounts.get(1).ok_or(Error::::IndexOutOfRange)?).into(); - let amount_a_desired = FixedU128::saturating_from_integer(amount_a_u); - let amount_b_desired = FixedU128::saturating_from_integer(amount_b_u); - let amount_a; - let amount_b; - - if *old_balance_a == FixedU128::zero() && *old_balance_b == FixedU128::zero() { - amount_a = amount_a_desired; - amount_b = amount_b_desired; - } else { - let amount_b_optimal = - Self::quote(amount_a_desired, *old_balance_a, *old_balance_b) - .ok_or(Error::::Math)?; - - if amount_b_optimal <= amount_b_desired { - amount_a = amount_a_desired; - amount_b = amount_b_optimal; - } else { - let amount_a_optimal = - Self::quote(amount_b_desired, *old_balance_b, *old_balance_a) - .ok_or(Error::::Math)?; - assert!(amount_a_optimal <= amount_a_desired); - amount_a = amount_a_optimal; - amount_b = amount_b_desired; - } - } - - let token_supply = T::LpToken::total_issuance(pool_lp_asset); - let token_supply_u: u128 = token_supply.into(); - let token_supply_f = FixedU128::saturating_from_integer(token_supply_u); - let mint_amount; - if token_supply_u == 0 { - let mint_amount_f = amount_a.checked_mul(&amount_b).ok_or(Error::::Math)?; - let mint_amount_b: T::Balance = - mint_amount_f.checked_mul_int(1_u64).ok_or(Error::::Math)?.into(); - mint_amount = mint_amount_b.integer_sqrt(); - } else { - let mint_a = amount_a - .checked_mul(&token_supply_f) - .ok_or(Error::::Math)? - .checked_div(&old_balance_a) - .ok_or(Error::::Math)?; - let mint_b = amount_b - .checked_mul(&token_supply_f) - .ok_or(Error::::Math)? - .checked_div(&old_balance_b) - .ok_or(Error::::Math)?; - let mint_amount_f = mint_a.min(mint_b); - mint_amount = mint_amount_f.checked_mul_int(1_u64).ok_or(Error::::Math)?.into(); - } - - let asset_id_a = *assets.get(0).ok_or(Error::::IndexOutOfRange)?; - let asset_id_b = *assets.get(1).ok_or(Error::::IndexOutOfRange)?; - let new_balance_a = old_balance_a.checked_add(&amount_a).ok_or(Error::::Math)?; - let new_balance_b = old_balance_b.checked_add(&amount_b).ok_or(Error::::Math)?; - PoolAssetBalance::::mutate(pool_id, asset_id_a, |balance| -> DispatchResult { - *balance = new_balance_a.checked_mul_int(1_u64).ok_or(Error::::Math)?.into(); - Ok(()) - })?; - PoolAssetBalance::::mutate(pool_id, asset_id_b, |balance| -> DispatchResult { - *balance = new_balance_b.checked_mul_int(1_u64).ok_or(Error::::Math)?.into(); - Ok(()) - })?; - - ensure!(mint_amount >= min_mint_amount, Error::::RequiredAmountNotReached); - - let new_token_supply = - token_supply.checked_add(&mint_amount).ok_or(Error::::Math)?; - - // Ensure that for all tokens user has sufficient amount - for (i, amount) in amounts.iter().enumerate() { - let asset_i = assets.get(i).ok_or(Error::::IndexOutOfRange)?; - ensure!( - T::LpToken::balance(*asset_i, who) >= *amount, - Error::::InsufficientFunds - ); - } - // Transfer funds to pool - for (i, amount) in amounts.iter().enumerate() { - if amount > &zero { - Self::transfer_liquidity_into_pool( - &Self::account_id(&pool_id), - pool_id, - who, - i, - *amount, - )?; - } - } + ensure!(base_amount > T::Balance::zero(), Error::::InvalidAmount); + + let pool = Self::get_pool(pool_id)?; + let pool_account = Self::account_id(&pool_id); + let pool_base_aum = + T::Convert::convert(T::Assets::balance(pool.pair.base, &pool_account)); + let pool_quote_aum = + T::Convert::convert(T::Assets::balance(pool.pair.quote, &pool_account)); + + let lp_total_issuance = T::Convert::convert(T::Assets::total_issuance(pool.lp_token)); + let (quote_amount, lp_to_mint) = compute_deposit_lp( + lp_total_issuance, + T::Convert::convert(base_amount), + T::Convert::convert(quote_amount), + pool_base_aum, + pool_quote_aum, + )?; + let quote_amount = T::Convert::convert(quote_amount); + let lp_to_mint = T::Convert::convert(lp_to_mint); - T::LpToken::mint_into(pool_lp_asset, who, mint_amount)?; + ensure!(quote_amount > T::Balance::zero(), Error::::InvalidAmount); + ensure!(lp_to_mint >= min_mint_amount, Error::::CannotRespectMinimumRequested); - let mut invariant = T::Balance::one(); - for asset_id in assets { - invariant *= PoolAssetBalance::::get(pool_id, asset_id); - } + T::Assets::transfer(pool.pair.base, who, &pool_account, base_amount, keep_alive)?; + T::Assets::transfer(pool.pair.quote, who, &pool_account, quote_amount, keep_alive)?; + T::Assets::mint_into(pool.lp_token, who, lp_to_mint)?; - Self::deposit_event(Event::LiquidityAdded { - who: who.clone(), + Self::deposit_event(Event::::LiquidityAdded { pool_id, - token_amounts: amounts, - fees: vec![], - invariant, - token_supply: new_token_supply, - mint_amount, + who: who.clone(), + base_amount, + quote_amount, + minted_lp: lp_to_mint, }); Ok(()) } + #[transactional] fn remove_liquidity( who: &Self::AccountId, pool_id: T::PoolId, - amount: Self::Balance, - min_amounts: Vec, + lp_amount: Self::Balance, + min_base_amount: Self::Balance, + min_quote_amount: Self::Balance, ) -> Result<(), DispatchError> { - let zero = FixedU128::zero(); - let b_zero = Self::Balance::zero(); - ensure!(amount >= b_zero, Error::::AssetAmountMustBePositiveNumber); - let amount_u: u128 = amount.into(); - let amount_f = FixedU128::saturating_from_integer(amount_u); - - let min_amounts_f: Vec = min_amounts - .iter() - .map(|b| { - let b_u: u128 = (*b).into(); - FixedU128::saturating_from_integer(b_u) - }) - .collect(); - - let pool = Self::get_pool_info(pool_id).ok_or(Error::::PoolNotFound)?; - let pool_lp_asset = pool.lp_token; - let assets_pair = PoolAssets::::get(pool_id).ok_or(Error::::PoolNotFound)?; - let assets = assets_pair.as_slice(); - let n_coins = assets.len(); - let mut balances = Vec::new(); - for asset_id in assets { - balances.push(PoolAssetBalance::::get(pool_id, asset_id)); - } - - ensure!(n_coins == balances.len(), Error::::InconsistentStorage); - - ensure!(n_coins == min_amounts.len(), Error::::IndexOutOfRange); - - let token_supply = T::LpToken::total_issuance(pool_lp_asset); - let token_supply_u: u128 = token_supply.into(); - - let mut amounts_f = vec![FixedU128::zero(); n_coins]; - - for (index, asset_id) in assets.iter().enumerate() { - let old_balance_u: u128 = - (*balances.get(index).ok_or(Error::::IndexOutOfRange)?).into(); - let old_balance = FixedU128::saturating_from_integer(old_balance_u); - // value = old_balance * n_amount / token_supply - let value = (|| { - old_balance - .checked_mul(&amount_f)? - .checked_div(&FixedU128::saturating_from_integer(token_supply_u)) - })() - .ok_or(Error::::Math)?; - let expected_min_amount = - min_amounts_f.get(index).ok_or(Error::::IndexOutOfRange)?; - ensure!(value >= *expected_min_amount, Error::::RequiredAmountNotReached); - PoolAssetBalance::::mutate(pool_id, asset_id, |balance| -> DispatchResult { - *balance = old_balance - .checked_sub(&value) - .ok_or(Error::::InsufficientFunds)? - .checked_mul_int(1_u64) - .ok_or(Error::::Math)? - .into(); - Ok(()) - })?; - amounts_f.insert(index, value); - } - - let amounts: Vec = amounts_f - .iter() - .map(|b_f| Ok(b_f.checked_mul_int(1_u64).ok_or(Error::::Math)?.into())) - .collect::, Error>>()?; - - let new_token_supply = token_supply.checked_sub(&amount).ok_or(Error::::Math)?; - - let fees = vec![T::Balance::zero(); n_coins]; - - T::LpToken::burn_from(pool_lp_asset, who, amount)?; - - // Ensure that for all tokens we have sufficient amount - for (index, asset_id) in assets.iter().enumerate() { - let amount_i = *amounts.get(index).ok_or(Error::::IndexOutOfRange)?; - ensure!( - T::LpToken::balance(*asset_id, &Self::account_id(&pool_id)) >= amount_i, - Error::::InsufficientFunds - ); - } - - for i in 0..n_coins { - let amount_f_i = *amounts_f.get(i).ok_or(Error::::IndexOutOfRange)?; - let amount_i = *amounts.get(i).ok_or(Error::::IndexOutOfRange)?; - if amount_f_i > zero { - Self::transfer_liquidity_from_pool( - &Self::account_id(&pool_id), - pool_id, - i, - who, - amount_i, - )?; - } - } - - Self::deposit_event(Event::LiquidityRemoved { - who: who.clone(), + let pool = Self::get_pool(pool_id)?; + + let pool_account = Self::account_id(&pool_id); + let pool_base_aum = + T::Convert::convert(T::Assets::balance(pool.pair.base, &pool_account)); + let pool_quote_aum = + T::Convert::convert(T::Assets::balance(pool.pair.quote, &pool_account)); + let lp_issued = T::Assets::total_issuance(pool.lp_token); + + let base_amount = T::Convert::convert(safe_multiply_by_rational( + T::Convert::convert(lp_amount), + pool_base_aum, + T::Convert::convert(lp_issued), + )?); + let quote_amount = T::Convert::convert(safe_multiply_by_rational( + T::Convert::convert(lp_amount), + pool_quote_aum, + T::Convert::convert(lp_issued), + )?); + + ensure!( + base_amount >= min_base_amount && quote_amount >= min_quote_amount, + Error::::CannotRespectMinimumRequested + ); + + // NOTE(hussein-aitlance): no need to keep alive the pool account + T::Assets::transfer(pool.pair.base, &pool_account, who, base_amount, false)?; + T::Assets::transfer(pool.pair.quote, &pool_account, who, quote_amount, false)?; + T::Assets::burn_from(pool.lp_token, who, lp_amount)?; + + Self::deposit_event(Event::::LiquidityRemoved { pool_id, - token_amounts: amounts, - fees, - token_supply: new_token_supply, + who: who.clone(), + base_amount, + quote_amount, + total_issuance: lp_issued.safe_sub(&lp_amount)?, }); Ok(()) } - fn exchange( + #[transactional] + fn buy( who: &Self::AccountId, - pool_id: T::PoolId, - i_token: T::PoolTokenIndex, - j_token: T::PoolTokenIndex, - dx: Self::Balance, - min_dy: Self::Balance, + pool_id: Self::PoolId, + asset_id: Self::AssetId, + amount: Self::Balance, + keep_alive: bool, ) -> Result { - let zero_b = Self::Balance::zero(); - ensure!(dx >= zero_b, Error::::AssetAmountMustBePositiveNumber); - - let pool = Self::get_pool_info(pool_id).ok_or(Error::::PoolNotFound)?; - - let i: usize = i_token.into() as usize; - let j: usize = j_token.into() as usize; - - let assets_pair = PoolAssets::::get(pool_id).ok_or(Error::::PoolNotFound)?; - let assets = assets_pair.as_slice(); - let mut balances = Vec::new(); - for asset_id in assets { - balances.push(PoolAssetBalance::::get(pool_id, asset_id)); - } - let n_coins = assets.len(); - - ensure!(i < n_coins && j < n_coins, Error::::IndexOutOfRange); - - let dx_u: u128 = dx.into(); - let dx_f = FixedU128::saturating_from_integer(dx_u); - let min_dy_u: u128 = min_dy.into(); - let min_dy_f = FixedU128::saturating_from_integer(min_dy_u); - - let xp: Vec = balances - .iter() - .map(|b| { - let b_u: u128 = (*b).into(); - FixedU128::saturating_from_integer(b_u) - }) - .collect(); - let xp_i = *xp.get(i).ok_or(Error::::IndexOutOfRange)?; - let xp_j = *xp.get(j).ok_or(Error::::IndexOutOfRange)?; - let x = xp_i.checked_add(&dx_f).ok_or(Error::::Math)?; - let dy_f = Self::get_y_out(dx_f, xp_i, xp_j).ok_or(Error::::Math)?; - - let fee_f: FixedU128 = pool.fee.into(); - let dy_fee_f = dy_f.checked_mul(&fee_f).ok_or(Error::::Math)?; - let dy_fee = dy_fee_f.checked_mul_int(1_u64).ok_or(Error::::Math)?.into(); - let dy_f = dy_f.checked_sub(&dy_fee_f).ok_or(Error::::Math)?; - ensure!(dy_f >= min_dy_f, Error::::RequiredAmountNotReached); - - let dy: Self::Balance = dy_f.checked_mul_int(1_u64).ok_or(Error::::Math)?.into(); - let asset_id_i = *assets.get(i).ok_or(Error::::IndexOutOfRange)?; - let asset_id_j = *assets.get(j).ok_or(Error::::IndexOutOfRange)?; - PoolAssetBalance::::mutate(pool_id, asset_id_i, |balance| -> DispatchResult { - *balance = x.checked_mul_int(1_u64).ok_or(Error::::Math)?.into(); - Ok(()) - })?; - let bal_j = xp_j.checked_sub(&dy_f).ok_or(Error::::Math)?; - PoolAssetBalance::::mutate(pool_id, asset_id_j, |balance| -> DispatchResult { - *balance = bal_j.checked_mul_int(1_u64).ok_or(Error::::Math)?.into(); - Ok(()) - })?; - - ensure!(T::LpToken::balance(asset_id_i, &who) >= dx, Error::::InsufficientFunds); - - ensure!( - T::LpToken::balance(asset_id_j, &Self::account_id(&pool_id)) >= dy, - Error::::InsufficientFunds - ); - - Self::transfer_liquidity_into_pool(&Self::account_id(&pool_id), pool_id, &who, i, dx)?; - Self::transfer_liquidity_from_pool(&Self::account_id(&pool_id), pool_id, j, &who, dy)?; - - Self::deposit_event(Event::TokenExchanged { - who: who.clone(), + let pool = Self::get_pool(pool_id)?; + let pair = if asset_id == pool.pair.base { pool.pair } else { pool.pair.swap() }; + let quote_amount = Self::get_exchange_value(pool_id, asset_id, amount)?; + ::exchange( + who, pool_id, - sent_token_index: i_token, - sent_amount: dx, - received_token_index: j_token, - received_amount: dy, - fee: dy_fee, - }); - Ok(dy) + pair, + quote_amount, + T::Balance::zero(), + keep_alive, + ) + } + + #[transactional] + fn sell( + who: &Self::AccountId, + pool_id: Self::PoolId, + asset_id: Self::AssetId, + amount: Self::Balance, + keep_alive: bool, + ) -> Result { + let pool = Self::get_pool(pool_id)?; + let pair = if asset_id == pool.pair.base { pool.pair.swap() } else { pool.pair }; + ::exchange(who, pool_id, pair, amount, T::Balance::zero(), keep_alive) } - fn withdraw_admin_fees( + #[transactional] + fn exchange( who: &Self::AccountId, pool_id: T::PoolId, - admin_fee_account: &Self::AccountId, - ) -> Result<(), DispatchError> { - let assets_pair = PoolAssets::::get(pool_id).ok_or(Error::::PoolNotFound)?; - let assets = assets_pair.as_slice(); - let mut balances = Vec::new(); - for asset_id in assets { - balances.push(PoolAssetBalance::::get(pool_id, asset_id)); - } - let mut total_balances = Vec::new(); - for asset_id in assets { - total_balances.push(PoolAssetTotalBalance::::get(pool_id, asset_id)); - } - let n_coins = assets.len(); - - ensure!(n_coins == balances.len(), Error::::InconsistentStorage); - - let admin_fees = total_balances - .iter() - .zip(balances) - .map(|(tb, b)| { - let admin_fee = tb.checked_sub(&b).ok_or(Error::::Math)?; - - Ok(admin_fee) - }) - .collect::, DispatchError>>()?; - - let assets = assets.clone(); - - for (index, asset_id) in assets.iter().enumerate() { - let total_balance = - *total_balances.get(index).ok_or(Error::::IndexOutOfRange)?; - let admin_fee = *admin_fees.get(index).ok_or(Error::::IndexOutOfRange)?; - let new_total_balance = - total_balance.checked_sub(&admin_fee).ok_or(Error::::Math)?; - PoolAssetTotalBalance::::mutate( - pool_id, - asset_id, - |total_balance| -> DispatchResult { - *total_balance = new_total_balance; - Ok(()) - }, - )?; - } - - for (asset, amount) in assets.into_iter().zip(admin_fees.iter().copied()) { - T::LpToken::transfer( - *asset, - &Self::account_id(&pool_id), - admin_fee_account, - amount, - true, - )?; - } + pair: CurrencyPair, + quote_amount: Self::Balance, + min_receive: Self::Balance, + keep_alive: bool, + ) -> Result { + let pool = Self::get_pool(pool_id)?; + // /!\ NOTE(hussein-aitlahcen): after this check, do not use pool.pair as the provided + // pair might have been swapped + ensure!(pair == pool.pair, Error::::PairMismatch); + + let (base_amount, quote_amount, lp_fees, owner_fees) = + Self::do_compute_swap(pool_id, pair, quote_amount, true)?; + let total_fees = lp_fees.safe_add(&owner_fees)?; + let quote_amount_including_fees = quote_amount.safe_add(&total_fees)?; + + ensure!(base_amount >= min_receive, Error::::CannotRespectMinimumRequested); + + let pool_account = Self::account_id(&pool_id); + T::Assets::transfer( + pair.quote, + who, + &pool_account, + quote_amount_including_fees, + keep_alive, + )?; + // NOTE(hussein-aitlance): no need to keep alive the pool account + T::Assets::transfer(pair.quote, &pool_account, &pool.owner, owner_fees, false)?; + T::Assets::transfer(pair.base, &pool_account, who, base_amount, false)?; - Self::deposit_event(Event::AdminFeesWithdrawn { - who: who.clone(), + Self::deposit_event(Event::::Swapped { pool_id, - admin_fee_account: admin_fee_account.clone(), - admin_fees, + who: who.clone(), + base_asset: pair.base, + quote_asset: pair.quote, + base_amount, + quote_amount, + fee: total_fees, }); - Ok(()) + Ok(base_amount) } } impl Pallet { - pub fn create_pool( + #[transactional] + pub fn do_create_pool( who: &T::AccountId, - assets: Vec, + pair: CurrencyPair, fee: Permill, - _admin_fee: Permill, + owner_fee: Permill, ) -> Result { - // Assets related checks - ensure!(assets.len() > 1, Error::::NotEnoughAssets); - let unique_assets = BTreeSet::::from_iter(assets.iter().copied()); - ensure!(unique_assets.len() == assets.len(), Error::::DuplicateAssets); + // NOTE(hussein-aitlahcen): do we allow such pair? + ensure!(pair.base != pair.quote, Error::::InvalidPair); + + let total_fees = fee.checked_add(&owner_fee).ok_or(ArithmeticError::Overflow)?; + ensure!(total_fees < Permill::one(), Error::::InvalidFees); + + let lp_token = T::CurrencyFactory::create(RangeId::LP_TOKENS)?; // Add new pool let pool_id = PoolCount::::try_mutate(|pool_count| -> Result { let pool_id = *pool_count; - - Pools::::try_mutate_exists(pool_id, |maybe_pool_info| -> DispatchResult { - // We expect that PoolInfos have sequential keys. - // No PoolInfo can have key greater or equal to PoolCount - ensure!(maybe_pool_info.is_none(), Error::::InconsistentStorage); - let lp_asset = T::CurrencyFactory::reserve_lp_token_id()?; - - *maybe_pool_info = Some(ConstantProductPoolInfo { + Pools::::insert( + pool_id, + ConstantProductPoolInfo { owner: who.clone(), - lp_token: lp_asset, + pair, + lp_token, fee, - }); - - Ok(()) - })?; - - for asset_id in &assets { - PoolAssetBalance::::insert(pool_id, asset_id, T::Balance::zero()); - PoolAssetTotalBalance::::insert(pool_id, asset_id, T::Balance::zero()); - } - - PoolAssets::::try_mutate(pool_id, |pool_assets| -> DispatchResult { - ensure!(pool_assets.is_none(), Error::::InconsistentStorage); - *pool_assets = Some(CurrencyPair::new( - *assets.get(0).ok_or(Error::::IndexOutOfRange)?, - *assets.get(1).ok_or(Error::::IndexOutOfRange)?, - )); - Ok(()) - })?; - - *pool_count = pool_id - .checked_add(&T::PoolId::one()) - .ok_or(Error::::InconsistentStorage)?; - + owner_fee, + }, + ); + *pool_count = pool_id.safe_add(&T::PoolId::one())?; Ok(pool_id) })?; - Self::deposit_event(Event::PoolCreated { who: who.clone(), pool_id }); + Self::deposit_event(Event::PoolCreated { pool_id, who: who.clone() }); Ok(pool_id) } /// Return pool information for given pool_id. - pub fn get_pool_info( - pool_id: T::PoolId, - ) -> Option> { - Pools::::get(pool_id) - } - - /// given some amount of an asset and pair balances, returns an equivalent amount of the - /// other asset - pub fn quote( - amount_a: FixedU128, - balance_a: FixedU128, - balance_b: FixedU128, - ) -> Option { - assert!(amount_a > FixedU128::zero()); - assert!(balance_a > FixedU128::zero() && balance_b > FixedU128::zero()); - // optimal amount_b - amount_a.checked_mul(&balance_b)?.checked_div(&balance_a) - } - - /// given an input amount of an asset and pair balances, returns the maximum output amount - /// of the other asset - pub fn get_y_out( - dx_f: FixedU128, - balance_x_f: FixedU128, - balance_y_f: FixedU128, - ) -> Option { - assert!(dx_f > FixedU128::zero()); - assert!(balance_x_f > FixedU128::zero() && balance_y_f > FixedU128::zero()); - let numerator = dx_f.checked_mul(&balance_y_f)?; - let denominator = balance_x_f.checked_add(&dx_f)?; - numerator.checked_div(&denominator) + pub(crate) fn get_pool(pool_id: T::PoolId) -> Result, DispatchError> { + Pools::::get(pool_id).ok_or_else(|| Error::::PoolNotFound.into()) } - fn transfer_liquidity_into_pool( - pool_account_id: &T::AccountId, - pool_id: T::PoolId, - source: &T::AccountId, - destination_asset_index: usize, - amount: T::Balance, - ) -> DispatchResult { - let assets_pair = PoolAssets::::get(pool_id).ok_or(Error::::PoolNotFound)?; - let assets = assets_pair.as_slice(); - let asset_id = - assets.get(destination_asset_index).ok_or(Error::::IndexOutOfRange)?; - T::LpToken::transfer(*asset_id, source, pool_account_id, amount, true)?; - PoolAssetTotalBalance::::mutate( - pool_id, - asset_id, - |total_balance| -> DispatchResult { - *total_balance = total_balance.checked_add(&amount).ok_or(Error::::Math)?; - Ok(()) - }, - )?; - - Ok(()) + /// Account of a pool + pub(crate) fn account_id(pool_id: &T::PoolId) -> T::AccountId { + T::PalletId::get().into_sub_account(pool_id) } - fn transfer_liquidity_from_pool( - pool_account_id: &T::AccountId, + /// Assume that the pair is valid for the pool + pub(crate) fn do_compute_swap( pool_id: T::PoolId, - source_asset_index: usize, - destination: &T::AccountId, - amount: T::Balance, - ) -> DispatchResult { - let assets_pair = PoolAssets::::get(pool_id).ok_or(Error::::PoolNotFound)?; - let assets = assets_pair.as_slice(); - let asset_id = assets.get(source_asset_index).ok_or(Error::::IndexOutOfRange)?; - T::LpToken::transfer(*asset_id, pool_account_id, destination, amount, true)?; - - PoolAssetTotalBalance::::mutate( - pool_id, - asset_id, - |total_balance| -> DispatchResult { - *total_balance = total_balance.checked_sub(&amount).ok_or(Error::::Math)?; - Ok(()) - }, + pair: CurrencyPair, + quote_amount: T::Balance, + apply_fees: bool, + ) -> Result<(T::Balance, T::Balance, T::Balance, T::Balance), DispatchError> { + let pool = Self::get_pool(pool_id)?; + let pool_account = Self::account_id(&pool_id); + let pool_base_aum = T::Convert::convert(T::Assets::balance(pair.base, &pool_account)); + let pool_quote_aum = T::Convert::convert(T::Assets::balance(pair.quote, &pool_account)); + let quote_amount = T::Convert::convert(quote_amount); + + // https://uniswap.org/whitepaper.pdf + // 3.2.1 + // we do not inflate the lp for the owner fees + // cut is done before enforcing the invariant + let (lp_fee, owner_fee) = if apply_fees { + let lp_fee = pool.fee.mul_floor(quote_amount); + let owner_fee = pool.owner_fee.mul_floor(quote_amount); + (lp_fee, owner_fee) + } else { + (0, 0) + }; + + let quote_amount_excluding_fees = + quote_amount.safe_sub(&lp_fee)?.safe_sub(&owner_fee)?; + + let half_weight = Permill::from_percent(50); + let base_amount = compute_out_given_in( + half_weight, + half_weight, + pool_quote_aum, + pool_base_aum, + quote_amount_excluding_fees, )?; - Ok(()) - } + ensure!(base_amount > 0 && quote_amount_excluding_fees > 0, Error::::InvalidAmount); - pub fn account_id(pool_id: &T::PoolId) -> T::AccountId { - T::PalletId::get().into_sub_account(pool_id) + Ok(( + T::Convert::convert(base_amount), + T::Convert::convert(quote_amount_excluding_fees), + T::Convert::convert(lp_fee), + T::Convert::convert(owner_fee), + )) } } } diff --git a/frame/uniswap-v2/src/mock.rs b/frame/uniswap-v2/src/mock.rs index a26a52950c8..46fd5d901b9 100644 --- a/frame/uniswap-v2/src/mock.rs +++ b/frame/uniswap-v2/src/mock.rs @@ -1,20 +1,19 @@ -use crate as constant_product_amm; +use crate as pallet_uniswap_v2; use frame_support::{parameter_types, traits::Everything, PalletId}; use frame_system as system; use orml_traits::parameter_type_with_key; -use sp_arithmetic::{traits::Zero, FixedU128}; +use sp_arithmetic::traits::Zero; use sp_core::H256; use sp_runtime::{ testing::Header, - traits::{BlakeTwo256, IdentityLookup}, - FixedPointNumber, + traits::{BlakeTwo256, ConvertInto, IdentityLookup}, }; use system::EnsureRoot; -pub type CurrencyId = u128; +pub type AssetId = u128; -pub const USDT: CurrencyId = 2; -pub const USDC: CurrencyId = 4; +pub const BTC: AssetId = 0; +pub const USDT: AssetId = 1; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; @@ -27,8 +26,7 @@ frame_support::construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic, { System: frame_system::{Pallet, Call, Config, Storage, Event}, - Balances: pallet_balances::{Pallet, Call, Storage, Event}, - ConstantProductAmm: constant_product_amm::{Pallet, Call, Storage, Event}, + Uni: pallet_uniswap_v2::{Pallet, Storage, Event}, LpTokenFactory: pallet_currency_factory::{Pallet, Storage, Event}, Tokens: orml_tokens::{Pallet, Call, Storage, Config, Event}, } @@ -36,7 +34,7 @@ frame_support::construct_runtime!( impl pallet_currency_factory::Config for Test { type Event = Event; - type AssetId = CurrencyId; + type AssetId = AssetId; type AddOrigin = EnsureRoot; type ReserveOrigin = EnsureRoot; type WeightInfo = (); @@ -47,7 +45,7 @@ parameter_types! { pub const SS58Prefix: u8 = 42; } -pub type AccountId = u64; +pub type AccountId = u128; #[allow(dead_code)] pub static ALICE: AccountId = 1; @@ -76,7 +74,7 @@ impl system::Config for Test { type BlockHashCount = BlockHashCount; type Version = (); type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; + type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); type SystemWeightInfo = (); @@ -85,30 +83,14 @@ impl system::Config for Test { type MaxConsumers = frame_support::traits::ConstU32<16>; } -parameter_types! { - pub const ExistentialDeposit: u64 = 1; -} - -impl pallet_balances::Config for Test { - type MaxLocks = (); - type Balance = Balance; - type DustRemoval = (); - type Event = Event; - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; -} - pub type Balance = u128; -pub type AssetId = CurrencyId; - pub type Amount = i128; +pub type PoolId = u32; + parameter_type_with_key! { - pub ExistentialDeposits: |_currency_id: CurrencyId| -> Balance { + pub ExistentialDeposits: |_currency_id: AssetId| -> Balance { Zero::zero() }; } @@ -117,7 +99,7 @@ impl orml_tokens::Config for Test { type Event = Event; type Balance = Balance; type Amount = Amount; - type CurrencyId = CurrencyId; + type CurrencyId = AssetId; type WeightInfo = (); type ExistentialDeposits = ExistentialDeposits; type OnDust = (); @@ -126,20 +108,19 @@ impl orml_tokens::Config for Test { } parameter_types! { - pub Precision: FixedU128 = FixedU128::saturating_from_rational(1, 1_000_000_000); pub TestPalletID : PalletId = PalletId(*b"const_am"); } -impl constant_product_amm::Config for Test { +impl pallet_uniswap_v2::Config for Test { type Event = Event; type AssetId = AssetId; type Balance = Balance; type CurrencyFactory = LpTokenFactory; - type Precision = Precision; - type LpToken = Tokens; - type PoolId = u32; - type PoolTokenIndex = u32; + type Assets = Tokens; + type Convert = ConvertInto; + type PoolId = PoolId; type PalletId = TestPalletID; + type WeightInfo = (); } // Build genesis storage according to the mock runtime. diff --git a/frame/uniswap-v2/src/tests.rs b/frame/uniswap-v2/src/tests.rs index 5ed74c8e479..8ab2bb9f096 100644 --- a/frame/uniswap-v2/src/tests.rs +++ b/frame/uniswap-v2/src/tests.rs @@ -1,156 +1,389 @@ -use frame_support::assert_ok; - use crate::mock::*; -use composable_traits::dex::CurveAmm as ConstantProductAmmTrait; -use frame_support::traits::fungibles::{Inspect, Mutate}; -use sp_runtime::Permill; +use composable_tests_helpers::{ + prop_assert_ok, + test::helper::{acceptable_computation_error, default_acceptable_computation_error}, +}; +use composable_traits::{defi::CurrencyPair, dex::Amm, math::safe_multiply_by_rational}; +use frame_support::{ + assert_err, assert_ok, + traits::fungibles::{Inspect, Mutate}, +}; +use proptest::prelude::*; +use sp_runtime::{traits::IntegerSquareRoot, Permill, TokenError}; + +fn create_pool( + base_asset: AssetId, + quote_asset: AssetId, + base_amount: Balance, + quote_amount: Balance, + lp_fee: Permill, + protocol_fee: Permill, +) -> PoolId { + let pool_id = Uni::do_create_pool( + &ALICE, + CurrencyPair::new(base_asset, quote_asset), + lp_fee, + protocol_fee, + ) + .expect("pool creation failed"); + // Mint the tokens + assert_ok!(Tokens::mint_into(base_asset, &ALICE, base_amount)); + assert_ok!(Tokens::mint_into(quote_asset, &ALICE, quote_amount)); + + // Add the liquidity + assert_ok!(::add_liquidity(&ALICE, pool_id, base_amount, quote_amount, 0, false)); + pool_id +} #[test] -fn add_remove_liquidity() { +fn test() { new_test_ext().execute_with(|| { - // ConstantProductAmm configurations - let assets = vec![USDC, USDT]; - let fee = Permill::zero(); - let admin_fee = Permill::zero(); - - // Mint USDT for ALICE - assert_eq!(Tokens::balance(USDT, &ALICE), 0); - assert_ok!(Tokens::mint_into(USDT, &ALICE, 200000)); - assert_eq!(Tokens::balance(USDT, &ALICE), 200000); - // Mint USDC for ALICE - assert_eq!(Tokens::balance(USDC, &ALICE), 0); - assert_ok!(Tokens::mint_into(USDC, &ALICE, 200000)); - assert_eq!(Tokens::balance(USDC, &ALICE), 200000); - // Mint USDT for BOB - assert_eq!(Tokens::balance(USDT, &BOB), 0); - assert_ok!(Tokens::mint_into(USDT, &BOB, 200000)); - assert_eq!(Tokens::balance(USDT, &BOB), 200000); - // Mint USDC for BOB - assert_eq!(Tokens::balance(USDC, &BOB), 0); - assert_ok!(Tokens::mint_into(USDC, &BOB, 200000)); - assert_eq!(Tokens::balance(USDC, &BOB), 200000); - - // Create ConstantProductAmm pool - let p = ConstantProductAmm::create_pool(&ALICE, assets, fee, admin_fee); - assert_ok!(&p); - let pool_id = p.unwrap(); - let pool = ConstantProductAmm::get_pool_info(pool_id); - assert!(pool.is_some()); - let pool = pool.unwrap(); - let pool_lp_asset = pool.lp_token; - // 1 USDC = 1 USDT - - // Add liquidity from ALICE's account to pool - let amounts = vec![130000u128, 130000u128]; - assert_ok!(ConstantProductAmm::add_liquidity(&ALICE, pool_id, amounts.clone(), 0u128)); - let alice_balance = Tokens::balance(pool_lp_asset, &ALICE); - assert_ne!(alice_balance, 0); - assert_eq!(Tokens::balance(USDT, &ALICE), 200000 - 130000); - assert_eq!(Tokens::balance(USDC, &ALICE), 200000 - 130000); - let pool = ConstantProductAmm::get_pool_info(pool_id); - assert!(pool.is_some()); - - // Add liquidity from BOB's account to pool - assert_ok!(ConstantProductAmm::add_liquidity(&BOB, pool_id, amounts.clone(), 0u128)); - let bob_balance = Tokens::balance(pool_lp_asset, &BOB); - assert_ne!(bob_balance, 0); - assert_eq!(Tokens::balance(USDT, &BOB), 200000 - 130000); - assert_eq!(Tokens::balance(USDC, &BOB), 200000 - 130000); - let min_amt = vec![0u128, 0u128]; - - // Check that pool has USDT and USDC transferred from ALICE and BOB - assert_eq!(Tokens::balance(USDC, &ConstantProductAmm::account_id(&pool_id)), 260000); - assert_eq!(Tokens::balance(USDT, &ConstantProductAmm::account_id(&pool_id)), 260000); - - // Withdraw ALICE"s fund from pool. - assert_ok!(ConstantProductAmm::remove_liquidity( + let pool_id = Uni::do_create_pool( + &ALICE, + CurrencyPair::new(BTC, USDT), + Permill::zero(), + Permill::zero(), + ) + .expect("pool creation failed"); + + let pool = Uni::pools(pool_id).expect("pool not found"); + + let current_product = |a| { + let balance_btc = Tokens::balance(BTC, &a); + let balance_usdt = Tokens::balance(USDT, &a); + balance_btc * balance_usdt + }; + let current_pool_product = || current_product(Uni::account_id(&pool_id)); + + let unit = 1_000_000_000_000; + + let btc_price = 45_000; + + let nb_of_btc = 100; + + // 100 BTC/4.5M USDT + let initial_btc = nb_of_btc * unit; + let initial_usdt = nb_of_btc * btc_price * unit; + + // Mint the tokens + assert_ok!(Tokens::mint_into(BTC, &ALICE, initial_btc)); + assert_ok!(Tokens::mint_into(USDT, &ALICE, initial_usdt)); + + let initial_user_invariant = current_product(ALICE); + + // Add the liquidity + assert_ok!(::add_liquidity( &ALICE, pool_id, - alice_balance, - min_amt.clone() + initial_btc, + initial_usdt, + 0, + false )); - // Check balances which should be impacted. - assert_eq!(Tokens::balance(pool_lp_asset, &ALICE), 0); - assert_eq!(Tokens::balance(USDT, &ALICE), 200000); - assert_eq!(Tokens::balance(USDC, &ALICE), 200000); - assert_eq!(Tokens::balance(USDC, &ConstantProductAmm::account_id(&pool_id)), 130000); - assert_eq!(Tokens::balance(USDT, &ConstantProductAmm::account_id(&pool_id)), 130000); - - // Withdraw BOB"s fund from pool. - assert_ok!(ConstantProductAmm::remove_liquidity( - &BOB, - pool_id, - bob_balance, - min_amt.clone() + + // 1 unit of btc = 45k + some unit of usdt + let ratio = ::get_exchange_value(pool_id, BTC, unit) + .expect("get_exchange_value failed"); + assert!(ratio > (initial_usdt / initial_btc) * unit); + + let initial_pool_invariant = current_pool_product(); + + assert_eq!(initial_user_invariant, initial_pool_invariant); + + // swap a btc + let swap_btc = unit; + assert_ok!(Tokens::mint_into(BTC, &BOB, swap_btc)); + + ::sell(&BOB, pool_id, BTC, swap_btc, false).expect("sell failed"); + + let new_pool_invariant = current_pool_product(); + assert_ok!(default_acceptable_computation_error( + initial_pool_invariant, + new_pool_invariant )); - // Check balances which should be impacted. - assert_eq!(Tokens::balance(pool_lp_asset, &BOB), 0); - assert_eq!(Tokens::balance(USDT, &BOB), 200000); - assert_eq!(Tokens::balance(USDC, &BOB), 200000); - assert_eq!(Tokens::balance(USDC, &ConstantProductAmm::account_id(&pool_id)), 0); - assert_eq!(Tokens::balance(USDT, &ConstantProductAmm::account_id(&pool_id)), 0); + + ::buy(&BOB, pool_id, BTC, swap_btc, false).expect("buy failed"); + + let precision = 100; + let epsilon = 5; + let bob_btc = Tokens::balance(BTC, &BOB); + assert_ok!(acceptable_computation_error(bob_btc, swap_btc, precision, epsilon)); + + let new_pool_invariant = current_pool_product(); + assert_ok!(default_acceptable_computation_error( + initial_pool_invariant, + new_pool_invariant + )); + + let lp = Tokens::balance(pool.lp_token, &ALICE); + assert_ok!(::remove_liquidity(&ALICE, pool_id, lp, 0, 0)); + + // Alice should get back a different amount of tokens. + let alice_btc = Tokens::balance(BTC, &ALICE); + let alice_usdt = Tokens::balance(USDT, &ALICE); + assert_ok!(default_acceptable_computation_error(alice_btc, initial_btc)); + assert_ok!(default_acceptable_computation_error(alice_usdt, initial_usdt)); + }); +} + +//- test lp mint/burn +#[test] +fn add_remove_lp() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_btc = 1_00_u128 * unit; + let btc_price = 45_000_u128; + let initial_usdt = initial_btc * btc_price; + let pool_id = + create_pool(BTC, USDT, initial_btc, initial_usdt, Permill::zero(), Permill::zero()); + let pool = Uni::pools(pool_id).expect("pool not found"); + let bob_btc = 10 * unit; + let bob_usdt = bob_btc * btc_price; + // Mint the tokens + assert_ok!(Tokens::mint_into(BTC, &BOB, bob_btc)); + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + + let lp = Tokens::balance(pool.lp_token, &BOB); + assert_eq!(lp, 0_u128); + // Add the liquidity + assert_ok!(::add_liquidity(&BOB, pool_id, bob_btc, bob_usdt, 0, false)); + let lp = Tokens::balance(pool.lp_token, &BOB); + // must have received some lp tokens + assert!(lp > 0_u128); + assert_ok!(::remove_liquidity(&BOB, pool_id, lp, 0, 0)); + let lp = Tokens::balance(pool.lp_token, &BOB); + // all lp tokens must have been burnt + assert_eq!(lp, 0_u128); + }); +} + +// +// - test error if trying to remove > lp than we have +#[test] +fn remove_lp_failure() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_btc = 1_00_u128 * unit; + let btc_price = 45_000_u128; + let initial_usdt = initial_btc * btc_price; + let pool_id = + create_pool(BTC, USDT, initial_btc, initial_usdt, Permill::zero(), Permill::zero()); + let pool = Uni::pools(pool_id).expect("pool not found"); + let bob_btc = 10 * unit; + let bob_usdt = bob_btc * btc_price; + // Mint the tokens + assert_ok!(Tokens::mint_into(BTC, &BOB, bob_btc)); + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + + // Add the liquidity + assert_ok!(::add_liquidity(&BOB, pool_id, bob_btc, bob_usdt, 0, false)); + let lp = Tokens::balance(pool.lp_token, &BOB); + assert_err!( + ::remove_liquidity(&BOB, pool_id, lp + 1, 0, 0), + TokenError::NoFunds + ); + let min_expected_btc = (bob_btc + 1) * unit; + let min_expected_usdt = (bob_usdt + 1) * unit; + assert_err!( + ::remove_liquidity(&BOB, pool_id, lp, min_expected_btc, min_expected_usdt), + crate::Error::::CannotRespectMinimumRequested + ); + }); +} + +// +// - test exchange failure +#[test] +fn exchange_failure() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_btc = 1_00_u128 * unit; + let btc_price = 45_000_u128; + let initial_usdt = initial_btc * btc_price; + let pool_id = + create_pool(BTC, USDT, initial_btc, initial_usdt, Permill::zero(), Permill::zero()); + let bob_btc = 10 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(BTC, &BOB, bob_btc)); + + let exchange_btc = 100_u128 * unit; + assert_err!( + ::exchange( + &BOB, + pool_id, + CurrencyPair::new(USDT, BTC), + exchange_btc, + 0, + false + ), + orml_tokens::Error::::BalanceTooLow + ); + let exchange_value = 10 * unit; + let expected_value = exchange_value * btc_price + 1; + assert_err!( + ::exchange( + &BOB, + pool_id, + CurrencyPair::new(USDT, BTC), + exchange_value, + expected_value, + false + ), + crate::Error::::CannotRespectMinimumRequested + ); }); } +// +// - test high slippage scenario +// trying to exchange a large value, will result in high_slippage scenario +// there should be substential difference between expected exchange value and received amount. #[test] -fn exchange_test() { +fn high_slippage() { new_test_ext().execute_with(|| { - // ConstantProductAmm configurations - let assets = vec![USDC, USDT]; - let fee = Permill::zero(); - let admin_fee = Permill::zero(); - - // Mint USDT for ALICE - assert_eq!(Tokens::balance(USDT, &ALICE), 0); - assert_ok!(Tokens::mint_into(USDT, &ALICE, 200000)); - assert_eq!(Tokens::balance(USDT, &ALICE), 200000); - // Mint USDC for ALICE - assert_eq!(Tokens::balance(USDC, &ALICE), 0); - assert_ok!(Tokens::mint_into(USDC, &ALICE, 200000)); - assert_eq!(Tokens::balance(USDC, &ALICE), 200000); - // Mint USDT for BOB - assert_eq!(Tokens::balance(USDT, &BOB), 0); - assert_ok!(Tokens::mint_into(USDT, &BOB, 200000)); - assert_eq!(Tokens::balance(USDT, &BOB), 200000); - // Mint USDC for BOB - assert_eq!(Tokens::balance(USDC, &BOB), 0); - assert_ok!(Tokens::mint_into(USDC, &BOB, 200000)); - assert_eq!(Tokens::balance(USDC, &BOB), 200000); - // Mint USDT for CHARLIE - assert_eq!(Tokens::balance(USDT, &CHARLIE), 0); - assert_ok!(Tokens::mint_into(USDT, &CHARLIE, 200000)); - assert_eq!(Tokens::balance(USDT, &CHARLIE), 200000); - - // Create ConstantProductAmm pool - let p = ConstantProductAmm::create_pool(&ALICE, assets, fee, admin_fee); - assert_ok!(&p); - let pool_id = p.unwrap(); - let pool = ConstantProductAmm::get_pool_info(pool_id); - assert!(pool.is_some()); - let pool = pool.unwrap(); - let pool_lp_asset = pool.lp_token; - // 1 USDC = 1 USDT - // Add liquidity from ALICE's account to pool - let amounts = vec![130000u128, 130000u128]; - assert_ok!(ConstantProductAmm::add_liquidity(&ALICE, pool_id, amounts.clone(), 0u128)); - let alice_balance = Tokens::balance(pool_lp_asset, &ALICE); - assert_ne!(alice_balance, 0); - assert_eq!(Tokens::balance(USDT, &ALICE), 200000 - 130000); - assert_eq!(Tokens::balance(USDC, &ALICE), 200000 - 130000); - let pool = ConstantProductAmm::get_pool_info(pool_id); - assert!(pool.is_some()); - // Add liquidity from BOB's account to pool - assert_ok!(ConstantProductAmm::add_liquidity(&BOB, pool_id, amounts.clone(), 0u128)); - let bob_balance = Tokens::balance(pool_lp_asset, &BOB); - assert_ne!(bob_balance, 0); - assert_eq!(Tokens::balance(USDT, &BOB), 200000 - 130000); - assert_eq!(Tokens::balance(USDC, &BOB), 200000 - 130000); - assert_eq!(Tokens::balance(USDC, &CHARLIE), 0); - // CHARLIE exchanges USDT for USDC - assert_ok!(ConstantProductAmm::exchange(&CHARLIE, pool_id, 1, 0, 65000, 0)); - sp_std::if_std! { - println!("CHARLIE's USDC balance {:?}" , Tokens::balance( USDC, &CHARLIE)); - } - assert!(65000 >= Tokens::balance(USDC, &CHARLIE)); + let unit = 1_000_000_000_000_u128; + let initial_btc = 1_00_u128 * unit; + let btc_price = 45_000_u128; + let initial_usdt = initial_btc * btc_price; + let pool_id = + create_pool(BTC, USDT, initial_btc, initial_usdt, Permill::zero(), Permill::zero()); + let bob_btc = 99_u128 * unit; + // Mint the tokens + assert_ok!(Tokens::mint_into(BTC, &BOB, bob_btc)); + + assert_ok!(::sell(&BOB, pool_id, BTC, bob_btc, false)); + let usdt_balance = Tokens::balance(USDT, &BOB); + let idea_usdt_balance = bob_btc * btc_price; + assert!((idea_usdt_balance - usdt_balance) > 5_u128); + }); +} + +// +// - test protocol_fee and owner_fee +#[test] +fn fees() { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_btc = 1_00_u128 * unit; + let btc_price = 45_000_u128; + let initial_usdt = initial_btc * btc_price; + let fee = Permill::from_float(0.05); + let protocol_fee = Permill::from_float(0.01); + let total_fee = fee + protocol_fee; + let pool_id = create_pool(BTC, USDT, initial_btc, initial_usdt, fee, protocol_fee); + let bob_usdt = 45_000_u128 * unit; + let quote_usdt = bob_usdt - total_fee.mul_floor(bob_usdt); + let expected_btc_value = ::get_exchange_value(pool_id, USDT, quote_usdt) + .expect("get_exchange_value failed"); + // Mint the tokens + assert_ok!(Tokens::mint_into(USDT, &BOB, bob_usdt)); + + assert_ok!(::sell(&BOB, pool_id, USDT, bob_usdt, false)); + let btc_balance = Tokens::balance(BTC, &BOB); + assert_ok!(default_acceptable_computation_error(expected_btc_value, btc_balance)); }); } + +proptest! { + #![proptest_config(ProptestConfig::with_cases(10000))] + #[test] + fn buy_sell_proptest( + btc_value in 1..u32::MAX, + ) { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_btc = 1_000_000_000_000_u128 * unit; + let btc_price = 45_000_u128; + let initial_usdt = initial_btc * btc_price; + let btc_value = btc_value as u128 * unit; + let usdt_value = btc_value * btc_price; + let pool_id = create_pool( + BTC, + USDT, + initial_btc, + initial_usdt, + Permill::zero(), + Permill::zero(), + ); + prop_assert_ok!(Tokens::mint_into(USDT, &BOB, usdt_value)); + prop_assert_ok!(Uni::sell(Origin::signed(BOB), pool_id, USDT, usdt_value, false)); + let bob_btc = Tokens::balance(BTC, &BOB); + // mint extra BTC equal to slippage so that original amount of USDT can be buy back + prop_assert_ok!(Tokens::mint_into(BTC, &BOB, btc_value - bob_btc)); + prop_assert_ok!(Uni::buy(Origin::signed(BOB), pool_id, USDT, usdt_value, false)); + let bob_usdt = Tokens::balance(USDT, &BOB); + let slippage = usdt_value - bob_usdt; + let slippage_percentage = slippage as f64 * 100.0_f64 / usdt_value as f64; + prop_assert!(slippage_percentage < 1.0_f64); + Ok(()) + })?; + } + + #[test] + fn add_remove_liquidity_proptest( + btc_value in 1..u32::MAX, + ) { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_btc = 1_000_000_000_000_u128 * unit; + let btc_price = 45_000_u128; + let initial_usdt = initial_btc * btc_price; + let btc_value = btc_value as u128 * unit; + let usdt_value = btc_value * btc_price; + let pool_id = create_pool( + BTC, + USDT, + initial_btc, + initial_usdt, + Permill::zero(), + Permill::zero(), + ); + let pool = Uni::pools(pool_id).expect("pool not found"); + prop_assert_ok!(Tokens::mint_into(USDT, &BOB, usdt_value)); + prop_assert_ok!(Tokens::mint_into(BTC, &BOB, btc_value)); + prop_assert_ok!(Uni::add_liquidity(Origin::signed(BOB), pool_id, btc_value, usdt_value, 0, false)); + let term1 = initial_usdt.integer_sqrt_checked().expect("integer_sqrt failed"); + let term2 = initial_btc.integer_sqrt_checked().expect("integer_sqrt failed"); + let expected_lp_tokens = safe_multiply_by_rational(term1, btc_value, term2).expect("multiply_by_rational failed"); + let lp_token = Tokens::balance(pool.lp_token, &BOB); + prop_assert_ok!(default_acceptable_computation_error(expected_lp_tokens, lp_token)); + prop_assert_ok!(Uni::remove_liquidity(Origin::signed(BOB), pool_id, lp_token, 0, 0)); + let btc_value_redeemed = Tokens::balance(BTC, &BOB); + let usdt_value_redeemed = Tokens::balance(USDT, &BOB); + prop_assert_ok!(default_acceptable_computation_error(btc_value_redeemed, btc_value)); + prop_assert_ok!(default_acceptable_computation_error(usdt_value_redeemed, usdt_value)); + Ok(()) + })?; + } + + #[test] + fn swap_proptest( + usdt_value in 1..u32::MAX, + ) { + new_test_ext().execute_with(|| { + let unit = 1_000_000_000_000_u128; + let initial_btc = 1_000_000_000_000_u128 * unit; + let btc_price = 45_000_u128; + let initial_usdt = initial_btc * btc_price; + let usdt_value = usdt_value as u128 * unit; + let pool_id = create_pool( + BTC, + USDT, + initial_btc, + initial_usdt, + Permill::from_float(0.025), + Permill::zero(), + ); + let pool = Uni::pools(pool_id).expect("pool not found"); + prop_assert_ok!(Tokens::mint_into(USDT, &BOB, usdt_value)); + prop_assert_ok!(Uni::swap(Origin::signed(BOB), pool_id, CurrencyPair::new(BTC, USDT), usdt_value, 0, false)); + let usdt_value_after_fee = usdt_value - pool.fee.mul_floor(usdt_value); + let ratio = initial_btc as f64 / initial_usdt as f64; + let expected_btc_value = ratio * usdt_value_after_fee as f64; + let expected_btc_value = expected_btc_value as u128; + let bob_btc = Tokens::balance(BTC, &BOB); + prop_assert_ok!(default_acceptable_computation_error(bob_btc, expected_btc_value)); + Ok(()) + })?; +} +} diff --git a/frame/uniswap-v2/src/weights.rs b/frame/uniswap-v2/src/weights.rs new file mode 100644 index 00000000000..3f12a09a1c3 --- /dev/null +++ b/frame/uniswap-v2/src/weights.rs @@ -0,0 +1,43 @@ +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(clippy::unnecessary_cast)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +pub trait WeightInfo { + fn create() -> Weight; + fn buy() -> Weight; + fn sell() -> Weight; + fn swap() -> Weight; + fn add_liquidity() -> Weight; + fn remove_liquidity() -> Weight; +} + +// For backwards compatibility and tests +impl WeightInfo for () { + fn create() -> Weight { + 10_000 + } + + fn buy() -> Weight { + 10_000 + } + + fn sell() -> Weight { + 10_000 + } + + fn swap() -> Weight { + 10_000 + } + + fn add_liquidity() -> Weight { + 10_000 + } + + fn remove_liquidity() -> Weight { + 10_000 + } +} diff --git a/frame/vault/Cargo.toml b/frame/vault/Cargo.toml index c3745b43635..c02612e0270 100644 --- a/frame/vault/Cargo.toml +++ b/frame/vault/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "pallet-vault" -version = "0.0.1" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2021" +homepage = "https://composable.finance" +name = "pallet-vault" +version = "0.0.1" [package.metadata.docs.rs] @@ -16,50 +16,53 @@ package = "parity-scale-codec" version = "2.0.0" [dependencies] -frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.16" } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -composable-traits = { path = "../composable-traits", default-features = false } +composable-support = { path = "../composable-support", default-features = false } +composable-traits = { path = "../composable-traits", default-features = false } +bitflags = "1.3.2" log = { version = "0.4.14", default-features = false } num-traits = { version = "0.2.14", default-features = false } -bitflags = "1.3.2" -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } [dev-dependencies] +composable-tests-helpers = { version = "0.0.1", path = "../composable-tests-helpers" } once_cell = "1.8.0" -proptest = "0.9.6" +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +proptest = "1.0" serde = "1.0.130" -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -composable-tests-helpers = { version = "0.0.1", path = "../composable-tests-helpers", default-features = false } [features] default = ["std"] std = [ - "codec/std", - "log/std", - "frame-support/std", - "frame-system/std", - "sp-runtime/std", - "sp-io/std", - "sp-core/std", - "sp-std/std", - "sp-arithmetic/std", - "composable-traits/std", - "scale-info/std", + "codec/std", + "log/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-io/std", + "sp-core/std", + "sp-std/std", + "sp-arithmetic/std", + "composable-traits/std", + "scale-info/std", ] runtime-benchmarks = [ - "frame-benchmarking", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", ] diff --git a/frame/vault/src/benchmarking.rs b/frame/vault/src/benchmarking.rs index 60f9fd32edd..804f7166f3f 100644 --- a/frame/vault/src/benchmarking.rs +++ b/frame/vault/src/benchmarking.rs @@ -1,6 +1,7 @@ use super::*; use crate::Pallet as Vault; +use composable_support::validation::Validated; use composable_traits::vault::{CapabilityVault, Deposit, Vault as VaultTrait, VaultConfig}; use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller}; use frame_support::{ @@ -30,15 +31,13 @@ fn create_vault_extended( reserved: Perquintill, deposit_: Deposit, BlockNumberOf>, ) -> (T::VaultId, VaultInfo) { - let v = Vault::::do_create_vault( - deposit_, - VaultConfig { - asset_id: T::AssetId::from(asset_id), - manager: whitelisted_caller(), - reserved, - strategies: [(strategy_account_id, strategy_share)].iter().cloned().collect(), - }, - ); + let config = VaultConfig { + asset_id: T::AssetId::from(asset_id), + manager: whitelisted_caller(), + reserved, + strategies: [(strategy_account_id, strategy_share)].iter().cloned().collect(), + }; + let v = Vault::::do_create_vault(deposit_, Validated::new(config).unwrap()); assert_ok!(&v); v.expect("unreachable; qed;") } @@ -141,7 +140,7 @@ benchmarks! { add_surcharge { let caller: T::AccountId = whitelisted_caller(); let amount = T::CreationDeposit::get() * 10u32.into(); - let add_amount = T::CreationDeposit::get(); + let add_amount = Validated::new(T::CreationDeposit::get()).unwrap(); let block = System::::block_number(); let deposit_ = Deposit::Rent { amount, at: block }; T::Currency::mint_into(T::AssetId::from(A), &caller, amount * 2u32.into())?; diff --git a/frame/vault/src/lib.rs b/frame/vault/src/lib.rs index 97fedd8752b..4403d135b5f 100644 --- a/frame/vault/src/lib.rs +++ b/frame/vault/src/lib.rs @@ -41,6 +41,7 @@ mod capabilities; pub mod models; mod rent; mod traits; +mod validation; pub use crate::weights::WeightInfo; pub use capabilities::Capabilities; @@ -63,9 +64,11 @@ pub mod pallet { models::StrategyOverview, rent::{self, Verdict}, traits::{CurrencyFactory, StrategicVault}, + validation::{ValidateCreationDeposit, ValidateMaxStrategies}, weights::WeightInfo, }; use codec::{Codec, FullCodec}; + use composable_support::validation::Validated; use composable_traits::{ currency::RangeId, defi::Rate, @@ -102,6 +105,7 @@ pub mod pallet { ArithmeticError, DispatchError, FixedPointNumber, Perquintill, }; use sp_std::fmt::Debug; + #[allow(missing_docs)] pub type AssetIdOf = <::Currency as Inspect<::AccountId>>::AssetId; @@ -531,11 +535,11 @@ pub mod pallet { pub fn add_surcharge( origin: OriginFor, dest: T::VaultId, - amount: T::Balance, + amount: Validated, ValidateCreationDeposit>, ) -> DispatchResultWithPostInfo { let origin = ensure_signed(origin)?; - ensure!(amount >= T::CreationDeposit::get(), Error::::InsufficientCreationDeposit); + let amount = amount.value(); Vaults::::try_mutate_exists(dest, |vault| -> DispatchResultWithPostInfo { let mut vault = vault.as_mut().ok_or(Error::::VaultDoesNotExist)?; @@ -698,7 +702,7 @@ pub mod pallet { impl Pallet { pub fn do_create_vault( deposit: Deposit, BlockNumberOf>, - config: VaultConfig, + config: Validated, ValidateMaxStrategies>, ) -> Result<(T::VaultId, VaultInfo), DispatchError> { // 1. check config // 2. lock endowment @@ -712,10 +716,7 @@ pub mod pallet { // Perhaps later on, we'll make this configurable per creator account id, if we want // to allow special projects to create more complex vaults. - ensure!( - config.strategies.len() <= T::MaxStrategies::get(), - Error::::TooManyStrategies - ); + let config = config.value(); // We do allow vaults without strategies, since strategies can be decided on later // through governance. If strategies are present, their allocations must sum up to @@ -958,7 +959,11 @@ pub mod pallet { deposit: Deposit, config: VaultConfig, ) -> Result { - Self::do_create_vault(deposit, config).map(|(id, _)| id) + match Validated::new(config) { + Ok(validated_config) => + Self::do_create_vault(deposit, validated_config).map(|(id, _)| id), + Err(_) => Err(DispatchError::from(Error::::TooManyStrategies)), + } } fn deposit( diff --git a/frame/vault/src/tests.rs b/frame/vault/src/tests.rs index 7b79e007730..58765169b7a 100644 --- a/frame/vault/src/tests.rs +++ b/frame/vault/src/tests.rs @@ -10,6 +10,7 @@ use crate::{ models::VaultInfo, *, }; +use composable_support::validation::Validated; use composable_tests_helpers::{ prop_assert_acceptable_computation_error, prop_assert_ok, test::helper::default_acceptable_computation_error, @@ -37,15 +38,15 @@ fn create_vault_with_share( strategy_share: Perquintill, reserved: Perquintill, ) -> (u64, VaultInfo) { - let v = Vaults::do_create_vault( - Deposit::Existential, - VaultConfig { - asset_id, - manager: ALICE, - reserved, - strategies: [(strategy_account_id, strategy_share)].iter().cloned().collect(), - }, - ); + let config = VaultConfig { + asset_id, + manager: ALICE, + reserved, + strategies: [(strategy_account_id, strategy_share)].iter().cloned().collect(), + }; + + let v = Vaults::do_create_vault(Deposit::Existential, Validated::new(config).unwrap()); + assert_ok!(&v); v.expect("unreachable; qed;") } @@ -729,7 +730,9 @@ proptest! { prop_assert_acceptable_computation_error!(new_native_tokens, half_initial_native_tokens + diff); } else { // Our balance should be equivalent - prop_assert_acceptable_computation_error!(new_native_tokens, half_initial_native_tokens); + let precision = 1000; + let epsilon = 5; + prop_assert_acceptable_computation_error!(new_native_tokens, half_initial_native_tokens, precision, epsilon); } } @@ -828,7 +831,12 @@ fn test_vault_add_surcharge() { assert!(Balances::balance(&CHARLIE) > 0); let vault = Vaults::vault_data(id).unwrap(); assert!(vault.capabilities.is_tombstoned()); - Vaults::add_surcharge(Origin::signed(ALICE), id, CreationDeposit::get()).unwrap(); + Vaults::add_surcharge( + Origin::signed(ALICE), + id, + Validated::new(CreationDeposit::get()).unwrap(), + ) + .unwrap(); let vault = Vaults::vault_data(id).unwrap(); assert!(!vault.capabilities.is_tombstoned()); }) diff --git a/frame/vault/src/validation.rs b/frame/vault/src/validation.rs new file mode 100644 index 00000000000..4557faaed8d --- /dev/null +++ b/frame/vault/src/validation.rs @@ -0,0 +1,39 @@ +use crate::pallet::{BalanceOf, Config}; +use composable_support::validation::Validate; +use composable_traits::vault::VaultConfig; +use core::marker::PhantomData; +use frame_support::traits::Get; + +#[derive(Clone, Copy)] +pub struct ValidateCreationDeposit { + _marker: PhantomData, +} + +#[derive(Clone, Copy)] +pub struct ValidateMaxStrategies { + _marker: PhantomData, +} + +impl Validate, ValidateCreationDeposit> for ValidateCreationDeposit { + fn validate(input: BalanceOf) -> Result, &'static str> { + if input < T::CreationDeposit::get() { + return Err("Insufficent Creation Deposit") + } + + Ok(input) + } +} + +impl Validate, ValidateMaxStrategies> + for ValidateMaxStrategies +{ + fn validate( + input: VaultConfig, + ) -> Result, &'static str> { + if input.strategies.len() > T::MaxStrategies::get() { + return Err("Too Many Strategies") + } + + Ok(input) + } +} diff --git a/frame/vesting/Cargo.toml b/frame/vesting/Cargo.toml index 6a070412422..e4a88ef7641 100644 --- a/frame/vesting/Cargo.toml +++ b/frame/vesting/Cargo.toml @@ -1,46 +1,55 @@ [package] -name = "pallet-vesting" -description = "Provides multi-asset scheduled balance locking mechanism, in a *graded vesting* way." -version = "0.0.1" authors = ["Composable Developers"] -homepage = "https://composable.finance" +description = "Provides multi-asset scheduled balance locking mechanism, in a *graded vesting* way." edition = "2021" +homepage = "https://composable.finance" +name = "pallet-vesting" +version = "0.0.1" [dependencies] -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false, features = [ + "derive", +] } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } serde = { version = "1.0.130", optional = true } -codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false, features = ["derive"] } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } composable-traits = { version = "0.0.1", path = "../../frame/composable-traits", default-features = false } -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } [dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb" } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } [features] default = ["std"] std = [ - "serde", - "codec/std", - "scale-info/std", - "sp-runtime/std", - "sp-std/std", - "sp-io/std", - "frame-support/std", - "frame-system/std", - "composable-traits/std", - "orml-traits/std", + "serde", + "codec/std", + "scale-info/std", + "sp-runtime/std", + "sp-std/std", + "sp-io/std", + "frame-support/std", + "frame-system/std", + "composable-traits/std", + "orml-traits/std", ] + runtime-benchmarks = [ - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", + "frame-benchmarking", + "frame-system/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] try-runtime = ["frame-support/try-runtime"] diff --git a/frame/vesting/README.md b/frame/vesting/README.md index eaff6eecd5c..5b6ded47379 100644 --- a/frame/vesting/README.md +++ b/frame/vesting/README.md @@ -6,8 +6,12 @@ Vesting module provides a means of scheduled balance lock on an account. It uses ### Vesting Schedule -The schedule of a vesting is described by data structure `VestingSchedule`: from the block number of `start`, for every `period` amount of blocks, `per_period` amount of balance would unlocked, until number of periods `period_count` reached. Note in vesting schedules, *time* is measured by block number. All `VestingSchedule`s under an account could be queried in chain state. +The schedule of a vesting is described by data structure `VestingSchedule`: from the time of `window.start`, for every `window.period` amount of time, `per_period` amount of balance would unlocked, until number of periods `period_count` reached. The pallet supports measuring time windows in terms of absolute timestamps as well as block numbers for vesting schedules. All `VestingSchedule`s under an account could be queried in chain state. ### Why fork -The original Vesting pallet is not currency agnostic. This tweaked version is generalized to any currency and usable with the `MultiLockableCurrency` trait. Other than that, most of the code is the original version from the [open runtime module repo](https://github.com/open-web3-stack/open-runtime-module-library/blob/1f520348f31b5e94b8a5dd7f8e6b8ec359df4177/vesting/README.md) +This tweaked version includes the following changes, +1. The original Vesting pallet is not currency agnostic. This fork is generalized to any currency and usable with the `MultiLockableCurrency` trait. +2. Modified to support measuring time in terms of absolute timestamps as well as the original block number based scheme for vesting schedules. + +Other than that, most of the code is the original version from the [open runtime module repo](https://github.com/open-web3-stack/open-runtime-module-library/blob/1f520348f31b5e94b8a5dd7f8e6b8ec359df4177/vesting/README.md) diff --git a/frame/vesting/src/benchmarks.rs b/frame/vesting/src/benchmarks.rs new file mode 100644 index 00000000000..6ec384f03b0 --- /dev/null +++ b/frame/vesting/src/benchmarks.rs @@ -0,0 +1,144 @@ +#![cfg(feature = "runtime-benchmarks")] + +#[cfg(test)] +use crate::Pallet as Vesting; +use crate::{ + AssetIdOf, BalanceOf, BlockNumberOf, Call, Config, Pallet, VestedTransfer, VestingScheduleOf, +}; +use codec::Decode; +use composable_traits::vesting::{VestingSchedule, VestingWindow::BlockNumberBased}; +use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, vec, whitelisted_caller}; +use frame_support::traits::{fungibles::Mutate, Get}; +use frame_system::RawOrigin; +use sp_runtime::traits::{StaticLookup, TrailingZeroInput}; + +const FUNDING: u64 = 1_000_000_000_000_000; +const PERIOD_COUNT: u32 = 10; +const PERIOD: u32 = 1; +const START_BLOCK_NUMBER: u32 = 1; + +fn asset() -> AssetIdOf +where + T: Config, +{ + let a = 0u128.to_be_bytes(); + AssetIdOf::::decode(&mut &a[..]).unwrap() +} + +fn fund_account(caller: &T::AccountId, asset_id: AssetIdOf, amount: BalanceOf) +where + T: Config, + BalanceOf: From, + ::Currency: Mutate, AssetId = AssetIdOf>, +{ + T::Currency::mint_into(asset_id, &caller, amount).unwrap() +} + +fn create_account(name: &'static str, index: u32) -> T::AccountId +where + T: Config, +{ + let caller: T::AccountId = account(name, index, 0); + caller +} + +fn vesting_schedule( + start: BlockNumberOf, + period: BlockNumberOf, + period_count: u32, + per_period: BalanceOf, +) -> VestingScheduleOf +where + T: Config, + BalanceOf: From, +{ + VestingSchedule { window: BlockNumberBased { start, period }, period_count, per_period } +} + +fn zero_account() -> T::AccountId +where + T: Config, +{ + T::AccountId::decode(&mut TrailingZeroInput::zeroes()).unwrap() +} + +benchmarks! { + where_clause { + where + T::Lookup: StaticLookup, + BalanceOf: From, + BlockNumberOf: From, + ::Currency: Mutate, AssetId = AssetIdOf>, + } + claim { + let s in 0 .. T::MaxVestingSchedules::get(); + let asset_id = asset::(); + let caller: T::AccountId = whitelisted_caller(); + let per_period = T::MinVestedTransfer::get(); + let schedule = vesting_schedule::( + START_BLOCK_NUMBER.into(), + PERIOD.into(), + PERIOD_COUNT, + per_period.into() + ); + for i in 0 .. s { + let source = create_account::("source", i); + fund_account::(&source, asset_id.clone(), FUNDING.into()); + as VestedTransfer>::vested_transfer(asset_id.clone(), &source, &caller, schedule.clone()).unwrap(); + } + }: _(RawOrigin::Signed(caller), asset_id) + + vested_transfer { + let asset_id = asset::(); + let from: T::AccountId = create_account::("from", 0xCAFEBABE); + fund_account::(&from, asset_id.clone(), FUNDING.into()); + let dest = T::Lookup::unlookup(create_account::("dest", 1)); + let per_period = T::MinVestedTransfer::get(); + let schedule = vesting_schedule::( + START_BLOCK_NUMBER.into(), + PERIOD.into(), + PERIOD_COUNT, + per_period.into() + ); + }: _(RawOrigin::Root, T::Lookup::unlookup(from), dest, asset_id, schedule) + + update_vesting_schedules { + let s in 0 .. T::MaxVestingSchedules::get(); + let mut schedules = vec![]; + let asset_id = asset::(); + let caller: T::AccountId = whitelisted_caller(); + let dest = create_account::("dest", 1); + let dest_look_up = T::Lookup::unlookup(dest.clone()); + let per_period = T::MinVestedTransfer::get(); + for i in 0..s { + fund_account::(&dest, asset_id.clone(), FUNDING.into()); + schedules.push(vesting_schedule::( + START_BLOCK_NUMBER.into(), + PERIOD.into(), + PERIOD_COUNT, + per_period.into() + )); + } + }: _(RawOrigin::Root, dest_look_up, asset_id, schedules) + + claim_for { + let s in 0 .. T::MaxVestingSchedules::get(); + let asset_id = asset::(); + let caller: T::AccountId = whitelisted_caller(); + let per_period = T::MinVestedTransfer::get(); + let schedule = vesting_schedule::( + START_BLOCK_NUMBER.into(), + PERIOD.into(), + PERIOD_COUNT, + per_period.into() + ); + let dest = create_account::("dest", 1); + let dest_look_up = T::Lookup::unlookup(dest.clone()); + for i in 0 .. s { + fund_account::(&caller, asset_id.clone(), FUNDING.into()); + as VestedTransfer>::vested_transfer(asset_id.clone(), &caller, &dest, schedule.clone()).unwrap(); + } + }: _(RawOrigin::Signed(caller), dest_look_up, asset_id) +} + +impl_benchmark_test_suite!(Vesting, crate::mock::ExtBuilder::build(), crate::mock::Runtime); diff --git a/frame/vesting/src/default_weight.rs b/frame/vesting/src/default_weight.rs deleted file mode 100644 index 9a4008031a1..00000000000 --- a/frame/vesting/src/default_weight.rs +++ /dev/null @@ -1,27 +0,0 @@ -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.0 - -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(clippy::unnecessary_cast)] - -use frame_support::weights::{constants::RocksDbWeight as DbWeight, Weight}; - -impl crate::WeightInfo for () { - fn vested_transfer() -> Weight { - (310_862_000 as Weight) - .saturating_add(DbWeight::get().reads(4 as Weight)) - .saturating_add(DbWeight::get().writes(4 as Weight)) - } - fn claim(i: u32) -> Weight { - (158_614_000 as Weight) - .saturating_add((958_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(DbWeight::get().reads(3 as Weight)) - .saturating_add(DbWeight::get().writes(3 as Weight)) - } - fn update_vesting_schedules(i: u32) -> Weight { - (119_811_000 as Weight) - .saturating_add((2_320_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(DbWeight::get().reads(2 as Weight)) - .saturating_add(DbWeight::get().writes(3 as Weight)) - } -} diff --git a/frame/vesting/src/lib.rs b/frame/vesting/src/lib.rs index 7ee819ba083..471f736ab55 100644 --- a/frame/vesting/src/lib.rs +++ b/frame/vesting/src/lib.rs @@ -9,11 +9,11 @@ //! ### Vesting Schedule //! //! The schedule of a vesting is described by data structure `VestingSchedule`: -//! from the block number of `start`, for every `period` amount of blocks, +//! from the time of `window.start`, for every `window.period` amount of time, //! `per_period` amount of balance would unlocked, until number of periods -//! `period_count` reached. Note in vesting schedules, *time* is measured by -//! block number. All `VestingSchedule`s under an account could be queried in -//! chain state. +//! `period_count` reached. The pallet supports measuring time windows in terms of absolute +//! timestamps as well as block numbers for vesting schedules. All `VestingSchedule`s under +//! an account could be queried in chain state. //! //! ## Interface //! - `VestedTransfer` - allowing a third party pallet to have this implementation as dependency to @@ -45,7 +45,7 @@ use composable_traits::vesting::{VestedTransfer, VestingSchedule}; use frame_support::{ ensure, pallet_prelude::*, - traits::{EnsureOrigin, Get, LockIdentifier}, + traits::{EnsureOrigin, Get, LockIdentifier, Time}, transactional, BoundedVec, }; use frame_system::{ensure_root, ensure_signed, pallet_prelude::*}; @@ -56,9 +56,14 @@ use sp_runtime::{ }; use sp_std::{convert::TryInto, vec::Vec}; +mod weights; + +#[cfg(any(feature = "runtime-benchmarks", test))] +mod benchmarks; +#[cfg(test)] mod mock; +#[cfg(test)] mod tests; -mod weights; pub use module::*; pub use weights::WeightInfo; @@ -67,24 +72,27 @@ pub const VESTING_LOCK_ID: LockIdentifier = *b"compvest"; #[frame_support::pallet] pub mod module { - use composable_traits::vesting::VestingSchedule; + use codec::FullCodec; + use composable_traits::vesting::{VestingSchedule, VestingWindow}; + use frame_support::traits::Time; use orml_traits::{MultiCurrency, MultiLockableCurrency}; + use sp_runtime::traits::AtLeast32Bit; use super::*; pub(crate) type BlockNumberOf = ::BlockNumber; + pub(crate) type MomentOf = ::Moment; pub(crate) type AccountIdOf = ::AccountId; pub(crate) type AssetIdOf = <::Currency as MultiCurrency>>::CurrencyId; pub(crate) type BalanceOf = <::Currency as MultiCurrency>>::Balance; pub(crate) type VestingScheduleOf = - VestingSchedule<::BlockNumber, BalanceOf>; + VestingSchedule, MomentOf, BalanceOf>; pub type ScheduledItem = ( AssetIdOf, ::AccountId, - ::BlockNumber, - ::BlockNumber, + VestingWindow, MomentOf>, u32, BalanceOf, ); @@ -100,13 +108,25 @@ pub mod module { type MinVestedTransfer: Get>; /// Required origin for vested transfer. - type VestedTransferOrigin: EnsureOrigin; + type VestedTransferOrigin: EnsureOrigin; /// Weight information for extrinsics in this module. type WeightInfo: WeightInfo; /// The maximum vesting schedules type MaxVestingSchedules: Get; + + /// Type of time + type Moment: AtLeast32Bit + + Parameter + + Default + + Copy + + MaxEncodedLen + + FullCodec + + MaybeSerializeDeserialize; + + /// The time provider. + type Time: Time; } #[pallet::error] @@ -123,6 +143,8 @@ pub mod module { AmountLow, /// Failed because the maximum vesting schedules was exceeded MaxVestingSchedulesExceeded, + /// Trying to vest to ourselves + TryingToSelfVest, } #[pallet::event] @@ -174,38 +196,35 @@ pub mod module { #[pallet::genesis_build] impl GenesisBuild for GenesisConfig { fn build(&self) { - self.vesting.iter().for_each( - |(asset, who, start, period, period_count, per_period)| { - let mut bounded_schedules = VestingSchedules::::get(who, asset); - bounded_schedules - .try_push(VestingSchedule { - start: *start, - period: *period, - period_count: *period_count, - per_period: *per_period, - }) - .expect("Max vesting schedules exceeded"); - let total_amount = bounded_schedules - .iter() - .try_fold::<_, _, Result, DispatchError>>( - Zero::zero(), - |acc_amount, schedule| { - let amount = ensure_valid_vesting_schedule::(schedule)?; - Ok(acc_amount + amount) - }, - ) - .expect("Invalid vesting schedule"); - - assert!( - T::Currency::free_balance(*asset, who) >= total_amount, - "Account do not have enough balance" - ); - - T::Currency::set_lock(VESTING_LOCK_ID, *asset, who, total_amount) - .expect("impossible; qed;"); - VestingSchedules::::insert(who, asset, bounded_schedules); - }, - ); + self.vesting.iter().for_each(|(asset, who, window, period_count, per_period)| { + let mut bounded_schedules = VestingSchedules::::get(who, asset); + bounded_schedules + .try_push(VestingSchedule { + window: window.clone(), + period_count: *period_count, + per_period: *per_period, + }) + .expect("Max vesting schedules exceeded"); + let total_amount = bounded_schedules + .iter() + .try_fold::<_, _, Result, DispatchError>>( + Zero::zero(), + |acc_amount, schedule| { + let amount = ensure_valid_vesting_schedule::(schedule)?; + Ok(acc_amount + amount) + }, + ) + .expect("Invalid vesting schedule"); + + assert!( + T::Currency::free_balance(*asset, who) >= total_amount, + "Account do not have enough balance" + ); + + T::Currency::set_lock(VESTING_LOCK_ID, *asset, who, total_amount) + .expect("impossible; qed;"); + VestingSchedules::::insert(who, asset, bounded_schedules); + }); } } @@ -217,7 +236,7 @@ pub mod module { #[pallet::call] impl Pallet { - #[pallet::weight(T::WeightInfo::claim((::MaxVestingSchedules::get() / 2) as u32))] + #[pallet::weight(::WeightInfo::claim((::MaxVestingSchedules::get() / 2) as u32))] pub fn claim(origin: OriginFor, asset: AssetIdOf) -> DispatchResult { let who = ensure_signed(origin)?; let locked_amount = Self::do_claim(&who, asset)?; @@ -226,22 +245,24 @@ pub mod module { Ok(()) } - #[pallet::weight(T::WeightInfo::vested_transfer())] + #[pallet::weight(::WeightInfo::vested_transfer())] pub fn vested_transfer( origin: OriginFor, - dest: ::Source, + from: ::Source, + beneficiary: ::Source, asset: AssetIdOf, schedule: VestingScheduleOf, ) -> DispatchResult { - let from = T::VestedTransferOrigin::ensure_origin(origin)?; - let to = T::Lookup::lookup(dest)?; + T::VestedTransferOrigin::ensure_origin(origin)?; + let from = T::Lookup::lookup(from)?; + let to = T::Lookup::lookup(beneficiary)?; ::vested_transfer(asset, &from, &to, schedule.clone())?; Self::deposit_event(Event::VestingScheduleAdded { from, to, asset, schedule }); Ok(()) } - #[pallet::weight(T::WeightInfo::update_vesting_schedules(vesting_schedules.len() as u32))] + #[pallet::weight(::WeightInfo::update_vesting_schedules(vesting_schedules.len() as u32))] pub fn update_vesting_schedules( origin: OriginFor, who: ::Source, @@ -257,7 +278,7 @@ pub mod module { Ok(()) } - #[pallet::weight(T::WeightInfo::claim((::MaxVestingSchedules::get() / 2) as u32))] + #[pallet::weight(::WeightInfo::claim((::MaxVestingSchedules::get() / 2) as u32))] pub fn claim_for( origin: OriginFor, dest: ::Source, @@ -277,6 +298,7 @@ impl VestedTransfer for Pallet { type AccountId = AccountIdOf; type AssetId = AssetIdOf; type BlockNumber = BlockNumberOf; + type Moment = MomentOf; type Balance = BalanceOf; type MinVestedTransfer = T::MinVestedTransfer; @@ -285,8 +307,10 @@ impl VestedTransfer for Pallet { asset: Self::AssetId, from: &Self::AccountId, to: &Self::AccountId, - schedule: VestingSchedule, + schedule: VestingSchedule, ) -> frame_support::dispatch::DispatchResult { + ensure!(from != to, Error::::TryingToSelfVest); + let schedule_amount = ensure_valid_vesting_schedule::(&schedule)?; let total_amount = Self::locked_balance(to, asset) @@ -316,12 +340,14 @@ impl Pallet { /// Returns locked balance based on current block number. fn locked_balance(who: &AccountIdOf, asset: AssetIdOf) -> BalanceOf { - let now = frame_system::Pallet::::current_block_number(); >::mutate_exists(who, asset, |maybe_schedules| { let total = if let Some(schedules) = maybe_schedules.as_mut() { let mut total: BalanceOf = Zero::zero(); schedules.retain(|s| { - let amount = s.locked_amount(now); + let amount = s.locked_amount( + frame_system::Pallet::::current_block_number(), + T::Time::now(), + ); total = total.saturating_add(amount); !amount.is_zero() }); @@ -375,9 +401,9 @@ impl Pallet { fn ensure_valid_vesting_schedule( schedule: &VestingScheduleOf, ) -> Result, DispatchError> { - ensure!(!schedule.period.is_zero(), Error::::ZeroVestingPeriod); - ensure!(!schedule.period_count.is_zero(), Error::::ZeroVestingPeriodCount); + ensure!(!schedule.is_zero_period(), Error::::ZeroVestingPeriod); ensure!(schedule.end().is_some(), ArithmeticError::Overflow); + ensure!(!schedule.period_count.is_zero(), Error::::ZeroVestingPeriodCount); let total_total = schedule.total_amount().ok_or(ArithmeticError::Overflow)?; diff --git a/frame/vesting/src/mock.rs b/frame/vesting/src/mock.rs index bf7e87741a7..151cf026e56 100644 --- a/frame/vesting/src/mock.rs +++ b/frame/vesting/src/mock.rs @@ -3,18 +3,23 @@ #![cfg(test)] use super::*; +use composable_traits::vesting::VestingWindow::{BlockNumberBased, MomentBased}; use frame_support::{ construct_runtime, parameter_types, traits::{EnsureOrigin, Everything}, }; -use frame_system::RawOrigin; +use frame_system::{EnsureRoot, RawOrigin}; use orml_traits::parameter_type_with_key; use scale_info::TypeInfo; use sp_core::H256; -use sp_runtime::{testing::Header, traits::IdentityLookup}; +use sp_runtime::{ + testing::Header, + traits::{IdentityLookup, TrailingZeroInput}, +}; use crate as vesting; +pub type Moment = u64; pub type Balance = u64; pub type Amount = i64; pub type AccountId = u128; @@ -22,6 +27,7 @@ pub type AccountId = u128; pub const ALICE: AccountId = 1; pub const BOB: AccountId = 2; pub const CHARLIE: AccountId = 3; +pub const MILLISECS_PER_BLOCK: u64 = 6000; #[derive( PartialOrd, @@ -75,21 +81,44 @@ impl frame_system::Config for Runtime { type MaxConsumers = frame_support::traits::ConstU32<16>; } +parameter_types! { + pub const MinimumPeriod: u64 = MILLISECS_PER_BLOCK / 2; +} + +impl pallet_timestamp::Config for Runtime { + type Moment = Moment; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + +fn benchmark_vested_transfer_account() -> AccountId { + AccountId::decode(&mut TrailingZeroInput::zeroes()) + .expect("infinite length input; no invalid inputs for type; qed") +} + pub struct EnsureAliceOrBob; impl EnsureOrigin for EnsureAliceOrBob { type Success = AccountId; fn try_origin(o: Origin) -> Result { + let benchmark_acc = benchmark_vested_transfer_account(); Into::, Origin>>::into(o).and_then(|o| match o { RawOrigin::Signed(ALICE) => Ok(ALICE), RawOrigin::Signed(BOB) => Ok(BOB), + RawOrigin::Signed(acc) => + if acc == benchmark_acc { + Ok(benchmark_acc) + } else { + Err(Origin::from(RawOrigin::Signed(acc))) + }, r => Err(Origin::from(r)), }) } #[cfg(feature = "runtime-benchmarks")] fn successful_origin() -> Origin { - Origin::from(RawOrigin::Signed(Default::default())) + Origin::from(RawOrigin::Signed(benchmark_vested_transfer_account())) } } @@ -116,7 +145,7 @@ impl orml_tokens::Config for Runtime { } parameter_types! { - pub const MaxVestingSchedule: u32 = 2; + pub const MaxVestingSchedule: u32 = 3; pub const MinVestedTransfer: u64 = 5; } @@ -124,9 +153,11 @@ impl Config for Runtime { type Event = Event; type Currency = Tokens; type MinVestedTransfer = MinVestedTransfer; - type VestedTransferOrigin = EnsureAliceOrBob; + type VestedTransferOrigin = EnsureRoot; type WeightInfo = (); type MaxVestingSchedules = MaxVestingSchedule; + type Moment = Moment; + type Time = Timestamp; } type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; @@ -140,7 +171,8 @@ construct_runtime!( { System: frame_system::{Pallet, Call, Storage, Config, Event}, Vesting: vesting::{Pallet, Storage, Call, Event, Config}, - Tokens: orml_tokens::{Pallet, Call, Storage, Config, Event}, + Tokens: orml_tokens::{Pallet, Call, Storage, Config, Event}, + Timestamp: pallet_timestamp::{Pallet, Call, Storage}, } ); @@ -152,16 +184,17 @@ impl ExtBuilder { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); orml_tokens::GenesisConfig:: { - balances: vec![(ALICE, MockCurrencyId::BTC, 100), (CHARLIE, MockCurrencyId::BTC, 50)], + balances: vec![(ALICE, MockCurrencyId::BTC, 100), (CHARLIE, MockCurrencyId::BTC, 65)], } .assimilate_storage(&mut t) .unwrap(); vesting::GenesisConfig:: { vesting: vec![ - // asset, who, start, period, period_count, per_period - (MockCurrencyId::BTC, CHARLIE, 2, 3, 1, 5), - (MockCurrencyId::BTC, CHARLIE, 2 + 3, 3, 3, 5), + // asset, who, VestingWindow {start, period}, period_count, per_period + (MockCurrencyId::BTC, CHARLIE, BlockNumberBased { start: 2, period: 3 }, 1, 5), + (MockCurrencyId::BTC, CHARLIE, BlockNumberBased { start: 2 + 3, period: 3 }, 3, 5), + (MockCurrencyId::BTC, CHARLIE, MomentBased { start: 40000, period: 50000 }, 3, 5), ], } .assimilate_storage(&mut t) diff --git a/frame/vesting/src/tests.rs b/frame/vesting/src/tests.rs index 8c41d5563cb..fef688539cb 100644 --- a/frame/vesting/src/tests.rs +++ b/frame/vesting/src/tests.rs @@ -3,7 +3,10 @@ #![cfg(test)] use super::*; -use composable_traits::vesting::VestingSchedule; +use composable_traits::vesting::{ + VestingSchedule, + VestingWindow::{BlockNumberBased, MomentBased}, +}; use frame_support::{assert_noop, assert_ok, error::BadOrigin}; use mock::{Event, *}; use orml_tokens::BalanceLock; @@ -14,57 +17,114 @@ fn vesting_from_chain_spec_works() { // From the vesting below, only 20 out of 50 are locked at block 0. assert_ok!(Tokens::ensure_can_withdraw(MockCurrencyId::BTC, &CHARLIE, 30)); assert!(Tokens::ensure_can_withdraw(MockCurrencyId::BTC, &CHARLIE, 31).is_err()); + let schedules = vec![ + /* + +------+------+-----+ + |block |vested|total| + | | | | + +------+------+-----+ + |5 |5 |5 | + +------+------+-----+ + */ + VestingSchedule { + window: BlockNumberBased { start: 2_u64, period: 3_u64 }, + period_count: 1_u32, + per_period: 5_u64, + }, + /* + +------+------+-----+ + |block |vested|total| + | | | | + +------+------+-----+ + |8 |5 |5 | + +------+------+-----+ + |11 |5 |10 | + +------+------+-----+ + |14 |5 |15 | + +------+------+-----+ + */ + VestingSchedule { + window: BlockNumberBased { start: 2_u64 + 3_u64, period: 3_u64 }, + period_count: 3_u32, + per_period: 5_u64, + }, + /* + +---------+-----------+-----------+ + |block |timestamp |vested | total | + | | | | | + +---------+-----------+-------+-------| + |8 |48000 |0 |0 | + +---------+-----------+-------+-------| + |14 |84000 |0 |0 | + +---------+-----------+-------+-------| + |18 |108000 |5 |5 + +---------+-----------+-------+-------| + |25 |150000 |5 |10 | + +---------+-----------+-------+-------| + |34 |204000 |5 |15 | + +---------+-----------+-------+-------| + */ + VestingSchedule { + window: MomentBased { start: 40000_u64, period: 50000_u64 }, + period_count: 3_u32, + per_period: 5_u64, + }, + ]; + + assert_eq!(Vesting::vesting_schedules(&CHARLIE, MockCurrencyId::BTC), schedules); + System::set_block_number(1); + Timestamp::set_timestamp(System::block_number() * MILLISECS_PER_BLOCK); + assert_ok!(Vesting::claim(Origin::signed(CHARLIE), MockCurrencyId::BTC)); + assert_ok!(Tokens::ensure_can_withdraw(MockCurrencyId::BTC, &CHARLIE, 30)); + assert!(Tokens::ensure_can_withdraw(MockCurrencyId::BTC, &CHARLIE, 31).is_err()); - assert_eq!( - Vesting::vesting_schedules(&CHARLIE, MockCurrencyId::BTC), - vec![ - /* - +------+------+-----+ - |block |vested|total| - | | | | - +------+------+-----+ - |5 |5 |5 | - +------+------+-----+ - */ - VestingSchedule { - start: 2_u64, - period: 3_u64, - period_count: 1_u32, - per_period: 5_u64 - }, - /* - +------+------+-----+ - |block |vested|total| - | | | | - +------+------+-----+ - |8 |5 |5 | - +------+------+-----+ - |11 |5 |10 | - +------+------+-----+ - |14 |5 |15 | - +------+------+-----+ - */ - VestingSchedule { - start: 2_u64 + 3_u64, - period: 3_u64, - period_count: 3_u32, - per_period: 5_u64, - } - ] - ); - - System::set_block_number(13); - + System::set_block_number(11); + Timestamp::set_timestamp(System::block_number() * MILLISECS_PER_BLOCK); assert_ok!(Vesting::claim(Origin::signed(CHARLIE), MockCurrencyId::BTC)); - // At block 13, we only have 5 out of the 50 that are locked. assert_ok!(Tokens::ensure_can_withdraw(MockCurrencyId::BTC, &CHARLIE, 45)); assert!(Tokens::ensure_can_withdraw(MockCurrencyId::BTC, &CHARLIE, 46).is_err()); System::set_block_number(14); - + Timestamp::set_timestamp(System::block_number() * MILLISECS_PER_BLOCK); assert_ok!(Vesting::claim(Origin::signed(CHARLIE), MockCurrencyId::BTC)); - // Everything is unlocked from blcok 14 onwards. + // Block number based schedules are unlocked from block 14 onwards. assert_ok!(Tokens::ensure_can_withdraw(MockCurrencyId::BTC, &CHARLIE, 50)); + assert!(Tokens::ensure_can_withdraw(MockCurrencyId::BTC, &CHARLIE, 51).is_err()); + + System::set_block_number(25); + Timestamp::set_timestamp(System::block_number() * MILLISECS_PER_BLOCK); + assert_ok!(Vesting::claim(Origin::signed(CHARLIE), MockCurrencyId::BTC)); + assert_ok!(Tokens::ensure_can_withdraw(MockCurrencyId::BTC, &CHARLIE, 60)); + assert!(Tokens::ensure_can_withdraw(MockCurrencyId::BTC, &CHARLIE, 61).is_err()); + + System::set_block_number(34); + Timestamp::set_timestamp(System::block_number() * MILLISECS_PER_BLOCK); + // everything unlocked + assert_ok!(Vesting::claim(Origin::signed(CHARLIE), MockCurrencyId::BTC)); + assert_ok!(Tokens::ensure_can_withdraw(MockCurrencyId::BTC, &CHARLIE, 65)); + }); +} + +#[test] +fn vested_transfer_self_vest_ko() { + ExtBuilder::build().execute_with(|| { + System::set_block_number(1); + + let schedule = VestingSchedule { + window: BlockNumberBased { start: 0_u64, period: 10_u64 }, + period_count: 1_u32, + per_period: 100_u64, + }; + assert_noop!( + Vesting::vested_transfer( + Origin::root(), + ALICE, + ALICE, + MockCurrencyId::BTC, + schedule.clone(), + ), + Error::::TryingToSelfVest + ); }); } @@ -74,13 +134,41 @@ fn vested_transfer_works() { System::set_block_number(1); let schedule = VestingSchedule { - start: 0_u64, - period: 10_u64, + window: BlockNumberBased { start: 0_u64, period: 10_u64 }, period_count: 1_u32, per_period: 100_u64, }; assert_ok!(Vesting::vested_transfer( - Origin::signed(ALICE), + Origin::root(), + ALICE, + BOB, + MockCurrencyId::BTC, + schedule.clone(), + )); + assert_eq!(Vesting::vesting_schedules(&BOB, MockCurrencyId::BTC), vec![schedule.clone()]); + System::assert_last_event(Event::Vesting(crate::Event::VestingScheduleAdded { + from: ALICE, + to: BOB, + asset: MockCurrencyId::BTC, + schedule, + })); + }); +} + +#[test] +fn vested_transfer_for_moment_based_schedule_works() { + ExtBuilder::build().execute_with(|| { + System::set_block_number(1); + Timestamp::set_timestamp(System::block_number() * MILLISECS_PER_BLOCK); + + let schedule = VestingSchedule { + window: MomentBased { start: 0_u64, period: 10_u64 }, + period_count: 1_u32, + per_period: 100_u64, + }; + assert_ok!(Vesting::vested_transfer( + Origin::root(), + ALICE, BOB, MockCurrencyId::BTC, schedule.clone(), @@ -99,36 +187,50 @@ fn vested_transfer_works() { fn add_new_vesting_schedule_merges_with_current_locked_balance_and_until() { ExtBuilder::build().execute_with(|| { let schedule = VestingSchedule { - start: 0_u64, - period: 10_u64, + window: BlockNumberBased { start: 0_u64, period: 10_u64 }, period_count: 2_u32, per_period: 10_u64, }; assert_ok!(Vesting::vested_transfer( - Origin::signed(ALICE), + Origin::root(), + ALICE, BOB, MockCurrencyId::BTC, schedule, )); System::set_block_number(12); + Timestamp::set_timestamp(System::block_number() * MILLISECS_PER_BLOCK); let another_schedule = VestingSchedule { - start: 10_u64, - period: 13_u64, + window: BlockNumberBased { start: 10_u64, period: 13_u64 }, period_count: 1_u32, per_period: 7_u64, }; assert_ok!(Vesting::vested_transfer( - Origin::signed(ALICE), + Origin::root(), + ALICE, BOB, MockCurrencyId::BTC, another_schedule, )); + let moment_based_schedule = VestingSchedule { + window: MomentBased { start: 72000_u64, period: 5000_u64 }, + period_count: 2_u32, + per_period: 7_u64, + }; + assert_ok!(Vesting::vested_transfer( + Origin::root(), + ALICE, + BOB, + MockCurrencyId::BTC, + moment_based_schedule, + )); + assert_eq!( Tokens::locks(&BOB, MockCurrencyId::BTC).get(0), - Some(&BalanceLock { id: VESTING_LOCK_ID, amount: 17_u64 }) + Some(&BalanceLock { id: VESTING_LOCK_ID, amount: 31_u64 }) ); }); } @@ -137,44 +239,73 @@ fn add_new_vesting_schedule_merges_with_current_locked_balance_and_until() { fn cannot_use_fund_if_not_claimed() { ExtBuilder::build().execute_with(|| { let schedule = VestingSchedule { - start: 10_u64, - period: 10_u64, + window: BlockNumberBased { start: 10_u64, period: 10_u64 }, period_count: 1_u32, per_period: 50_u64, }; assert_ok!(Vesting::vested_transfer( - Origin::signed(ALICE), + Origin::root(), + ALICE, BOB, MockCurrencyId::BTC, schedule, )); - assert!(Tokens::ensure_can_withdraw(MockCurrencyId::BTC, &BOB, 49).is_err()); + let moment_based_schedule = VestingSchedule { + window: MomentBased { start: 1000_u64, period: 5000_u64 }, + period_count: 1_u32, + per_period: 10_u64, + }; + assert_ok!(Vesting::vested_transfer( + Origin::root(), + ALICE, + BOB, + MockCurrencyId::BTC, + moment_based_schedule, + )); + System::set_block_number(21); + Timestamp::set_timestamp(System::block_number() * MILLISECS_PER_BLOCK); + assert!(Tokens::ensure_can_withdraw(MockCurrencyId::BTC, &BOB, 59).is_err()); + assert_ok!(Vesting::claim(Origin::signed(BOB), MockCurrencyId::BTC)); + assert_ok!(Tokens::ensure_can_withdraw(MockCurrencyId::BTC, &BOB, 59)); + }); +} + +#[test] +fn vested_transfer_fails_if_zero_period_count() { + ExtBuilder::build().execute_with(|| { + let schedule = VestingSchedule { + window: BlockNumberBased { start: 1_u64, period: 1_u64 }, + period_count: 0_u32, + per_period: 100_u64, + }; + assert_noop!( + Vesting::vested_transfer(Origin::root(), ALICE, BOB, MockCurrencyId::BTC, schedule,), + Error::::ZeroVestingPeriodCount + ); }); } #[test] -fn vested_transfer_fails_if_zero_period_or_count() { +fn vested_transfer_fails_if_zero_period() { ExtBuilder::build().execute_with(|| { let schedule = VestingSchedule { - start: 1_u64, - period: 0_u64, + window: BlockNumberBased { start: 1_u64, period: 0_u64 }, period_count: 1_u32, per_period: 100_u64, }; assert_noop!( - Vesting::vested_transfer(Origin::signed(ALICE), BOB, MockCurrencyId::BTC, schedule,), + Vesting::vested_transfer(Origin::root(), ALICE, BOB, MockCurrencyId::BTC, schedule,), Error::::ZeroVestingPeriod ); let schedule = VestingSchedule { - start: 1_u64, - period: 1_u64, - period_count: 0_u32, + window: MomentBased { start: 1_u64, period: 0_u64 }, + period_count: 1_u32, per_period: 100_u64, }; assert_noop!( - Vesting::vested_transfer(Origin::signed(ALICE), BOB, MockCurrencyId::BTC, schedule,), - Error::::ZeroVestingPeriodCount + Vesting::vested_transfer(Origin::root(), ALICE, BOB, MockCurrencyId::BTC, schedule,), + Error::::ZeroVestingPeriod ); }); } @@ -183,13 +314,12 @@ fn vested_transfer_fails_if_zero_period_or_count() { fn vested_transfer_fails_if_transfer_err() { ExtBuilder::build().execute_with(|| { let schedule = VestingSchedule { - start: 1_u64, - period: 1_u64, + window: BlockNumberBased { start: 1_u64, period: 1_u64 }, period_count: 1_u32, per_period: 100_u64, }; assert_noop!( - Vesting::vested_transfer(Origin::signed(BOB), ALICE, MockCurrencyId::BTC, schedule,), + Vesting::vested_transfer(Origin::root(), BOB, ALICE, MockCurrencyId::BTC, schedule,), orml_tokens::Error::::BalanceTooLow, ); }); @@ -199,31 +329,46 @@ fn vested_transfer_fails_if_transfer_err() { fn vested_transfer_fails_if_overflow() { ExtBuilder::build().execute_with(|| { let schedule = VestingSchedule { - start: 1_u64, - period: 1_u64, + window: BlockNumberBased { start: 1_u64, period: 1_u64 }, period_count: 2_u32, per_period: u64::MAX, }; assert_noop!( - Vesting::vested_transfer(Origin::signed(ALICE), BOB, MockCurrencyId::BTC, schedule,), + Vesting::vested_transfer(Origin::root(), ALICE, BOB, MockCurrencyId::BTC, schedule,), ArithmeticError::Overflow, ); let another_schedule = VestingSchedule { - start: u64::MAX, - period: 1_u64, + window: BlockNumberBased { start: u64::MAX, period: 1_u64 }, period_count: 2_u32, per_period: 1_u64, }; assert_noop!( Vesting::vested_transfer( - Origin::signed(ALICE), + Origin::root(), + ALICE, BOB, MockCurrencyId::BTC, another_schedule, ), ArithmeticError::Overflow, ); + + let moment_based_schedule = VestingSchedule { + window: MomentBased { start: u64::MAX, period: 1_u64 }, + period_count: 2_u32, + per_period: 1_u64, + }; + assert_noop!( + Vesting::vested_transfer( + Origin::root(), + ALICE, + BOB, + MockCurrencyId::BTC, + moment_based_schedule, + ), + ArithmeticError::Overflow, + ); }); } @@ -231,13 +376,18 @@ fn vested_transfer_fails_if_overflow() { fn vested_transfer_fails_if_bad_origin() { ExtBuilder::build().execute_with(|| { let schedule = VestingSchedule { - start: 0_u64, - period: 10_u64, + window: BlockNumberBased { start: 0_u64, period: 10_u64 }, period_count: 1_u32, per_period: 100_u64, }; assert_noop!( - Vesting::vested_transfer(Origin::signed(CHARLIE), BOB, MockCurrencyId::BTC, schedule,), + Vesting::vested_transfer( + Origin::signed(CHARLIE), + CHARLIE, + BOB, + MockCurrencyId::BTC, + schedule, + ), BadOrigin ); }); @@ -247,13 +397,13 @@ fn vested_transfer_fails_if_bad_origin() { fn claim_works() { ExtBuilder::build().execute_with(|| { let schedule = VestingSchedule { - start: 0_u64, - period: 10_u64, + window: BlockNumberBased { start: 0_u64, period: 10_u64 }, period_count: 2_u32, per_period: 10_u64, }; assert_ok!(Vesting::vested_transfer( - Origin::signed(ALICE), + Origin::root(), + ALICE, BOB, MockCurrencyId::BTC, schedule, @@ -286,13 +436,13 @@ fn claim_works() { fn claim_for_works() { ExtBuilder::build().execute_with(|| { let schedule = VestingSchedule { - start: 0_u64, - period: 10_u64, + window: BlockNumberBased { start: 0_u64, period: 10_u64 }, period_count: 2_u32, per_period: 10_u64, }; assert_ok!(Vesting::vested_transfer( - Origin::signed(ALICE), + Origin::root(), + ALICE, BOB, MockCurrencyId::BTC, schedule, @@ -307,9 +457,46 @@ fn claim_for_works() { assert!(VestingSchedules::::contains_key(&BOB, MockCurrencyId::BTC)); System::set_block_number(21); + assert_eq!( + Tokens::locks(&BOB, MockCurrencyId::BTC).get(0), + Some(&BalanceLock { id: VESTING_LOCK_ID, amount: 20_u64 }) + ); + assert_ok!(Vesting::claim_for(Origin::signed(ALICE), BOB, MockCurrencyId::BTC)); + // no locks anymore + assert_eq!(Tokens::locks(&BOB, MockCurrencyId::BTC), vec![]); + assert!(!VestingSchedules::::contains_key(&BOB, MockCurrencyId::BTC)); + }); +} + +#[test] +fn claim_for_works_moment_based() { + ExtBuilder::build().execute_with(|| { + let schedule = VestingSchedule { + window: MomentBased { start: 0_u64, period: 10_u64 }, + period_count: 2_u32, + per_period: 10_u64, + }; + assert_ok!(Vesting::vested_transfer( + Origin::root(), + ALICE, + BOB, + MockCurrencyId::BTC, + schedule, + )); assert_ok!(Vesting::claim_for(Origin::signed(ALICE), BOB, MockCurrencyId::BTC)); + assert_eq!( + Tokens::locks(&BOB, MockCurrencyId::BTC).get(0), + Some(&BalanceLock { id: VESTING_LOCK_ID, amount: 20_u64 }) + ); + assert!(VestingSchedules::::contains_key(&BOB, MockCurrencyId::BTC)); + Timestamp::set_timestamp(21); + assert_eq!( + Tokens::locks(&BOB, MockCurrencyId::BTC).get(0), + Some(&BalanceLock { id: VESTING_LOCK_ID, amount: 20_u64 }) + ); + assert_ok!(Vesting::claim_for(Origin::signed(ALICE), BOB, MockCurrencyId::BTC)); // no locks anymore assert_eq!(Tokens::locks(&BOB, MockCurrencyId::BTC), vec![]); assert!(!VestingSchedules::::contains_key(&BOB, MockCurrencyId::BTC)); @@ -320,21 +507,38 @@ fn claim_for_works() { fn update_vesting_schedules_works() { ExtBuilder::build().execute_with(|| { let schedule = VestingSchedule { - start: 0_u64, - period: 10_u64, + window: BlockNumberBased { start: 0_u64, period: 10_u64 }, period_count: 2_u32, per_period: 10_u64, }; assert_ok!(Vesting::vested_transfer( - Origin::signed(ALICE), + Origin::root(), + ALICE, BOB, MockCurrencyId::BTC, schedule, )); + let moment_based_schedule = VestingSchedule { + window: MomentBased { start: 0_u64, period: 60000_u64 }, + period_count: 2_u32, + per_period: 10_u64, + }; + assert_ok!(Vesting::vested_transfer( + Origin::root(), + ALICE, + BOB, + MockCurrencyId::BTC, + moment_based_schedule, + )); + let updated_schedule = VestingSchedule { - start: 0_u64, - period: 20_u64, + window: BlockNumberBased { start: 0_u64, period: 20_u64 }, + period_count: 2_u32, + per_period: 10_u64, + }; + let updated_moment_based_schedule = VestingSchedule { + window: MomentBased { start: 0_u64, period: 120000_u64 }, period_count: 2_u32, per_period: 10_u64, }; @@ -342,22 +546,24 @@ fn update_vesting_schedules_works() { Origin::root(), BOB, MockCurrencyId::BTC, - vec![updated_schedule], + vec![updated_schedule, updated_moment_based_schedule], )); System::set_block_number(11); + Timestamp::set_timestamp(System::block_number() * MILLISECS_PER_BLOCK); assert_ok!(Vesting::claim(Origin::signed(BOB), MockCurrencyId::BTC)); assert!(Tokens::transfer(Origin::signed(BOB), ALICE, MockCurrencyId::BTC, 1).is_err()); System::set_block_number(21); + Timestamp::set_timestamp(System::block_number() * MILLISECS_PER_BLOCK); assert_ok!(Vesting::claim(Origin::signed(BOB), MockCurrencyId::BTC)); - assert_ok!(Tokens::transfer(Origin::signed(BOB), ALICE, MockCurrencyId::BTC, 10)); + assert_ok!(Tokens::transfer(Origin::signed(BOB), ALICE, MockCurrencyId::BTC, 20)); // empty vesting schedules cleanup the storage and unlock the fund assert!(VestingSchedules::::contains_key(BOB, MockCurrencyId::BTC)); assert_eq!( Tokens::locks(&BOB, MockCurrencyId::BTC).get(0), - Some(&BalanceLock { id: VESTING_LOCK_ID, amount: 10_u64 }) + Some(&BalanceLock { id: VESTING_LOCK_ID, amount: 20_u64 }) ); assert_ok!(Vesting::update_vesting_schedules( Origin::root(), @@ -381,10 +587,13 @@ fn update_vesting_schedules_fails_if_unexpected_existing_locks() { #[test] fn vested_transfer_check_for_min() { ExtBuilder::build().execute_with(|| { - let schedule = - VestingSchedule { start: 1_u64, period: 1_u64, period_count: 1_u32, per_period: 3_u64 }; + let schedule = VestingSchedule { + window: BlockNumberBased { start: 1_u64, period: 1_u64 }, + period_count: 1_u32, + per_period: 3_u64, + }; assert_noop!( - Vesting::vested_transfer(Origin::signed(BOB), ALICE, MockCurrencyId::BTC, schedule,), + Vesting::vested_transfer(Origin::root(), BOB, ALICE, MockCurrencyId::BTC, schedule,), Error::::AmountLow ); }); @@ -394,26 +603,26 @@ fn vested_transfer_check_for_min() { fn multiple_vesting_schedule_claim_works() { ExtBuilder::build().execute_with(|| { let schedule = VestingSchedule { - start: 0_u64, - period: 10_u64, + window: BlockNumberBased { start: 0_u64, period: 10_u64 }, period_count: 2_u32, per_period: 10_u64, }; assert_ok!(Vesting::vested_transfer( - Origin::signed(ALICE), + Origin::root(), + ALICE, BOB, MockCurrencyId::BTC, schedule.clone(), )); let schedule2 = VestingSchedule { - start: 0_u64, - period: 10_u64, + window: BlockNumberBased { start: 0_u64, period: 10_u64 }, period_count: 3_u32, per_period: 10_u64, }; assert_ok!(Vesting::vested_transfer( - Origin::signed(ALICE), + Origin::root(), + ALICE, BOB, MockCurrencyId::BTC, schedule2.clone(), @@ -425,15 +634,11 @@ fn multiple_vesting_schedule_claim_works() { ); System::set_block_number(21); - assert_ok!(Vesting::claim(Origin::signed(BOB), MockCurrencyId::BTC)); - assert_eq!(Vesting::vesting_schedules(&BOB, MockCurrencyId::BTC), vec![schedule2]); System::set_block_number(31); - assert_ok!(Vesting::claim(Origin::signed(BOB), MockCurrencyId::BTC)); - assert!(!VestingSchedules::::contains_key(&BOB, MockCurrencyId::BTC)); assert_eq!(Tokens::locks(&BOB, MockCurrencyId::BTC), vec![]); @@ -444,26 +649,40 @@ fn multiple_vesting_schedule_claim_works() { fn exceeding_maximum_schedules_should_fail() { ExtBuilder::build().execute_with(|| { let schedule = VestingSchedule { - start: 0_u64, - period: 10_u64, + window: BlockNumberBased { start: 0_u64, period: 10_u64 }, + period_count: 2_u32, + per_period: 10_u64, + }; + let moment_schedule = VestingSchedule { + window: MomentBased { start: 0_u64, period: 10_u64 }, period_count: 2_u32, per_period: 10_u64, }; assert_ok!(Vesting::vested_transfer( - Origin::signed(ALICE), + Origin::root(), + ALICE, BOB, MockCurrencyId::BTC, schedule.clone(), )); assert_ok!(Vesting::vested_transfer( - Origin::signed(ALICE), + Origin::root(), + ALICE, BOB, MockCurrencyId::BTC, schedule.clone(), )); + assert_ok!(Vesting::vested_transfer( + Origin::root(), + ALICE, + BOB, + MockCurrencyId::BTC, + moment_schedule, + )); assert_noop!( Vesting::vested_transfer( - Origin::signed(ALICE), + Origin::root(), + ALICE, BOB, MockCurrencyId::BTC, schedule.clone(), @@ -471,7 +690,7 @@ fn exceeding_maximum_schedules_should_fail() { Error::::MaxVestingSchedulesExceeded ); - let schedules = vec![schedule.clone(), schedule.clone(), schedule]; + let schedules = vec![schedule.clone(), schedule.clone(), schedule.clone(), schedule]; assert_noop!( Vesting::update_vesting_schedules(Origin::root(), BOB, MockCurrencyId::BTC, schedules,), diff --git a/frame/vesting/src/weights.rs b/frame/vesting/src/weights.rs index 0efb3bb8b0b..e912d823572 100644 --- a/frame/vesting/src/weights.rs +++ b/frame/vesting/src/weights.rs @@ -33,6 +33,7 @@ pub trait WeightInfo { fn vested_transfer() -> Weight; fn claim(i: u32, ) -> Weight; fn update_vesting_schedules(i: u32, ) -> Weight; + fn claim_for(i: u32, ) -> Weight; } /// Default weights. @@ -56,4 +57,10 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } + + fn claim_for(i: u32, ) -> Weight { + (31_747_000 as Weight) + // Standard Error: 4_000 + .saturating_add((63_000 as Weight).saturating_mul(i as Weight)) + } } diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml deleted file mode 100644 index 3daf3f68097..00000000000 --- a/integration-tests/Cargo.toml +++ /dev/null @@ -1,205 +0,0 @@ -[package] -name = "integration-tests" -version = "0.1.0" -edition = "2021" - - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[package.metadata.cargo-udeps.ignore] -normal = [ - "currency-factory", - "oracle", - "pallet-bonded-finance", - "pallet-vault", - "session-benchmarking", - "vault" -] - -[dependencies] -frame-system = { package = "frame-system", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -support = { package = "frame-support", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -executive = { package = "frame-executive", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } - -# primitives -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } - -# modules -aura = { package = "pallet-aura", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -authorship = { package = "pallet-authorship", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -balances = { package = "pallet-balances", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -indices = { package = "pallet-indices", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -randomness-collective-flip = { package = "pallet-randomness-collective-flip", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -collective = { package = "pallet-collective", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -membership = { package = "pallet-membership", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -scheduler = { package = "pallet-scheduler", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -session = { package = "pallet-session", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sudo = { package = "pallet-sudo", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -timestamp = { package = "pallet-timestamp", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -treasury = { package = "pallet-treasury", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -democracy = { package = "pallet-democracy", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -transaction-payment = { package = "pallet-transaction-payment", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -utility = { package = "pallet-utility", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -smallvec = "1.6.1" - -# local modules -common = { path = "../runtime/common", default-features = false } -primitives = { path = "../runtime/primitives", default-features = false } -oracle = { package = "pallet-oracle", path = "../frame/oracle", default-features = false } -vault = { package = "pallet-vault", path = "../frame/vault", default-features = false } -currency-factory = { package = "pallet-currency-factory", path = "../frame/currency-factory", default-features = false } -composable-traits = { path = "../frame/composable-traits" , default-features = false} -call-filter = { package = "pallet-call-filter", path = "../frame/call-filter", default-features = false } -assets-registry = { package = "pallet-assets-registry", path = "../frame/assets-registry", default-features = false, optional = true} -governance-registry = { package = "pallet-governance-registry", path = "../frame/governance-registry", default-features = false, optional = true} -assets = { package = "pallet-assets", path = "../frame/assets", default-features = false, optional = true} - -# Used for the node template's RPCs -system-rpc-runtime-api = { package = "frame-system-rpc-runtime-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -transaction-payment-rpc-runtime-api = { package = "pallet-transaction-payment-rpc-runtime-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } - -# Used for runtime benchmarking -benchmarking = { package = "frame-benchmarking", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false, optional = true } -system-benchmarking = { package = "frame-system-benchmarking", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false, optional = true } -hex-literal = { version = "0.3.1", optional = true } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } - -# Parachain Utilities -cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -collator-selection = { package = "pallet-collator-selection", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -session-benchmarking = { package = "cumulus-pallet-session-benchmarking", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } - - -# added on top of runtime for emulation of network -paste = "1.0.5" -polkadot-core-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -xcm-emulator = { git = "https://github.com/shaunxw/xcm-simulator", rev = "a250ffc998bac4831c5692c591dee7bc13f3aead", default-features = false } -kusama-runtime = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -dali-runtime = { package = "dali-runtime", path = "../runtime/dali", default-features = false } - -[dev-dependencies] -env_logger = "0.9.0" - -[features] -default = ["std", "develop"] -std = [ - "codec/std", - "sp-api/std", - "sp-std/std", - "sp-core/std", - "sp-runtime/std", - "sp-version/std", - "sp-offchain/std", - "sp-session/std", - "sp-io/std", - "sp-block-builder/std", - "sp-transaction-pool/std", - "sp-inherents/std", - "support/std", - "executive/std", - "frame-system/std", - "utility/std", - "authorship/std", - "balances/std", - "randomness-collective-flip/std", - "timestamp/std", - "session/std", - "sudo/std", - "indices/std", - "oracle/std", - "vault/std", - "currency-factory/std", - "orml-tokens/std", - "orml-traits/std", - "treasury/std", - "democracy/std", - "scheduler/std", - "common/std", - "dali-runtime/std", - "primitives/std", - "collective/std", - "transaction-payment/std", - "parachain-info/std", - "cumulus-pallet-aura-ext/std", - "cumulus-pallet-parachain-system/std", - "cumulus-pallet-xcmp-queue/std", - "cumulus-pallet-xcm/std", - "cumulus-primitives-core/std", - "cumulus-primitives-timestamp/std", - "cumulus-primitives-utility/std", - "collator-selection/std", - "xcm/std", - "xcm-builder/std", - "xcm-executor/std", - "aura/std", - "sp-consensus-aura/std", - "scale-info/std", - "kusama-runtime/std", - "polkadot-core-primitives/std", - "polkadot-primitives/std", - "polkadot-runtime-parachains/std", -] - -runtime-benchmarks = [ - "benchmarking", - "support/runtime-benchmarks", - "system-benchmarking", - "frame-system/runtime-benchmarks", - "hex-literal", - "balances/runtime-benchmarks", - "timestamp/runtime-benchmarks", - "oracle/runtime-benchmarks", - "collective/runtime-benchmarks", - "collator-selection/runtime-benchmarks", - "session-benchmarking/runtime-benchmarks", - "pallet-xcm/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "xcm-builder/runtime-benchmarks", - "indices/runtime-benchmarks", - "membership/runtime-benchmarks", - "treasury/runtime-benchmarks", - "scheduler/runtime-benchmarks", - "collective/runtime-benchmarks", - "democracy/runtime-benchmarks", - "utility/runtime-benchmarks", - "kusama-runtime/runtime-benchmarks", - "dali-runtime/runtime-benchmarks", - "polkadot-primitives/runtime-benchmarks", - "polkadot-runtime-parachains/runtime-benchmarks", -] - -develop = [ - "assets", - "assets-registry", - "governance-registry", -] \ No newline at end of file diff --git a/integration-tests/README.md b/integration-tests/README.md deleted file mode 100644 index c9a7bc53d0d..00000000000 --- a/integration-tests/README.md +++ /dev/null @@ -1,109 +0,0 @@ -# Overview - -Runs transfers from some Composable based parachain to Composable parachain. And other parachains integrations. - -We do not use direct XCM messages as these are alfa quality. -So all messages go via Realay. Using Direct XCM messaging open channels amid chains with no hops. - -We do not use `Teleport` messages as it is considered unsafe. - -## Flow - -Each XCMP exchange consists of two phases, setup of connection and transfer. - -### Setup - -- Communicating parachains pair should be added to Relay -- Each parachain must add other parachain into `ParachainSystem` to allow requests from another chain -- Each parachain setups execution prices and filters to secure XCMP messaging -- Each parachain must add mapping for currency it wants to send to other parachain -- Each parachain must deposit to Relayer - -### Transfer currency - -Amounts are defined as next: -```rust -// next tells 1 networks up (jump to relay, find chain with ID, than encode para native asset), -let asset_id = AssetId::Concrete(MultiLocation::new(1, X2(Parachain(PICASSO_PARA_ID), GeneralKey(СurrencyId::PICA.encode()))); -// here we encode amount of 42 tokens to be manipulated -let amount_and_asset_id = MultiAsset{ fun : Fungible(42), id: asset_id}; -``` - -Transfer currency is based on sending some named messages interpreted on each chain, but always ends with `dispatch` calls on the target chain. It is possible to send a message and ask for a callback response about success/fail operation, but that happens not in the same block. For selling out things on DEX, will add `Transact` instruction to appreciate pallet. - - -```plantuml -@startuml - -box Picasso #LightYellow - participant Pallet as pallet - participant XTokens as xtokens - participant XcmExecutor - participant TransactAsset - participant Converters - participant XcmQueue - participant Assets -end box - -box Hydra #LightBlue - participant "XcmQueue" as hydra_xcm_queue - participant "XcmExecutor" as hydra_xcm_executor - participant "Assets" as hydra_assets -end box -pallet -> xtokens: Transfer Local Assets -xtokens -> Converters: pallet to map local tokens to remote -xtokens -> xtokens : Build XCM message depending on remote type -xtokens -> XcmExecutor : Execute -XcmExecutor -> TransactAsset : Withdraw -TransactAsset -> Assets: Withdraw -XcmExecutor -> XcmQueue : Put message -note right - - Networking layer will ensure that messages appear on another chain -end note -... -hydra_xcm_queue -> hydra_xcm_executor: Receive message -hydra_xcm_executor -> hydra_assets: Dispatch to call relevant pallet for accepting foreign assets - -@enduml -``` - -## Readings - - -### How to setup XCMP - -- [Polkadot XCM Cross-Chain Asset Transfer Demo](https://medium.com/oak-blockchain/polkadot-xcm-cross-chain-asset-transfer-demo-53aa9a2e97a7) -- https://medium.com/oak-blockchain/tutorial-polkadot-cross-chain-message-passing-xcmp-demo-with-ping-pallet-f53397158ab4 - -### Format of messages - -- https://medium.com/polkadot-network/xcm-part-ii-versioning-and-compatibility-b313fc257b83 -- https://medium.com/polkadot-network/xcm-part-iii-execution-and-error-management-ceb8155dd166 -- https://github.com/paritytech/xcm-format/blob/master/README.md -- https://research.web3.foundation/en/latest/polkadot/XCMP/index.html -- https://medium.com/polkadot-network/xcm-the-cross-consensus-message-format-3b77b1373392 - - -### XCMP desing - -- https://www.youtube.com/watch?v=wrA9vlPjVPE -- https://research.web3.foundation/en/latest/polkadot/XCMP/Opening_closing%20XCMP%20Channel.html - -### Generic context - -- https://wiki.polkadot.network/docs/learn-bridges -- https://wiki.polkadot.network/docs/learn-parachains -- https://polkadot.network/Polkadot-lightpaper.pdf -- https://wiki.polkadot.network/docs/learn-crosschain -- https://medium.com/web3foundation/polkadots-messaging-scheme-b1ec560908b7 - - -## How to run - -```shell -RUST_LOG=trace,parity-db=error,trie=error,runtime=trace,substrate-relay=trace,bridge=trace cargo test --features develop -- --nocapture --test-threads=1 -``` - -### Issues - -We use ORML + Cumulus, which does not support out of box access to all instruction. diff --git a/integration-tests/local-integration-tests/Cargo.toml b/integration-tests/local-integration-tests/Cargo.toml new file mode 100644 index 00000000000..f4f937ef0e0 --- /dev/null +++ b/integration-tests/local-integration-tests/Cargo.toml @@ -0,0 +1,219 @@ +[package] +description = "Local in memory(no OS handles opened) integrations tests via simulator. It may take time as it builds several runtimes as has direct dependnency on runtime configuration" +edition = "2021" +name = "local-integration-tests" +version = "0.1.0" + + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[package.metadata.cargo-udeps.ignore] +normal = [ + "currency-factory", + "oracle", + "pallet-bonded-finance", + "pallet-vault", + "session-benchmarking", + "vault", +] + +[dependencies] +executive = { package = "frame-executive", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +frame-system = { package = "frame-system", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +num-traits = { version = "0.2.14", default-features = false } +support = { package = "frame-support", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } + +# primitives +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } + +# modules +aura = { package = "pallet-aura", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +authorship = { package = "pallet-authorship", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +balances = { package = "pallet-balances", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +collective = { package = "pallet-collective", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +democracy = { package = "pallet-democracy", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +indices = { package = "pallet-indices", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +membership = { package = "pallet-membership", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } +orml-xtokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } +randomness-collective-flip = { package = "pallet-randomness-collective-flip", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +scheduler = { package = "pallet-scheduler", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +session = { package = "pallet-session", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +smallvec = "1.6.1" +sudo = { package = "pallet-sudo", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +timestamp = { package = "pallet-timestamp", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +transaction-payment = { package = "pallet-transaction-payment", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +treasury = { package = "pallet-treasury", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +utility = { package = "pallet-utility", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } + +# local modules +assets = { package = "pallet-assets", path = "../../frame/assets", default-features = false, optional = true } +assets-registry = { package = "pallet-assets-registry", path = "../../frame/assets-registry", default-features = false, optional = true } +call-filter = { package = "pallet-call-filter", path = "../../frame/call-filter", default-features = false } +common = { path = "../../runtime/common", default-features = false } +composable-traits = { path = "../../frame/composable-traits", default-features = false } +currency-factory = { package = "pallet-currency-factory", path = "../../frame/currency-factory", default-features = false } +governance-registry = { package = "pallet-governance-registry", path = "../../frame/governance-registry", default-features = false, optional = true } +oracle = { package = "pallet-oracle", path = "../../frame/oracle", default-features = false } +primitives = { path = "../../runtime/primitives", default-features = false } +vault = { package = "pallet-vault", path = "../../frame/vault", default-features = false } + +# Used for the node template's RPCs +system-rpc-runtime-api = { package = "frame-system-rpc-runtime-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +transaction-payment-rpc-runtime-api = { package = "pallet-transaction-payment-rpc-runtime-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } + +# Used for runtime benchmarking +benchmarking = { package = "frame-benchmarking", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false, optional = true } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ + "derive", +] } +hex-literal = { version = "0.3.3", optional = true } +system-benchmarking = { package = "frame-system-benchmarking", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false, optional = true } + +# Parachain Utilities +collator-selection = { package = "pallet-collator-selection", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } +session-benchmarking = { package = "cumulus-pallet-session-benchmarking", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } + + +# added on top of runtime for emulation of network +kusama-runtime = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +paste = "1.0.6" +polkadot-core-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +xcm-emulator = { git = "https://github.com/shaunxw/xcm-simulator", rev = "24ccbce563d1f99019b4cdfa2f3af4e99bac0dfc", default-features = false } + +dali-runtime = { package = "dali-runtime", path = "../../runtime/dali", default-features = false } +picasso-runtime = { package = "picasso-runtime", path = "../../runtime/picasso", default-features = false, optional = true } + +[dev-dependencies] +env_logger = "0.9.0" + +[features] +dali = ["std", "develop", "local-integration-tests"] +default = ["std", "develop", "local-integration-tests", "picasso"] +local-integration-tests = [ + "dali-runtime/local-integration-tests", + "picasso-runtime/local-integration-tests", +] +picasso = ["std", "develop", "local-integration-tests"] +std = [ + "codec/std", + "sp-api/std", + "sp-std/std", + "sp-core/std", + "sp-runtime/std", + "sp-version/std", + "sp-offchain/std", + "sp-session/std", + "sp-io/std", + "sp-block-builder/std", + "sp-transaction-pool/std", + "sp-inherents/std", + "support/std", + "executive/std", + "frame-system/std", + "utility/std", + "authorship/std", + "balances/std", + "randomness-collective-flip/std", + "timestamp/std", + "session/std", + "sudo/std", + "indices/std", + "oracle/std", + "vault/std", + "currency-factory/std", + "orml-tokens/std", + "orml-xtokens/std", + "orml-traits/std", + "treasury/std", + "democracy/std", + "scheduler/std", + "common/std", + "dali-runtime/std", + "picasso-runtime/std", + "primitives/std", + "collective/std", + "transaction-payment/std", + "parachain-info/std", + "cumulus-pallet-aura-ext/std", + "cumulus-pallet-parachain-system/std", + "cumulus-pallet-xcmp-queue/std", + "cumulus-pallet-xcm/std", + "cumulus-primitives-core/std", + "cumulus-primitives-timestamp/std", + "cumulus-primitives-utility/std", + "collator-selection/std", + "xcm/std", + "xcm-builder/std", + "xcm-executor/std", + "aura/std", + "sp-consensus-aura/std", + "scale-info/std", + "kusama-runtime/std", + "polkadot-core-primitives/std", + "polkadot-primitives/std", + "polkadot-runtime-parachains/std", +] + +runtime-benchmarks = [ + "benchmarking", + "support/runtime-benchmarks", + "system-benchmarking", + "frame-system/runtime-benchmarks", + "hex-literal", + "balances/runtime-benchmarks", + "timestamp/runtime-benchmarks", + "oracle/runtime-benchmarks", + "collective/runtime-benchmarks", + "collator-selection/runtime-benchmarks", + "session-benchmarking/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", + "indices/runtime-benchmarks", + "membership/runtime-benchmarks", + "treasury/runtime-benchmarks", + "scheduler/runtime-benchmarks", + "collective/runtime-benchmarks", + "democracy/runtime-benchmarks", + "utility/runtime-benchmarks", + "kusama-runtime/runtime-benchmarks", + "dali-runtime/runtime-benchmarks", + "picasso-runtime/runtime-benchmarks", + "polkadot-primitives/runtime-benchmarks", + "polkadot-runtime-parachains/runtime-benchmarks", +] + +develop = ["assets", "assets-registry", "governance-registry"] diff --git a/integration-tests/local-integration-tests/README.md b/integration-tests/local-integration-tests/README.md new file mode 100644 index 00000000000..a01d2e18676 --- /dev/null +++ b/integration-tests/local-integration-tests/README.md @@ -0,0 +1,32 @@ +# Overview + +Runs transfers from some Composable based parachain to Composable parachain. And other parachains integrations. + +We do not use direct XCM messages as these are alfa quality. +So all messages go via Realay. Using Direct XCM messaging open channels amid chains with no hops. + +We do not use `Teleport` messages as it is considered unsafe. + +## Flow + +Each XCMP exchange consists of two phases, setup of connection and transfer. + +### Setup + +- Communicating parachains pair should be added to Relay +- Each parachain must add other parachain into `ParachainSystem` to allow requests from another chain +- Each parachain setups execution prices and filters to secure XCMP messaging +- Each parachain must add mapping for currency it wants to send to other parachain +- Each parachain must deposit to Relayer + +### Transfer currency + +Amounts are defined as next: +```rust +// next tells 1 networks up (jump to relay, find chain with ID, than encode para native asset), +let asset_id = AssetId::Concrete(MultiLocation::new(1, X2(Parachain(PICASSO_PARA_ID), GeneralKey(СurrencyId::PICA.encode()))); +// here we encode amount of 42 tokens to be manipulated +let amount_and_asset_id = MultiAsset{ fun : Fungible(42), id: asset_id}; +``` + +Transfer currency is based on sending some named messages interpreted on each chain, but always ends with `dispatch` calls on the target chain. It is possible to send a message and ask for a callback response about success/fail operation, but that happens not in the same block. For selling out things on DEX, will add `Transact` instruction to appreciate pallet. \ No newline at end of file diff --git a/integration-tests/local-integration-tests/awesome-xcmp.md b/integration-tests/local-integration-tests/awesome-xcmp.md new file mode 100644 index 00000000000..35f0b8f5e1a --- /dev/null +++ b/integration-tests/local-integration-tests/awesome-xcmp.md @@ -0,0 +1,50 @@ +## Overview + +Resources which allows to grasp XCM. General undrestanding how bridges work will help too. + +### Conceptual + +https://www.youtube.com/watch?v=XU6dAAQD9UE - trust and XCMP + +### How to setup XCMP + +- [Polkadot XCM Cross-Chain Asset Transfer Demo](https://medium.com/oak-blockchain/polkadot-xcm-cross-chain-asset-transfer-demo-53aa9a2e97a7) +- https://medium.com/oak-blockchain/tutorial-polkadot-cross-chain-message-passing-xcmp-demo-with-ping-pallet-f53397158ab4 + +### Format of messages + +- https://medium.com/polkadot-network/xcm-part-ii-versioning-and-compatibility-b313fc257b83 +- https://medium.com/polkadot-network/xcm-part-iii-execution-and-error-management-ceb8155dd166 +- https://github.com/paritytech/xcm-format/blob/master/README.md +- https://research.web3.foundation/en/latest/polkadot/XCMP/index.html +- https://medium.com/polkadot-network/xcm-the-cross-consensus-message-format-3b77b1373392 + +### XCM(P) desing + +- https://www.youtube.com/watch?v=cS8GvPGMLS0 +- https://www.youtube.com/watch?v=5cgq5jOZx9g +- https://substrate.stackexchange.com/questions/37/how-can-i-transfer-assets-using-xcm +- https://www.youtube.com/watch?v=wrA9vlPjVPE +- https://research.web3.foundation/en/latest/polkadot/XCMP/Opening_closing%20XCMP%20Channel.html +- https://www.youtube.com/watch?v=P_yLrFfmLrU + +### Generic context + +- https://wiki.polkadot.network/docs/learn-bridges +- https://wiki.polkadot.network/docs/learn-parachains +- https://polkadot.network/Polkadot-lightpaper.pdf +- https://wiki.polkadot.network/docs/learn-crosschain +- https://medium.com/web3foundation/polkadots-messaging-scheme-b1ec560908b7 + +### Assets + +https://polkadot.network/blog/statemint-becomes-first-common-good-parachain-on-polkadot/ + + +### Other parachains usage + +https://www.youtube.com/watch?v=5mspUoK1aIE + +### Issues + +We use ORML + Cumulus, which does not support out of box access to all instructions. diff --git a/integration-tests/local-integration-tests/sibling-asset-transfer.sequence.plantuml b/integration-tests/local-integration-tests/sibling-asset-transfer.sequence.plantuml new file mode 100644 index 00000000000..0ae2c9cb742 --- /dev/null +++ b/integration-tests/local-integration-tests/sibling-asset-transfer.sequence.plantuml @@ -0,0 +1,32 @@ +@startuml + +box Picasso #LightYellow + participant Pallet as pallet + participant XTokens as xtokens + participant XcmExecutor + participant TransactAsset + participant Converters + participant XcmQueue + participant Assets +end box + +box Sibling #LightBlue + participant "XcmQueue" as sibling_xcm_queue + participant "XcmExecutor" as sibling_xcm_executor + participant "Assets" as sibling_assets +end box +pallet -> xtokens: Transfer Local Assets +xtokens -> Converters: pallet to map local tokens to remote +xtokens -> xtokens : Build XCM message depending on remote type +xtokens -> XcmExecutor : Execute +XcmExecutor -> TransactAsset : Withdraw +TransactAsset -> Assets: Withdraw +XcmExecutor -> XcmQueue : Put message +note right + - Networking layer will ensure that messages appear on another chain +end note +... +sibling_xcm_queue -> sibling_xcm_executor: Receive message +sibling_xcm_executor -> sibling_assets: Dispatch to call relevant pallet for accepting foreign assets + +@enduml \ No newline at end of file diff --git a/integration-tests/local-integration-tests/src/cross_chain_transfer.rs b/integration-tests/local-integration-tests/src/cross_chain_transfer.rs new file mode 100644 index 00000000000..fcbfeed0424 --- /dev/null +++ b/integration-tests/local-integration-tests/src/cross_chain_transfer.rs @@ -0,0 +1,1101 @@ +// TODO: +// Withdraw assets and trap it via polka xcm trap- if will fail always +// let does_not_exists= u128::MAX-1; +// (0, GeneralKey(does_not_exists.encode())), +// Because Convert will not find assets and execution will never reach to AssetsTrapped +// cannot handle it because of ORML design +//pallet_xcm::Event::AssetsTrapped + +use crate::{ + helpers::*, + kusama_test_net::{ + KusamaRelay, Sibling, This, ALICE, ALICE_PARACHAIN_KSM, BOB, CHARLIE, PICA, + SIBLING_PARA_ID, THIS_PARA_ID, + }, + prelude::*, +}; +use codec::Encode; +use common::{AccountId, Balance}; +use composable_traits::assets::{RemoteAssetRegistry, XcmAssetLocation}; + +use this_runtime::{ + Assets, AssetsRegistry, Balances, MaxInstructions, Origin, Runtime, System, Tokens, + UnitWeightCost, XTokens, +}; + +use num_traits::Zero; +use orml_traits::currency::MultiCurrency; + +use primitives::currency::*; +use sp_runtime::{assert_eq_error_rate, traits::AccountIdConversion, MultiAddress}; +use support::{assert_ok, log}; +use xcm::latest::prelude::*; +use xcm_builder::ParentIsPreset; +use xcm_emulator::TestExt; +use xcm_executor::{traits::Convert, XcmExecutor}; + +#[test] +fn reserve_transfer_from_relay_alice_bob() { + simtest(); + let from = ALICE; + let to = BOB; + reserve_transfer(from, to); +} + +#[test] +fn reserve_transfer_from_relay_alice_alice() { + simtest(); + let from = ALICE; + let to = ALICE; + reserve_transfer(from, to); +} + +#[test] +fn reserve_transfer_from_relay_map() { + simtest(); + let from = ALICE; + let to = BOB; + This::execute_with(|| { + assert_ok!(this_runtime::AssetsRegistry::set_location( + CurrencyId::KSM, // KSM id as it is locally + // if we get tokens from parent chain, these can be only native token + XcmAssetLocation::RELAY_NATIVE, + )); + }); + + reserve_transfer(from, to); +} + +/// how it works: +/// top level ReserveTransfer instruction is interprtered first on sending chain +/// it transfers amount from sender account to target chain account on sending chain +/// send it custs wrapper part of XCM message, and sends remaining with deposit +/// target chain sees deposit amount and mints approciate amount +/// validats origin of reserve (must be relay) +fn reserve_transfer(from: [u8; 32], to: [u8; 32]) { + let from_account = &AccountId::from(from); + let to_account = &AccountId::from(to); + let balance = enough_weigth(); + let before = + This::execute_with(|| this_runtime::Assets::free_balance(CurrencyId::KSM, to_account)); + KusamaRelay::execute_with(|| { + >::deposit_creating( + from_account, + balance, + ); + let result = kusama_runtime::XcmPallet::reserve_transfer_assets( + kusama_runtime::Origin::signed(from.into()), + Box::new(Parachain(THIS_PARA_ID).into().into()), + Box::new(Junction::AccountId32 { id: to, network: NetworkId::Any }.into().into()), + Box::new((Here, balance).into()), + 0, + ); + assert_ok!(result); + relay_dump_events(); + }); + This::execute_with(|| { + let new_balance = this_runtime::Assets::free_balance(CurrencyId::KSM, to_account); + dump_events(); + assert_eq_error_rate!(new_balance, before + balance, (UnitWeightCost::get() * 10) as u128); + assert!(!this_runtime::System::events() + .iter() + .any(|r| { matches!(r.event, this_runtime::Event::XTokens(_)) })); + }); +} + +#[test] +fn transfer_to_relay_chain() { + simtest(); + This::execute_with(|| { + assert_ok!(::set_location( + CurrencyId::KSM, + XcmAssetLocation::RELAY_NATIVE, + )); + let transferred = this_runtime::XTokens::transfer( + this_runtime::Origin::signed(ALICE.into()), + CurrencyId::KSM, + 3 * PICA, + Box::new( + MultiLocation::new( + 1, + X1(Junction::AccountId32 { id: BOB, network: NetworkId::Any }), + ) + .into(), + ), + 4_600_000_000, + ); + + assert_ok!(transferred); + + let remaining = + this_runtime::Assets::free_balance(CurrencyId::KSM, &AccountId::from(ALICE)); + + assert_eq!(remaining, ALICE_PARACHAIN_KSM - 3 * PICA); + }); + + KusamaRelay::execute_with(|| { + assert_eq!( + kusama_runtime::Balances::free_balance(&AccountId::from(BOB)), + 2999893333340 // 3 * PICA - fee + ); + }); +} + +#[test] +fn transfer_from_dali() { + simtest(); + + This::execute_with(|| { + assert_ok!(::set_location( + CurrencyId::PICA, + composable_traits::assets::XcmAssetLocation(MultiLocation::new( + 1, + X2(Parachain(SIBLING_PARA_ID), GeneralKey(CurrencyId::PICA.encode())) + )) + )); + }); + + let local_withdraw_amount = 3 * PICA; + Sibling::execute_with(|| { + assert_ok!(sibling_runtime::XTokens::transfer( + sibling_runtime::Origin::signed(ALICE.into()), + CurrencyId::PICA, + local_withdraw_amount, + Box::new( + MultiLocation::new( + 1, + X2( + Junction::Parachain(THIS_PARA_ID), + Junction::AccountId32 { id: BOB, network: NetworkId::Any } + ) + ) + .into() + ), + 399_600_000_000 + )); + assert_eq!( + sibling_runtime::Assets::free_balance(CurrencyId::PICA, &AccountId::from(ALICE)), + 200 * PICA - local_withdraw_amount + ); + }); + + This::execute_with(|| { + let balance = this_runtime::Assets::free_balance(CurrencyId::PICA, &AccountId::from(BOB)); + assert_eq_error_rate!(balance, local_withdraw_amount, (UnitWeightCost::get() * 10) as u128); + }); +} + +#[test] +fn transfer_from_picasso_to_dali() { + simtest(); + + Sibling::execute_with(|| { + assert_ok!(::set_location( + // local id + CurrencyId::PICA, + // remote id + // first part is remote network, + // second part is id of asset on remote + composable_traits::assets::XcmAssetLocation(MultiLocation::new( + 1, + X2(Parachain(THIS_PARA_ID), GeneralKey(CurrencyId::PICA.encode())) + )) + )); + }); + + This::execute_with(|| { + assert_ok!(::set_location( + CurrencyId::PICA, + composable_traits::assets::XcmAssetLocation(MultiLocation::new( + 1, + X2(Parachain(SIBLING_PARA_ID), GeneralKey(CurrencyId::PICA.encode())) + )) + )); + + assert_ok!(this_runtime::XTokens::transfer( + this_runtime::Origin::signed(ALICE.into()), + CurrencyId::PICA, + 3 * PICA, + Box::new( + MultiLocation::new( + 1, + X2( + Junction::Parachain(SIBLING_PARA_ID), + Junction::AccountId32 { id: BOB, network: NetworkId::Any } + ) + ) + .into() + ), + 399_600_000_000 + )); + assert_eq!( + this_runtime::Balances::free_balance(&AccountId::from(ALICE)), + 200 * PICA - 3 * PICA + ); + }); + + Sibling::execute_with(|| { + let balance = + sibling_runtime::Assets::free_balance(CurrencyId::PICA, &AccountId::from(BOB)); + assert_eq_error_rate!(balance, 3 * PICA, (UnitWeightCost::get() * 10) as u128); + }); +} + +// from: Hydra +#[test] +fn transfer_insufficient_amount_should_fail() { + simtest(); + Sibling::execute_with(|| { + assert_ok!(sibling_runtime::XTokens::transfer( + sibling_runtime::Origin::signed(ALICE.into()), + CurrencyId::PICA, + 1_000_000 - 1, + Box::new( + MultiLocation::new( + 1, + X2( + Junction::Parachain(THIS_PARA_ID), + Junction::AccountId32 { id: BOB, network: NetworkId::Any } + ) + ) + .into() + ), + 399_600_000_000 + )); + assert_eq!( + sibling_runtime::Balances::free_balance(&AccountId::from(ALICE)), + 199999999000001 + ); + }); + + This::execute_with(|| { + // Xcm should fail therefore nothing should be deposit into beneficiary account + assert_eq!(this_runtime::Tokens::free_balance(CurrencyId::PICA, &AccountId::from(BOB)), 0); + }); +} + +#[test] +#[ignore = "until fixed sibling trust map"] +fn transfer_to_sibling() { + simtest(); + let _other_currency = CurrencyId::KSM; + fn this_native_reserve_account() -> AccountId { + use sp_runtime::traits::AccountIdConversion; + polkadot_parachain::primitives::Sibling::from(THIS_PARA_ID).into_account() + } + + let alice_original = This::execute_with(|| { + assert_ok!(Tokens::deposit(CurrencyId::KSM, &AccountId::from(ALICE), 100_000_000_000_000)); + Tokens::free_balance(CurrencyId::KSM, &AccountId::from(ALICE)) + }); + let alice_from_amount = alice_original / 10; + let alice_remaining = alice_original - alice_from_amount; + let weight_to_pay = (alice_from_amount / 2) as u64; + + let picasso_on_sibling = Sibling::execute_with(|| { + assert_ok!(Tokens::deposit( + CurrencyId::KSM, + &this_native_reserve_account(), + 100 * CurrencyId::unit::(), + )); + Tokens::free_balance(CurrencyId::KSM, &this_native_reserve_account()) + }); + + assert_ne!(picasso_on_sibling, Balance::zero()); + + This::execute_with(|| { + assert_ok!(XTokens::transfer( + Origin::signed(ALICE.into()), + CurrencyId::KSM, + alice_from_amount, + Box::new( + MultiLocation::new( + 1, + X2( + Parachain(SIBLING_PARA_ID), + Junction::AccountId32 { network: NetworkId::Any, id: BOB.into() } + ) + ) + .into() + ), + weight_to_pay, + )); + + assert_eq!(Tokens::free_balance(CurrencyId::KSM, &AccountId::from(ALICE)), alice_remaining); + }); + + // TODO: also XCM not failes, it really fails with not enough balance, not clear so what balance + // is needed to transfer + Sibling::execute_with(|| { + assert_eq!( + Tokens::free_balance(CurrencyId::KSM, &this_native_reserve_account()), + picasso_on_sibling + ); + assert_eq!(Tokens::free_balance(CurrencyId::KSM, &AccountId::from(BOB)), 9_989_760_000_000); + + assert_ok!(XTokens::transfer( + Origin::signed(BOB.into()), + CurrencyId::KSM, + 5_000_000_000_000, + Box::new( + MultiLocation::new( + 1, + X2( + Parachain(THIS_PARA_ID), + Junction::AccountId32 { network: NetworkId::Any, id: ALICE.into() } + ) + ) + .into() + ), + 1_000_000_000, + )); + + assert_eq!( + Tokens::free_balance(CurrencyId::KSM, &this_native_reserve_account()), + 95_000_000_000_000 + ); + assert_eq!(Tokens::free_balance(CurrencyId::KSM, &AccountId::from(BOB)), 4_989_760_000_000); + }); + + This::execute_with(|| { + assert_eq!( + Tokens::free_balance(CurrencyId::KSM, &AccountId::from(ALICE)), + 94_989_760_000_000 + ); + }); +} + +/// if Bob sends amount of his tokens and these are above weigth but less than ED, +/// than our treasury takes that amount, sorry Bob +/// Acala's tests +#[test] +fn transfer_from_relay_chain_deposit_to_treasury_if_below_existential_deposit() { + simtest(); + let amount = under_existential_deposit(LocalAssetId::KSM, 3); + let receiver = CHARLIE; + let picasso_treasury = This::execute_with(|| { + assert_eq!( + this_runtime::Tokens::free_balance(CurrencyId::KSM, &AccountId::from(receiver)), + 0, + ); + this_runtime::Tokens::free_balance(CurrencyId::KSM, &this_runtime::TreasuryAccount::get()) + }); + + KusamaRelay::execute_with(|| { + assert_ok!(kusama_runtime::XcmPallet::reserve_transfer_assets( + kusama_runtime::Origin::signed(ALICE.into()), + Box::new(Parachain(THIS_PARA_ID).into().into()), + Box::new(Junction::AccountId32 { id: receiver, network: NetworkId::Any }.into().into()), + Box::new((Here, amount).into()), + 0 + )); + }); + + This::execute_with(|| { + assert_eq!( + this_runtime::Tokens::free_balance(CurrencyId::KSM, &AccountId::from(receiver)), + 0, + "assets did not get to recepient as it is not enough to pay ED" + ); + assert_eq!( + this_runtime::Tokens::free_balance( + CurrencyId::KSM, + &this_runtime::TreasuryAccount::get() + ), + amount - picasso_treasury + ); + }); +} + +/// from: Acala +/// this test resonably iff we know ratio of KSM to PICA, if not, it should be rewritten to ensure +/// permissioned execution of some very specific action from other chains +#[test] +fn xcm_transfer_execution_barrier_trader_works() { + simtest(); + + let unit_instruction_weight = UnitWeightCost::get() / 50; + assert!(unit_instruction_weight > 0, "barrier makes sence iff there is pay for messages"); + + // relay-chain use normal account to send xcm, destination para-chain can't pass Barrier check + let tiny = 100; + let message = Xcm(vec![ + ReserveAssetDeposited((Parent, tiny).into()), + BuyExecution { fees: (Parent, tiny).into(), weight_limit: Unlimited }, + DepositAsset { assets: All.into(), max_assets: 1, beneficiary: Here.into() }, + ]); + KusamaRelay::execute_with(|| { + let r = pallet_xcm::Pallet::::send( + kusama_runtime::Origin::signed(ALICE.into()), + Box::new(Parachain(THIS_PARA_ID).into().into()), + Box::new(xcm::VersionedXcm::from(message)), + ); + assert_ok!(r); + }); + This::execute_with(|| { + assert!(this_runtime::System::events().iter().any(|r| { + matches!( + r.event, + this_runtime::Event::DmpQueue(cumulus_pallet_dmp_queue::Event::ExecutedDownward( + _, + Outcome::Error(XcmError::Barrier) + )) + ) + })); + }); + + // AllowTopLevelPaidExecutionFrom barrier test case: + // para-chain use XcmExecutor `execute_xcm()` method to execute xcm. + // if `weight_limit` in BuyExecution is less than `xcm_weight(max_weight)`, then Barrier can't + // pass. other situation when `weight_limit` is `Unlimited` or large than `xcm_weight`, then + // it's ok. + let expect_weight_limit = UnitWeightCost::get() * (MaxInstructions::get() as u64) * 100; + let message = Xcm::(vec![ + ReserveAssetDeposited((Parent, tiny).into()), + BuyExecution { fees: (Parent, tiny).into(), weight_limit: Limited(100) }, + DepositAsset { assets: All.into(), max_assets: 1, beneficiary: Here.into() }, + ]); + This::execute_with(|| { + let r = XcmExecutor::::execute_xcm( + Parent, + message, + expect_weight_limit, + ); + assert_eq!(r, Outcome::Error(XcmError::Barrier)); + }); + + // trader inside BuyExecution have TooExpensive error if payment less than calculated weight + // amount. the minimum of calculated weight amount(`FixedRateOfFungible`) is + let ksm_per_second = UnitWeightCost::get() as u128 / 50 - 1_000; // TODO: define all calculation somehow in runtime as in Acala + let message = Xcm::(vec![ + ReserveAssetDeposited((Parent, ksm_per_second).into()), + BuyExecution { + fees: (Parent, ksm_per_second).into(), + weight_limit: Limited(expect_weight_limit), + }, + DepositAsset { assets: All.into(), max_assets: 1, beneficiary: Here.into() }, + ]); + This::execute_with(|| { + let r = XcmExecutor::::execute_xcm( + Parent, + message, + expect_weight_limit, + ); + assert_eq!( + r, + Outcome::Incomplete( + unit_instruction_weight * 2 * 50, /* so here we have report in PICA, while we + * allowed to pay in KSM */ + XcmError::TooExpensive + ) + ); + }); + + // all situation fulfilled, execute success + let total = (unit_instruction_weight * MaxInstructions::get() as u64) as u128; + let message = Xcm::(vec![ + ReserveAssetDeposited((Parent, total).into()), + BuyExecution { fees: (Parent, total).into(), weight_limit: Limited(expect_weight_limit) }, + DepositAsset { assets: All.into(), max_assets: 1, beneficiary: Here.into() }, + ]); + This::execute_with(|| { + let r = XcmExecutor::::execute_xcm( + Parent, + message, + expect_weight_limit, + ); + assert_eq!(r, Outcome::Complete(unit_instruction_weight * 3 * 50)); + }); +} + +/// source: Acala +#[test] +fn para_chain_subscribe_version_notify_of_sibling_chain() { + simtest(); + This::execute_with(|| { + let r = pallet_xcm::Pallet::::force_subscribe_version_notify( + this_runtime::Origin::root(), + Box::new((Parent, Parachain(SIBLING_PARA_ID)).into()), + ); + assert_ok!(r); + }); + This::execute_with(|| { + assert!(this_runtime::System::events().iter().any(|r| matches!( + r.event, + this_runtime::Event::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent( + Some(_) + )) + ))); + }); + Sibling::execute_with(|| { + assert!(sibling_runtime::System::events().iter().any(|r| matches!( + r.event, + this_runtime::Event::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent( + Some(_) + )) | this_runtime::Event::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success(Some(_))) + ))); + }); +} + +/// source: Acala +#[test] +fn para_chain_subscribe_version_notify_of_relay_chain() { + This::execute_with(|| { + let r = pallet_xcm::Pallet::::force_subscribe_version_notify( + this_runtime::Origin::root(), + Box::new(Parent.into()), + ); + assert_ok!(r); + }); + This::execute_with(|| { + this_runtime::System::assert_has_event(this_runtime::Event::RelayerXcm( + pallet_xcm::Event::SupportedVersionChanged( + MultiLocation { parents: 1, interior: Here }, + 2, + ), + )); + }); +} + +/// source: Acala +#[test] +fn relay_chain_subscribe_version_notify_of_para_chain() { + KusamaRelay::execute_with(|| { + let r = pallet_xcm::Pallet::::force_subscribe_version_notify( + kusama_runtime::Origin::root(), + Box::new(Parachain(THIS_PARA_ID).into().into()), + ); + assert_ok!(r); + }); + KusamaRelay::execute_with(|| { + kusama_runtime::System::assert_has_event(kusama_runtime::Event::XcmPallet( + pallet_xcm::Event::SupportedVersionChanged( + MultiLocation { parents: 0, interior: X1(Parachain(THIS_PARA_ID)) }, + 2, + ), + )); + }); +} + +#[test] +fn test_assets_registry_module() { + simtest(); + + let local_asset = CurrencyId::PICA; + let foreign_asset = CurrencyId::PICA; + + fn picasso_reserve_account() -> AccountId { + use sp_runtime::traits::AccountIdConversion; + polkadot_parachain::primitives::Sibling::from(THIS_PARA_ID).into_account() + } + + This::execute_with(|| { + let local_admin = AccountId::from(ALICE); + let foreign_admin = AccountId::from(BOB); + let decimals = 12; + let location = XcmAssetLocation( + MultiLocation::new( + 1, + X2(Parachain(SIBLING_PARA_ID), GeneralKey(CurrencyId::PICA.encode())), + ) + .into(), + ); + + assert_ok!(AssetsRegistry::set_local_admin(Origin::root(), local_admin.clone())); + assert_ok!(AssetsRegistry::set_foreign_admin(Origin::root(), foreign_admin.clone())); + + assert_ok!(AssetsRegistry::approve_assets_mapping_candidate( + Origin::signed(local_admin), + local_asset, + foreign_asset, + location.clone(), + decimals, + )); + assert_ok!(AssetsRegistry::approve_assets_mapping_candidate( + Origin::signed(foreign_admin), + local_asset, + foreign_asset, + location, + decimals, + )); + }); + + Sibling::execute_with(|| { + let local_admin = AccountId::from(ALICE); + let foreign_admin = AccountId::from(BOB); + let decimals = 12; + let location = XcmAssetLocation( + MultiLocation::new( + 1, + X2(Parachain(THIS_PARA_ID), GeneralKey(CurrencyId::PICA.encode())), + ) + .into(), + ); + + assert_ok!(AssetsRegistry::set_local_admin(Origin::root(), local_admin.clone())); + assert_ok!(AssetsRegistry::set_foreign_admin(Origin::root(), foreign_admin.clone())); + + assert_ok!(AssetsRegistry::approve_assets_mapping_candidate( + Origin::signed(local_admin), + foreign_asset, + local_asset, + location.clone(), + decimals, + )); + assert_ok!(AssetsRegistry::approve_assets_mapping_candidate( + Origin::signed(foreign_admin), + foreign_asset, + local_asset, + location, + decimals, + )); + }); + + Sibling::execute_with(|| { + assert_eq!(Balances::free_balance(&picasso_reserve_account()), 0); + + assert_ok!(XTokens::transfer( + this_runtime::Origin::signed(ALICE.into()), + CurrencyId::PICA, + 5 * PICA, + Box::new( + MultiLocation::new( + 1, + X2( + Parachain(THIS_PARA_ID), + Junction::AccountId32 { network: NetworkId::Any, id: BOB.into() } + ) + ) + .into() + ), + 1_000_000_000, + )); + + assert_eq!(Balances::free_balance(&picasso_reserve_account()), 5 * PICA); + assert_eq!(Balances::free_balance(&AccountId::from(ALICE)), 200 * PICA - 5 * PICA); + }); + + This::execute_with(|| { + let balance = this_runtime::Assets::free_balance(CurrencyId::PICA, &AccountId::from(BOB)); + assert_eq_error_rate!(balance, 5 * PICA, (UnitWeightCost::get() * 10) as u128); + + assert_ok!(XTokens::transfer( + Origin::signed(BOB.into()), + foreign_asset, + PICA, + Box::new( + MultiLocation::new( + 1, + X2( + Parachain(SIBLING_PARA_ID), + Junction::AccountId32 { network: NetworkId::Any, id: ALICE.into() } + ) + ) + .into() + ), + 1_000_000_000, + )); + + let balance = this_runtime::Assets::free_balance(CurrencyId::PICA, &AccountId::from(BOB)); + assert_eq_error_rate!(balance, 5 * PICA - PICA, (UnitWeightCost::get() * 10) as u128); + }); + + Sibling::execute_with(|| { + assert_eq!(Balances::free_balance(&picasso_reserve_account()), 5 * PICA); + let balance = this_runtime::Assets::free_balance(CurrencyId::PICA, &AccountId::from(ALICE)); + assert_eq_error_rate!( + balance, + 200 * PICA - 5 * PICA + PICA, + (UnitWeightCost::get() * 10) as u128 + ); + }); + + Sibling::execute_with(|| { + assert_eq!(Balances::free_balance(&picasso_reserve_account()), 5 * PICA); + let balance = this_runtime::Assets::free_balance(CurrencyId::PICA, &AccountId::from(ALICE)); + assert_eq_error_rate!( + balance, + 200 * PICA - 5 * PICA + PICA, + (UnitWeightCost::get() * 10) as u128 + ); + + assert_ok!(XTokens::transfer( + Origin::signed(ALICE.into()), + CurrencyId::PICA, + 5 * PICA, + Box::new( + MultiLocation::new( + 1, + X2( + Parachain(THIS_PARA_ID), + Junction::AccountId32 { network: NetworkId::Any, id: BOB.into() } + ) + ) + .into() + ), + 1_000_000_000, + )); + + assert_eq!(Balances::free_balance(&picasso_reserve_account()), 10 * PICA); + let balance = this_runtime::Assets::free_balance(CurrencyId::PICA, &AccountId::from(ALICE)); + assert_eq_error_rate!( + balance, + 200 * PICA - 5 * PICA + PICA - 5 * PICA, + (UnitWeightCost::get() * 10) as u128 + ); + }); + + This::execute_with(|| { + let balance = this_runtime::Assets::free_balance(CurrencyId::PICA, &AccountId::from(BOB)); + assert_eq_error_rate!( + balance, + 5 * PICA - PICA + 5 * PICA, + (UnitWeightCost::get() * 10) as u128 + ); + }); +} + +#[test] +fn unspent_xcm_fee_is_returned_correctly() { + let parachain_account: AccountId = + This::execute_with(|| this_runtime::ParachainInfo::parachain_id().into_account()); + let some_account: AccountId = AccountId::from(CHARLIE); + + KusamaRelay::execute_with(|| { + assert_ok!(kusama_runtime::Balances::transfer( + kusama_runtime::Origin::signed(ALICE.into()), + MultiAddress::Id(some_account.clone()), + 1_000 * CurrencyId::unit::() + )); + assert_ok!(kusama_runtime::Balances::transfer( + kusama_runtime::Origin::signed(ALICE.into()), + MultiAddress::Id(parachain_account.clone()), + 1_000 * CurrencyId::unit::() + )); + assert_eq!( + kusama_runtime::Balances::free_balance(&AccountId::from(ALICE)), + 2 * CurrencyId::unit::() + ); + assert_eq!( + kusama_runtime::Balances::free_balance(&some_account), + 1_000 * CurrencyId::unit::() + ); + assert_eq!(kusama_runtime::Balances::free_balance(&AccountId::from(BOB)), 0); + assert_eq!( + kusama_runtime::Balances::free_balance(¶chain_account.clone()), + 1_010 * CurrencyId::unit::() + ); + }); + + This::execute_with(|| { + // Construct a transfer XCM call with returning the deposit + let transfer_call = crate::relaychain::balances_transfer_keep_alive::( + AccountId::from(BOB), + CurrencyId::unit(), + ); + let batch_call = crate::relaychain::utility_as_derivative_call::(transfer_call, 0); + let weight = 10_000_000_000; // Fee to transfer into the hold register + let asset = MultiAsset { + id: Concrete(MultiLocation::here()), + fun: Fungibility::Fungible(CurrencyId::unit()), + }; + let xcm_msg = Xcm(vec![ + WithdrawAsset(asset.clone().into()), + BuyExecution { fees: asset, weight_limit: Unlimited }, + Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: weight, + call: batch_call.encode().into(), + }, + ]); + + let res = this_runtime::RelayerXcm::send_xcm(Here, Parent, xcm_msg); + assert!(res.is_ok()); + }); + + KusamaRelay::execute_with(|| { + // 1 dollar is transferred to BOB + assert_eq!( + kusama_runtime::Balances::free_balance(&some_account), + 1000 * CurrencyId::unit::() + ); + // ISSUE: ported from Acala, not clear how BOB at all got s amount as we never transfer that + // there is no transfer of KSM at all + // assert_eq!( + // kusama_runtime::Balances::free_balance(&AccountId::from(BOB)), + // CurrencyId::unit::() + // ); + // 1 dollar is given to Hold Register for XCM call and never returned. + assert_eq!( + kusama_runtime::Balances::free_balance(¶chain_account.clone()), + 1_009 * CurrencyId::unit::() + ); + }); + + This::execute_with(|| { + // Construct a transfer using the RelaychainCallBuilder + let transfer_call = crate::relaychain::balances_transfer_keep_alive::( + AccountId::from(BOB), + CurrencyId::unit(), + ); + let batch_call = crate::relaychain::utility_as_derivative_call::(transfer_call, 0); + let finalized_call = crate::relaychain::finalize_call_into_xcm_message::( + batch_call, + CurrencyId::unit(), + 10_000_000_000, + ); + + let res = this_runtime::RelayerXcm::send_xcm(Here, Parent, finalized_call); + assert!(res.is_ok()); + }); + + KusamaRelay::execute_with(|| { + // 1 dollar is transferred to BOB + assert_eq!( + kusama_runtime::Balances::free_balance(&some_account), + 1_000 * CurrencyId::unit::() + ); + // ISSUE: ported from Acala, not clear how BOB at all got s amount as we never transfer that + // there is no transfer of KSM at all + // assert_eq!( + // kusama_runtime::Balances::free_balance(&AccountId::from(BOB)), + // 2 * CurrencyId::unit::() + // ); + // Unspent fund from the 1 dollar XCM fee is returned to the sovereign account. + assert_eq!( + kusama_runtime::Balances::free_balance(¶chain_account.clone()), + 1_000 * CurrencyId::unit::() + 8_999_626_666_690 + ); + }); +} + +// from Acala +#[test] +fn trap_assets_larger_than_ed_works() { + simtest(); + + let mut native_treasury_amount = 0; + let (ksm_asset_amount, native_asset_amount) = + (3 * CurrencyId::unit::(), 2 * CurrencyId::unit::()); + let parent_account: AccountId = ParentIsPreset::::convert(Parent.into()).unwrap(); + This::execute_with(|| { + assert_ok!(Tokens::deposit( + CurrencyId::KSM, + &parent_account, + 42 * CurrencyId::unit::() + )); + let _ = + as support::traits::Currency>::deposit_creating( + &parent_account, + 123 * CurrencyId::unit::(), + ); + // TODO: if we do not top up account initially, than any depositn_creating do not create + // anything may be somethign with zero block or like - fix it better way + let _ = + as support::traits::Currency>::deposit_creating( + &this_runtime::TreasuryAccount::get(), + 7 * CurrencyId::unit::(), + ); + + native_treasury_amount = + Assets::free_balance(CurrencyId::PICA, &this_runtime::TreasuryAccount::get()); + }); + + let assets: MultiAsset = (Parent, ksm_asset_amount).into(); + KusamaRelay::execute_with(|| { + let xcm = vec![ + WithdrawAsset(assets.clone().into()), + BuyExecution { + fees: assets, + weight_limit: Limited(CurrencyId::unit::() as u64), + }, + WithdrawAsset(((0, GeneralKey(CurrencyId::PICA.encode())), native_asset_amount).into()), + ]; + assert_ok!(pallet_xcm::Pallet::::send_xcm( + Here, + Parachain(THIS_PARA_ID).into(), + Xcm(xcm), + )); + }); + + This::execute_with(|| { + assert_eq!( + 3 * CurrencyId::unit::(), + Assets::free_balance(CurrencyId::KSM, &this_runtime::TreasuryAccount::get()) + ); + log::error!("{:?}", &this_runtime::TreasuryAccount::get()); + assert_eq!( + native_asset_amount, + this_runtime::Balances::free_balance(&this_runtime::TreasuryAccount::get()) - + 7 * CurrencyId::unit::(), + ); + }); +} + +// from Acala +#[test] +fn trap_assets_lower_than_existential_deposit_works() { + simtest(); + + let other_non_native_amount = 1_000_000_000_000; + let some_native_amount = 1_000_000_000_000_000; + let any_asset = CurrencyId::KSM; + let this_native_asset = CurrencyId::PICA; + + let parent_account: AccountId = ParentIsPreset::::convert(Parent.into()).unwrap(); + + let (this_treasury_amount, other_treasury_amount) = This::execute_with(|| { + assert_ok!(Assets::deposit(any_asset, &parent_account, other_non_native_amount)); + let _ = >::deposit_creating( + &parent_account, + some_native_amount, + ); + ( + >::free_balance( + this_native_asset, + &this_runtime::TreasuryAccount::get(), + ), + >::free_balance( + any_asset, + &this_runtime::TreasuryAccount::get(), + ), + ) + }); + + let assets: MultiAsset = (Parent, other_non_native_amount).into(); + KusamaRelay::execute_with(|| { + let xcm = vec![ + WithdrawAsset(assets.clone().into()), + BuyExecution { fees: assets, weight_limit: Limited(other_non_native_amount as u64) }, + WithdrawAsset( + ( + (Parent, X2(Parachain(THIS_PARA_ID), GeneralKey(this_native_asset.encode()))), + some_native_amount, + ) + .into(), + ), + //two asset left in holding register, they both lower than ED, so goes to treasury. + ]; + assert_ok!(pallet_xcm::Pallet::::send_xcm( + Here, + Parachain(THIS_PARA_ID).into(), + Xcm(xcm), + )); + }); + + This::execute_with(|| { + assert_eq!( + System::events().iter().find(|r| matches!( + r.event, + this_runtime::Event::RelayerXcm(pallet_xcm::Event::AssetsTrapped(_, _, _)) + )), + None + ); + + assert_eq!( + some_native_amount, + >::free_balance( + this_native_asset, + &this_runtime::TreasuryAccount::get() + ) - this_treasury_amount + ); + + assert_eq!( + other_non_native_amount, + >::free_balance( + any_asset, + &this_runtime::TreasuryAccount::get() + ) - other_treasury_amount + ); + }); +} + +// From Acala +#[test] +fn sibling_trap_assets_works() { + simtest(); + + let any_asset = CurrencyId::kUSD; + // TODO: create foregn asset via factory + // TODO: set key for it to allow transfer + // TODO: parametriz test. ISSUE: how to solve DEX swap paying for transfer? + let sibling_non_native_amount = assert_above_deposit(any_asset, 100_000_000_000); + let some_native_amount = 1_000_000_000; + let this_liveness_native_amount = enough_weigth(); + let this_native_asset = CurrencyId::PICA; + + let this_native_treasury_amount = This::execute_with(|| { + assert_ok!(Assets::deposit(any_asset, &sibling_account(), sibling_non_native_amount)); + let _ = + as support::traits::Currency>::deposit_creating( + &sibling_account(), + this_liveness_native_amount, + ); + let _ = + as support::traits::Currency>::deposit_creating( + &this_runtime::TreasuryAccount::get(), + this_liveness_native_amount, + ); + as support::traits::Currency>::free_balance( + &this_runtime::TreasuryAccount::get(), + ) + }); + + let remote = composable_traits::assets::XcmAssetLocation(MultiLocation::new( + 1, + X2(Parachain(SIBLING_PARA_ID), GeneralKey(any_asset.encode())), + )); + + This::execute_with(|| { + assert_ok!(this_runtime::AssetsRegistry::set_location(any_asset, remote,)); + }); + + // buy execution via native token, and try withdraw on this some amount + Sibling::execute_with(|| { + let assets: MultiAsset = ( + (Parent, X2(Parachain(THIS_PARA_ID), GeneralKey(this_native_asset.encode()))), + some_native_amount, + ) + .into(); + let xcm = vec![ + WithdrawAsset(assets.clone().into()), /* withdrow native on target chain from origin + * account */ + BuyExecution { + // pay for origin account + fees: assets, + weight_limit: Unlimited, + }, + WithdrawAsset( + ( + (Parent, X2(Parachain(SIBLING_PARA_ID), GeneralKey(any_asset.encode()))), + sibling_non_native_amount, + ) // withdraw into VM holder asset, and do nothing... + .into(), + ), + ]; + assert_ok!(pallet_xcm::Pallet::::send_xcm( + Here, + (Parent, Parachain(THIS_PARA_ID)), + Xcm(xcm), + )); + }); + + This::execute_with(|| { + assert_eq!( + System::events().iter().find(|r| matches!( + r.event, + this_runtime::Event::RelayerXcm(pallet_xcm::Event::AssetsTrapped(_, _, _)) + )), + None // non of assets trapped by hash, because all are known + ); + assert_eq!( + this_runtime::Assets::free_balance(any_asset, &this_runtime::TreasuryAccount::get()), + sibling_non_native_amount + ); + + assert_eq!( + this_runtime::Balances::free_balance(&this_runtime::TreasuryAccount::get()), + some_native_amount + this_native_treasury_amount, + ); + }); +} diff --git a/integration-tests/local-integration-tests/src/helpers.rs b/integration-tests/local-integration-tests/src/helpers.rs new file mode 100644 index 00000000000..fe7d3d3e47c --- /dev/null +++ b/integration-tests/local-integration-tests/src/helpers.rs @@ -0,0 +1,59 @@ +use common::{xcmp::BaseXcmWeight, AccountId, Balance, MultiExistentialDeposits}; +use cumulus_primitives_core::ParaId; + +use num_traits::One; +use orml_traits::GetByKey; +use primitives::currency::CurrencyId; +use sp_runtime::traits::AccountIdConversion; +use support::log; + +use crate::{env_logger_init, kusama_test_net::SIBLING_PARA_ID, prelude::*}; + +// TODO: make marco of it +pub fn simtest() { + crate::kusama_test_net::KusamaNetwork::reset(); + env_logger_init(); +} + +/// create account ids from test paraid +pub fn para_account_id(id: u32) -> AccountId { + ParaId::from(id).into_account() +} + +/// under ED, but above Weight +pub fn under_existential_deposit(asset_id: LocalAssetId, _instruction_count: usize) -> Balance { + MultiExistentialDeposits::get(&asset_id).saturating_sub(Balance::one()) +} + +/// dumps events for debugging +#[allow(dead_code)] +pub fn dump_events() { + sibling_runtime::System::events().iter().for_each(|x| { + log::info!("{:?}", x); + }); +} + +/// dumps events for debugging +#[allow(dead_code)] +pub fn relay_dump_events() { + kusama_runtime::System::events().iter().for_each(|x| { + log::info!("{:?}", x); + }); +} + +pub fn sibling_account() -> AccountId { + polkadot_parachain::primitives::Sibling::from(SIBLING_PARA_ID).into_account() +} + +/// assert amount is supported deposit amount and is above it +pub fn assert_above_deposit(asset_id: CurrencyId, amount: Balance) -> Balance { + assert!(MultiExistentialDeposits::get(&asset_id) <= amount); + amount +} + +/// weigh enough to handle any XCMP message +pub fn enough_weigth() -> u128 { + let this_liveness_native_amount = BaseXcmWeight::get() as u128 + + 100 * UnitWeightCost::get() as Balance * MaxInstructions::get() as Balance; + this_liveness_native_amount +} diff --git a/integration-tests/src/kusama_test_net.rs b/integration-tests/local-integration-tests/src/kusama_test_net.rs similarity index 76% rename from integration-tests/src/kusama_test_net.rs rename to integration-tests/local-integration-tests/src/kusama_test_net.rs index 4732874547c..0fda874e06c 100644 --- a/integration-tests/src/kusama_test_net.rs +++ b/integration-tests/local-integration-tests/src/kusama_test_net.rs @@ -1,7 +1,17 @@ //! Setup of Picasso running as if it is on Kusama relay use common::AccountId; use cumulus_primitives_core::ParaId; -use dali_runtime as picasso_runtime; + +#[cfg(feature = "dali")] +use dali_runtime as sibling_runtime; +#[cfg(feature = "dali")] +use dali_runtime as other_runtime; + +#[cfg(feature = "picasso")] +use picasso_runtime as sibling_runtime; +#[cfg(feature = "picasso")] +use picasso_runtime as other_runtime; + use polkadot_primitives::v1::{BlockNumber, MAX_CODE_SIZE, MAX_POV_SIZE}; use polkadot_runtime_parachains::configuration::HostConfiguration; use primitives::currency::CurrencyId; @@ -10,60 +20,69 @@ use support::traits::GenesisBuild; use xcm_emulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain}; type Balances = u128; + pub const ALICE: [u8; 32] = [4_u8; 32]; pub const BOB: [u8; 32] = [5_u8; 32]; +pub const CHARLIE: [u8; 32] = [6_u8; 32]; + pub const PICA: Balances = 1_000_000_000_000; +pub const KSM: Balances = PICA / 50; decl_test_parachain! { - pub struct Picasso { - Runtime = picasso_runtime::Runtime, - Origin = picasso_runtime::Origin, - new_ext = picasso_ext(PICASSO_PARA_ID), + pub struct This { + Runtime = sibling_runtime::Runtime, + Origin = sibling_runtime::Origin, + XcmpMessageHandler = sibling_runtime::XcmpQueue, + DmpMessageHandler = sibling_runtime::DmpQueue, + new_ext = picasso_ext(THIS_PARA_ID), } } // we use picasso as test, need to test out transfer // and then decide how to imitate hydra decl_test_parachain! { - pub struct Dali { - Runtime = dali_runtime::Runtime, - Origin = dali_runtime::Origin, - new_ext = picasso_ext(DALI_PARA_ID), + pub struct Sibling { + Runtime = other_runtime::Runtime, + Origin = other_runtime::Origin, + XcmpMessageHandler = other_runtime::XcmpQueue, + DmpMessageHandler = other_runtime::DmpQueue, + new_ext = picasso_ext(SIBLING_PARA_ID), } } decl_test_relay_chain! { pub struct KusamaRelay { Runtime = kusama_runtime::Runtime, - XcmConfig = kusama_runtime::XcmConfig, + XcmConfig = kusama_runtime::xcm_config::XcmConfig, new_ext = kusama_ext(), } } // keep in sync with parachains, as macro does not allows for names -pub const PICASSO_PARA_ID: u32 = 2000; -pub const DALI_PARA_ID: u32 = 3000; +pub const THIS_PARA_ID: u32 = 2000; +pub const SIBLING_PARA_ID: u32 = 3000; decl_test_network! { pub struct KusamaNetwork { relay_chain = KusamaRelay, parachains = vec![ - (2000, Picasso), - (3000, Dali), + (2000, This), + (3000, Sibling), ], } } fn default_parachains_host_configuration() -> HostConfiguration { HostConfiguration { - validation_upgrade_frequency: 1_u32, - validation_upgrade_delay: 1, + validation_upgrade_cooldown: 1_u32, + validation_upgrade_delay: 5, code_retention_period: 1200, max_code_size: MAX_CODE_SIZE, max_pov_size: MAX_POV_SIZE, max_head_data_size: 32 * 1024, group_rotation_frequency: 20, chain_availability_period: 4, + minimum_validation_upgrade_delay: 5, thread_availability_period: 4, max_upward_queue_count: 8, max_upward_queue_size: 1024 * 1024, @@ -97,10 +116,11 @@ pub const PICASSO_RELAY_BALANCE: u128 = 10 * PICA; pub fn kusama_ext() -> sp_io::TestExternalities { use kusama_runtime::{Runtime, System}; let mut storage = frame_system::GenesisConfig::default().build_storage::().unwrap(); + // TODO: remove implicit assets and mint these directly in test balances::GenesisConfig:: { balances: vec![ (AccountId::from(ALICE), ALICE_RELAY_BALANCE), - (ParaId::from(PICASSO_PARA_ID).into_account(), PICASSO_RELAY_BALANCE), + (ParaId::from(THIS_PARA_ID).into_account(), PICASSO_RELAY_BALANCE), ], } .assimilate_storage(&mut storage) @@ -128,7 +148,7 @@ pub const ALICE_PARACHAIN_KSM: u128 = 13 * 1_000_000_000_000; pub fn picasso_ext(parachain_id: u32) -> sp_io::TestExternalities { let parachain_id = parachain_id.into(); - use dali_runtime::{Runtime, System}; + use sibling_runtime::{Runtime, System}; let mut storage = frame_system::GenesisConfig::default().build_storage::().unwrap(); balances::GenesisConfig:: { balances: vec![(AccountId::from(ALICE), ALICE_PARACHAIN_BALANCE)], @@ -141,6 +161,7 @@ pub fn picasso_ext(parachain_id: u32) -> sp_io::TestExternalities { &mut storage, ) .unwrap(); + // TODO: remove implicit assets and mint these directly in test orml_tokens::GenesisConfig:: { balances: vec![ (AccountId::from(ALICE), CurrencyId::PICA, ALICE_PARACHAIN_PICA), diff --git a/integration-tests/local-integration-tests/src/lib.rs b/integration-tests/local-integration-tests/src/lib.rs new file mode 100644 index 00000000000..ead5451f6f2 --- /dev/null +++ b/integration-tests/local-integration-tests/src/lib.rs @@ -0,0 +1,58 @@ +#![cfg_attr( + not(any(test, feature = "runtime-benchmarks")), + deny( + clippy::disallowed_method, + clippy::disallowed_type, + clippy::indexing_slicing, + clippy::todo, + clippy::unwrap_used, + clippy::panic + ) +)] // allow in tests +#![warn(clippy::unseparated_literal_suffix)] +#![cfg_attr(not(feature = "std"), no_std)] +#![deny( + unused_imports, + clippy::useless_conversion, + bad_style, + bare_trait_objects, + const_err, + improper_ctypes, + non_shorthand_field_patterns, + no_mangle_generic_items, + overflowing_literals, + path_statements, + patterns_in_fns_without_body, + private_in_public, + unconditional_recursion, + unused_allocation, + unused_comparisons, + unused_parens, + while_true, + trivial_casts, + trivial_numeric_casts, + unused_extern_crates +)] + +/// this must be singleton +#[cfg(test)] +pub fn env_logger_init() { + let _ = env_logger::builder().is_test(true).try_init(); +} + +#[cfg(test)] +mod kusama_test_net; + +#[cfg(test)] +mod xcm_tests; + +#[cfg(test)] +mod cross_chain_transfer; + +#[cfg(test)] +mod runtime_tests; + +#[cfg(test)] +mod helpers; +pub mod prelude; +mod relaychain; diff --git a/integration-tests/local-integration-tests/src/prelude.rs b/integration-tests/local-integration-tests/src/prelude.rs new file mode 100644 index 00000000000..af7e7a1700d --- /dev/null +++ b/integration-tests/local-integration-tests/src/prelude.rs @@ -0,0 +1,26 @@ +//! prelude for pallet Rust level work (not low level storage code neither for IPC calls) +pub use codec::{Decode, Encode}; +pub use frame_system::{pallet_prelude::*, Config}; +use primitives::currency::CurrencyId; +pub use support::RuntimeDebug; + +/// just making it easier to refactor generalized code +pub type LocalAssetId = CurrencyId; + +#[cfg(feature = "dali")] +pub use dali_runtime as this_runtime; + +#[cfg(feature = "dali")] +pub use dali_runtime as sibling_runtime; + +#[cfg(feature = "dali")] +pub use dali_runtime::{MaxInstructions, UnitWeightCost, Weight, XcmConfig}; + +#[cfg(feature = "picasso")] +pub use picasso_runtime as this_runtime; + +#[cfg(feature = "picasso")] +pub use picasso_runtime as sibling_runtime; + +#[cfg(feature = "picasso")] +pub use picasso_runtime::{MaxInstructions, UnitWeightCost, Weight, XcmConfig}; diff --git a/integration-tests/local-integration-tests/src/relaychain.rs b/integration-tests/local-integration-tests/src/relaychain.rs new file mode 100644 index 00000000000..3f69afb6a40 --- /dev/null +++ b/integration-tests/local-integration-tests/src/relaychain.rs @@ -0,0 +1,100 @@ +//! utilities to work with relay chain and XCM transact calls into it + +use self::kusama::RelayChainCall; +use crate::prelude::*; +use common::Balance; + +use support::RuntimeDebug; +use xcm::latest::{ + prelude::*, Junction::Parachain, Junctions::X1, MultiAsset, MultiLocation, OriginKind, + WeightLimit::Unlimited, Xcm, +}; + +use frame_system::Config; +use sp_runtime::traits::StaticLookup; + +pub type RelayBalance = u64; + +#[derive(Encode, Decode, RuntimeDebug)] +pub enum BalancesCall { + #[codec(index = 3)] + TransferKeepAlive(::Source, #[codec(compact)] RelayBalance), +} + +#[derive(Encode, Decode, RuntimeDebug)] +pub enum UtilityCall { + #[codec(index = 1)] + AsDerivative(u16, RelayChainCall), + #[codec(index = 2)] + BatchAll(Vec), +} + +mod kusama { + use crate::*; + use prelude::*; + + use super::{BalancesCall, UtilityCall}; + /// The encoded index correspondes to Kusama's Runtime module configuration. + /// https://github.com/paritytech/polkadot/blob/main/runtime/kusama/src/lib.rs#L1379 + #[derive(Encode, Decode, RuntimeDebug)] + pub enum RelayChainCall { + #[codec(index = 4)] + Balances(BalancesCall), + #[codec(index = 24)] + Utility(Box>), + } +} + +/// Transfer Staking currency to another account, disallowing "death". +/// params: +/// - to: The destination for the transfer +/// - amount: The amount of staking currency to be transferred. +pub fn balances_transfer_keep_alive( + to: T::AccountId, + amount: RelayBalance, +) -> RelayChainCall { + RelayChainCall::Balances(BalancesCall::TransferKeepAlive(T::Lookup::unlookup(to), amount)) +} + +/// Execute a call, replacing the `Origin` with a sub-account. +/// params: +/// - call: The call to be executed. Can be nested with `utility_batch_call` +/// - index: The index of sub-account to be used as the new origin. +pub fn utility_as_derivative_call( + call: RelayChainCall, + index: u16, +) -> RelayChainCall { + RelayChainCall::Utility(Box::new(UtilityCall::AsDerivative(index, call))) +} + +/// Wrap the final calls into the Xcm format. +/// params: +/// - call: The call to be executed +/// - extra_fee: Extra fee (in staking currency) used for buy the `weight` and `debt`. +/// - weight: the weight limit used for XCM. +/// - debt: the weight limit used to process the `call`. +pub fn finalize_call_into_xcm_message( + call: RelayChainCall, + extra_fee: Balance, + weight: Weight, +) -> Xcm<()> { + let asset = + MultiAsset { id: Concrete(MultiLocation::here()), fun: Fungibility::Fungible(extra_fee) }; + Xcm(vec![ + WithdrawAsset(asset.clone().into()), + BuyExecution { fees: asset, weight_limit: Unlimited }, + Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: weight, + call: call.encode().into(), + }, + DepositAsset { + assets: All.into(), + max_assets: u32::max_value(), + beneficiary: MultiLocation { + parents: 0, + interior: X1(Parachain(sibling_runtime::ParachainInfo::parachain_id().into())), + }, + }, + ]) +} diff --git a/integration-tests/src/runtime_tests.rs b/integration-tests/local-integration-tests/src/runtime_tests.rs similarity index 73% rename from integration-tests/src/runtime_tests.rs rename to integration-tests/local-integration-tests/src/runtime_tests.rs index 4815c69e730..9f1240bc489 100644 --- a/integration-tests/src/runtime_tests.rs +++ b/integration-tests/local-integration-tests/src/runtime_tests.rs @@ -3,6 +3,7 @@ use crate::{ env_logger_init, kusama_test_net::{KusamaNetwork, *}, + prelude::*, }; use cumulus_primitives_core::{ChannelStatus, GetChannelInfo, ParaId}; use xcm_emulator::TestExt; @@ -12,8 +13,8 @@ use xcm_emulator::TestExt; fn channel_to_relay() { env_logger_init(); KusamaNetwork::reset(); - Picasso::execute_with(|| { - let status = ::get_channel_status( + This::execute_with(|| { + let status = ::get_channel_status( ParaId::new(2090), ); assert!(matches!(status, ChannelStatus::Closed)); @@ -25,9 +26,9 @@ fn channel_to_relay() { fn channel_to_self() { env_logger_init(); KusamaNetwork::reset(); - Picasso::execute_with(|| { - let status = ::get_channel_status( - ParaId::new(PICASSO_PARA_ID), + This::execute_with(|| { + let status = ::get_channel_status( + ParaId::new(THIS_PARA_ID), ); assert!(matches!(status, ChannelStatus::Ready(_, _))); }); @@ -38,9 +39,9 @@ fn channel_to_self() { fn channel_to_parachain() { env_logger_init(); KusamaNetwork::reset(); - Picasso::execute_with(|| { - let status = ::get_channel_status( - ParaId::new(DALI_PARA_ID), + This::execute_with(|| { + let status = ::get_channel_status( + ParaId::new(SIBLING_PARA_ID), ); assert!(matches!(status, ChannelStatus::Ready(_, _))); diff --git a/integration-tests/local-integration-tests/src/transact_calls.rs b/integration-tests/local-integration-tests/src/transact_calls.rs new file mode 100644 index 00000000000..e56fffa9794 --- /dev/null +++ b/integration-tests/local-integration-tests/src/transact_calls.rs @@ -0,0 +1,6 @@ +// TODO: in Acala they have huge binary transact surfcae in relay_chain.rs +// for us may be relevant : +// bonded pallet call +// dex call(actually router call, actually basis for future dex liqudation) +// liqudation call +// lending call diff --git a/integration-tests/src/xcm_tests.rs b/integration-tests/local-integration-tests/src/xcm_tests.rs similarity index 59% rename from integration-tests/src/xcm_tests.rs rename to integration-tests/local-integration-tests/src/xcm_tests.rs index 58b8fc7cfb8..45bb14bdb89 100644 --- a/integration-tests/src/xcm_tests.rs +++ b/integration-tests/local-integration-tests/src/xcm_tests.rs @@ -2,18 +2,10 @@ //! Cumulus/ORML abstractions) Partially ported from articles and examples of https://github.com/paritytech/polkadot/blob/master/xcm/xcm-simulator/example/src/lib.rs //! Cannot port QueryHold because it is not implemented -use crate::{ - env_logger_init, - kusama_test_net::{KusamaNetwork, *}, -}; -use codec::Encode; -use common::AccountId; +use crate::{helpers::*, kusama_test_net::*, prelude::*}; use composable_traits::assets::{RemoteAssetRegistry, XcmAssetLocation}; -use cumulus_primitives_core::ParaId; -use dali_runtime as picasso_runtime; -use kusama_runtime::*; + use primitives::currency::CurrencyId; -use sp_runtime::traits::AccountIdConversion; use support::assert_ok; use xcm::latest::prelude::*; use xcm_emulator::TestExt; @@ -24,15 +16,11 @@ fn buy_execution(fees: impl Into) -> Instruction { BuyExecution { fees: fees.into(), weight_limit: Unlimited } } -pub fn para_account_id(id: u32) -> AccountId { - ParaId::from(id).into_account() -} - /// as per documentation is way to throw exception with specific error code as Trap, and that should /// be handled #[test] fn throw_exception() { - Picasso::execute_with(|| { + This::execute_with(|| { let here = MultiLocation::new(0, Here); let xcm = Xcm(vec![Trap(42)]); @@ -49,10 +37,9 @@ fn throw_exception() { /// this is low levl #[test] fn initiate_reserver_withdraw_on_relay() { - crate::kusama_test_net::KusamaNetwork::reset(); - env_logger_init(); - Picasso::execute_with(|| { - assert_ok!(::set_location( + simtest(); + This::execute_with(|| { + assert_ok!(::set_location( CurrencyId::KSM, XcmAssetLocation::RELAY_NATIVE, )); @@ -76,10 +63,12 @@ fn initiate_reserver_withdraw_on_relay() { xcm: Xcm(vec![]), }, ]); + let units = xcm.len() as u64; + + let executed = ::XcmExecutor::execute_xcm_in_credit(origin, xcm, 10000000000, 10000000000); - let executed = ::XcmExecutor::execute_xcm_in_credit(origin, xcm, 10000000000, 10000000000); match executed { - Outcome::Complete(0) => {}, + Outcome::Complete(weight) if weight == UnitWeightCost::get() * units => {}, _ => unreachable!("{:?}", executed), } }); @@ -87,54 +76,61 @@ fn initiate_reserver_withdraw_on_relay() { #[test] fn send_remark() { - KusamaNetwork::reset(); - - let remark = picasso_runtime::Call::System( - frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }, + simtest(); + let remark = this_runtime::Call::System( + frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }, ); - Picasso::execute_with(|| { - assert_ok!(picasso_runtime::RelayerXcm::send_xcm( + let execution = (UnitWeightCost::get() * 5) as u128; + This::execute_with(|| { + assert_ok!(this_runtime::RelayerXcm::send_xcm( Here, - (Parent, Parachain(DALI_PARA_ID)), - Xcm(vec![Transact { - origin_type: OriginKind::SovereignAccount, - require_weight_at_most: 40000, - call: remark.encode().into(), - }]), + (Parent, Parachain(SIBLING_PARA_ID)), + Xcm(vec![ + ReserveAssetDeposited((Parent, execution).into()), + BuyExecution { fees: (Parent, execution).into(), weight_limit: Unlimited }, + Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: execution as u64, + call: remark.encode().into(), + } + ]), )); }); - Dali::execute_with(|| { - use dali_runtime::{Event, System}; - assert!(System::events() - .iter() - .any(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _))))); + Sibling::execute_with(|| { + use sibling_runtime::{Event, System}; + assert!(System::events().iter().any(|r| matches!( + r.event, + Event::System(frame_system::Event::Remarked { sender: _, hash: _ }) + ))); }); } #[test] fn withdraw_and_deposit_back() { - KusamaNetwork::reset(); - env_logger_init(); + simtest(); let send_amount = 10; - Picasso::execute_with(|| { + This::execute_with(|| { let message = Xcm(vec![ WithdrawAsset((Here, send_amount).into()), buy_execution((Here, send_amount)), DepositAsset { assets: All.into(), max_assets: 1, - beneficiary: Parachain(PICASSO_PARA_ID).into(), + beneficiary: Parachain(THIS_PARA_ID).into(), }, ]); - assert_ok!(picasso_runtime::RelayerXcm::send_xcm(Here, Parent, message,)); + assert_ok!(this_runtime::RelayerXcm::send_xcm(Here, Parent, message,)); }); KusamaRelay::execute_with(|| { assert_eq!( - kusama_runtime::Balances::free_balance(para_account_id(PICASSO_PARA_ID)), + kusama_runtime::Balances::free_balance(para_account_id(THIS_PARA_ID)), PICASSO_RELAY_BALANCE - send_amount ); }); } + +#[test] +fn location_of_deposit_asset() {} diff --git a/integration-tests/local-integration-tests/xcmp.sequence.plantuml b/integration-tests/local-integration-tests/xcmp.sequence.plantuml new file mode 100644 index 00000000000..7b553fc000e --- /dev/null +++ b/integration-tests/local-integration-tests/xcmp.sequence.plantuml @@ -0,0 +1,11 @@ +@startuml +' pure Cumulus/Polkadot, not ORML flow +"cumulus:DmpMessageHandler" -> "cumulus:DmpMessageHandler": handle_dmp_messages +"cumulus:DmpMessageHandler" -> "cumulus:DmpMessageHandler": try_service_message +"cumulus:DmpMessageHandler" -> XcmExecutor: execute_xcm_in_credit +XcmExecutor -> Weigher : weight is computalbe and under limit +XcmExecutor -> Barrier : should execute +XcmExecutor -> vm : execute +XcmExecutor -> process_instruction: for each instruction in message +XcmExecutor -> vm : either accue weight while there are messages or call error handler +@enduml \ No newline at end of file diff --git a/integration-tests/runtime-tests/.mocharc.json b/integration-tests/runtime-tests/.mocharc.json index 2374a46832f..a70c8eb46b3 100644 --- a/integration-tests/runtime-tests/.mocharc.json +++ b/integration-tests/runtime-tests/.mocharc.json @@ -1,6 +1,6 @@ { "diff": true, - "extension": ["js", "cjs", "mjs"], + "inline-diffs": true, "package": "./package.json", "reporter": "mochawesome", "reporterOptions": { @@ -10,13 +10,15 @@ "html": true, "json": true }, - "slow": 75, + "slow": 600000, "timeout": 2000, "retries": 0, "ui": "bdd", - "watch-files": ["src/**/*.js", "src/**/*.ts"], + "trace-warnings": true, + "watch-files": ["src/**/*.ts"], "watch-ignore": ["lib/vendor"], - "require": "src/utils/testSetup.js", + "require": ["mochawesome/register", "src/utils/testSetup.ts"], "full-trace": true, - "parallel": false + "parallel": false, + "recursive": true } diff --git a/integration-tests/runtime-tests/DockerRun.sh b/integration-tests/runtime-tests/DockerRun.sh new file mode 100755 index 00000000000..ab039047cb3 --- /dev/null +++ b/integration-tests/runtime-tests/DockerRun.sh @@ -0,0 +1,3 @@ +#!/bin/bash +npm install +npm run test diff --git a/integration-tests/runtime-tests/README.md b/integration-tests/runtime-tests/README.md index e30a53cf6ff..bd4281c5c3c 100644 --- a/integration-tests/runtime-tests/README.md +++ b/integration-tests/runtime-tests/README.md @@ -4,13 +4,18 @@ Picasso Integration Tester is a collection of different implementation tests for ## Installation - ```bash $ npm ci ``` + ## Usage +### To run the fully automated test suite on Docker: +```bash +$ docker-compose up +``` + ### To run the devnet dummy data initializer ```bash $ npm run init @@ -26,11 +31,11 @@ $ npm run test $ npm run gen ``` +### If you want to check for dependency updates: +```bash +$ npm run check_dep_updates +``` -## ToDo: -* Add all general test cases. -* Add non-conventional test cases. -* Enhance code documentation. ## Contributing @@ -50,15 +55,8 @@ e.g. describe('Imaginary Test', function () { // Timeout set to 2 minutes this.timeout(2*60*1000); // <-- - it('Imaginary test part', async (done) => { - // Test Stuff... + it('Imaginary test part', async function (done) { + // Test Stuff... }); }); ``` - - -## License -Temporary: -[GNU AGPLv3](https://choosealicense.com/licenses/agpl-3.0/) - -Final License TBD. diff --git a/integration-tests/runtime-tests/docker-compose.yml b/integration-tests/runtime-tests/docker-compose.yml new file mode 100644 index 00000000000..f3d869c1ce3 --- /dev/null +++ b/integration-tests/runtime-tests/docker-compose.yml @@ -0,0 +1,17 @@ +version: "3.9" + +services: + composable: + image: composablefi/composable-sandbox + ports: + - "9988:9988" + integration-tests: + image: node:bullseye + command: ./DockerRun.sh + working_dir: /code + volumes: + - .:/code + environment: + - ENDPOINT=composable:9988 + depends_on: + - composable diff --git a/integration-tests/runtime-tests/package-lock.json b/integration-tests/runtime-tests/package-lock.json index 882060b5329..439e9da0d6e 100644 --- a/integration-tests/runtime-tests/package-lock.json +++ b/integration-tests/runtime-tests/package-lock.json @@ -1,52 +1,65 @@ { "name": "picasso-integration-tester", - "version": "0.0.2", + "version": "1.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "picasso-integration-tester", - "version": "0.0.2", - "license": "GNU AGPLv3", + "version": "1.0.0", + "license": "Public Domain", "dependencies": { - "@polkadot/api": "^7.4.1", + "@polkadot/api": "^7.12.1", "@polkadot/ts": "^0.4.22", - "@polkadot/typegen": "^7.4.1", - "@polkadot/types": "^7.4.1", - "@polkadot/types-augment": "^7.4.1", - "@polkadot/types-codec": "^7.4.1", - "@polkadot/types-create": "^7.4.1", - "@polkadot/types-known": "^7.4.1", - "@polkadot/types-support": "^7.4.1", - "@types/mocha": "^9.0.0", - "@types/node": "^17.0.9", - "@types/ramda": "^0.27.64", - "chai": "^4.3.4", + "@polkadot/typegen": "^7.12.1", + "@polkadot/types": "^7.12.1", + "@polkadot/types-augment": "^7.12.1", + "@polkadot/types-codec": "^7.12.1", + "@polkadot/types-create": "^7.12.1", + "@polkadot/types-known": "^7.12.1", + "@polkadot/types-support": "^7.12.1", + "@types/mocha": "^9.1.0", + "@types/node": "^17.0.21", + "@types/ramda": "^0.28.1", + "chai": "^4.3.6", "chai-as-promised": "^7.1.1", + "chai-bn": "^0.3.1", "minimist": "^1.2.5", - "mocha": "^8.4.0", - "mochawesome": "^7.0.1", + "mocha": "^9.2.2", + "mochawesome": "^7.1.2", + "npm-check-updates": "^12.5.3", "ramda": "^0.28.0", - "tsconfig-paths": "^3.12.0", - "web3": "^1.7.0" + "web3": "^1.7.1" }, "devDependencies": { "@types/chai": "^4.3.0", "@types/minimist": "^1.2.2", - "@typescript-eslint/eslint-plugin": "^5.10.0", - "@typescript-eslint/parser": "^5.10.0", + "@typescript-eslint/eslint-plugin": "^5.15.0", + "@typescript-eslint/parser": "^5.15.0", "assert": "^2.0.0", - "eslint": "^8.7.0", + "eslint": "^8.11.0", "eslint-config-google": "^0.14.0", "mocha-prepare": "^0.1.0", - "ts-mocha": "^8.0.0", - "ts-node": "^10.4.0", - "typescript": "^4.5.4" + "ts-mocha": "^9.0.2", + "ts-node": "^10.7.0", + "tsconfig-paths": "^3.14.0", + "typescript": "^4.6.2" }, "engines": { "node": ">=12.0.0" } }, + "node_modules/@ampproject/remapping": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", + "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", @@ -59,33 +72,33 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.8.tgz", - "integrity": "sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz", + "integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.16.12", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.12.tgz", - "integrity": "sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.7.tgz", + "integrity": "sha512-djHlEfFHnSnTAcPb7dATbiM5HxGOP98+3JLBZtjRb5I7RXrw7kFRoG2dXM8cm3H+o11A8IFH/uprmJpwFynRNQ==", "dependencies": { + "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.16.8", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helpers": "^7.16.7", - "@babel/parser": "^7.16.12", + "@babel/generator": "^7.17.7", + "@babel/helper-compilation-targets": "^7.17.7", + "@babel/helper-module-transforms": "^7.17.7", + "@babel/helpers": "^7.17.7", + "@babel/parser": "^7.17.7", "@babel/template": "^7.16.7", - "@babel/traverse": "^7.16.10", - "@babel/types": "^7.16.8", + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.1.2", - "semver": "^6.3.0", - "source-map": "^0.5.0" + "semver": "^6.3.0" }, "engines": { "node": ">=6.9.0" @@ -109,20 +122,12 @@ "node": ">=6" } }, - "node_modules/@babel/core/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@babel/generator": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.8.tgz", - "integrity": "sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", + "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", "dependencies": { - "@babel/types": "^7.16.8", + "@babel/types": "^7.17.0", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, @@ -139,11 +144,11 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz", - "integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz", + "integrity": "sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==", "dependencies": { - "@babel/compat-data": "^7.16.4", + "@babel/compat-data": "^7.17.7", "@babel/helper-validator-option": "^7.16.7", "browserslist": "^4.17.5", "semver": "^6.3.0" @@ -213,29 +218,29 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz", - "integrity": "sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", + "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", "dependencies": { "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.16.7", + "@babel/helper-simple-access": "^7.17.7", "@babel/helper-split-export-declaration": "^7.16.7", "@babel/helper-validator-identifier": "^7.16.7", "@babel/template": "^7.16.7", - "@babel/traverse": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz", - "integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", + "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.17.0" }, "engines": { "node": ">=6.9.0" @@ -269,13 +274,13 @@ } }, "node_modules/@babel/helpers": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.7.tgz", - "integrity": "sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.7.tgz", + "integrity": "sha512-TKsj9NkjJfTBxM7Phfy7kv6yYc4ZcOo+AaWGqQOKTPDOmcGkIFb5xNA746eKisQkm4yavUYh4InYM9S+VnO01w==", "dependencies": { "@babel/template": "^7.16.7", - "@babel/traverse": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0" }, "engines": { "node": ">=6.9.0" @@ -359,9 +364,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.16.12", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.12.tgz", - "integrity": "sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.7.tgz", + "integrity": "sha512-bm3AQf45vR4gKggRfvJdYJ0gFLoCbsPxiFLSH6hTVYABptNHY6l9NrhnucVjQ/X+SPtLANT9lc0fFhikj+VBRA==", "bin": { "parser": "bin/babel-parser.js" }, @@ -370,14 +375,14 @@ } }, "node_modules/@babel/register": { - "version": "7.16.9", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.16.9.tgz", - "integrity": "sha512-jJ72wcghdRIlENfvALcyODhNoGE5j75cYHdC+aQMh6cU/P86tiiXTp9XYZct1UxUMo/4+BgQRyNZEGx0KWGS+g==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.17.7.tgz", + "integrity": "sha512-fg56SwvXRifootQEDQAu1mKdjh5uthPzdO0N6t358FktfL4XjAVXuH58ULoiW8mesxiOgNIrxiImqEwv0+hRRA==", "dependencies": { "clone-deep": "^4.0.1", "find-cache-dir": "^2.0.0", "make-dir": "^2.1.0", - "pirates": "^4.0.0", + "pirates": "^4.0.5", "source-map-support": "^0.5.16" }, "engines": { @@ -388,8 +393,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.16.7", - "license": "MIT", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.7.tgz", + "integrity": "sha512-L6rvG9GDxaLgFjg41K+5Yv9OMrU98sWe+Ykmc6FDJW/+vYZMhdOMKkISgzptMaERHvS2Y2lw9MDRm2gHhlQQoA==", "dependencies": { "regenerator-runtime": "^0.13.4" }, @@ -411,18 +417,18 @@ } }, "node_modules/@babel/traverse": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.10.tgz", - "integrity": "sha512-yzuaYXoRJBGMlBhsMJoUW7G1UmSb/eXr/JHYM/MsOJgavJibLwASijW7oXBdw3NQ6T0bW7Ty5P/VarOs9cHmqw==", + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", + "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", "dependencies": { "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.16.8", + "@babel/generator": "^7.17.3", "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-function-name": "^7.16.7", "@babel/helper-hoist-variables": "^7.16.7", "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.16.10", - "@babel/types": "^7.16.8", + "@babel/parser": "^7.17.3", + "@babel/types": "^7.17.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -430,18 +436,10 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/types": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.8.tgz", - "integrity": "sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", "dependencies": { "@babel/helper-validator-identifier": "^7.16.7", "to-fast-properties": "^2.0.0" @@ -472,15 +470,16 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "1.0.5", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", + "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", "dev": true, - "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.2.0", + "espree": "^9.3.1", "globals": "^13.9.0", - "ignore": "^4.0.6", + "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.0.4", @@ -490,30 +489,37 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "4.0.6", + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.13.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", + "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", "dev": true, - "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, "engines": { - "node": ">= 4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@ethereumjs/common": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.0.tgz", - "integrity": "sha512-Cq2qS0FTu6O2VU1sgg+WyU9Ps0M6j/BEMHN+hRaECXCV/r0aI78u4N6p52QW/BDVhwWZpCdrvG8X7NJdzlpNUA==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.2.tgz", + "integrity": "sha512-vDwye5v0SVeuDky4MtKsu+ogkH2oFUV8pBKzH/eNBzT8oI91pKa8WyzDuYuxOQsgNgv5R34LfFDh2aaw3H4HbQ==", "dependencies": { "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.3" + "ethereumjs-util": "^7.1.4" } }, "node_modules/@ethereumjs/tx": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.4.0.tgz", - "integrity": "sha512-WWUwg1PdjHKZZxPPo274ZuPsJCWV3SqATrEKQP1n2DrVYVP1aZIYpo/mFaA0BDoE0tIQmBeimRCEA0Lgil+yYw==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.5.0.tgz", + "integrity": "sha512-/+ZNbnJhQhXC83Xuvy6I9k4jT5sXiV0tMR9C+AzSSpcCV64+NB8dTE1m3x98RYMqb8+TLYWA+HML4F5lfXTlJw==", "dependencies": { - "@ethereumjs/common": "^2.6.0", - "ethereumjs-util": "^7.1.3" + "@ethereumjs/common": "^2.6.1", + "ethereumjs-util": "^7.1.4" } }, "node_modules/@ethersproject/abi": { @@ -533,9 +539,9 @@ } }, "node_modules/@ethersproject/abstract-provider": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.5.1.tgz", - "integrity": "sha512-m+MA/ful6eKbxpr99xUYeRvLkfnlqzrF8SZ46d/xFB1A7ZVknYc/sXJG0RcufF52Qn2jeFj1hhcoQ7IXjNKUqg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.6.0.tgz", + "integrity": "sha512-oPMFlKLN+g+y7a79cLK3WiLcjWFnZQtXWgnLAbHZcN3s7L4v90UHpTOrLk+m3yr0gt+/h9STTM6zrr7PM8uoRw==", "funding": [ { "type": "individual", @@ -547,19 +553,19 @@ } ], "dependencies": { - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/networks": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/transactions": "^5.5.0", - "@ethersproject/web": "^5.5.0" + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/networks": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/transactions": "^5.6.0", + "@ethersproject/web": "^5.6.0" } }, "node_modules/@ethersproject/abstract-signer": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.5.0.tgz", - "integrity": "sha512-lj//7r250MXVLKI7sVarXAbZXbv9P50lgmJQGr2/is82EwEb8r7HrxsmMqAjTsztMYy7ohrIhGMIml+Gx4D3mA==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.6.0.tgz", + "integrity": "sha512-WOqnG0NJKtI8n0wWZPReHtaLkDByPL67tn4nBaDAhmVq8sjHTPbCdz4DRhVu/cfTOvfy9w3iq5QZ7BX7zw56BQ==", "funding": [ { "type": "individual", @@ -571,17 +577,17 @@ } ], "dependencies": { - "@ethersproject/abstract-provider": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0" + "@ethersproject/abstract-provider": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0" } }, "node_modules/@ethersproject/address": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.5.0.tgz", - "integrity": "sha512-l4Nj0eWlTUh6ro5IbPTgbpT4wRbdH5l8CQf7icF7sb/SI3Nhd9Y9HzhonTSTi6CefI0necIw7LJqQPopPLZyWw==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.6.0.tgz", + "integrity": "sha512-6nvhYXjbXsHPS+30sHZ+U4VMagFC/9zAk6Gd/h3S21YW4+yfb0WfRtaAIZ4kfM4rrVwqiy284LP0GtL5HXGLxQ==", "funding": [ { "type": "individual", @@ -593,17 +599,17 @@ } ], "dependencies": { - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/keccak256": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/rlp": "^5.5.0" + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/rlp": "^5.6.0" } }, "node_modules/@ethersproject/base64": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.5.0.tgz", - "integrity": "sha512-tdayUKhU1ljrlHzEWbStXazDpsx4eg1dBXUSI6+mHlYklOXoXF6lZvw8tnD6oVaWfnMxAgRSKROg3cVKtCcppA==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.6.0.tgz", + "integrity": "sha512-2Neq8wxJ9xHxCF9TUgmKeSh9BXJ6OAxWfeGWvbauPh8FuHEjamgHilllx8KkSd5ErxyHIX7Xv3Fkcud2kY9ezw==", "funding": [ { "type": "individual", @@ -615,13 +621,13 @@ } ], "dependencies": { - "@ethersproject/bytes": "^5.5.0" + "@ethersproject/bytes": "^5.6.0" } }, "node_modules/@ethersproject/bignumber": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.5.0.tgz", - "integrity": "sha512-6Xytlwvy6Rn3U3gKEc1vP7nR92frHkv6wtVr95LFR3jREXiCPzdWxKQ1cx4JGQBXxcguAwjA8murlYN2TSiEbg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.6.0.tgz", + "integrity": "sha512-VziMaXIUHQlHJmkv1dlcd6GY2PmT0khtAqaMctCIDogxkrarMzA9L94KN1NeXqqOfFD6r0sJT3vCTOFSmZ07DA==", "funding": [ { "type": "individual", @@ -633,15 +639,20 @@ } ], "dependencies": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", "bn.js": "^4.11.9" } }, + "node_modules/@ethersproject/bignumber/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "node_modules/@ethersproject/bytes": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.5.0.tgz", - "integrity": "sha512-ABvc7BHWhZU9PNM/tANm/Qx4ostPGadAuQzWTr3doklZOhDlmcBqclrQe/ZXUIj3K8wC28oYeuRa+A37tX9kog==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.6.0.tgz", + "integrity": "sha512-3hJPlYemb9V4VLfJF5BfN0+55vltPZSHU3QKUyP9M3Y2TcajbiRrz65UG+xVHOzBereB1b9mn7r12o177xgN7w==", "funding": [ { "type": "individual", @@ -653,13 +664,13 @@ } ], "dependencies": { - "@ethersproject/logger": "^5.5.0" + "@ethersproject/logger": "^5.6.0" } }, "node_modules/@ethersproject/constants": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.5.0.tgz", - "integrity": "sha512-2MsRRVChkvMWR+GyMGY4N1sAX9Mt3J9KykCsgUFd/1mwS0UH1qw+Bv9k1UJb3X3YJYFco9H20pjSlOIfCG5HYQ==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.6.0.tgz", + "integrity": "sha512-SrdaJx2bK0WQl23nSpV/b1aq293Lh0sUaZT/yYKPDKn4tlAbkH96SPJwIhwSwTsoQQZxuh1jnqsKwyymoiBdWA==", "funding": [ { "type": "individual", @@ -671,13 +682,13 @@ } ], "dependencies": { - "@ethersproject/bignumber": "^5.5.0" + "@ethersproject/bignumber": "^5.6.0" } }, "node_modules/@ethersproject/hash": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.5.0.tgz", - "integrity": "sha512-dnGVpK1WtBjmnp3mUT0PlU2MpapnwWI0PibldQEq1408tQBAbZpPidkWoVVuNMOl/lISO3+4hXZWCL3YV7qzfg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.6.0.tgz", + "integrity": "sha512-fFd+k9gtczqlr0/BruWLAu7UAOas1uRRJvOR84uDf4lNZ+bTkGl366qvniUZHKtlqxBRU65MkOobkmvmpHU+jA==", "funding": [ { "type": "individual", @@ -689,20 +700,20 @@ } ], "dependencies": { - "@ethersproject/abstract-signer": "^5.5.0", - "@ethersproject/address": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/keccak256": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/strings": "^5.5.0" + "@ethersproject/abstract-signer": "^5.6.0", + "@ethersproject/address": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/strings": "^5.6.0" } }, "node_modules/@ethersproject/keccak256": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.5.0.tgz", - "integrity": "sha512-5VoFCTjo2rYbBe1l2f4mccaRFN/4VQEYFwwn04aJV2h7qf4ZvI2wFxUE1XOX+snbwCLRzIeikOqtAoPwMza9kg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.6.0.tgz", + "integrity": "sha512-tk56BJ96mdj/ksi7HWZVWGjCq0WVl/QvfhFQNeL8fxhBlGoP+L80uDCiQcpJPd+2XxkivS3lwRm3E0CXTfol0w==", "funding": [ { "type": "individual", @@ -714,14 +725,14 @@ } ], "dependencies": { - "@ethersproject/bytes": "^5.5.0", + "@ethersproject/bytes": "^5.6.0", "js-sha3": "0.8.0" } }, "node_modules/@ethersproject/logger": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.5.0.tgz", - "integrity": "sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.6.0.tgz", + "integrity": "sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg==", "funding": [ { "type": "individual", @@ -734,9 +745,9 @@ ] }, "node_modules/@ethersproject/networks": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.5.2.tgz", - "integrity": "sha512-NEqPxbGBfy6O3x4ZTISb90SjEDkWYDUbEeIFhJly0F7sZjoQMnj5KYzMSkMkLKZ+1fGpx00EDpHQCy6PrDupkQ==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.6.0.tgz", + "integrity": "sha512-DaVzgyThzHgSDLuURhvkp4oviGoGe9iTZW4jMEORHDRCgSZ9K9THGFKqL+qGXqPAYLEgZTf5z2w56mRrPR1MjQ==", "funding": [ { "type": "individual", @@ -748,13 +759,13 @@ } ], "dependencies": { - "@ethersproject/logger": "^5.5.0" + "@ethersproject/logger": "^5.6.0" } }, "node_modules/@ethersproject/properties": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.5.0.tgz", - "integrity": "sha512-l3zRQg3JkD8EL3CPjNK5g7kMx4qSwiR60/uk5IVjd3oq1MZR5qUg40CNOoEJoX5wc3DyY5bt9EbMk86C7x0DNA==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.6.0.tgz", + "integrity": "sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg==", "funding": [ { "type": "individual", @@ -766,13 +777,13 @@ } ], "dependencies": { - "@ethersproject/logger": "^5.5.0" + "@ethersproject/logger": "^5.6.0" } }, "node_modules/@ethersproject/rlp": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.5.0.tgz", - "integrity": "sha512-hLv8XaQ8PTI9g2RHoQGf/WSxBfTB/NudRacbzdxmst5VHAqd1sMibWG7SENzT5Dj3yZ3kJYx+WiRYEcQTAkcYA==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.6.0.tgz", + "integrity": "sha512-dz9WR1xpcTL+9DtOT/aDO+YyxSSdO8YIS0jyZwHHSlAmnxA6cKU3TrTd4Xc/bHayctxTgGLYNuVVoiXE4tTq1g==", "funding": [ { "type": "individual", @@ -784,14 +795,14 @@ } ], "dependencies": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0" + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0" } }, "node_modules/@ethersproject/signing-key": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.5.0.tgz", - "integrity": "sha512-5VmseH7qjtNmDdZBswavhotYbWB0bOwKIlOTSlX14rKn5c11QmJwGt4GHeo7NrL/Ycl7uo9AHvEqs5xZgFBTng==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.6.0.tgz", + "integrity": "sha512-S+njkhowmLeUu/r7ir8n78OUKx63kBdMCPssePS89So1TH4hZqnWFsThEd/GiXYp9qMxVrydf7KdM9MTGPFukA==", "funding": [ { "type": "individual", @@ -803,18 +814,23 @@ } ], "dependencies": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", "bn.js": "^4.11.9", "elliptic": "6.5.4", "hash.js": "1.1.7" } }, + "node_modules/@ethersproject/signing-key/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "node_modules/@ethersproject/strings": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.5.0.tgz", - "integrity": "sha512-9fy3TtF5LrX/wTrBaT8FGE6TDJyVjOvXynXJz5MT5azq+E6D92zuKNx7i29sWW2FjVOaWjAsiZ1ZWznuduTIIQ==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.6.0.tgz", + "integrity": "sha512-uv10vTtLTZqrJuqBZR862ZQjTIa724wGPWQqZrofaPI/kUsf53TBG0I0D+hQ1qyNtllbNzaW+PDPHHUI6/65Mg==", "funding": [ { "type": "individual", @@ -826,15 +842,15 @@ } ], "dependencies": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/constants": "^5.5.0", - "@ethersproject/logger": "^5.5.0" + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/constants": "^5.6.0", + "@ethersproject/logger": "^5.6.0" } }, "node_modules/@ethersproject/transactions": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.5.0.tgz", - "integrity": "sha512-9RZYSKX26KfzEd/1eqvv8pLauCKzDTub0Ko4LfIgaERvRuwyaNV78mJs7cpIgZaDl6RJui4o49lHwwCM0526zA==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.6.0.tgz", + "integrity": "sha512-4HX+VOhNjXHZyGzER6E/LVI2i6lf9ejYeWD6l4g50AdmimyuStKc39kvKf1bXWQMg7QNVh+uC7dYwtaZ02IXeg==", "funding": [ { "type": "individual", @@ -846,21 +862,21 @@ } ], "dependencies": { - "@ethersproject/address": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/constants": "^5.5.0", - "@ethersproject/keccak256": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/rlp": "^5.5.0", - "@ethersproject/signing-key": "^5.5.0" + "@ethersproject/address": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/constants": "^5.6.0", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/rlp": "^5.6.0", + "@ethersproject/signing-key": "^5.6.0" } }, "node_modules/@ethersproject/web": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.5.1.tgz", - "integrity": "sha512-olvLvc1CB12sREc1ROPSHTdFCdvMh0J5GSJYiQg2D0hdD4QmJDy8QYDb1CvoqD/bF1c++aeKv2sR5uduuG9dQg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.6.0.tgz", + "integrity": "sha512-G/XHj0hV1FxI2teHRfCGvfBUHFmU+YOSbCxlAMqJklxSa7QMiHFQfAxvwY2PFqgvdkxEKwRNr/eCjfAPEm2Ctg==", "funding": [ { "type": "individual", @@ -872,13 +888,18 @@ } ], "dependencies": { - "@ethersproject/base64": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/strings": "^5.5.0" + "@ethersproject/base64": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/strings": "^5.6.0" } }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==" + }, "node_modules/@humanwhocodes/config-array": { "version": "0.9.2", "dev": true, @@ -897,21 +918,48 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", + "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", + "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", + "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@noble/hashes": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-0.5.7.tgz", - "integrity": "sha512-R9PPYv7TqoYi+enikzZvwRQesGTxR0+jwqzZJGL0uNcf2NFL+lt/uvCCewtXXmr6jWBxiMuNjBfJwKv9UJaCng==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.0.0.tgz", + "integrity": "sha512-DZVbtY62kc3kkBtMHqwCOfXrT/hnoORy5BJ4+HU1IR59X0KWAOqsfzQPcUl/lQLlG7qXbe/fZ3r/emxtAl+sqg==" }, "node_modules/@noble/secp256k1": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.3.4.tgz", - "integrity": "sha512-ZVRouDO5mbdCiDg4zCd3ZZABduRtpy4tCnB33Gh9upHe9tRzpiqbRSN1VTjrj/2g8u2c6MBi0YLNnNQpBYOiWg==" + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.5.5.tgz", + "integrity": "sha512-sZ1W6gQzYnu45wPrWx8D3kwI2/U29VYTx9OjbDAd7jwRItJ0cSTMPRL/C8AWZFn9kWFLQGqEXVEE86w4Z8LpIQ==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -924,7 +972,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, "engines": { "node": ">= 8" } @@ -933,7 +980,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -942,162 +988,314 @@ "node": ">= 8" } }, - "node_modules/@polkadot/api": { + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/fs/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/git": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-3.0.0.tgz", + "integrity": "sha512-xfSBJ+KBMZWWqRHFbEgIaXG/LtELHrQZMJ72Gkb3yWdHysu/7+VGOs8ME0c3td7QNQX57Ggo3kYL6ylcd70/kA==", + "dependencies": { + "@npmcli/promise-spawn": "^1.3.2", + "lru-cache": "^7.3.1", + "mkdirp": "^1.0.4", + "npm-pick-manifest": "^7.0.0", + "proc-log": "^2.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^2.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/@npmcli/git/node_modules/lru-cache": { "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-7.5.1.tgz", - "integrity": "sha512-/3AI4Kbznt289+swtiFEYiX+XR9d+qzHhL8XxEzcqQudw2ElrfpLTAx3RzTUEEeEfwwPGmNVWPWaG4egUPsosQ==", - "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/api-augment": "7.5.1", - "@polkadot/api-base": "7.5.1", - "@polkadot/api-derive": "7.5.1", - "@polkadot/keyring": "^8.3.3", - "@polkadot/rpc-augment": "7.5.1", - "@polkadot/rpc-core": "7.5.1", - "@polkadot/rpc-provider": "7.5.1", - "@polkadot/types": "7.5.1", - "@polkadot/types-augment": "7.5.1", - "@polkadot/types-codec": "7.5.1", - "@polkadot/types-create": "7.5.1", - "@polkadot/types-known": "7.5.1", - "@polkadot/util": "^8.3.3", - "@polkadot/util-crypto": "^8.3.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.5.1.tgz", + "integrity": "sha512-q1TS8IqKvcg3aScamKCHpepSrHF537Ww7nHahBOxhDu9D2YoBXAsj/7uFdZFj1xJr9LmyeJ62AdyofCHafUbIA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/@npmcli/git/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/git/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/git/node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/installed-package-contents": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz", + "integrity": "sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==", + "dependencies": { + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + }, + "bin": { + "installed-package-contents": "index.js" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/node-gyp": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-1.0.3.tgz", + "integrity": "sha512-fnkhw+fmX65kiLqk6E3BFLXNC26rUhK90zVwe2yncPliVT/Qos3xjhTLE59Df8KnPlcwIERXKVlU1bXoUQ+liA==" + }, + "node_modules/@npmcli/promise-spawn": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz", + "integrity": "sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg==", + "dependencies": { + "infer-owner": "^1.0.4" + } + }, + "node_modules/@npmcli/run-script": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-3.0.1.tgz", + "integrity": "sha512-o2fkld5hYwu9sKYzoXTpqEocMnDLaigobaPzLaGB63k/ExmLBTaB+KpfKlpcIePPnuP8RFR+0GDI4KopJCM6Xg==", + "dependencies": { + "@npmcli/node-gyp": "^1.0.3", + "@npmcli/promise-spawn": "^1.3.2", + "node-gyp": "^9.0.0", + "read-package-json-fast": "^2.0.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/@polkadot/api": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-7.12.1.tgz", + "integrity": "sha512-kA6o9ZdRsJ9Iis+PyZN8sayrioJmgf8r5cAqnjoCmA+cb9h+FcqLoHe4kojA6uQMsX2PnsunX2nVuFaZSstoSg==", + "dependencies": { + "@babel/runtime": "^7.17.2", + "@polkadot/api-augment": "7.12.1", + "@polkadot/api-base": "7.12.1", + "@polkadot/api-derive": "7.12.1", + "@polkadot/keyring": "^8.5.1", + "@polkadot/rpc-augment": "7.12.1", + "@polkadot/rpc-core": "7.12.1", + "@polkadot/rpc-provider": "7.12.1", + "@polkadot/types": "7.12.1", + "@polkadot/types-augment": "7.12.1", + "@polkadot/types-codec": "7.12.1", + "@polkadot/types-create": "7.12.1", + "@polkadot/types-known": "7.12.1", + "@polkadot/util": "^8.5.1", + "@polkadot/util-crypto": "^8.5.1", "eventemitter3": "^4.0.7", - "rxjs": "^7.5.2" + "rxjs": "^7.5.5" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/api-augment": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-7.5.1.tgz", - "integrity": "sha512-2sj+D8gvyo9ijqFFqJS5meaMVRllr5fWnE440nACsXIbcbHuXRWAF9tWdhESOIfue7hlFLo5plDdRfU7cSjIZQ==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-7.12.1.tgz", + "integrity": "sha512-/SFrV4+VNLYZlfoQ80UVOQWeen/YOmWNeuyVa+KaywyTowLLZ4X1MWXB3Dwtk/aQYCbwxm82+R8IJun2zl6mVw==", "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/api-base": "7.5.1", - "@polkadot/rpc-augment": "7.5.1", - "@polkadot/types": "7.5.1", - "@polkadot/types-augment": "7.5.1", - "@polkadot/types-codec": "7.5.1", - "@polkadot/util": "^8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/api-base": "7.12.1", + "@polkadot/rpc-augment": "7.12.1", + "@polkadot/types": "7.12.1", + "@polkadot/types-augment": "7.12.1", + "@polkadot/types-codec": "7.12.1", + "@polkadot/util": "^8.5.1" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/api-base": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-7.5.1.tgz", - "integrity": "sha512-vqMjmMOQuYLSwfTHTgmvPBtF6eAgrlyuBw0t0IiaTDfjP6xRRGMDIVb7lJCqvYL0VrHmTC7X5MVbJn1SNUut9w==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-7.12.1.tgz", + "integrity": "sha512-AhBnYOtImoaaUoCI6srbnwQ4vn1fSbOSCfpzkLLEJi+KMuNO9vfZU3O8ob8MdY2Y3V7kGQMPWulGGaCqOcDepQ==", "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/rpc-core": "7.5.1", - "@polkadot/types": "7.5.1", - "@polkadot/util": "^8.3.3", - "rxjs": "^7.5.2" + "@babel/runtime": "^7.17.2", + "@polkadot/rpc-core": "7.12.1", + "@polkadot/types": "7.12.1", + "@polkadot/util": "^8.5.1", + "rxjs": "^7.5.5" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/api-derive": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-7.5.1.tgz", - "integrity": "sha512-O4x/DG+sSWgbXYGuYm4d3iYMTv5WTzoX5HX/xAIG+H+g7ob5RDdyLW9oQowrOX9ZOKt1cHPbHi0dLj+hDOD1CQ==", - "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/api": "7.5.1", - "@polkadot/api-augment": "7.5.1", - "@polkadot/api-base": "7.5.1", - "@polkadot/rpc-core": "7.5.1", - "@polkadot/types": "7.5.1", - "@polkadot/types-codec": "7.5.1", - "@polkadot/util": "^8.3.3", - "@polkadot/util-crypto": "^8.3.3", - "rxjs": "^7.5.2" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-7.12.1.tgz", + "integrity": "sha512-MePzdiicdvfhd8Y+9xQXlfo/imU/7dxc2hBu8Iy33f8VnImJJTXMvcK84MKDxZraQ3k93rj2XAv1VYM1eh1R2w==", + "dependencies": { + "@babel/runtime": "^7.17.2", + "@polkadot/api": "7.12.1", + "@polkadot/api-augment": "7.12.1", + "@polkadot/api-base": "7.12.1", + "@polkadot/rpc-core": "7.12.1", + "@polkadot/types": "7.12.1", + "@polkadot/types-codec": "7.12.1", + "@polkadot/util": "^8.5.1", + "@polkadot/util-crypto": "^8.5.1", + "rxjs": "^7.5.5" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/keyring": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-8.3.3.tgz", - "integrity": "sha512-TgoIpaTqn7voT7lDu5W6p0Z+216OImpqtHuaiFy125ekCQurrf9BVIdwp56y5qoFLDAZ5i9gnWHMIgOQ6AJj/Q==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-8.5.1.tgz", + "integrity": "sha512-ivJ/pEfu9Pu78h3Gldf3p5odXr5weAbwcz22VyjmTpege1bIHmw4HdYC0lOZznTDAIGUMk7IoswHYmvZWTHgNA==", "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/util": "8.3.3", - "@polkadot/util-crypto": "8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/util": "8.5.1", + "@polkadot/util-crypto": "8.5.1" }, "engines": { "node": ">=14.0.0" }, "peerDependencies": { - "@polkadot/util": "8.3.3", - "@polkadot/util-crypto": "8.3.3" + "@polkadot/util": "8.5.1", + "@polkadot/util-crypto": "8.5.1" } }, "node_modules/@polkadot/networks": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-8.3.3.tgz", - "integrity": "sha512-yj0DMqmzRZbvgaoZztV3/RPgYJjBhT17Dhu+FX/LUJzVbAF/RfjkzNsJT4Ta4kLDxQMYZq1avUac0ia2j9NcNw==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-8.5.1.tgz", + "integrity": "sha512-gPfOhP2SrJTOywmdq2IYgxxq/W90wePG+A+xqNvvP7briPGty7+yXmaIJk7HowZChnerOeQ2z0gunbXiacVHFA==", "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/util": "8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/util": "8.5.1", + "@substrate/ss58-registry": "^1.16.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/rpc-augment": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-7.5.1.tgz", - "integrity": "sha512-LPTDjtBZJe5KIOErOW+h2HY85G57WZVOiwm+SOgJ6J5g+BnUD0Rv+VH9pGC8dfoUsYBHSSvFELLnoTIZw6jltg==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-7.12.1.tgz", + "integrity": "sha512-2Gr4dkM5ZGrv5J5LKwK0vX7V6i/WTdvJzNs1BwDY+RMLwOFp8eStRyPuCJNgdBF7xkeXR9BKoaU0cqB1xmK+Gg==", "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/rpc-core": "7.5.1", - "@polkadot/types": "7.5.1", - "@polkadot/types-codec": "7.5.1", - "@polkadot/util": "^8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/rpc-core": "7.12.1", + "@polkadot/types": "7.12.1", + "@polkadot/types-codec": "7.12.1", + "@polkadot/util": "^8.5.1" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/rpc-core": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-7.5.1.tgz", - "integrity": "sha512-/UN7fQSqGnyjd5W0fFZ2RDBxAYoS8UreIea0eu+Zz4t6D2Fjp1syHNkw710wuv6ALhaRUjW6USO8XNSHDBIz+w==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-7.12.1.tgz", + "integrity": "sha512-qL2+5MHjBjMETPr8tLmiIykfSyooBYZ8bBwJ4j9OEENd+e6F8k0KnEuoeyA826CU20cUDydP9YdqOR2CP2fSww==", "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/rpc-augment": "7.5.1", - "@polkadot/rpc-provider": "7.5.1", - "@polkadot/types": "7.5.1", - "@polkadot/util": "^8.3.3", - "rxjs": "^7.5.2" + "@babel/runtime": "^7.17.2", + "@polkadot/rpc-augment": "7.12.1", + "@polkadot/rpc-provider": "7.12.1", + "@polkadot/types": "7.12.1", + "@polkadot/util": "^8.5.1", + "rxjs": "^7.5.5" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/rpc-provider": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-7.5.1.tgz", - "integrity": "sha512-6t5PyEDFBYJiK1/oegQkET4DnKdfk/mskELOVflDd4sLN+mXSAUW4DvS+KiVldHfUBtMQqX/w3p7x26xmWjmqQ==", - "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/keyring": "^8.3.3", - "@polkadot/types": "7.5.1", - "@polkadot/types-support": "7.5.1", - "@polkadot/util": "^8.3.3", - "@polkadot/util-crypto": "^8.3.3", - "@polkadot/x-fetch": "^8.3.3", - "@polkadot/x-global": "^8.3.3", - "@polkadot/x-ws": "^8.3.3", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-7.12.1.tgz", + "integrity": "sha512-gMvlbqq3xXg54CVoMdiugvrwLNnUI5QhO/YIWv6vOnpc8AOs+JVYgdPaBTNleHiyV7Lw6sVQJno0QH8vx8xjIg==", + "dependencies": { + "@babel/runtime": "^7.17.2", + "@polkadot/keyring": "^8.5.1", + "@polkadot/types": "7.12.1", + "@polkadot/types-support": "7.12.1", + "@polkadot/util": "^8.5.1", + "@polkadot/util-crypto": "^8.5.1", + "@polkadot/x-fetch": "^8.5.1", + "@polkadot/x-global": "^8.5.1", + "@polkadot/x-ws": "^8.5.1", "eventemitter3": "^4.0.7", - "mock-socket": "^9.1.0", - "nock": "^13.2.2" + "mock-socket": "^9.1.2", + "nock": "^13.2.4" }, "engines": { "node": ">=14.0.0" @@ -1112,24 +1310,24 @@ } }, "node_modules/@polkadot/typegen": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/typegen/-/typegen-7.5.1.tgz", - "integrity": "sha512-0ma//yfYBEcpYftoqS3Jbl3mVGA/zl3WRfnW3KK3cQ8J1xqKXusjeQ/9egyuWSP8qn34XHXQcvE6T+rfX+ki4A==", - "dependencies": { - "@babel/core": "^7.16.12", - "@babel/register": "^7.16.9", - "@babel/runtime": "^7.16.7", - "@polkadot/api": "7.5.1", - "@polkadot/api-augment": "7.5.1", - "@polkadot/rpc-augment": "7.5.1", - "@polkadot/rpc-provider": "7.5.1", - "@polkadot/types": "7.5.1", - "@polkadot/types-augment": "7.5.1", - "@polkadot/types-codec": "7.5.1", - "@polkadot/types-create": "7.5.1", - "@polkadot/types-support": "7.5.1", - "@polkadot/util": "^8.3.3", - "@polkadot/x-ws": "^8.3.3", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/typegen/-/typegen-7.12.1.tgz", + "integrity": "sha512-K0UUbkwUJZgBA8HaHLyUepuaGJINdSj7LjrwKRCxjLy5Pz3K6W39c+yiwLHYIsCV4SBZhllXBVyvOkV4Dx6rJA==", + "dependencies": { + "@babel/core": "^7.17.5", + "@babel/register": "^7.17.0", + "@babel/runtime": "^7.17.2", + "@polkadot/api": "7.12.1", + "@polkadot/api-augment": "7.12.1", + "@polkadot/rpc-augment": "7.12.1", + "@polkadot/rpc-provider": "7.12.1", + "@polkadot/types": "7.12.1", + "@polkadot/types-augment": "7.12.1", + "@polkadot/types-codec": "7.12.1", + "@polkadot/types-create": "7.12.1", + "@polkadot/types-support": "7.12.1", + "@polkadot/util": "^8.5.1", + "@polkadot/x-ws": "^8.5.1", "handlebars": "^4.7.7", "websocket": "^1.0.34", "yargs": "^17.3.1" @@ -1171,102 +1369,102 @@ } }, "node_modules/@polkadot/types": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-7.5.1.tgz", - "integrity": "sha512-71KY3Ia8AZywb0wWP0F588qFJbQMcgZqqP/dw6RP1A5ja2pR5SnqRP/zcaSena1cm9f24rAxgxiluOzzJxrfsA==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-7.12.1.tgz", + "integrity": "sha512-GMqVTXCN6oCJnyAz7NwABez+I42luNyMMbIzIwrYD3XlMsQnnPc2GkhCLjeLf/0InTx/xij+C7z2zma4hYQZtQ==", "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/keyring": "^8.3.3", - "@polkadot/types-augment": "7.5.1", - "@polkadot/types-codec": "7.5.1", - "@polkadot/types-create": "7.5.1", - "@polkadot/util": "^8.3.3", - "@polkadot/util-crypto": "^8.3.3", - "rxjs": "^7.5.2" + "@babel/runtime": "^7.17.2", + "@polkadot/keyring": "^8.5.1", + "@polkadot/types-augment": "7.12.1", + "@polkadot/types-codec": "7.12.1", + "@polkadot/types-create": "7.12.1", + "@polkadot/util": "^8.5.1", + "@polkadot/util-crypto": "^8.5.1", + "rxjs": "^7.5.5" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/types-augment": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-7.5.1.tgz", - "integrity": "sha512-YWXYfc0a2AOb2naG2uWAHkTuGvfPz8hrKv3UMTWUrCok/kVbUovqSXoBAORaX+tphpaKbEuBnBtBhk2cXP6KWA==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-7.12.1.tgz", + "integrity": "sha512-giQao8jm2M9HufRT3H4r1a2C76G3HEKxJAfVaMLL4tcV0BqbkpBG/I2V8Bc6cDaSsgfxizSE4+UzsDZwelEH3w==", "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/types": "7.5.1", - "@polkadot/types-codec": "7.5.1", - "@polkadot/util": "^8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/types": "7.12.1", + "@polkadot/types-codec": "7.12.1", + "@polkadot/util": "^8.5.1" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/types-codec": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-7.5.1.tgz", - "integrity": "sha512-+MClbgg0sbEIsPnqVf1wVzR5qPCE5Xb+QXkwawx86mIyxb4eptdBnU0CFgHVcrNnKx6EcaUZWQgz17UxtmTWaA==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-7.12.1.tgz", + "integrity": "sha512-v7/vnrQuYxsou7ck+N0Cc7b+fqawCbvf3kJbU6tcJMvh745abnfF6gP+yt/fhDT4jkDufBNPagtrY7+z5e56Ew==", "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/util": "^8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/util": "^8.5.1" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/types-create": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-7.5.1.tgz", - "integrity": "sha512-OCsdDp4vd/6yNThTEmjbndHks4VHlfeuNwcQQN2NcM4Gs072LnuDTbRgFHAqvcSKB0SVOiWoy/UxkktLE+0w2Q==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-7.12.1.tgz", + "integrity": "sha512-p7dWBV2vJX9H/CPkgS3nkVit4rZJs2WJGzwBUtYy5fK07Iu1FvIGKSd4/bJVEuJwqmFlElliADjg5qlbiv3KOg==", "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/types-codec": "7.5.1", - "@polkadot/util": "^8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/types-codec": "7.12.1", + "@polkadot/util": "^8.5.1" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/types-known": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-7.5.1.tgz", - "integrity": "sha512-mECocUHbvb/ly5KOu+nKfqXAEKzYxkflO4xQflaEpcCIxtqBmy8AXSvyD8Dl5LFrBwHqnRbtXaPETCOYn1LWPg==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-7.12.1.tgz", + "integrity": "sha512-y+hu/qrE874WI0tNXIge7SX6kIC2sfhGWSWU0uyrA8khc7ByR9ENwAzxkJD3zht2taZZCM+ucVVH9ogpJZKCTg==", "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/networks": "^8.3.3", - "@polkadot/types": "7.5.1", - "@polkadot/types-codec": "7.5.1", - "@polkadot/types-create": "7.5.1", - "@polkadot/util": "^8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/networks": "^8.5.1", + "@polkadot/types": "7.12.1", + "@polkadot/types-codec": "7.12.1", + "@polkadot/types-create": "7.12.1", + "@polkadot/util": "^8.5.1" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/types-support": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-7.5.1.tgz", - "integrity": "sha512-6LrYMQVF6G9+r1mnYpSGX6irN0eG5OQQRb2YXX4wtYT3JIU+G9EK0NjLngSDf0KMMm80aD0hFKYF0DcuQSGk+A==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-7.12.1.tgz", + "integrity": "sha512-dlTRXJmBWIcRi3wryvaqPxGBv9vDfu+vWeyQF93CMRdCuBwKB25jeoh2n2xCMZ9c0TbziJzE+Qg2oGoKK2Dzeg==", "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/util": "^8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/util": "^8.5.1" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/util": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-8.3.3.tgz", - "integrity": "sha512-8u1NShSHrCFeFvxWL8WAyRN8y1/iPvijqYCDeeHziBxCNBrL3VKDc9GNF11skeay/EKQiCHBSBeAYyyQOpLebA==", - "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/x-bigint": "8.3.3", - "@polkadot/x-global": "8.3.3", - "@polkadot/x-textdecoder": "8.3.3", - "@polkadot/x-textencoder": "8.3.3", - "@types/bn.js": "^4.11.6", - "bn.js": "^4.12.0", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-8.5.1.tgz", + "integrity": "sha512-B+W3VdLo4ignLZXRTA/gAF7TwFe+kgW6XTt+BBWJL9dcjGVU66aL8xjTbohUNUtwlaD2p5kua6jJqTJC/3u3hQ==", + "dependencies": { + "@babel/runtime": "^7.17.2", + "@polkadot/x-bigint": "8.5.1", + "@polkadot/x-global": "8.5.1", + "@polkadot/x-textdecoder": "8.5.1", + "@polkadot/x-textencoder": "8.5.1", + "@types/bn.js": "^5.1.0", + "bn.js": "^5.2.0", "ip-regex": "^4.3.0" }, "engines": { @@ -1274,37 +1472,37 @@ } }, "node_modules/@polkadot/util-crypto": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-8.3.3.tgz", - "integrity": "sha512-kXaT2VTEbJq1wNiV0Dz5qJuVWy7pK+x1QLcyWC+6OFERYO+BCp1Y2bTOcLUeF/gyyR/ZaRMMdTyu0ZbHrwH0xg==", - "dependencies": { - "@babel/runtime": "^7.16.7", - "@noble/hashes": "0.5.7", - "@noble/secp256k1": "1.3.4", - "@polkadot/networks": "8.3.3", - "@polkadot/util": "8.3.3", - "@polkadot/wasm-crypto": "^4.5.1", - "@polkadot/x-bigint": "8.3.3", - "@polkadot/x-randomvalues": "8.3.3", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-8.5.1.tgz", + "integrity": "sha512-/+4Cwcd4vlIzvIVFXfNjNeoLWw4wSZY58OiXlq8apISrJly63u8KCa8DwV9SxxgMBU0xzpWi/4W1m7hihGh8RQ==", + "dependencies": { + "@babel/runtime": "^7.17.2", + "@noble/hashes": "1.0.0", + "@noble/secp256k1": "1.5.5", + "@polkadot/networks": "8.5.1", + "@polkadot/util": "8.5.1", + "@polkadot/wasm-crypto": "^4.6.1", + "@polkadot/x-bigint": "8.5.1", + "@polkadot/x-randomvalues": "8.5.1", + "@scure/base": "1.0.0", "ed2curve": "^0.3.0", - "micro-base": "^0.10.2", "tweetnacl": "^1.0.3" }, "engines": { "node": ">=14.0.0" }, "peerDependencies": { - "@polkadot/util": "8.3.3" + "@polkadot/util": "8.5.1" } }, "node_modules/@polkadot/wasm-crypto": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto/-/wasm-crypto-4.5.1.tgz", - "integrity": "sha512-Cr21ais3Kq3aedIHZ3J1tjgeD/+K8FCiwEawr0oRywNBSJR8wyuZMePs4swR/6xm8wbBkpqoBVHz/UQHqqQJmA==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto/-/wasm-crypto-4.6.1.tgz", + "integrity": "sha512-2wEftBDxDG+TN8Ah6ogtvzjdZdcF0mAjU4UNNOfpmkBCxQYZOrAHB8HXhzo3noSsKkLX7PDX57NxvJ9OhoTAjw==", "dependencies": { - "@babel/runtime": "^7.16.3", - "@polkadot/wasm-crypto-asmjs": "^4.5.1", - "@polkadot/wasm-crypto-wasm": "^4.5.1" + "@babel/runtime": "^7.17.2", + "@polkadot/wasm-crypto-asmjs": "^4.6.1", + "@polkadot/wasm-crypto-wasm": "^4.6.1" }, "engines": { "node": ">=14.0.0" @@ -1315,47 +1513,53 @@ } }, "node_modules/@polkadot/wasm-crypto-asmjs": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-4.5.1.tgz", - "integrity": "sha512-DOdRiWhxVvmqTvp+E9z1j+Yr0zDOGsDvqnT/eNw0Dl1FVUOImsEa7FKns/urASmcxCVEE1jtUWSnij29jrORMQ==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-4.6.1.tgz", + "integrity": "sha512-1oHQjz2oEO1kCIcQniOP+dZ9N2YXf2yCLHLsKaKSvfXiWaetVCaBNB8oIHIVYvuLnVc8qlMi66O6xc1UublHsw==", "dependencies": { - "@babel/runtime": "^7.16.3" + "@babel/runtime": "^7.17.2" }, "engines": { "node": ">=14.0.0" + }, + "peerDependencies": { + "@polkadot/util": "*" } }, "node_modules/@polkadot/wasm-crypto-wasm": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-4.5.1.tgz", - "integrity": "sha512-hPwke85HxpgG/RAlwdCE8u5w7bThvWg399mlB+XjogXMxOUWBZSgq2XYbgzROUXx27inK9nStF4Pnc4zJnqs9A==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-4.6.1.tgz", + "integrity": "sha512-NI3JVwmLjrSYpSVuhu0yeQYSlsZrdpK41UC48sY3kyxXC71pi6OVePbtHS1K3xh3FFmDd9srSchExi3IwzKzMw==", "dependencies": { - "@babel/runtime": "^7.16.3" + "@babel/runtime": "^7.17.2" }, "engines": { "node": ">=14.0.0" + }, + "peerDependencies": { + "@polkadot/util": "*" } }, "node_modules/@polkadot/x-bigint": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-8.3.3.tgz", - "integrity": "sha512-2CT25f0zN/uhch3KpM38jtQfFJ1zJCNT41exg49ztsOvm4f6l+6hW91NLhNAZ313B/c6Z4Lm3DalsjAOdBZ8Nw==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-8.5.1.tgz", + "integrity": "sha512-6HaINISJYIf2t9FFnUh6aFC5/Zf8wifcuHpMQGTlfXGeK7egmTmkVE9fjkoDOOSt6jbJ+jvlPcWcPh9WdY4tkg==", "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/x-global": "8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/x-global": "8.5.1" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/x-fetch": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-8.3.3.tgz", - "integrity": "sha512-+ScnWnt0i1IF+fM9IC+OnjkTi5NonK+ji8q861hwkNCtK2ziibibcD3mGavCA6wZvij4wUTovWEsTc5Su0+KTA==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-8.5.1.tgz", + "integrity": "sha512-c3VytuvXPm5NLOCF6TTm8avJ6jO8nmyrmVR4IQlq1hhQM556bbAv1+/PSnzwO6Rhr8KWu6TdsTIbl+wyky96Jw==", "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/x-global": "8.3.3", - "@types/node-fetch": "^2.5.12", + "@babel/runtime": "^7.17.2", + "@polkadot/x-global": "8.5.1", + "@types/node-fetch": "^2.6.1", "node-fetch": "^2.6.7" }, "engines": { @@ -1363,66 +1567,77 @@ } }, "node_modules/@polkadot/x-global": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-8.3.3.tgz", - "integrity": "sha512-7DWjcNhTDIpYNiQmLq56o6xYOONr0i6WXdoPUxYrToxZWeWyj/FWaYMfttedLydABPcy87lmvIy8ECp7qCcnyw==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-8.5.1.tgz", + "integrity": "sha512-fjKivdI0fOrT86YyLZJHGFkAZSo7ZyrAos2CoJ/DPhSNYOYg6wwaqLloodDBx5awpt0383jns97MOPdkFu3n6A==", "dependencies": { - "@babel/runtime": "^7.16.7" + "@babel/runtime": "^7.17.2" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/x-randomvalues": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-8.3.3.tgz", - "integrity": "sha512-yxM6GWQholf+vY4dHxKVwtJwDzNUz4UJlL/iN3PA0cuhQ37gxmtJugnNAllcFd8LDNXEN47Ky6Ifw1OHHmZaVw==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-8.5.1.tgz", + "integrity": "sha512-4FRCiieOcHEsWoO95NpPLm/6bjyalYylPyKuMw16cEOTrbtGzYi9mYW34gLyR5vy08ZDOBBM5b1zRzmzAL7yQg==", "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/x-global": "8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/x-global": "8.5.1" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/x-textdecoder": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-8.3.3.tgz", - "integrity": "sha512-oEvFJv/F+fQ336ciRuJJgJFtfyOX6a2Nyr/5GCkiSQjkEIdnBUuO49yXpHNmQsNI0WndLWIEitiVVa9KuDslYw==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-8.5.1.tgz", + "integrity": "sha512-UVGMy8bibZDaF9BadwsNOHExHDyDp+f7chqqLEMVdu48l+gTqFmtqhGhegYz2ft23JBHIO0t93MYa8R3RwEEwA==", "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/x-global": "8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/x-global": "8.5.1" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/x-textencoder": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-8.3.3.tgz", - "integrity": "sha512-acVsJjmlQ7aluUq8JARY2wJAbf+6dvZNoUrvgzdX/jl5MqvqeIXmX3LX71MyidLt27Z537VDgNzWw8V/524AVQ==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-8.5.1.tgz", + "integrity": "sha512-c2ZD7mHxrz8rE87eF78QfN7d1IFcHsu4aRTuja/oXMf1MEebChP/XmjHUGog/Ib5W6Hn4+Bm8at2DTgxjYfROg==", "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/x-global": "8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/x-global": "8.5.1" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@polkadot/x-ws": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-8.3.3.tgz", - "integrity": "sha512-Dd0kscZSb7MULVqo5isPZyqvErvgE7lYIwZ4IA0rNdgUWi3mrJWeeWrzVMxC6nbg6q1ahIEGxxZLMVzeI3u/Ew==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-8.5.1.tgz", + "integrity": "sha512-61TT3dMt9J0JihaprZo/8Lr75qIGr0A/TKuflCBnHw24kRbaamnCYUAtyJC1uL3X50LDqtGRybvpKPGOnzl5sQ==", "dependencies": { - "@babel/runtime": "^7.16.7", - "@polkadot/x-global": "8.3.3", - "@types/websocket": "^1.0.4", + "@babel/runtime": "^7.17.2", + "@polkadot/x-global": "8.5.1", + "@types/websocket": "^1.0.5", "websocket": "^1.0.34" }, "engines": { "node": ">=14.0.0" } }, + "node_modules/@scure/base": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.0.0.tgz", + "integrity": "sha512-gIVaYhUsy+9s58m/ETjSJVKHhKTBMmcRb9cEV5/5dwvfDlfORjKrFsDeDHWRrm6RjcPvCLZFwGJjAjLj1gg4HA==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, "node_modules/@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -1431,6 +1646,11 @@ "node": ">=6" } }, + "node_modules/@substrate/ss58-registry": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/@substrate/ss58-registry/-/ss58-registry-1.16.0.tgz", + "integrity": "sha512-z88145A9NE0mnDbIYRP1SlHndDtm6Jd1cRnG2InRCA/M7UprFRc0zrtaTWj1KBHfcVc2uYUMggGXuenQPBQ8yQ==" + }, "node_modules/@szmarczak/http-timer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", @@ -1442,6 +1662,14 @@ "node": ">=6" } }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "engines": { + "node": ">= 10" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", @@ -1467,9 +1695,9 @@ "dev": true }, "node_modules/@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", + "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", "dependencies": { "@types/node": "*" } @@ -1511,7 +1739,8 @@ "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true }, "node_modules/@types/minimist": { "version": "1.2.2", @@ -1520,19 +1749,19 @@ "dev": true }, "node_modules/@types/mocha": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.0.0.tgz", - "integrity": "sha512-scN0hAWyLVAvLR9AyW7HoFF5sJZglyBsbPuHO4fv7JRvfmPBMfp1ozWqOf/e4wwPNxezBZXRfWzMb6iFLgEVRA==" + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.0.tgz", + "integrity": "sha512-QCWHkbMv4Y5U9oW10Uxbr45qMMSzl4OzijsozynUAgx3kEHUdXB00udx2dWDQ7f2TU2a2uuiFaRZjCe3unPpeg==" }, "node_modules/@types/node": { - "version": "17.0.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.9.tgz", - "integrity": "sha512-5dNBXu/FOER+EXnyah7rn8xlNrfMOQb/qXnw4NQgLkCygKBKhdmF/CA5oXVOKZLBEahw8s2WP9LxIcN/oDDRgQ==" + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==" }, "node_modules/@types/node-fetch": { - "version": "2.5.12", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.12.tgz", - "integrity": "sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA==", "dependencies": { "@types/node": "*", "form-data": "^3.0.0" @@ -1547,9 +1776,9 @@ } }, "node_modules/@types/ramda": { - "version": "0.27.64", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.27.64.tgz", - "integrity": "sha512-EDf++ss/JoMiDpvT1MuA8oi88OwpvmqVE+o8Ojm5v/5bdJEPZ6eIQd/XYAeQ0imlwG6Tf0Npfq4Z9w3hAKBk9Q==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.28.1.tgz", + "integrity": "sha512-8wnJK5aPaGL7AYhQSe7olwxjhIB9GO4GOCxd6JjYlVNe128DHJDOu7Kyve4kx4uazeKJdnOS3N5TVRv0z1bb1g==", "dependencies": { "ts-toolbelt": "^6.15.1" } @@ -1571,14 +1800,14 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.10.1.tgz", - "integrity": "sha512-xN3CYqFlyE/qOcy978/L0xLR2HlcAGIyIK5sMOasxaaAPfQRj/MmMV6OC3I7NZO84oEUdWCOju34Z9W8E0pFDQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.15.0.tgz", + "integrity": "sha512-u6Db5JfF0Esn3tiAKELvoU5TpXVSkOpZ78cEGn/wXtT2RVqs2vkt4ge6N8cRCyw7YVKhmmLDbwI2pg92mlv7cA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.10.1", - "@typescript-eslint/type-utils": "5.10.1", - "@typescript-eslint/utils": "5.10.1", + "@typescript-eslint/scope-manager": "5.15.0", + "@typescript-eslint/type-utils": "5.15.0", + "@typescript-eslint/utils": "5.15.0", "debug": "^4.3.2", "functional-red-black-tree": "^1.0.1", "ignore": "^5.1.8", @@ -1618,14 +1847,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.10.1.tgz", - "integrity": "sha512-GReo3tjNBwR5RnRO0K2wDIDN31cM3MmDtgyQ85oAxAmC5K3j/g85IjP+cDfcqDsDDBf1HNKQAD0WqOYL8jXqUA==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.15.0.tgz", + "integrity": "sha512-NGAYP/+RDM2sVfmKiKOCgJYPstAO40vPAgACoWPO/+yoYKSgAXIFaBKsV8P0Cc7fwKgvj27SjRNX4L7f4/jCKQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.10.1", - "@typescript-eslint/types": "5.10.1", - "@typescript-eslint/typescript-estree": "5.10.1", + "@typescript-eslint/scope-manager": "5.15.0", + "@typescript-eslint/types": "5.15.0", + "@typescript-eslint/typescript-estree": "5.15.0", "debug": "^4.3.2" }, "engines": { @@ -1645,13 +1874,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.10.1.tgz", - "integrity": "sha512-Lyvi559Gvpn94k7+ElXNMEnXu/iundV5uFmCUNnftbFrUbAJ1WBoaGgkbOBm07jVZa682oaBU37ao/NGGX4ZDg==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.15.0.tgz", + "integrity": "sha512-EFiZcSKrHh4kWk0pZaa+YNJosvKE50EnmN4IfgjkA3bTHElPtYcd2U37QQkNTqwMCS7LXeDeZzEqnsOH8chjSg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.10.1", - "@typescript-eslint/visitor-keys": "5.10.1" + "@typescript-eslint/types": "5.15.0", + "@typescript-eslint/visitor-keys": "5.15.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1662,12 +1891,12 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.10.1.tgz", - "integrity": "sha512-AfVJkV8uck/UIoDqhu+ptEdBoQATON9GXnhOpPLzkQRJcSChkvD//qsz9JVffl2goxX+ybs5klvacE9vmrQyCw==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.15.0.tgz", + "integrity": "sha512-KGeDoEQ7gHieLydujGEFLyLofipe9PIzfvA/41urz4hv+xVxPEbmMQonKSynZ0Ks2xDhJQ4VYjB3DnRiywvKDA==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "5.10.1", + "@typescript-eslint/utils": "5.15.0", "debug": "^4.3.2", "tsutils": "^3.21.0" }, @@ -1688,9 +1917,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.10.1.tgz", - "integrity": "sha512-ZvxQ2QMy49bIIBpTqFiOenucqUyjTQ0WNLhBM6X1fh1NNlYAC6Kxsx8bRTY3jdYsYg44a0Z/uEgQkohbR0H87Q==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.15.0.tgz", + "integrity": "sha512-yEiTN4MDy23vvsIksrShjNwQl2vl6kJeG9YkVJXjXZnkJElzVK8nfPsWKYxcsGWG8GhurYXP4/KGj3aZAxbeOA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1701,13 +1930,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.1.tgz", - "integrity": "sha512-PwIGnH7jIueXv4opcwEbVGDATjGPO1dx9RkUl5LlHDSe+FXxPwFL5W/qYd5/NHr7f6lo/vvTrAzd0KlQtRusJQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.15.0.tgz", + "integrity": "sha512-Hb0e3dGc35b75xLzixM3cSbG1sSbrTBQDfIScqdyvrfJZVEi4XWAT+UL/HMxEdrJNB8Yk28SKxPLtAhfCbBInA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.10.1", - "@typescript-eslint/visitor-keys": "5.10.1", + "@typescript-eslint/types": "5.15.0", + "@typescript-eslint/visitor-keys": "5.15.0", "debug": "^4.3.2", "globby": "^11.0.4", "is-glob": "^4.0.3", @@ -1743,15 +1972,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.10.1.tgz", - "integrity": "sha512-RRmlITiUbLuTRtn/gcPRi4202niF+q7ylFLCKu4c+O/PcpRvZ/nAUwQ2G00bZgpWkhrNLNnvhZLbDn8Ml0qsQw==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.15.0.tgz", + "integrity": "sha512-081rWu2IPKOgTOhHUk/QfxuFog8m4wxW43sXNOMSCdh578tGJ1PAaWPsj42LOa7pguh173tNlMigsbrHvh/mtA==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.10.1", - "@typescript-eslint/types": "5.10.1", - "@typescript-eslint/typescript-estree": "5.10.1", + "@typescript-eslint/scope-manager": "5.15.0", + "@typescript-eslint/types": "5.15.0", + "@typescript-eslint/typescript-estree": "5.15.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, @@ -1767,12 +1996,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.1.tgz", - "integrity": "sha512-NjQ0Xinhy9IL979tpoTRuLKxMc0zJC7QVSdeerXs2/QvOy2yRkzX5dRb10X5woNUdJgU8G3nYRDlI33sq1K4YQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.15.0.tgz", + "integrity": "sha512-+vX5FKtgvyHbmIJdxMJ2jKm9z2BIlXJiuewI8dsDYMp5LzPUcuTT78Ya5iwvQg3VqSVdmxyM8Anj1Jeq7733ZQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.10.1", + "@typescript-eslint/types": "5.15.0", "eslint-visitor-keys": "^3.0.0" }, "engines": { @@ -1787,13 +2016,18 @@ "version": "1.1.2", "license": "ISC" }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "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" }, "engines": { "node": ">= 0.6" @@ -1812,8 +2046,9 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -1827,6 +2062,42 @@ "node": ">=0.4.0" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", + "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", + "dependencies": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ajv": { "version": "6.12.6", "license": "MIT", @@ -1841,6 +2112,14 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dependencies": { + "string-width": "^4.1.0" + } + }, "node_modules/ansi-colors": { "version": "4.1.1", "license": "MIT", @@ -1880,6 +2159,23 @@ "node": ">= 8" } }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz", + "integrity": "sha512-0GWpv50YSOcLXaN6/FAKY3vfRbllXWV2xvfA/oKJF8pzFhWXPV+yjhJXDBbjscDYowv7Yw1A3uigpzn5iEGTyw==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, "node_modules/arg": { "version": "4.1.3", "dev": true, @@ -1898,7 +2194,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, "engines": { "node": ">=8" } @@ -1931,6 +2226,11 @@ "safer-buffer": "^2.1.0" } }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "node_modules/assert": { "version": "2.0.0", "dev": true, @@ -2061,24 +2361,24 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" }, "node_modules/body-parser": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz", - "integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==", + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", "dependencies": { - "bytes": "3.1.1", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.2", "http-errors": "1.8.1", "iconv-lite": "0.4.24", "on-finished": "~2.3.0", - "qs": "6.9.6", - "raw-body": "2.4.2", + "qs": "6.9.7", + "raw-body": "2.4.3", "type-is": "~1.6.18" }, "engines": { @@ -2093,11 +2393,43 @@ "ms": "2.0.0" } }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "node_modules/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "license": "MIT", @@ -2108,7 +2440,8 @@ }, "node_modules/braces": { "version": "3.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dependencies": { "fill-range": "^7.0.1" }, @@ -2168,11 +2501,6 @@ "randombytes": "^2.0.1" } }, - "node_modules/browserify-rsa/node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" - }, "node_modules/browserify-sign": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", @@ -2189,20 +2517,25 @@ "safe-buffer": "^5.2.0" } }, - "node_modules/browserify-sign/node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" - }, "node_modules/browserslist": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz", - "integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==", + "version": "4.20.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz", + "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], "dependencies": { - "caniuse-lite": "^1.0.30001286", - "electron-to-chromium": "^1.4.17", + "caniuse-lite": "^1.0.30001317", + "electron-to-chromium": "^1.4.84", "escalade": "^3.1.1", - "node-releases": "^2.0.1", + "node-releases": "^2.0.2", "picocolors": "^1.0.0" }, "bin": { @@ -2210,10 +2543,6 @@ }, "engines": { "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" } }, "node_modules/bs58": { @@ -2282,14 +2611,66 @@ "node": ">=6.14.2" } }, + "node_modules/builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=" + }, "node_modules/bytes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", - "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "engines": { "node": ">= 0.8" } }, + "node_modules/cacache": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.0.1.tgz", + "integrity": "sha512-tHPtfdZDqQpZ15eaEZeLspIqS5mK5fOBDZi6AjuqaIi53QNVXH3dQv6uKT3YuUu6uxV/8pjU9in0CoJ8fgaHqw==", + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.1.2", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^7.2.0", + "infer-owner": "^1.0.4", + "lru-cache": "^7.5.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.1.11", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.5.1.tgz", + "integrity": "sha512-q1TS8IqKvcg3aScamKCHpepSrHF537Ww7nHahBOxhDu9D2YoBXAsj/7uFdZFj1xJr9LmyeJ62AdyofCHafUbIA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/cacache/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/cacheable-request": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", @@ -2342,8 +2723,9 @@ }, "node_modules/callsites": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } @@ -2359,9 +2741,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001299", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001299.tgz", - "integrity": "sha512-iujN4+x7QzqA2NCSrS5VUy+4gLmRd4xv6vbBBsmfVqTx8bLAD8097euLqQgKxSVLvxjSDcvF1T/i9ocgnUFexw==", + "version": "1.0.30001317", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001317.tgz", + "integrity": "sha512-xIZLh8gBm4dqNX0gkzrBeyI86J2eCjWzYAs40q88smG844YIrN4tVQl/RhquHvKEKImWWFIVh1Lxe5n1G/N+GQ==", "funding": { "type": "opencollective", "url": "https://opencollective.com/browserslist" @@ -2373,13 +2755,15 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "node_modules/chai": { - "version": "4.3.4", - "license": "MIT", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", + "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", "deep-eql": "^3.0.1", "get-func-name": "^2.0.0", + "loupe": "^2.3.1", "pathval": "^1.1.1", "type-detect": "^4.0.5" }, @@ -2397,6 +2781,15 @@ "chai": ">= 2.1.2 < 5" } }, + "node_modules/chai-bn": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/chai-bn/-/chai-bn-0.3.1.tgz", + "integrity": "sha512-vuzEy0Cb+k8zqi2SHOmvZdRSbKcSOJfS1Nv8+6YDJIyCzfxkTCHLNRyjRIoRJ3WJtYb/c7OHjrvLoGeyO4A/gA==", + "peerDependencies": { + "bn.js": "^5.0.0", + "chai": "^4.0.0" + } + }, "node_modules/chalk": { "version": "4.1.2", "license": "MIT", @@ -2429,29 +2822,43 @@ } }, "node_modules/chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], "dependencies": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "glob-parent": "~5.1.0", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "readdirp": "~3.6.0" }, "engines": { "node": ">= 8.10.0" }, "optionalDependencies": { - "fsevents": "~2.3.1" + "fsevents": "~2.3.2" } }, "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" }, "node_modules/cids": { "version": "0.7.5", @@ -2480,6 +2887,11 @@ "varint": "^5.0.0" } }, + "node_modules/cint": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/cint/-/cint-8.2.1.tgz", + "integrity": "sha1-cDhrG0jidz0NYxZqVa/5TvRFahI=" + }, "node_modules/cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -2494,6 +2906,36 @@ "resolved": "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz", "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==" }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz", + "integrity": "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==", + "dependencies": { + "colors": "1.0.3" + }, + "engines": { + "node": ">= 0.2.0" + } + }, "node_modules/cliui": { "version": "7.0.4", "license": "ISC", @@ -2538,6 +2980,22 @@ "version": "1.1.4", "license": "MIT" }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -2549,6 +3007,14 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.0.0.tgz", + "integrity": "sha512-JJfP2saEKbQqvW+FI93OYUB4ByV5cizMpFMiiJI8xDbBvQvSkIk0VvQdn1CZ8mqAO8Loq2h0gYTYtDFUZUeERw==", + "engines": { + "node": "^12.20.0 || >=14" + } + }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -2558,6 +3024,41 @@ "version": "0.0.1", "license": "MIT" }, + "node_modules/configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dependencies": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/configstore/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -2601,9 +3102,9 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", "engines": { "node": ">= 0.6" } @@ -2636,12 +3137,12 @@ } }, "node_modules/crc-32": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", - "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.1.tgz", + "integrity": "sha512-Dn/xm/1vFFgs3nfrpEVScHoIslO9NZRITWGz/1E/St6u4xw99vfZzVkW0OSnzx2h9egej9xwMCEut6sqwokM/w==", "dependencies": { "exit-on-epipe": "~1.0.1", - "printj": "~1.1.0" + "printj": "~1.3.1" }, "bin": { "crc32": "bin/crc32.njs" @@ -2659,6 +3160,11 @@ "elliptic": "^6.5.3" } }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "node_modules/create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", @@ -2723,6 +3229,14 @@ "node": "*" } }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "engines": { + "node": ">=8" + } + }, "node_modules/d": { "version": "1.0.1", "license": "ISC", @@ -2744,14 +3258,16 @@ }, "node_modules/dateformat": { "version": "4.6.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", "engines": { "node": "*" } }, "node_modules/debug": { - "version": "4.3.2", - "license": "MIT", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "dependencies": { "ms": "2.1.2" }, @@ -2807,6 +3323,14 @@ "node": ">=0.12" } }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/deep-is": { "version": "0.1.4", "dev": true, @@ -2835,6 +3359,11 @@ "node": ">=0.4.0" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, "node_modules/depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -2874,11 +3403,15 @@ "randombytes": "^2.0.0" } }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, "dependencies": { "path-type": "^4.0.0" }, @@ -2902,6 +3435,17 @@ "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -2930,9 +3474,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "node_modules/electron-to-chromium": { - "version": "1.4.44", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.44.tgz", - "integrity": "sha512-tHGWiUUmY7GABK8+DNcr474cnZDTzD8x1736SlDosVH8+/vRJeqfaIBAEHFtMjddz/0T4rKKYsxEc8BwQRdBpw==" + "version": "1.4.85", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.85.tgz", + "integrity": "sha512-K9AsQ41WS2bjZUFpRWfvaS4RjEcRCamEkBJN1Z1TQILBfP1H8QnJ9ti0wiLiMv0sRjX3EHKzgs9jDnmGFx2jXg==" }, "node_modules/elliptic": { "version": "6.5.4", @@ -2948,6 +3492,11 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "node_modules/emoji-regex": { "version": "8.0.0", "license": "MIT" @@ -2960,6 +3509,15 @@ "node": ">= 0.8" } }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -2968,6 +3526,19 @@ "once": "^1.4.0" } }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" + }, "node_modules/es-abstract": { "version": "1.19.1", "license": "MIT", @@ -3053,9 +3624,18 @@ "node": ">=6" } }, + "node_modules/escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "engines": { + "node": ">=8" + } + }, "node_modules/escape-html": { "version": "1.0.3", - "license": "MIT" + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, "node_modules/escape-string-regexp": { "version": "4.0.0", @@ -3068,12 +3648,12 @@ } }, "node_modules/eslint": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.7.0.tgz", - "integrity": "sha512-ifHYzkBGrzS2iDU7KjhCAVMGCvF6M3Xfs8X8b37cgrUlDt6bWRTpRh6T/gtSXv1HJ/BUGgmjvNvOEGu85Iif7w==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.11.0.tgz", + "integrity": "sha512-/KRpd9mIRg2raGxHRGwW9ZywYNAClZrHjdueHcrVDuO3a6bj83eoTirCCk0M0yPwOjWYKHwRVRid+xK4F/GHgA==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.0.5", + "@eslint/eslintrc": "^1.2.1", "@humanwhocodes/config-array": "^0.9.2", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -3081,10 +3661,10 @@ "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.0", + "eslint-scope": "^7.1.1", "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.2.0", - "espree": "^9.3.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -3169,18 +3749,19 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz", - "integrity": "sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.0", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -3191,8 +3772,9 @@ }, "node_modules/eslint/node_modules/estraverse": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -3208,14 +3790,30 @@ "node": ">=10.13.0" } }, + "node_modules/eslint/node_modules/globals": { + "version": "13.13.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", + "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/espree": { - "version": "9.3.0", + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", + "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.7.0", "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.1.0" + "eslint-visitor-keys": "^3.3.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3242,8 +3840,9 @@ }, "node_modules/esrecurse": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -3253,8 +3852,9 @@ }, "node_modules/esrecurse/node_modules/estraverse": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -3311,6 +3911,11 @@ "xhr-request-promise": "^0.1.2" } }, + "node_modules/eth-lib/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "node_modules/ethereum-bloom-filters": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz", @@ -3342,9 +3947,9 @@ } }, "node_modules/ethereumjs-util": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.3.tgz", - "integrity": "sha512-y+82tEbyASO0K0X1/SRhbJJoAlfcvq8JbrG4a5cjrOks7HS/36efU/0j2flxCPOUM++HFahk33kr/ZxyC4vNuw==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.4.tgz", + "integrity": "sha512-p6KmuPCX4mZIqsQzXfmSx9Y0l2hqf+VkAiwSisW3UKUFdk8ZkAt+AYaor83z2nSi6CU2zSsXMlD80hAbNEGM0A==", "dependencies": { "@types/bn.js": "^5.1.0", "bn.js": "^5.1.2", @@ -3356,19 +3961,6 @@ "node": ">=10.0.0" } }, - "node_modules/ethereumjs-util/node_modules/@types/bn.js": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", - "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/ethereumjs-util/node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" - }, "node_modules/ethjs-unit": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", @@ -3410,16 +4002,16 @@ } }, "node_modules/express": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.2.tgz", - "integrity": "sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg==", + "version": "4.17.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", + "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", "dependencies": { - "accepts": "~1.3.7", + "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.1", + "body-parser": "1.19.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.1", + "cookie": "0.4.2", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "~1.1.2", @@ -3434,7 +4026,7 @@ "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.7", - "qs": "6.9.6", + "qs": "6.9.7", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.17.2", @@ -3494,7 +4086,6 @@ "version": "3.2.11", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -3515,15 +4106,24 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-memoize": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz", + "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==" + }, "node_modules/fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, "dependencies": { "reusify": "^1.0.4" } }, + "node_modules/figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==" + }, "node_modules/file-entry-cache": { "version": "6.0.1", "dev": true, @@ -3537,7 +4137,8 @@ }, "node_modules/fill-range": { "version": "7.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -3659,6 +4260,14 @@ "node": ">= 0.6" } }, + "node_modules/fp-and-or": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/fp-and-or/-/fp-and-or-0.1.3.tgz", + "integrity": "sha512-wJaE62fLaB3jCYvY2ZHjZvmKK2iiLiiehX38rz5QZxtdN8fVPJDeZUiVvJrHStdTc+23LHlyZuSEKgFc0pxi2g==", + "engines": { + "node": ">=10" + } + }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -3668,8 +4277,9 @@ } }, "node_modules/fs-extra": { - "version": "10.0.0", - "license": "MIT", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", + "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -3680,11 +4290,14 @@ } }, "node_modules/fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dependencies": { - "minipass": "^2.6.0" + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" } }, "node_modules/fs.realpath": { @@ -3706,7 +4319,8 @@ }, "node_modules/fsu": { "version": "1.1.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/fsu/-/fsu-1.1.1.tgz", + "integrity": "sha512-xQVsnjJ/5pQtcKh+KjUoZGzVWn4uNkchxTF6Lwjr4Gf7nQr8fmUfhKJ62zE77+xQg9xnxi5KUps7XGs+VC986A==" }, "node_modules/function-bind": { "version": "1.1.1", @@ -3717,6 +4331,24 @@ "dev": true, "license": "MIT" }, + "node_modules/gauge": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.3.tgz", + "integrity": "sha512-ICw1DhAwMtb22rYFwEHgJcx1JCwJGv3x6G0OQUq56Nge+H4Q8JEwr8iveS0XFlsUNSI67F5ffMGK25bK4Pmskw==", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -3751,6 +4383,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-stdin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -3785,9 +4428,9 @@ } }, "node_modules/glob": { - "version": "7.1.7", - "dev": true, - "license": "ISC", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3805,7 +4448,8 @@ }, "node_modules/glob-parent": { "version": "5.1.2", - "license": "ISC", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dependencies": { "is-glob": "^4.0.1" }, @@ -3822,25 +4466,40 @@ "process": "^0.11.10" } }, - "node_modules/globals": { - "version": "13.12.0", - "dev": true, - "license": "MIT", + "node_modules/global-dirs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", + "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", "dependencies": { - "type-fest": "^0.20.2" + "ini": "2.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/global-dirs/node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -3995,6 +4654,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "node_modules/has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "engines": { + "node": ">=8" + } + }, "node_modules/hash-base": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", @@ -4034,6 +4706,17 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", @@ -4059,6 +4742,19 @@ "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", "integrity": "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=" }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -4073,12 +4769,33 @@ "npm": ">=1.3.7" } }, + "node_modules/https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "dependencies": { + "ms": "^2.0.0" + } + }, "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" @@ -4124,16 +4841,27 @@ }, "node_modules/ignore": { "version": "5.2.0", - "dev": true, "license": "MIT", "engines": { "node": ">= 4" } }, + "node_modules/ignore-walk": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-4.0.1.tgz", + "integrity": "sha512-rzDQLaW4jQbh2YrOFlJdCtX8qgJTehFRYiUB2r1osqTeDzV/3+Jh8fz1oAPzUThf3iku8Ds4IDqawI5d8mUiQw==", + "dependencies": { + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/import-fresh": { "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, - "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -4145,14 +4873,34 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "engines": { + "node": ">=4" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", - "dev": true, "license": "MIT", "engines": { "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" + }, "node_modules/inflight": { "version": "1.0.6", "license": "ISC", @@ -4165,6 +4913,11 @@ "version": "2.0.4", "license": "ISC" }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, "node_modules/internal-slot": { "version": "1.0.3", "license": "MIT", @@ -4177,6 +4930,11 @@ "node": ">= 0.4" } }, + "node_modules/ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, "node_modules/ip-regex": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", @@ -4252,6 +5010,28 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-date-object": { "version": "1.0.5", "license": "MIT", @@ -4316,6 +5096,26 @@ "npm": ">=3" } }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=" + }, "node_modules/is-nan": { "version": "1.3.2", "dev": true, @@ -4341,9 +5141,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-npm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-number": { "version": "7.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "engines": { "node": ">=0.12.0" } @@ -4361,6 +5173,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "engines": { + "node": ">=8" + } + }, "node_modules/is-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", @@ -4369,6 +5189,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-obj": { "version": "2.1.0", "license": "MIT", @@ -4471,6 +5299,17 @@ "version": "1.0.0", "license": "MIT" }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-weakref": { "version": "1.0.2", "license": "MIT", @@ -4481,6 +5320,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" + }, "node_modules/isexe": { "version": "2.0.0", "license": "ISC" @@ -4510,6 +5354,11 @@ "node": ">= 4" } }, + "node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=" + }, "node_modules/js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", @@ -4521,7 +5370,6 @@ }, "node_modules/js-yaml": { "version": "4.1.0", - "dev": true, "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -4551,6 +5399,19 @@ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/json-parse-helpfulerror": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz", + "integrity": "sha1-E/FM4C7tTpgSl7ZOueO5MuLdE9w=", + "dependencies": { + "jju": "^1.1.0" + } + }, "node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", @@ -4573,6 +5434,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, "dependencies": { "minimist": "^1.2.0" }, @@ -4582,7 +5444,8 @@ }, "node_modules/jsonfile": { "version": "6.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dependencies": { "universalify": "^2.0.0" }, @@ -4590,6 +5453,19 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonlines": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsonlines/-/jsonlines-0.1.1.tgz", + "integrity": "sha1-T80kbcXQ44aRkHxEqwAveC0dlMw=" + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "engines": [ + "node >= 0.2.0" + ] + }, "node_modules/jsprim": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", @@ -4634,6 +5510,25 @@ "node": ">=0.10.0" } }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, + "node_modules/latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dependencies": { + "package-json": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/levn": { "version": "0.4.1", "dev": true, @@ -4646,6 +5541,72 @@ "node": ">= 0.8.0" } }, + "node_modules/libnpmconfig": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/libnpmconfig/-/libnpmconfig-1.2.1.tgz", + "integrity": "sha512-9esX8rTQAHqarx6qeZqmGQKBNZR5OIbl/Ayr0qQDy3oXja2iFVQQI81R6GZ2a02bSNZ9p3YOGX1O6HHCb1X7kA==", + "dependencies": { + "figgy-pudding": "^3.5.1", + "find-up": "^3.0.0", + "ini": "^1.3.5" + } + }, + "node_modules/libnpmconfig/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/libnpmconfig/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/libnpmconfig/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/libnpmconfig/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/libnpmconfig/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "engines": { + "node": ">=4" + } + }, "node_modules/locate-path": { "version": "6.0.0", "license": "MIT", @@ -4659,13 +5620,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "node_modules/lodash.isempty": { "version": "4.4.0", "license": "MIT" }, "node_modules/lodash.isfunction": { "version": "3.0.9", - "license": "MIT" + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" }, "node_modules/lodash.isobject": { "version": "3.0.2", @@ -4686,19 +5653,24 @@ "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=" }, "node_modules/log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dependencies": { - "chalk": "^4.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/loose-envify": { "version": "1.4.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -4706,7 +5678,15 @@ "loose-envify": "cli.js" } }, - "node_modules/lowercase-keys": { + "node_modules/loupe": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.1.tgz", + "integrity": "sha512-EN1D3jyVmaX4tnajVlfbREU4axL647hLec1h/PXAb8CPDMJiYitcWF2UeLVNttRqaIqQs4x+mRvXf+d+TlDrCA==", + "dependencies": { + "get-func-name": "^2.0.0" + } + }, + "node_modules/lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", @@ -4716,7 +5696,6 @@ }, "node_modules/lru-cache": { "version": "6.0.0", - "dev": true, "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -4750,6 +5729,40 @@ "dev": true, "license": "ISC" }, + "node_modules/make-fetch-happen": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.0.6.tgz", + "integrity": "sha512-4Gfh6lV3TLXmj7qz79hBFuvVqjYSMW6v2+sxtdX4LFQU0rK3V/txRjE0DoZb7X0IF3t9f8NO3CxPSWlvdckhVA==", + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.0.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.5.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.1.1", + "ssri": "^8.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.5.1.tgz", + "integrity": "sha512-q1TS8IqKvcg3aScamKCHpepSrHF537Ww7nHahBOxhDu9D2YoBXAsj/7uFdZFj1xJr9LmyeJ62AdyofCHafUbIA==", + "engines": { + "node": ">=12" + } + }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -4777,7 +5790,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, "engines": { "node": ">= 8" } @@ -4790,17 +5802,10 @@ "node": ">= 0.6" } }, - "node_modules/micro-base": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/micro-base/-/micro-base-0.10.2.tgz", - "integrity": "sha512-lqqJrT7lfJtDmmiQ4zRLZuIJBk96t0RAc5pCrrWpL9zDeH5i/SUL85mku9HqzTI/OCZ8EQ3aicbMW+eK5Nyu5w==", - "deprecated": "Switch to @scure/base for audited version of the lib & updates" - }, "node_modules/micromatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, "dependencies": { "braces": "^3.0.1", "picomatch": "^2.2.3" @@ -4821,6 +5826,11 @@ "miller-rabin": "bin/miller-rabin" } }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -4833,19 +5843,19 @@ } }, "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { - "mime-db": "1.51.0" + "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" @@ -4893,25 +5903,95 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "node_modules/minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", + "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", "dependencies": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/minipass/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.0.3.tgz", + "integrity": "sha512-VA+eiiUtaIvpQJXISwE3OiMvQwAWrgKb97F0aXlCS1Ahikr8fEQq8m3Hf7Kv9KT3nokuHigJKsDMB6atU04olQ==", + "dependencies": { + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-json-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", + "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", + "dependencies": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } }, "node_modules/minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dependencies": { - "minipass": "^2.9.0" + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" } }, "node_modules/mkdirp": { @@ -4938,32 +6018,31 @@ } }, "node_modules/mocha": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", - "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", + "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", "dependencies": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.5.1", - "debug": "4.3.1", + "chokidar": "3.5.3", + "debug": "4.3.3", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.1.6", + "glob": "7.2.0", "growl": "1.10.5", "he": "1.2.0", - "js-yaml": "4.0.0", - "log-symbols": "4.0.0", - "minimatch": "3.0.4", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "4.2.1", "ms": "2.1.3", - "nanoid": "3.1.20", - "serialize-javascript": "5.0.1", + "nanoid": "3.3.1", + "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.1.0", + "workerpool": "6.2.0", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" @@ -4973,7 +6052,7 @@ "mocha": "bin/mocha" }, "engines": { - "node": ">= 10.12.0" + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", @@ -4989,60 +6068,21 @@ "mocha": ">=1.0.0" } }, - "node_modules/mocha/node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/mocha/node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/mocha/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "node_modules/mocha/node_modules/minimatch": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", + "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", "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" + "brace-expansion": "^1.1.7" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", - "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "node": ">=10" } }, "node_modules/mochawesome": { - "version": "7.0.1", - "license": "MIT", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/mochawesome/-/mochawesome-7.1.2.tgz", + "integrity": "sha512-kZBHRYoiV+zPrqMO0TU4LOiYDCMR5ciBZEE6fvS6RFMtB2MMndeOQ2LQEpFHtPG8yxFsqg1F6gym5qo3rPs/XA==", "dependencies": { "chalk": "^4.1.2", "diff": "^5.0.0", @@ -5051,7 +6091,7 @@ "lodash.isfunction": "^3.0.9", "lodash.isobject": "^3.0.2", "lodash.isstring": "^4.0.1", - "mochawesome-report-generator": "^6.0.1", + "mochawesome-report-generator": "^6.1.1", "strip-ansi": "^6.0.1", "uuid": "^8.3.2" }, @@ -5060,8 +6100,9 @@ } }, "node_modules/mochawesome-report-generator": { - "version": "6.0.1", - "license": "MIT", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/mochawesome-report-generator/-/mochawesome-report-generator-6.1.1.tgz", + "integrity": "sha512-wTYGAH2KHOSDi7eSvwniq+h4Wvrvt+Bd4mz8774HOHTcxRTECh5zjvG5fP+/VvPbhzsjOlIsylZaOVEdwZlfJg==", "dependencies": { "chalk": "^4.1.2", "dateformat": "^4.5.1", @@ -5082,7 +6123,8 @@ }, "node_modules/mochawesome-report-generator/node_modules/yargs": { "version": "17.3.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", + "integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -5097,8 +6139,9 @@ } }, "node_modules/mochawesome-report-generator/node_modules/yargs-parser": { - "version": "21.0.0", - "license": "ISC", + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", "engines": { "node": ">=12" } @@ -5165,9 +6208,9 @@ "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=" }, "node_modules/nanoid": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", - "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -5181,9 +6224,9 @@ "license": "MIT" }, "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "engines": { "node": ">= 0.6" } @@ -5198,9 +6241,9 @@ "license": "MIT" }, "node_modules/nock": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.2.2.tgz", - "integrity": "sha512-PcBHuvl9i6zfaJ50A7LS55oU+nFLv8htXIhffJO+FxyfibdZ4jEvd9kTuvkrJireBFIGMZ+oUIRpMK5gU9h//g==", + "version": "13.2.4", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.2.4.tgz", + "integrity": "sha512-8GPznwxcPNCH/h8B+XZcKjYPXnUV5clOKCjAqyjsiqA++MpNx9E9+t8YPp0MbThO+KauRo7aZJ1WuIZmOrT2Ug==", "dependencies": { "debug": "^4.1.0", "json-stringify-safe": "^5.0.1", @@ -5235,6 +6278,29 @@ } } }, + "node_modules/node-gyp": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.0.0.tgz", + "integrity": "sha512-Ma6p4s+XCTPxCuAMrOA/IJRmVy16R8Sdhtwl4PrCr7IBlj4cPawF0vg/l7nOT1jPbuNS7lIRJpBSvVsXwEZuzw==", + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^10.0.3", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^12.22 || ^14.13 || >=16" + } + }, "node_modules/node-gyp-build": { "version": "4.3.0", "license": "MIT", @@ -5244,25 +6310,336 @@ "node-gyp-build-test": "build-test.js" } }, - "node_modules/node-releases": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", - "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==" + "node_modules/node-gyp/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-releases": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", + "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==" + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-package-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.0.tgz", + "integrity": "sha512-m+GL22VXJKkKbw62ZaBBjv8u6IE3UI4Mh5QakIqs3fWiKe0Xyi6L97hakwZK41/LD4R/2ly71Bayx0NLMwLA/g==", + "dependencies": { + "hosted-git-info": "^5.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/normalize-package-data/node_modules/hosted-git-info": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.0.0.tgz", + "integrity": "sha512-rRnjWu0Bxj+nIfUOkz0695C0H6tRrN5iYIzYejb0tDEefe2AekHu/U5Kn9pEie5vsJqpNQU02az7TGSH3qpz4Q==", + "dependencies": { + "lru-cache": "^7.5.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/normalize-package-data/node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.5.1.tgz", + "integrity": "sha512-q1TS8IqKvcg3aScamKCHpepSrHF537Ww7nHahBOxhDu9D2YoBXAsj/7uFdZFj1xJr9LmyeJ62AdyofCHafUbIA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm-bundled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", + "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", + "dependencies": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/npm-check-updates": { + "version": "12.5.3", + "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-12.5.3.tgz", + "integrity": "sha512-siFg/+Un+j4tLA6GJCnk6hz2YU4Yc5bftDnOoiSRLKL6NeAS3FScB32mtKNBtITMJf2nsoZSr8vH+wdUGeP19g==", + "dependencies": { + "chalk": "^4.1.2", + "cint": "^8.2.1", + "cli-table": "^0.3.11", + "commander": "^9.0.0", + "fast-memoize": "^2.5.2", + "find-up": "5.0.0", + "fp-and-or": "^0.1.3", + "get-stdin": "^8.0.0", + "globby": "^11.0.4", + "hosted-git-info": "^4.1.0", + "json-parse-helpfulerror": "^1.0.3", + "jsonlines": "^0.1.1", + "libnpmconfig": "^1.2.1", + "lodash": "^4.17.21", + "minimatch": "^5.0.1", + "p-map": "^4.0.0", + "pacote": "^13.0.3", + "parse-github-url": "^1.0.2", + "progress": "^2.0.3", + "prompts": "^2.4.2", + "rc-config-loader": "^4.0.0", + "remote-git-tags": "^3.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "semver-utils": "^1.1.4", + "source-map-support": "^0.5.21", + "spawn-please": "^1.0.0", + "update-notifier": "^5.1.0", + "yaml": "^1.10.2" + }, + "bin": { + "ncu": "build/src/bin/cli.js", + "npm-check-updates": "build/src/bin/cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/npm-check-updates/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/npm-check-updates/node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-check-updates/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-install-checks": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-4.0.0.tgz", + "integrity": "sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==", + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-install-checks/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + }, + "node_modules/npm-package-arg": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.0.1.tgz", + "integrity": "sha512-Xs9wznfEAmZAR61qsYH3iN24V/qMYYkvAR5CRQNMvC6PjN2fHtO8y9XP/xdp5K+Icx+u1wMBMgWRPCmAEChSog==", + "dependencies": { + "hosted-git-info": "^5.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/npm-package-arg/node_modules/hosted-git-info": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.0.0.tgz", + "integrity": "sha512-rRnjWu0Bxj+nIfUOkz0695C0H6tRrN5iYIzYejb0tDEefe2AekHu/U5Kn9pEie5vsJqpNQU02az7TGSH3qpz4Q==", + "dependencies": { + "lru-cache": "^7.5.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/npm-package-arg/node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.5.1.tgz", + "integrity": "sha512-q1TS8IqKvcg3aScamKCHpepSrHF537Ww7nHahBOxhDu9D2YoBXAsj/7uFdZFj1xJr9LmyeJ62AdyofCHafUbIA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/npm-package-arg/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-packlist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-4.0.0.tgz", + "integrity": "sha512-gL6XC/iw9YSmqArmZOGSkyy+yIZf2f7uH0p4Vmxef/irn73vd9/rDkCtvm+a9rh/QK2xGYfCAMOghM06ymzC0A==", + "dependencies": { + "glob": "^7.2.0", + "ignore-walk": "^4.0.1", + "npm-bundled": "^1.1.2", + "npm-normalize-package-bin": "^1.0.1" + }, + "bin": { + "npm-packlist": "bin/index.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/npm-pick-manifest": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-7.0.0.tgz", + "integrity": "sha512-njM1AcdioFaKd0JSGtLO09YA1WRwctjGQJbnHGmKS+u+uwP8oFvtZtOQWPYdxrnY5eJud3wn8OpH4sEIx6+GEQ==", + "dependencies": { + "npm-install-checks": "^4.0.0", + "npm-normalize-package-bin": "^1.0.1", + "npm-package-arg": "^9.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/npm-pick-manifest/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "node_modules/npm-registry-fetch": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-13.0.1.tgz", + "integrity": "sha512-Ak+LXVtSrCLOdscFW/apUw67OPNph8waHsPKM9UOJosL7i59EF5XoSWQMEsXEOeifM9Bb4/2+WrQC4t/pd8DGg==", + "dependencies": { + "make-fetch-happen": "^10.0.3", + "minipass": "^3.1.6", + "minipass-fetch": "^2.0.1", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^9.0.0", + "proc-log": "^2.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^12.13.0 || ^14.15.0 || >=16" } }, - "node_modules/normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "node_modules/npmlog": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.1.tgz", + "integrity": "sha512-BTHDvY6nrRHuRfyjt1MAufLxYdVXZfd099H4+i1f0lPywNQyI4foeNXJRObB/uy+TYqUW0vAD9gbdSOXPst7Eg==", + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.0", + "set-blocking": "^2.0.0" + }, "engines": { - "node": ">=8" + "node": "^12.13.0 || ^14.15.0 || >=16" } }, "node_modules/number-to-bn": { @@ -5293,7 +6670,8 @@ }, "node_modules/object-assign": { "version": "4.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "engines": { "node": ">=0.10.0" } @@ -5371,7 +6749,8 @@ }, "node_modules/opener": { "version": "1.5.2", - "license": "(WTFPL OR MIT)", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", "bin": { "opener": "bin/opener-bin.js" } @@ -5434,6 +6813,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-timeout": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", @@ -5453,10 +6846,70 @@ "node": ">=6" } }, + "node_modules/package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dependencies": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pacote": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-13.0.5.tgz", + "integrity": "sha512-6CYfot3/rUAn3qqzF2d/jrrXm5HlBtvaSgfmg0VtOUAdJ8fbSq21BJwftMGArkL71yXHIbUJ7Bt5B04547HELA==", + "dependencies": { + "@npmcli/git": "^3.0.0", + "@npmcli/installed-package-contents": "^1.0.7", + "@npmcli/promise-spawn": "^1.2.0", + "@npmcli/run-script": "^3.0.1", + "cacache": "^16.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "infer-owner": "^1.0.4", + "minipass": "^3.1.6", + "mkdirp": "^1.0.4", + "npm-package-arg": "^9.0.0", + "npm-packlist": "^4.0.0", + "npm-pick-manifest": "^7.0.0", + "npm-registry-fetch": "^13.0.1", + "proc-log": "^2.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^5.0.0", + "read-package-json-fast": "^2.0.3", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "lib/bin.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/pacote/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/parent-module": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, - "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -5476,10 +6929,21 @@ "safe-buffer": "^5.1.1" } }, + "node_modules/parse-github-url": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz", + "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==", + "bin": { + "parse-github-url": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/parse-headers": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.4.tgz", - "integrity": "sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz", + "integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==" }, "node_modules/parseurl": { "version": "1.3.3", @@ -5520,7 +6984,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, "engines": { "node": ">=8" } @@ -5559,7 +7022,8 @@ }, "node_modules/picomatch": { "version": "2.3.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "engines": { "node": ">=8.6" }, @@ -5576,9 +7040,9 @@ } }, "node_modules/pirates": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.4.tgz", - "integrity": "sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", "engines": { "node": ">= 6" } @@ -5667,9 +7131,9 @@ } }, "node_modules/printj": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", - "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.3.1.tgz", + "integrity": "sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg==", "bin": { "printj": "bin/printj.njs" }, @@ -5677,6 +7141,14 @@ "node": ">=0.8" } }, + "node_modules/proc-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.0.tgz", + "integrity": "sha512-I/35MfCX2H8jBUhKN8JB8nmqvQo/nKdrBodBY7L3RhDSPPyvOHwLYNmPuhwuJq7a7C3vgFKWGQM+ecPStcvOHA==", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -5685,9 +7157,47 @@ "node": ">= 0.6.0" } }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/prop-types": { "version": "15.8.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -5732,6 +7242,11 @@ "safe-buffer": "^5.1.2" } }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -5748,10 +7263,21 @@ "node": ">=6" } }, + "node_modules/pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dependencies": { + "escape-goat": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/qs": { - "version": "6.9.6", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", - "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==", + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", "engines": { "node": ">=0.6" }, @@ -5776,7 +7302,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -5827,11 +7352,11 @@ } }, "node_modules/raw-body": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", - "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", + "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", "dependencies": { - "bytes": "3.1.1", + "bytes": "3.1.2", "http-errors": "1.8.1", "iconv-lite": "0.4.24", "unpipe": "1.0.0" @@ -5840,9 +7365,94 @@ "node": ">= 0.8" } }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc-config-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rc-config-loader/-/rc-config-loader-4.0.0.tgz", + "integrity": "sha512-//LRTblJEcqbmmro1GCmZ39qZXD+JqzuD8Y5/IZU3Dhp3A1Yr0Xn68ks8MQ6qKfKvYCWDveUmRDKDA40c+sCXw==", + "dependencies": { + "debug": "^4.1.1", + "js-yaml": "^4.0.0", + "json5": "^2.1.2", + "require-from-string": "^2.0.2" + } + }, + "node_modules/rc-config-loader/node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react-is": { "version": "16.13.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/read-package-json": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-5.0.0.tgz", + "integrity": "sha512-1cjk2MV5ONDMn34uxSID3X8NY7VKsXfJnjbcVdFMvHEnJOBzU6MJ7/3yg6QFVZDq5/1yFNrKBUK9kGnonyGP2Q==", + "dependencies": { + "glob": "^7.2.0", + "json-parse-even-better-errors": "^2.3.1", + "normalize-package-data": "^4.0.0", + "npm-normalize-package-bin": "^1.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/read-package-json-fast": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz", + "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==", + "dependencies": { + "json-parse-even-better-errors": "^2.3.0", + "npm-normalize-package-bin": "^1.0.1" + }, + "engines": { + "node": ">=10" + } }, "node_modules/readable-stream": { "version": "3.6.0", @@ -5858,9 +7468,9 @@ } }, "node_modules/readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dependencies": { "picomatch": "^2.2.1" }, @@ -5870,7 +7480,8 @@ }, "node_modules/regenerator-runtime": { "version": "0.13.9", - "license": "MIT" + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" }, "node_modules/regexpp": { "version": "3.2.0", @@ -5883,6 +7494,36 @@ "url": "https://github.com/sponsors/mysticatea" } }, + "node_modules/registry-auth-token": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", + "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/remote-git-tags": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remote-git-tags/-/remote-git-tags-3.0.0.tgz", + "integrity": "sha512-C9hAO4eoEsX+OXA4rla66pXZQ+TLQ8T9dttgQj18yuKlPMTVkIkdYXvlMC55IuUsIkV6DpmQYi10JKFLaU+l7w==", + "engines": { + "node": ">=8" + } + }, "node_modules/request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", @@ -5951,10 +7592,19 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve-from": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -5967,11 +7617,18 @@ "lowercase-keys": "^1.0.0" } }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "engines": { + "node": ">= 4" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -5979,7 +7636,6 @@ }, "node_modules/rimraf": { "version": "3.0.2", - "dev": true, "license": "ISC", "dependencies": { "glob": "^7.1.3" @@ -6011,16 +7667,10 @@ "rlp": "bin/rlp" } }, - "node_modules/rlp/node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "funding": [ { "type": "github", @@ -6040,9 +7690,9 @@ } }, "node_modules/rxjs": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.2.tgz", - "integrity": "sha512-PwDt186XaL3QN5qXj/H9DGyHhP3/RYYgZZwqBv9Tv8rsAaiwFH1IsJJlcgD37J7UW5a6O67qX0KWKS3/pu0m4w==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", + "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", "dependencies": { "tslib": "^2.1.0" } @@ -6097,6 +7747,22 @@ "semver": "bin/semver.js" } }, + "node_modules/semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dependencies": { + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/semver-utils": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/semver-utils/-/semver-utils-1.1.4.tgz", + "integrity": "sha512-EjnoLE5OGmDAVV/8YDoN5KiajNadjzIp9BAHOhYeQHt7j0UWxjmgsx4YD48wp4Ue1Qogq38F1GNUJNqF1kKKxA==" + }, "node_modules/send": { "version": "0.17.2", "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", @@ -6134,9 +7800,9 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "node_modules/serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dependencies": { "randombytes": "^2.1.0" } @@ -6170,6 +7836,11 @@ "node": ">=6" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -6234,6 +7905,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, "node_modules/simple-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", @@ -6254,24 +7930,63 @@ ] }, "node_modules/simple-get": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", - "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.2.tgz", + "integrity": "sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw==", "dependencies": { "decompress-response": "^3.3.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, "engines": { "node": ">=8" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", + "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", + "dependencies": { + "ip": "^1.1.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz", + "integrity": "sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==", + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.1", + "socks": "^2.6.1" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/source-map": { "version": "0.6.1", "license": "BSD-3-Clause", @@ -6279,14 +7994,50 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "license": "MIT", + "node_modules/source-map-support": { + "version": "0.5.21", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spawn-please": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/spawn-please/-/spawn-please-1.0.0.tgz", + "integrity": "sha512-Kz33ip6NRNKuyTRo3aDWyWxeGeM0ORDO552Fs6E1nj4pLWPkl37SrRtTnq+MEopVaqgmaO6bAvVS+v64BJ5M/A==", + "engines": { + "node": ">=10" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, + "node_modules/spdx-license-ids": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==" + }, "node_modules/sshpk": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", @@ -6316,6 +8067,17 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -6388,6 +8150,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, "engines": { "node": ">=4" } @@ -6445,6 +8208,11 @@ "xhr-request": "^1.0.1" } }, + "node_modules/swarm-js/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, "node_modules/swarm-js/node_modules/fs-extra": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", @@ -6455,6 +8223,14 @@ "universalify": "^0.1.0" } }, + "node_modules/swarm-js/node_modules/fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dependencies": { + "minipass": "^2.6.0" + } + }, "node_modules/swarm-js/node_modules/get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", @@ -6503,6 +8279,23 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/swarm-js/node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/swarm-js/node_modules/minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dependencies": { + "minipass": "^2.9.0" + } + }, "node_modules/swarm-js/node_modules/p-cancelable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", @@ -6519,6 +8312,23 @@ "node": ">=0.10.0" } }, + "node_modules/swarm-js/node_modules/tar": { + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", + "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", + "dependencies": { + "chownr": "^1.1.4", + "fs-minipass": "^1.2.7", + "minipass": "^2.9.0", + "minizlib": "^1.3.3", + "mkdirp": "^0.5.5", + "safe-buffer": "^5.2.1", + "yallist": "^3.1.1" + }, + "engines": { + "node": ">=4.5" + } + }, "node_modules/swarm-js/node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -6538,35 +8348,47 @@ "node": ">=0.10.0" } }, + "node_modules/swarm-js/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, "node_modules/tar": { - "version": "4.4.19", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", - "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", - "dependencies": { - "chownr": "^1.1.4", - "fs-minipass": "^1.2.7", - "minipass": "^2.9.0", - "minizlib": "^1.3.3", - "mkdirp": "^0.5.5", - "safe-buffer": "^5.2.1", - "yallist": "^3.1.1" + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" }, "engines": { - "node": ">=4.5" + "node": ">= 10" } }, - "node_modules/tar/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } }, "node_modules/tcomb": { "version": "3.2.29", - "license": "MIT" + "resolved": "https://registry.npmjs.org/tcomb/-/tcomb-3.2.29.tgz", + "integrity": "sha512-di2Hd1DB2Zfw6StGv861JoAF5h/uQVu/QJp2g8KVbtfKnoHdBQl5M32YWq6mnSYBQ1vFFrns5B1haWJL7rKaOQ==" }, "node_modules/tcomb-validation": { "version": "3.4.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/tcomb-validation/-/tcomb-validation-3.4.1.tgz", + "integrity": "sha512-urVVMQOma4RXwiVCa2nM2eqrAomHROHvWPuj6UkDGz/eb5kcy0x6P0dVt6kzpUZtYMNoAqJLWmz1BPtxrtjtrA==", "dependencies": { "tcomb": "^3.0.0" } @@ -6602,7 +8424,8 @@ }, "node_modules/to-regex-range": { "version": "5.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dependencies": { "is-number": "^7.0.0" }, @@ -6636,9 +8459,9 @@ "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" }, "node_modules/ts-mocha": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/ts-mocha/-/ts-mocha-8.0.0.tgz", - "integrity": "sha512-Kou1yxTlubLnD5C3unlCVO7nh0HERTezjoVhVw/M5S1SqoUec0WgllQvPk3vzPMc6by8m6xD1uR1yRf8lnVUbA==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/ts-mocha/-/ts-mocha-9.0.2.tgz", + "integrity": "sha512-WyQjvnzwrrubl0JT7EC1yWmNpcsU3fOuBFfdps30zbmFBgKniSaSOyZMZx+Wq7kytUs5CY+pEbSYEbGfIKnXTw==", "dev": true, "dependencies": { "ts-node": "7.0.1" @@ -6653,7 +8476,7 @@ "tsconfig-paths": "^3.5.0" }, "peerDependencies": { - "mocha": "^3.X.X || ^4.X.X || ^5.X.X || ^6.X.X || ^7.X.X || ^8.X.X" + "mocha": "^3.X.X || ^4.X.X || ^5.X.X || ^6.X.X || ^7.X.X || ^8.X.X || ^9.X.X" } }, "node_modules/ts-mocha/node_modules/diff": { @@ -6697,9 +8520,9 @@ } }, "node_modules/ts-node": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz", - "integrity": "sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==", + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", + "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", "dev": true, "dependencies": { "@cspotcode/source-map-support": "0.7.0", @@ -6713,11 +8536,13 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.0", "yn": "3.1.1" }, "bin": { "ts-node": "dist/bin.js", "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js", "ts-script": "dist/bin-script-deprecated.js" @@ -6751,9 +8576,10 @@ "integrity": "sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==" }, "node_modules/tsconfig-paths": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", - "integrity": "sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.0.tgz", + "integrity": "sha512-cg/1jAZoL57R39+wiw4u/SCC6Ic9Q5NqjBOb+9xISedOYurfog9ZNmKJSxAnb2m/5Bq4lE9lhUcau33Ml8DM0g==", + "dev": true, "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.1", @@ -6827,7 +8653,6 @@ }, "node_modules/type-fest": { "version": "0.20.2", - "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" @@ -6856,9 +8681,10 @@ } }, "node_modules/typescript": { - "version": "4.5.4", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", + "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", "dev": true, - "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6897,9 +8723,37 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/universalify": { "version": "2.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "engines": { "node": ">= 10.0.0" } @@ -6912,6 +8766,47 @@ "node": ">= 0.8" } }, + "node_modules/update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "dependencies": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" + } + }, + "node_modules/update-notifier/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/uri-js": { "version": "4.4.1", "license": "BSD-2-Clause", @@ -6996,9 +8891,33 @@ "dev": true, "license": "MIT" }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz", + "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "dependencies": { + "builtins": "^1.0.3" + } + }, "node_modules/validator": { "version": "13.7.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", "engines": { "node": ">= 0.10" } @@ -7030,27 +8949,27 @@ } }, "node_modules/web3": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3/-/web3-1.7.0.tgz", - "integrity": "sha512-n39O7QQNkpsjhiHMJ/6JY6TaLbdX+2FT5iGs8tb3HbIWOhPm4+a7UDbr5Lkm+gLa9aRKWesZs5D5hWyEvg4aJA==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.7.1.tgz", + "integrity": "sha512-RKVdyZ5FuVEykj62C1o2tc0teJciSOh61jpVB9yb344dBHO3ZV4XPPP24s/PPqIMXmVFN00g2GD9M/v1SoHO/A==", "hasInstallScript": true, "dependencies": { - "web3-bzz": "1.7.0", - "web3-core": "1.7.0", - "web3-eth": "1.7.0", - "web3-eth-personal": "1.7.0", - "web3-net": "1.7.0", - "web3-shh": "1.7.0", - "web3-utils": "1.7.0" + "web3-bzz": "1.7.1", + "web3-core": "1.7.1", + "web3-eth": "1.7.1", + "web3-eth-personal": "1.7.1", + "web3-net": "1.7.1", + "web3-shh": "1.7.1", + "web3-utils": "1.7.1" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-bzz": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.7.0.tgz", - "integrity": "sha512-XPhTWUnZa8gnARfiqaag3jJ9+6+a66Li8OikgBUJoMUqPuQTCJPncTbGYqOJIfRFGavEAdlMnfYXx9lvgv2ZPw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.7.1.tgz", + "integrity": "sha512-sVeUSINx4a4pfdnT+3ahdRdpDPvZDf4ZT/eBF5XtqGWq1mhGTl8XaQAk15zafKVm6Onq28vN8abgB/l+TrG8kA==", "hasInstallScript": true, "dependencies": { "@types/node": "^12.12.6", @@ -7062,58 +8981,58 @@ } }, "node_modules/web3-bzz/node_modules/@types/node": { - "version": "12.20.42", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.42.tgz", - "integrity": "sha512-aI3/oo5DzyiI5R/xAhxxRzfZlWlsbbqdgxfTPkqu/Zt+23GXiJvMCyPJT4+xKSXOnLqoL8jJYMLTwvK2M3a5hw==" + "version": "12.20.47", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.47.tgz", + "integrity": "sha512-BzcaRsnFuznzOItW1WpQrDHM7plAa7GIDMZ6b5pnMbkqEtM/6WCOhvZar39oeMQP79gwvFUWjjptE7/KGcNqFg==" }, "node_modules/web3-core": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.7.0.tgz", - "integrity": "sha512-U/CRL53h3T5KHl8L3njzCBT7fCaHkbE6BGJe3McazvFldRbfTDEHXkUJCyM30ZD0RoLi3aDfTVeFIusmEyCctA==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.7.1.tgz", + "integrity": "sha512-HOyDPj+4cNyeNPwgSeUkhtS0F+Pxc2obcm4oRYPW5ku6jnTO34pjaij0us+zoY3QEusR8FfAKVK1kFPZnS7Dzw==", "dependencies": { "@types/bn.js": "^4.11.5", "@types/node": "^12.12.6", "bignumber.js": "^9.0.0", - "web3-core-helpers": "1.7.0", - "web3-core-method": "1.7.0", - "web3-core-requestmanager": "1.7.0", - "web3-utils": "1.7.0" + "web3-core-helpers": "1.7.1", + "web3-core-method": "1.7.1", + "web3-core-requestmanager": "1.7.1", + "web3-utils": "1.7.1" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-core-helpers": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.7.0.tgz", - "integrity": "sha512-kFiqsZFHJliKF8VKZNjt2JvKu3gu7h3N1/ke3EPhdp9Li/rLmiyzFVr6ApryZ1FSjbSx6vyOkibG3m6xQ5EHJA==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.7.1.tgz", + "integrity": "sha512-xn7Sx+s4CyukOJdlW8bBBDnUCWndr+OCJAlUe/dN2wXiyaGRiCWRhuQZrFjbxLeBt1fYFH7uWyYHhYU6muOHgw==", "dependencies": { - "web3-eth-iban": "1.7.0", - "web3-utils": "1.7.0" + "web3-eth-iban": "1.7.1", + "web3-utils": "1.7.1" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-core-method": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.7.0.tgz", - "integrity": "sha512-43Om+kZX8wU5u1pJ28TltF9e9pSTRph6b8wrOb6wgXAfPHqMulq6UTBJWjXXIRVN46Eiqv0nflw35hp9bbgnbA==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.7.1.tgz", + "integrity": "sha512-383wu5FMcEphBFl5jCjk502JnEg3ugHj7MQrsX7DY76pg5N5/dEzxeEMIJFCN6kr5Iq32NINOG3VuJIyjxpsEg==", "dependencies": { "@ethersproject/transactions": "^5.0.0-beta.135", - "web3-core-helpers": "1.7.0", - "web3-core-promievent": "1.7.0", - "web3-core-subscriptions": "1.7.0", - "web3-utils": "1.7.0" + "web3-core-helpers": "1.7.1", + "web3-core-promievent": "1.7.1", + "web3-core-subscriptions": "1.7.1", + "web3-utils": "1.7.1" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-core-promievent": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.7.0.tgz", - "integrity": "sha512-xPH66XeC0K0k29GoRd0vyPQ07yxERPRd4yVPrbMzGAz/e9E4M3XN//XK6+PdfGvGw3fx8VojS+tNIMiw+PujbQ==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.7.1.tgz", + "integrity": "sha512-Vd+CVnpPejrnevIdxhCkzMEywqgVbhHk/AmXXceYpmwA6sX41c5a65TqXv1i3FWRJAz/dW7oKz9NAzRIBAO/kA==", "dependencies": { "eventemitter3": "4.0.4" }, @@ -7127,27 +9046,27 @@ "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==" }, "node_modules/web3-core-requestmanager": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.7.0.tgz", - "integrity": "sha512-rA3dBTBPrt+eIfTAQ2/oYNTN/2wbZaYNR3pFZGqG8+2oCK03+7oQyz4sWISKy/nYQhURh4GK01rs9sN4o/Tq9w==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.7.1.tgz", + "integrity": "sha512-/EHVTiMShpZKiq0Jka0Vgguxi3vxq1DAHKxg42miqHdUsz4/cDWay2wGALDR2x3ofDB9kqp7pb66HsvQImQeag==", "dependencies": { "util": "^0.12.0", - "web3-core-helpers": "1.7.0", - "web3-providers-http": "1.7.0", - "web3-providers-ipc": "1.7.0", - "web3-providers-ws": "1.7.0" + "web3-core-helpers": "1.7.1", + "web3-providers-http": "1.7.1", + "web3-providers-ipc": "1.7.1", + "web3-providers-ws": "1.7.1" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-core-subscriptions": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.7.0.tgz", - "integrity": "sha512-6giF8pyJrPmWrRpc2WLoVCvQdMMADp20ZpAusEW72axauZCNlW1XfTjs0i4QHQBfdd2lFp65qad9IuATPhuzrQ==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.7.1.tgz", + "integrity": "sha512-NZBsvSe4J+Wt16xCf4KEtBbxA9TOwSVr8KWfUQ0tC2KMdDYdzNswl0Q9P58xaVuNlJ3/BH+uDFZJJ5E61BSA1Q==", "dependencies": { "eventemitter3": "4.0.4", - "web3-core-helpers": "1.7.0" + "web3-core-helpers": "1.7.1" }, "engines": { "node": ">=8.0.0" @@ -7158,49 +9077,57 @@ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==" }, + "node_modules/web3-core/node_modules/@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/web3-core/node_modules/@types/node": { - "version": "12.20.42", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.42.tgz", - "integrity": "sha512-aI3/oo5DzyiI5R/xAhxxRzfZlWlsbbqdgxfTPkqu/Zt+23GXiJvMCyPJT4+xKSXOnLqoL8jJYMLTwvK2M3a5hw==" + "version": "12.20.47", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.47.tgz", + "integrity": "sha512-BzcaRsnFuznzOItW1WpQrDHM7plAa7GIDMZ6b5pnMbkqEtM/6WCOhvZar39oeMQP79gwvFUWjjptE7/KGcNqFg==" }, "node_modules/web3-eth": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.7.0.tgz", - "integrity": "sha512-3uYwjMjn/MZjKIzXCt4YL9ja/k9X5shfa4lKparZhZE6uesmu+xmSmrEFXA/e9qcveF50jkV7frjkT8H+cLYtw==", - "dependencies": { - "web3-core": "1.7.0", - "web3-core-helpers": "1.7.0", - "web3-core-method": "1.7.0", - "web3-core-subscriptions": "1.7.0", - "web3-eth-abi": "1.7.0", - "web3-eth-accounts": "1.7.0", - "web3-eth-contract": "1.7.0", - "web3-eth-ens": "1.7.0", - "web3-eth-iban": "1.7.0", - "web3-eth-personal": "1.7.0", - "web3-net": "1.7.0", - "web3-utils": "1.7.0" + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.7.1.tgz", + "integrity": "sha512-Uz3gO4CjTJ+hMyJZAd2eiv2Ur1uurpN7sTMATWKXYR/SgG+SZgncnk/9d8t23hyu4lyi2GiVL1AqVqptpRElxg==", + "dependencies": { + "web3-core": "1.7.1", + "web3-core-helpers": "1.7.1", + "web3-core-method": "1.7.1", + "web3-core-subscriptions": "1.7.1", + "web3-eth-abi": "1.7.1", + "web3-eth-accounts": "1.7.1", + "web3-eth-contract": "1.7.1", + "web3-eth-ens": "1.7.1", + "web3-eth-iban": "1.7.1", + "web3-eth-personal": "1.7.1", + "web3-net": "1.7.1", + "web3-utils": "1.7.1" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-eth-abi": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.7.0.tgz", - "integrity": "sha512-heqR0bWxgCJwjWIhq2sGyNj9bwun5+Xox/LdZKe+WMyTSy0cXDXEAgv3XKNkXC4JqdDt/ZlbTEx4TWak4TRMSg==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.7.1.tgz", + "integrity": "sha512-8BVBOoFX1oheXk+t+uERBibDaVZ5dxdcefpbFTWcBs7cdm0tP8CD1ZTCLi5Xo+1bolVHNH2dMSf/nEAssq5pUA==", "dependencies": { "@ethersproject/abi": "5.0.7", - "web3-utils": "1.7.0" + "web3-utils": "1.7.1" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-eth-accounts": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.7.0.tgz", - "integrity": "sha512-Zwm7TlQXdXGRuS6+ib1YsR5fQwpfnFyL6UAZg1zERdrUrs3IkCZSL3yCP/8ZYbAjdTEwWljoott2iSqXNH09ug==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.7.1.tgz", + "integrity": "sha512-3xGQ2bkTQc7LFoqGWxp5cQDrKndlX05s7m0rAFVoyZZODMqrdSGjMPMqmWqHzJRUswNEMc+oelqSnGBubqhguQ==", "dependencies": { "@ethereumjs/common": "^2.5.0", "@ethereumjs/tx": "^3.3.2", @@ -7209,15 +9136,20 @@ "ethereumjs-util": "^7.0.10", "scrypt-js": "^3.0.1", "uuid": "3.3.2", - "web3-core": "1.7.0", - "web3-core-helpers": "1.7.0", - "web3-core-method": "1.7.0", - "web3-utils": "1.7.0" + "web3-core": "1.7.1", + "web3-core-helpers": "1.7.1", + "web3-core-method": "1.7.1", + "web3-utils": "1.7.1" }, "engines": { "node": ">=8.0.0" } }, + "node_modules/web3-eth-accounts/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "node_modules/web3-eth-accounts/node_modules/eth-lib": { "version": "0.2.8", "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", @@ -7238,93 +9170,106 @@ } }, "node_modules/web3-eth-contract": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.7.0.tgz", - "integrity": "sha512-2LY1Xwxu5rx468nqHuhvupQAIpytxIUj3mGL9uexszkhrQf05THVe3i4OnUCzkeN6B2cDztNOqLT3j9SSnVQDg==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.7.1.tgz", + "integrity": "sha512-HpnbkPYkVK3lOyos2SaUjCleKfbF0SP3yjw7l551rAAi5sIz/vwlEzdPWd0IHL7ouxXbO0tDn7jzWBRcD3sTbA==", "dependencies": { "@types/bn.js": "^4.11.5", - "web3-core": "1.7.0", - "web3-core-helpers": "1.7.0", - "web3-core-method": "1.7.0", - "web3-core-promievent": "1.7.0", - "web3-core-subscriptions": "1.7.0", - "web3-eth-abi": "1.7.0", - "web3-utils": "1.7.0" + "web3-core": "1.7.1", + "web3-core-helpers": "1.7.1", + "web3-core-method": "1.7.1", + "web3-core-promievent": "1.7.1", + "web3-core-subscriptions": "1.7.1", + "web3-eth-abi": "1.7.1", + "web3-utils": "1.7.1" }, "engines": { "node": ">=8.0.0" } }, + "node_modules/web3-eth-contract/node_modules/@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/web3-eth-ens": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.7.0.tgz", - "integrity": "sha512-I1bikYJJWQ/FJZIAvwsGOvzAgcRIkosWG4s1L6veRoXaU8OEJFeh4s00KcfHDxg7GWZZGbUSbdbzKpwRbWnvkg==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.7.1.tgz", + "integrity": "sha512-DVCF76i9wM93DrPQwLrYiCw/UzxFuofBsuxTVugrnbm0SzucajLLNftp3ITK0c4/lV3x9oo5ER/wD6RRMHQnvw==", "dependencies": { "content-hash": "^2.5.2", "eth-ens-namehash": "2.0.8", - "web3-core": "1.7.0", - "web3-core-helpers": "1.7.0", - "web3-core-promievent": "1.7.0", - "web3-eth-abi": "1.7.0", - "web3-eth-contract": "1.7.0", - "web3-utils": "1.7.0" + "web3-core": "1.7.1", + "web3-core-helpers": "1.7.1", + "web3-core-promievent": "1.7.1", + "web3-eth-abi": "1.7.1", + "web3-eth-contract": "1.7.1", + "web3-utils": "1.7.1" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-eth-iban": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.7.0.tgz", - "integrity": "sha512-1PFE/Og+sPZaug+M9TqVUtjOtq0HecE+SjDcsOOysXSzslNC2CItBGkcRwbvUcS+LbIkA7MFsuqYxOL0IV/gyA==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.7.1.tgz", + "integrity": "sha512-XG4I3QXuKB/udRwZdNEhdYdGKjkhfb/uH477oFVMLBqNimU/Cw8yXUI5qwFKvBHM+hMQWfzPDuSDEDKC2uuiMg==", "dependencies": { "bn.js": "^4.11.9", - "web3-utils": "1.7.0" + "web3-utils": "1.7.1" }, "engines": { "node": ">=8.0.0" } }, + "node_modules/web3-eth-iban/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "node_modules/web3-eth-personal": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.7.0.tgz", - "integrity": "sha512-Dr9RZTNOR80PhrPKGdktDUXpOgExEcCcosBj080lKCJFU1paSPj9Zfnth3u6BtIOXyKsVFTrpqekqUDyAwXnNw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.7.1.tgz", + "integrity": "sha512-02H6nFBNfNmFjMGZL6xcDi0r7tUhxrUP91FTFdoLyR94eIJDadPp4rpXfG7MVES873i1PReh4ep5pSCHbc3+Pg==", "dependencies": { "@types/node": "^12.12.6", - "web3-core": "1.7.0", - "web3-core-helpers": "1.7.0", - "web3-core-method": "1.7.0", - "web3-net": "1.7.0", - "web3-utils": "1.7.0" + "web3-core": "1.7.1", + "web3-core-helpers": "1.7.1", + "web3-core-method": "1.7.1", + "web3-net": "1.7.1", + "web3-utils": "1.7.1" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-eth-personal/node_modules/@types/node": { - "version": "12.20.42", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.42.tgz", - "integrity": "sha512-aI3/oo5DzyiI5R/xAhxxRzfZlWlsbbqdgxfTPkqu/Zt+23GXiJvMCyPJT4+xKSXOnLqoL8jJYMLTwvK2M3a5hw==" + "version": "12.20.47", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.47.tgz", + "integrity": "sha512-BzcaRsnFuznzOItW1WpQrDHM7plAa7GIDMZ6b5pnMbkqEtM/6WCOhvZar39oeMQP79gwvFUWjjptE7/KGcNqFg==" }, "node_modules/web3-net": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.7.0.tgz", - "integrity": "sha512-8pmfU1Se7DmG40Pu8nOCKlhuI12VsVzCtdFDnLAai0zGVAOUuuOCK71B2aKm6u9amWBJjtOlyrCwvsG+QEd6dw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.7.1.tgz", + "integrity": "sha512-8yPNp2gvjInWnU7DCoj4pIPNhxzUjrxKlODsyyXF8j0q3Z2VZuQp+c63gL++r2Prg4fS8t141/HcJw4aMu5sVA==", "dependencies": { - "web3-core": "1.7.0", - "web3-core-method": "1.7.0", - "web3-utils": "1.7.0" + "web3-core": "1.7.1", + "web3-core-method": "1.7.1", + "web3-utils": "1.7.1" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-providers-http": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.7.0.tgz", - "integrity": "sha512-Y9reeEiApfvQKLUUtrU4Z0c+H6b7BMWcsxjgoXndI1C5NB297mIUfltXxfXsh5C/jk5qn4Q3sJp3SwQTyVjH7Q==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.7.1.tgz", + "integrity": "sha512-dmiO6G4dgAa3yv+2VD5TduKNckgfR97VI9YKXVleWdcpBoKXe2jofhdvtafd42fpIoaKiYsErxQNcOC5gI/7Vg==", "dependencies": { - "web3-core-helpers": "1.7.0", + "web3-core-helpers": "1.7.1", "xhr2-cookies": "1.1.0" }, "engines": { @@ -7332,24 +9277,24 @@ } }, "node_modules/web3-providers-ipc": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.7.0.tgz", - "integrity": "sha512-U5YLXgu6fvAK4nnMYqo9eoml3WywgTym0dgCdVX/n1UegLIQ4nctTubBAuWQEJzmAzwh+a6ValGcE7ZApTRI7Q==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.7.1.tgz", + "integrity": "sha512-uNgLIFynwnd5M9ZC0lBvRQU5iLtU75hgaPpc7ZYYR+kjSk2jr2BkEAQhFVJ8dlqisrVmmqoAPXOEU0flYZZgNQ==", "dependencies": { "oboe": "2.1.5", - "web3-core-helpers": "1.7.0" + "web3-core-helpers": "1.7.1" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-providers-ws": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.7.0.tgz", - "integrity": "sha512-0a8+lVV3JBf+eYnGOsdzOpftK1kis5X7s35QAdoaG5SDapnEylXFlR4xDSSSU88ZwMwvse8hvng2xW6A7oeWxw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.7.1.tgz", + "integrity": "sha512-Uj0n5hdrh0ESkMnTQBsEUS2u6Unqdc7Pe4Zl+iZFb7Yn9cIGsPJBl7/YOP4137EtD5ueXAv+MKwzcelpVhFiFg==", "dependencies": { "eventemitter3": "4.0.4", - "web3-core-helpers": "1.7.0", + "web3-core-helpers": "1.7.1", "websocket": "^1.0.32" }, "engines": { @@ -7362,24 +9307,24 @@ "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==" }, "node_modules/web3-shh": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.7.0.tgz", - "integrity": "sha512-RZhxcevALIPK178VZCpwMBvQeW+IoWtRJ4EMdegpbnETeZaC3aRUcs6vKnrf0jXJjm4J/E2Dt438Y1Ord/1IMw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.7.1.tgz", + "integrity": "sha512-NO+jpEjo8kYX6c7GiaAm57Sx93PLYkWYUCWlZmUOW7URdUcux8VVluvTWklGPvdM9H1WfDrol91DjuSW+ykyqg==", "hasInstallScript": true, "dependencies": { - "web3-core": "1.7.0", - "web3-core-method": "1.7.0", - "web3-core-subscriptions": "1.7.0", - "web3-net": "1.7.0" + "web3-core": "1.7.1", + "web3-core-method": "1.7.1", + "web3-core-subscriptions": "1.7.1", + "web3-net": "1.7.1" }, "engines": { "node": ">=8.0.0" } }, "node_modules/web3-utils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.7.0.tgz", - "integrity": "sha512-O8Tl4Ky40Sp6pe89Olk2FsaUkgHyb5QAXuaKo38ms3CxZZ4d3rPGfjP9DNKGm5+IUgAZBNpF1VmlSmNCqfDI1w==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.7.1.tgz", + "integrity": "sha512-fef0EsqMGJUgiHPdX+KN9okVWshbIumyJPmR+btnD1HgvoXijKEkuKBv0OmUqjbeqmLKP2/N9EiXKJel5+E1Dw==", "dependencies": { "bn.js": "^4.11.9", "ethereum-bloom-filters": "^1.0.6", @@ -7393,6 +9338,11 @@ "node": ">=8.0.0" } }, + "node_modules/web3-utils/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -7479,50 +9429,22 @@ } }, "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dependencies": { - "string-width": "^1.0.2 || 2" - } - }, - "node_modules/wide-align/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" + "string-width": "^1.0.2 || 2 || 3 || 4" } }, - "node_modules/wide-align/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", "dependencies": { - "ansi-regex": "^3.0.0" + "string-width": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/word-wrap": { @@ -7539,9 +9461,9 @@ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" }, "node_modules/workerpool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", - "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==" + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", + "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==" }, "node_modules/wrap-ansi": { "version": "7.0.0", @@ -7562,6 +9484,17 @@ "version": "1.0.2", "license": "ISC" }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, "node_modules/ws": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", @@ -7577,6 +9510,14 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "engines": { + "node": ">=8" + } + }, "node_modules/xhr": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", @@ -7642,9 +9583,16 @@ }, "node_modules/yallist": { "version": "4.0.0", - "dev": true, "license": "ISC" }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, "node_modules/yargs": { "version": "16.2.0", "license": "MIT", @@ -7701,6 +9649,14 @@ } }, "dependencies": { + "@ampproject/remapping": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", + "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", + "requires": { + "@jridgewell/trace-mapping": "^0.3.0" + } + }, "@babel/code-frame": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", @@ -7710,30 +9666,30 @@ } }, "@babel/compat-data": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.8.tgz", - "integrity": "sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q==" + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz", + "integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==" }, "@babel/core": { - "version": "7.16.12", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.12.tgz", - "integrity": "sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.7.tgz", + "integrity": "sha512-djHlEfFHnSnTAcPb7dATbiM5HxGOP98+3JLBZtjRb5I7RXrw7kFRoG2dXM8cm3H+o11A8IFH/uprmJpwFynRNQ==", "requires": { + "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.16.8", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helpers": "^7.16.7", - "@babel/parser": "^7.16.12", + "@babel/generator": "^7.17.7", + "@babel/helper-compilation-targets": "^7.17.7", + "@babel/helper-module-transforms": "^7.17.7", + "@babel/helpers": "^7.17.7", + "@babel/parser": "^7.17.7", "@babel/template": "^7.16.7", - "@babel/traverse": "^7.16.10", - "@babel/types": "^7.16.8", + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.1.2", - "semver": "^6.3.0", - "source-map": "^0.5.0" + "semver": "^6.3.0" }, "dependencies": { "json5": { @@ -7743,20 +9699,15 @@ "requires": { "minimist": "^1.2.5" } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" } } }, "@babel/generator": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.8.tgz", - "integrity": "sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", + "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", "requires": { - "@babel/types": "^7.16.8", + "@babel/types": "^7.17.0", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, @@ -7769,11 +9720,11 @@ } }, "@babel/helper-compilation-targets": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz", - "integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz", + "integrity": "sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==", "requires": { - "@babel/compat-data": "^7.16.4", + "@babel/compat-data": "^7.17.7", "@babel/helper-validator-option": "^7.16.7", "browserslist": "^4.17.5", "semver": "^6.3.0" @@ -7822,26 +9773,26 @@ } }, "@babel/helper-module-transforms": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz", - "integrity": "sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", + "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", "requires": { "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.16.7", + "@babel/helper-simple-access": "^7.17.7", "@babel/helper-split-export-declaration": "^7.16.7", "@babel/helper-validator-identifier": "^7.16.7", "@babel/template": "^7.16.7", - "@babel/traverse": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0" } }, "@babel/helper-simple-access": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz", - "integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", + "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.17.0" } }, "@babel/helper-split-export-declaration": { @@ -7863,13 +9814,13 @@ "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==" }, "@babel/helpers": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.7.tgz", - "integrity": "sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.7.tgz", + "integrity": "sha512-TKsj9NkjJfTBxM7Phfy7kv6yYc4ZcOo+AaWGqQOKTPDOmcGkIFb5xNA746eKisQkm4yavUYh4InYM9S+VnO01w==", "requires": { "@babel/template": "^7.16.7", - "@babel/traverse": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0" } }, "@babel/highlight": { @@ -7934,24 +9885,26 @@ } }, "@babel/parser": { - "version": "7.16.12", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.12.tgz", - "integrity": "sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==" + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.7.tgz", + "integrity": "sha512-bm3AQf45vR4gKggRfvJdYJ0gFLoCbsPxiFLSH6hTVYABptNHY6l9NrhnucVjQ/X+SPtLANT9lc0fFhikj+VBRA==" }, "@babel/register": { - "version": "7.16.9", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.16.9.tgz", - "integrity": "sha512-jJ72wcghdRIlENfvALcyODhNoGE5j75cYHdC+aQMh6cU/P86tiiXTp9XYZct1UxUMo/4+BgQRyNZEGx0KWGS+g==", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.17.7.tgz", + "integrity": "sha512-fg56SwvXRifootQEDQAu1mKdjh5uthPzdO0N6t358FktfL4XjAVXuH58ULoiW8mesxiOgNIrxiImqEwv0+hRRA==", "requires": { "clone-deep": "^4.0.1", "find-cache-dir": "^2.0.0", "make-dir": "^2.1.0", - "pirates": "^4.0.0", + "pirates": "^4.0.5", "source-map-support": "^0.5.16" } }, "@babel/runtime": { - "version": "7.16.7", + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.7.tgz", + "integrity": "sha512-L6rvG9GDxaLgFjg41K+5Yv9OMrU98sWe+Ykmc6FDJW/+vYZMhdOMKkISgzptMaERHvS2Y2lw9MDRm2gHhlQQoA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -7967,33 +9920,26 @@ } }, "@babel/traverse": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.10.tgz", - "integrity": "sha512-yzuaYXoRJBGMlBhsMJoUW7G1UmSb/eXr/JHYM/MsOJgavJibLwASijW7oXBdw3NQ6T0bW7Ty5P/VarOs9cHmqw==", + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", + "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", "requires": { "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.16.8", + "@babel/generator": "^7.17.3", "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-function-name": "^7.16.7", "@babel/helper-hoist-variables": "^7.16.7", "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.16.10", - "@babel/types": "^7.16.8", + "@babel/parser": "^7.17.3", + "@babel/types": "^7.17.0", "debug": "^4.1.0", "globals": "^11.1.0" - }, - "dependencies": { - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" - } } }, "@babel/types": { - "version": "7.16.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.8.tgz", - "integrity": "sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", "requires": { "@babel/helper-validator-identifier": "^7.16.7", "to-fast-properties": "^2.0.0" @@ -8015,42 +9961,49 @@ } }, "@eslint/eslintrc": { - "version": "1.0.5", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", + "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.2.0", + "espree": "^9.3.1", "globals": "^13.9.0", - "ignore": "^4.0.6", + "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" }, "dependencies": { - "ignore": { - "version": "4.0.6", - "dev": true + "globals": { + "version": "13.13.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", + "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } } } }, "@ethereumjs/common": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.0.tgz", - "integrity": "sha512-Cq2qS0FTu6O2VU1sgg+WyU9Ps0M6j/BEMHN+hRaECXCV/r0aI78u4N6p52QW/BDVhwWZpCdrvG8X7NJdzlpNUA==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.2.tgz", + "integrity": "sha512-vDwye5v0SVeuDky4MtKsu+ogkH2oFUV8pBKzH/eNBzT8oI91pKa8WyzDuYuxOQsgNgv5R34LfFDh2aaw3H4HbQ==", "requires": { "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.3" + "ethereumjs-util": "^7.1.4" } }, "@ethereumjs/tx": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.4.0.tgz", - "integrity": "sha512-WWUwg1PdjHKZZxPPo274ZuPsJCWV3SqATrEKQP1n2DrVYVP1aZIYpo/mFaA0BDoE0tIQmBeimRCEA0Lgil+yYw==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.5.0.tgz", + "integrity": "sha512-/+ZNbnJhQhXC83Xuvy6I9k4jT5sXiV0tMR9C+AzSSpcCV64+NB8dTE1m3x98RYMqb8+TLYWA+HML4F5lfXTlJw==", "requires": { - "@ethereumjs/common": "^2.6.0", - "ethereumjs-util": "^7.1.3" + "@ethereumjs/common": "^2.6.1", + "ethereumjs-util": "^7.1.4" } }, "@ethersproject/abi": { @@ -8070,182 +10023,201 @@ } }, "@ethersproject/abstract-provider": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.5.1.tgz", - "integrity": "sha512-m+MA/ful6eKbxpr99xUYeRvLkfnlqzrF8SZ46d/xFB1A7ZVknYc/sXJG0RcufF52Qn2jeFj1hhcoQ7IXjNKUqg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.6.0.tgz", + "integrity": "sha512-oPMFlKLN+g+y7a79cLK3WiLcjWFnZQtXWgnLAbHZcN3s7L4v90UHpTOrLk+m3yr0gt+/h9STTM6zrr7PM8uoRw==", "requires": { - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/networks": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/transactions": "^5.5.0", - "@ethersproject/web": "^5.5.0" + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/networks": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/transactions": "^5.6.0", + "@ethersproject/web": "^5.6.0" } }, "@ethersproject/abstract-signer": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.5.0.tgz", - "integrity": "sha512-lj//7r250MXVLKI7sVarXAbZXbv9P50lgmJQGr2/is82EwEb8r7HrxsmMqAjTsztMYy7ohrIhGMIml+Gx4D3mA==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.6.0.tgz", + "integrity": "sha512-WOqnG0NJKtI8n0wWZPReHtaLkDByPL67tn4nBaDAhmVq8sjHTPbCdz4DRhVu/cfTOvfy9w3iq5QZ7BX7zw56BQ==", "requires": { - "@ethersproject/abstract-provider": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0" + "@ethersproject/abstract-provider": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0" } }, "@ethersproject/address": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.5.0.tgz", - "integrity": "sha512-l4Nj0eWlTUh6ro5IbPTgbpT4wRbdH5l8CQf7icF7sb/SI3Nhd9Y9HzhonTSTi6CefI0necIw7LJqQPopPLZyWw==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.6.0.tgz", + "integrity": "sha512-6nvhYXjbXsHPS+30sHZ+U4VMagFC/9zAk6Gd/h3S21YW4+yfb0WfRtaAIZ4kfM4rrVwqiy284LP0GtL5HXGLxQ==", "requires": { - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/keccak256": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/rlp": "^5.5.0" + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/rlp": "^5.6.0" } }, "@ethersproject/base64": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.5.0.tgz", - "integrity": "sha512-tdayUKhU1ljrlHzEWbStXazDpsx4eg1dBXUSI6+mHlYklOXoXF6lZvw8tnD6oVaWfnMxAgRSKROg3cVKtCcppA==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.6.0.tgz", + "integrity": "sha512-2Neq8wxJ9xHxCF9TUgmKeSh9BXJ6OAxWfeGWvbauPh8FuHEjamgHilllx8KkSd5ErxyHIX7Xv3Fkcud2kY9ezw==", "requires": { - "@ethersproject/bytes": "^5.5.0" + "@ethersproject/bytes": "^5.6.0" } }, "@ethersproject/bignumber": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.5.0.tgz", - "integrity": "sha512-6Xytlwvy6Rn3U3gKEc1vP7nR92frHkv6wtVr95LFR3jREXiCPzdWxKQ1cx4JGQBXxcguAwjA8murlYN2TSiEbg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.6.0.tgz", + "integrity": "sha512-VziMaXIUHQlHJmkv1dlcd6GY2PmT0khtAqaMctCIDogxkrarMzA9L94KN1NeXqqOfFD6r0sJT3vCTOFSmZ07DA==", "requires": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", "bn.js": "^4.11.9" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } } }, "@ethersproject/bytes": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.5.0.tgz", - "integrity": "sha512-ABvc7BHWhZU9PNM/tANm/Qx4ostPGadAuQzWTr3doklZOhDlmcBqclrQe/ZXUIj3K8wC28oYeuRa+A37tX9kog==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.6.0.tgz", + "integrity": "sha512-3hJPlYemb9V4VLfJF5BfN0+55vltPZSHU3QKUyP9M3Y2TcajbiRrz65UG+xVHOzBereB1b9mn7r12o177xgN7w==", "requires": { - "@ethersproject/logger": "^5.5.0" + "@ethersproject/logger": "^5.6.0" } }, "@ethersproject/constants": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.5.0.tgz", - "integrity": "sha512-2MsRRVChkvMWR+GyMGY4N1sAX9Mt3J9KykCsgUFd/1mwS0UH1qw+Bv9k1UJb3X3YJYFco9H20pjSlOIfCG5HYQ==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.6.0.tgz", + "integrity": "sha512-SrdaJx2bK0WQl23nSpV/b1aq293Lh0sUaZT/yYKPDKn4tlAbkH96SPJwIhwSwTsoQQZxuh1jnqsKwyymoiBdWA==", "requires": { - "@ethersproject/bignumber": "^5.5.0" + "@ethersproject/bignumber": "^5.6.0" } }, "@ethersproject/hash": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.5.0.tgz", - "integrity": "sha512-dnGVpK1WtBjmnp3mUT0PlU2MpapnwWI0PibldQEq1408tQBAbZpPidkWoVVuNMOl/lISO3+4hXZWCL3YV7qzfg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.6.0.tgz", + "integrity": "sha512-fFd+k9gtczqlr0/BruWLAu7UAOas1uRRJvOR84uDf4lNZ+bTkGl366qvniUZHKtlqxBRU65MkOobkmvmpHU+jA==", "requires": { - "@ethersproject/abstract-signer": "^5.5.0", - "@ethersproject/address": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/keccak256": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/strings": "^5.5.0" + "@ethersproject/abstract-signer": "^5.6.0", + "@ethersproject/address": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/strings": "^5.6.0" } }, "@ethersproject/keccak256": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.5.0.tgz", - "integrity": "sha512-5VoFCTjo2rYbBe1l2f4mccaRFN/4VQEYFwwn04aJV2h7qf4ZvI2wFxUE1XOX+snbwCLRzIeikOqtAoPwMza9kg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.6.0.tgz", + "integrity": "sha512-tk56BJ96mdj/ksi7HWZVWGjCq0WVl/QvfhFQNeL8fxhBlGoP+L80uDCiQcpJPd+2XxkivS3lwRm3E0CXTfol0w==", "requires": { - "@ethersproject/bytes": "^5.5.0", + "@ethersproject/bytes": "^5.6.0", "js-sha3": "0.8.0" } }, "@ethersproject/logger": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.5.0.tgz", - "integrity": "sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg==" + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.6.0.tgz", + "integrity": "sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg==" }, "@ethersproject/networks": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.5.2.tgz", - "integrity": "sha512-NEqPxbGBfy6O3x4ZTISb90SjEDkWYDUbEeIFhJly0F7sZjoQMnj5KYzMSkMkLKZ+1fGpx00EDpHQCy6PrDupkQ==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.6.0.tgz", + "integrity": "sha512-DaVzgyThzHgSDLuURhvkp4oviGoGe9iTZW4jMEORHDRCgSZ9K9THGFKqL+qGXqPAYLEgZTf5z2w56mRrPR1MjQ==", "requires": { - "@ethersproject/logger": "^5.5.0" + "@ethersproject/logger": "^5.6.0" } }, "@ethersproject/properties": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.5.0.tgz", - "integrity": "sha512-l3zRQg3JkD8EL3CPjNK5g7kMx4qSwiR60/uk5IVjd3oq1MZR5qUg40CNOoEJoX5wc3DyY5bt9EbMk86C7x0DNA==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.6.0.tgz", + "integrity": "sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg==", "requires": { - "@ethersproject/logger": "^5.5.0" + "@ethersproject/logger": "^5.6.0" } }, "@ethersproject/rlp": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.5.0.tgz", - "integrity": "sha512-hLv8XaQ8PTI9g2RHoQGf/WSxBfTB/NudRacbzdxmst5VHAqd1sMibWG7SENzT5Dj3yZ3kJYx+WiRYEcQTAkcYA==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.6.0.tgz", + "integrity": "sha512-dz9WR1xpcTL+9DtOT/aDO+YyxSSdO8YIS0jyZwHHSlAmnxA6cKU3TrTd4Xc/bHayctxTgGLYNuVVoiXE4tTq1g==", "requires": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0" + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0" } }, "@ethersproject/signing-key": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.5.0.tgz", - "integrity": "sha512-5VmseH7qjtNmDdZBswavhotYbWB0bOwKIlOTSlX14rKn5c11QmJwGt4GHeo7NrL/Ycl7uo9AHvEqs5xZgFBTng==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.6.0.tgz", + "integrity": "sha512-S+njkhowmLeUu/r7ir8n78OUKx63kBdMCPssePS89So1TH4hZqnWFsThEd/GiXYp9qMxVrydf7KdM9MTGPFukA==", "requires": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", "bn.js": "^4.11.9", "elliptic": "6.5.4", "hash.js": "1.1.7" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } } }, "@ethersproject/strings": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.5.0.tgz", - "integrity": "sha512-9fy3TtF5LrX/wTrBaT8FGE6TDJyVjOvXynXJz5MT5azq+E6D92zuKNx7i29sWW2FjVOaWjAsiZ1ZWznuduTIIQ==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.6.0.tgz", + "integrity": "sha512-uv10vTtLTZqrJuqBZR862ZQjTIa724wGPWQqZrofaPI/kUsf53TBG0I0D+hQ1qyNtllbNzaW+PDPHHUI6/65Mg==", "requires": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/constants": "^5.5.0", - "@ethersproject/logger": "^5.5.0" + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/constants": "^5.6.0", + "@ethersproject/logger": "^5.6.0" } }, "@ethersproject/transactions": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.5.0.tgz", - "integrity": "sha512-9RZYSKX26KfzEd/1eqvv8pLauCKzDTub0Ko4LfIgaERvRuwyaNV78mJs7cpIgZaDl6RJui4o49lHwwCM0526zA==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.6.0.tgz", + "integrity": "sha512-4HX+VOhNjXHZyGzER6E/LVI2i6lf9ejYeWD6l4g50AdmimyuStKc39kvKf1bXWQMg7QNVh+uC7dYwtaZ02IXeg==", "requires": { - "@ethersproject/address": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/constants": "^5.5.0", - "@ethersproject/keccak256": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/rlp": "^5.5.0", - "@ethersproject/signing-key": "^5.5.0" + "@ethersproject/address": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/constants": "^5.6.0", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/rlp": "^5.6.0", + "@ethersproject/signing-key": "^5.6.0" } }, "@ethersproject/web": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.5.1.tgz", - "integrity": "sha512-olvLvc1CB12sREc1ROPSHTdFCdvMh0J5GSJYiQg2D0hdD4QmJDy8QYDb1CvoqD/bF1c++aeKv2sR5uduuG9dQg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.6.0.tgz", + "integrity": "sha512-G/XHj0hV1FxI2teHRfCGvfBUHFmU+YOSbCxlAMqJklxSa7QMiHFQfAxvwY2PFqgvdkxEKwRNr/eCjfAPEm2Ctg==", "requires": { - "@ethersproject/base64": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/strings": "^5.5.0" + "@ethersproject/base64": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/strings": "^5.6.0" } }, + "@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==" + }, "@humanwhocodes/config-array": { "version": "0.9.2", "dev": true, @@ -8259,21 +10231,39 @@ "version": "1.2.1", "dev": true }, + "@jridgewell/resolve-uri": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", + "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==" + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", + "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", + "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "@noble/hashes": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-0.5.7.tgz", - "integrity": "sha512-R9PPYv7TqoYi+enikzZvwRQesGTxR0+jwqzZJGL0uNcf2NFL+lt/uvCCewtXXmr6jWBxiMuNjBfJwKv9UJaCng==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.0.0.tgz", + "integrity": "sha512-DZVbtY62kc3kkBtMHqwCOfXrT/hnoORy5BJ4+HU1IR59X0KWAOqsfzQPcUl/lQLlG7qXbe/fZ3r/emxtAl+sqg==" }, "@noble/secp256k1": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.3.4.tgz", - "integrity": "sha512-ZVRouDO5mbdCiDg4zCd3ZZABduRtpy4tCnB33Gh9upHe9tRzpiqbRSN1VTjrj/2g8u2c6MBi0YLNnNQpBYOiWg==" + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.5.5.tgz", + "integrity": "sha512-sZ1W6gQzYnu45wPrWx8D3kwI2/U29VYTx9OjbDAd7jwRItJ0cSTMPRL/C8AWZFn9kWFLQGqEXVEE86w4Z8LpIQ==" }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, "requires": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -8282,147 +10272,260 @@ "@nodelib/fs.stat": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" }, "@nodelib/fs.walk": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, "requires": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, + "@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "requires": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@npmcli/git": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-3.0.0.tgz", + "integrity": "sha512-xfSBJ+KBMZWWqRHFbEgIaXG/LtELHrQZMJ72Gkb3yWdHysu/7+VGOs8ME0c3td7QNQX57Ggo3kYL6ylcd70/kA==", + "requires": { + "@npmcli/promise-spawn": "^1.3.2", + "lru-cache": "^7.3.1", + "mkdirp": "^1.0.4", + "npm-pick-manifest": "^7.0.0", + "proc-log": "^2.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^2.0.2" + }, + "dependencies": { + "lru-cache": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.5.1.tgz", + "integrity": "sha512-q1TS8IqKvcg3aScamKCHpepSrHF537Ww7nHahBOxhDu9D2YoBXAsj/7uFdZFj1xJr9LmyeJ62AdyofCHafUbIA==" + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + } + } + } + } + }, + "@npmcli/installed-package-contents": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz", + "integrity": "sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==", + "requires": { + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "requires": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + } + } + }, + "@npmcli/node-gyp": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-1.0.3.tgz", + "integrity": "sha512-fnkhw+fmX65kiLqk6E3BFLXNC26rUhK90zVwe2yncPliVT/Qos3xjhTLE59Df8KnPlcwIERXKVlU1bXoUQ+liA==" + }, + "@npmcli/promise-spawn": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz", + "integrity": "sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg==", + "requires": { + "infer-owner": "^1.0.4" + } + }, + "@npmcli/run-script": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-3.0.1.tgz", + "integrity": "sha512-o2fkld5hYwu9sKYzoXTpqEocMnDLaigobaPzLaGB63k/ExmLBTaB+KpfKlpcIePPnuP8RFR+0GDI4KopJCM6Xg==", + "requires": { + "@npmcli/node-gyp": "^1.0.3", + "@npmcli/promise-spawn": "^1.3.2", + "node-gyp": "^9.0.0", + "read-package-json-fast": "^2.0.3" + } + }, "@polkadot/api": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-7.5.1.tgz", - "integrity": "sha512-/3AI4Kbznt289+swtiFEYiX+XR9d+qzHhL8XxEzcqQudw2ElrfpLTAx3RzTUEEeEfwwPGmNVWPWaG4egUPsosQ==", - "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/api-augment": "7.5.1", - "@polkadot/api-base": "7.5.1", - "@polkadot/api-derive": "7.5.1", - "@polkadot/keyring": "^8.3.3", - "@polkadot/rpc-augment": "7.5.1", - "@polkadot/rpc-core": "7.5.1", - "@polkadot/rpc-provider": "7.5.1", - "@polkadot/types": "7.5.1", - "@polkadot/types-augment": "7.5.1", - "@polkadot/types-codec": "7.5.1", - "@polkadot/types-create": "7.5.1", - "@polkadot/types-known": "7.5.1", - "@polkadot/util": "^8.3.3", - "@polkadot/util-crypto": "^8.3.3", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-7.12.1.tgz", + "integrity": "sha512-kA6o9ZdRsJ9Iis+PyZN8sayrioJmgf8r5cAqnjoCmA+cb9h+FcqLoHe4kojA6uQMsX2PnsunX2nVuFaZSstoSg==", + "requires": { + "@babel/runtime": "^7.17.2", + "@polkadot/api-augment": "7.12.1", + "@polkadot/api-base": "7.12.1", + "@polkadot/api-derive": "7.12.1", + "@polkadot/keyring": "^8.5.1", + "@polkadot/rpc-augment": "7.12.1", + "@polkadot/rpc-core": "7.12.1", + "@polkadot/rpc-provider": "7.12.1", + "@polkadot/types": "7.12.1", + "@polkadot/types-augment": "7.12.1", + "@polkadot/types-codec": "7.12.1", + "@polkadot/types-create": "7.12.1", + "@polkadot/types-known": "7.12.1", + "@polkadot/util": "^8.5.1", + "@polkadot/util-crypto": "^8.5.1", "eventemitter3": "^4.0.7", - "rxjs": "^7.5.2" + "rxjs": "^7.5.5" } }, "@polkadot/api-augment": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-7.5.1.tgz", - "integrity": "sha512-2sj+D8gvyo9ijqFFqJS5meaMVRllr5fWnE440nACsXIbcbHuXRWAF9tWdhESOIfue7hlFLo5plDdRfU7cSjIZQ==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-7.12.1.tgz", + "integrity": "sha512-/SFrV4+VNLYZlfoQ80UVOQWeen/YOmWNeuyVa+KaywyTowLLZ4X1MWXB3Dwtk/aQYCbwxm82+R8IJun2zl6mVw==", "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/api-base": "7.5.1", - "@polkadot/rpc-augment": "7.5.1", - "@polkadot/types": "7.5.1", - "@polkadot/types-augment": "7.5.1", - "@polkadot/types-codec": "7.5.1", - "@polkadot/util": "^8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/api-base": "7.12.1", + "@polkadot/rpc-augment": "7.12.1", + "@polkadot/types": "7.12.1", + "@polkadot/types-augment": "7.12.1", + "@polkadot/types-codec": "7.12.1", + "@polkadot/util": "^8.5.1" } }, "@polkadot/api-base": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-7.5.1.tgz", - "integrity": "sha512-vqMjmMOQuYLSwfTHTgmvPBtF6eAgrlyuBw0t0IiaTDfjP6xRRGMDIVb7lJCqvYL0VrHmTC7X5MVbJn1SNUut9w==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-7.12.1.tgz", + "integrity": "sha512-AhBnYOtImoaaUoCI6srbnwQ4vn1fSbOSCfpzkLLEJi+KMuNO9vfZU3O8ob8MdY2Y3V7kGQMPWulGGaCqOcDepQ==", "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/rpc-core": "7.5.1", - "@polkadot/types": "7.5.1", - "@polkadot/util": "^8.3.3", - "rxjs": "^7.5.2" + "@babel/runtime": "^7.17.2", + "@polkadot/rpc-core": "7.12.1", + "@polkadot/types": "7.12.1", + "@polkadot/util": "^8.5.1", + "rxjs": "^7.5.5" } }, "@polkadot/api-derive": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-7.5.1.tgz", - "integrity": "sha512-O4x/DG+sSWgbXYGuYm4d3iYMTv5WTzoX5HX/xAIG+H+g7ob5RDdyLW9oQowrOX9ZOKt1cHPbHi0dLj+hDOD1CQ==", - "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/api": "7.5.1", - "@polkadot/api-augment": "7.5.1", - "@polkadot/api-base": "7.5.1", - "@polkadot/rpc-core": "7.5.1", - "@polkadot/types": "7.5.1", - "@polkadot/types-codec": "7.5.1", - "@polkadot/util": "^8.3.3", - "@polkadot/util-crypto": "^8.3.3", - "rxjs": "^7.5.2" + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-7.12.1.tgz", + "integrity": "sha512-MePzdiicdvfhd8Y+9xQXlfo/imU/7dxc2hBu8Iy33f8VnImJJTXMvcK84MKDxZraQ3k93rj2XAv1VYM1eh1R2w==", + "requires": { + "@babel/runtime": "^7.17.2", + "@polkadot/api": "7.12.1", + "@polkadot/api-augment": "7.12.1", + "@polkadot/api-base": "7.12.1", + "@polkadot/rpc-core": "7.12.1", + "@polkadot/types": "7.12.1", + "@polkadot/types-codec": "7.12.1", + "@polkadot/util": "^8.5.1", + "@polkadot/util-crypto": "^8.5.1", + "rxjs": "^7.5.5" } }, "@polkadot/keyring": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-8.3.3.tgz", - "integrity": "sha512-TgoIpaTqn7voT7lDu5W6p0Z+216OImpqtHuaiFy125ekCQurrf9BVIdwp56y5qoFLDAZ5i9gnWHMIgOQ6AJj/Q==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-8.5.1.tgz", + "integrity": "sha512-ivJ/pEfu9Pu78h3Gldf3p5odXr5weAbwcz22VyjmTpege1bIHmw4HdYC0lOZznTDAIGUMk7IoswHYmvZWTHgNA==", "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/util": "8.3.3", - "@polkadot/util-crypto": "8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/util": "8.5.1", + "@polkadot/util-crypto": "8.5.1" } }, "@polkadot/networks": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-8.3.3.tgz", - "integrity": "sha512-yj0DMqmzRZbvgaoZztV3/RPgYJjBhT17Dhu+FX/LUJzVbAF/RfjkzNsJT4Ta4kLDxQMYZq1avUac0ia2j9NcNw==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-8.5.1.tgz", + "integrity": "sha512-gPfOhP2SrJTOywmdq2IYgxxq/W90wePG+A+xqNvvP7briPGty7+yXmaIJk7HowZChnerOeQ2z0gunbXiacVHFA==", "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/util": "8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/util": "8.5.1", + "@substrate/ss58-registry": "^1.16.0" } }, "@polkadot/rpc-augment": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-7.5.1.tgz", - "integrity": "sha512-LPTDjtBZJe5KIOErOW+h2HY85G57WZVOiwm+SOgJ6J5g+BnUD0Rv+VH9pGC8dfoUsYBHSSvFELLnoTIZw6jltg==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-7.12.1.tgz", + "integrity": "sha512-2Gr4dkM5ZGrv5J5LKwK0vX7V6i/WTdvJzNs1BwDY+RMLwOFp8eStRyPuCJNgdBF7xkeXR9BKoaU0cqB1xmK+Gg==", "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/rpc-core": "7.5.1", - "@polkadot/types": "7.5.1", - "@polkadot/types-codec": "7.5.1", - "@polkadot/util": "^8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/rpc-core": "7.12.1", + "@polkadot/types": "7.12.1", + "@polkadot/types-codec": "7.12.1", + "@polkadot/util": "^8.5.1" } }, "@polkadot/rpc-core": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-7.5.1.tgz", - "integrity": "sha512-/UN7fQSqGnyjd5W0fFZ2RDBxAYoS8UreIea0eu+Zz4t6D2Fjp1syHNkw710wuv6ALhaRUjW6USO8XNSHDBIz+w==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-7.12.1.tgz", + "integrity": "sha512-qL2+5MHjBjMETPr8tLmiIykfSyooBYZ8bBwJ4j9OEENd+e6F8k0KnEuoeyA826CU20cUDydP9YdqOR2CP2fSww==", "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/rpc-augment": "7.5.1", - "@polkadot/rpc-provider": "7.5.1", - "@polkadot/types": "7.5.1", - "@polkadot/util": "^8.3.3", - "rxjs": "^7.5.2" + "@babel/runtime": "^7.17.2", + "@polkadot/rpc-augment": "7.12.1", + "@polkadot/rpc-provider": "7.12.1", + "@polkadot/types": "7.12.1", + "@polkadot/util": "^8.5.1", + "rxjs": "^7.5.5" } }, "@polkadot/rpc-provider": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-7.5.1.tgz", - "integrity": "sha512-6t5PyEDFBYJiK1/oegQkET4DnKdfk/mskELOVflDd4sLN+mXSAUW4DvS+KiVldHfUBtMQqX/w3p7x26xmWjmqQ==", - "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/keyring": "^8.3.3", - "@polkadot/types": "7.5.1", - "@polkadot/types-support": "7.5.1", - "@polkadot/util": "^8.3.3", - "@polkadot/util-crypto": "^8.3.3", - "@polkadot/x-fetch": "^8.3.3", - "@polkadot/x-global": "^8.3.3", - "@polkadot/x-ws": "^8.3.3", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-7.12.1.tgz", + "integrity": "sha512-gMvlbqq3xXg54CVoMdiugvrwLNnUI5QhO/YIWv6vOnpc8AOs+JVYgdPaBTNleHiyV7Lw6sVQJno0QH8vx8xjIg==", + "requires": { + "@babel/runtime": "^7.17.2", + "@polkadot/keyring": "^8.5.1", + "@polkadot/types": "7.12.1", + "@polkadot/types-support": "7.12.1", + "@polkadot/util": "^8.5.1", + "@polkadot/util-crypto": "^8.5.1", + "@polkadot/x-fetch": "^8.5.1", + "@polkadot/x-global": "^8.5.1", + "@polkadot/x-ws": "^8.5.1", "eventemitter3": "^4.0.7", - "mock-socket": "^9.1.0", - "nock": "^13.2.2" + "mock-socket": "^9.1.2", + "nock": "^13.2.4" } }, "@polkadot/ts": { @@ -8434,24 +10537,24 @@ } }, "@polkadot/typegen": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/typegen/-/typegen-7.5.1.tgz", - "integrity": "sha512-0ma//yfYBEcpYftoqS3Jbl3mVGA/zl3WRfnW3KK3cQ8J1xqKXusjeQ/9egyuWSP8qn34XHXQcvE6T+rfX+ki4A==", - "requires": { - "@babel/core": "^7.16.12", - "@babel/register": "^7.16.9", - "@babel/runtime": "^7.16.7", - "@polkadot/api": "7.5.1", - "@polkadot/api-augment": "7.5.1", - "@polkadot/rpc-augment": "7.5.1", - "@polkadot/rpc-provider": "7.5.1", - "@polkadot/types": "7.5.1", - "@polkadot/types-augment": "7.5.1", - "@polkadot/types-codec": "7.5.1", - "@polkadot/types-create": "7.5.1", - "@polkadot/types-support": "7.5.1", - "@polkadot/util": "^8.3.3", - "@polkadot/x-ws": "^8.3.3", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/typegen/-/typegen-7.12.1.tgz", + "integrity": "sha512-K0UUbkwUJZgBA8HaHLyUepuaGJINdSj7LjrwKRCxjLy5Pz3K6W39c+yiwLHYIsCV4SBZhllXBVyvOkV4Dx6rJA==", + "requires": { + "@babel/core": "^7.17.5", + "@babel/register": "^7.17.0", + "@babel/runtime": "^7.17.2", + "@polkadot/api": "7.12.1", + "@polkadot/api-augment": "7.12.1", + "@polkadot/rpc-augment": "7.12.1", + "@polkadot/rpc-provider": "7.12.1", + "@polkadot/types": "7.12.1", + "@polkadot/types-augment": "7.12.1", + "@polkadot/types-codec": "7.12.1", + "@polkadot/types-create": "7.12.1", + "@polkadot/types-support": "7.12.1", + "@polkadot/util": "^8.5.1", + "@polkadot/x-ws": "^8.5.1", "handlebars": "^4.7.7", "websocket": "^1.0.34", "yargs": "^17.3.1" @@ -8479,202 +10582,212 @@ } }, "@polkadot/types": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-7.5.1.tgz", - "integrity": "sha512-71KY3Ia8AZywb0wWP0F588qFJbQMcgZqqP/dw6RP1A5ja2pR5SnqRP/zcaSena1cm9f24rAxgxiluOzzJxrfsA==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-7.12.1.tgz", + "integrity": "sha512-GMqVTXCN6oCJnyAz7NwABez+I42luNyMMbIzIwrYD3XlMsQnnPc2GkhCLjeLf/0InTx/xij+C7z2zma4hYQZtQ==", "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/keyring": "^8.3.3", - "@polkadot/types-augment": "7.5.1", - "@polkadot/types-codec": "7.5.1", - "@polkadot/types-create": "7.5.1", - "@polkadot/util": "^8.3.3", - "@polkadot/util-crypto": "^8.3.3", - "rxjs": "^7.5.2" + "@babel/runtime": "^7.17.2", + "@polkadot/keyring": "^8.5.1", + "@polkadot/types-augment": "7.12.1", + "@polkadot/types-codec": "7.12.1", + "@polkadot/types-create": "7.12.1", + "@polkadot/util": "^8.5.1", + "@polkadot/util-crypto": "^8.5.1", + "rxjs": "^7.5.5" } }, "@polkadot/types-augment": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-7.5.1.tgz", - "integrity": "sha512-YWXYfc0a2AOb2naG2uWAHkTuGvfPz8hrKv3UMTWUrCok/kVbUovqSXoBAORaX+tphpaKbEuBnBtBhk2cXP6KWA==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-7.12.1.tgz", + "integrity": "sha512-giQao8jm2M9HufRT3H4r1a2C76G3HEKxJAfVaMLL4tcV0BqbkpBG/I2V8Bc6cDaSsgfxizSE4+UzsDZwelEH3w==", "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/types": "7.5.1", - "@polkadot/types-codec": "7.5.1", - "@polkadot/util": "^8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/types": "7.12.1", + "@polkadot/types-codec": "7.12.1", + "@polkadot/util": "^8.5.1" } }, "@polkadot/types-codec": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-7.5.1.tgz", - "integrity": "sha512-+MClbgg0sbEIsPnqVf1wVzR5qPCE5Xb+QXkwawx86mIyxb4eptdBnU0CFgHVcrNnKx6EcaUZWQgz17UxtmTWaA==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-7.12.1.tgz", + "integrity": "sha512-v7/vnrQuYxsou7ck+N0Cc7b+fqawCbvf3kJbU6tcJMvh745abnfF6gP+yt/fhDT4jkDufBNPagtrY7+z5e56Ew==", "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/util": "^8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/util": "^8.5.1" } }, "@polkadot/types-create": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-7.5.1.tgz", - "integrity": "sha512-OCsdDp4vd/6yNThTEmjbndHks4VHlfeuNwcQQN2NcM4Gs072LnuDTbRgFHAqvcSKB0SVOiWoy/UxkktLE+0w2Q==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-7.12.1.tgz", + "integrity": "sha512-p7dWBV2vJX9H/CPkgS3nkVit4rZJs2WJGzwBUtYy5fK07Iu1FvIGKSd4/bJVEuJwqmFlElliADjg5qlbiv3KOg==", "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/types-codec": "7.5.1", - "@polkadot/util": "^8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/types-codec": "7.12.1", + "@polkadot/util": "^8.5.1" } }, "@polkadot/types-known": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-7.5.1.tgz", - "integrity": "sha512-mECocUHbvb/ly5KOu+nKfqXAEKzYxkflO4xQflaEpcCIxtqBmy8AXSvyD8Dl5LFrBwHqnRbtXaPETCOYn1LWPg==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-7.12.1.tgz", + "integrity": "sha512-y+hu/qrE874WI0tNXIge7SX6kIC2sfhGWSWU0uyrA8khc7ByR9ENwAzxkJD3zht2taZZCM+ucVVH9ogpJZKCTg==", "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/networks": "^8.3.3", - "@polkadot/types": "7.5.1", - "@polkadot/types-codec": "7.5.1", - "@polkadot/types-create": "7.5.1", - "@polkadot/util": "^8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/networks": "^8.5.1", + "@polkadot/types": "7.12.1", + "@polkadot/types-codec": "7.12.1", + "@polkadot/types-create": "7.12.1", + "@polkadot/util": "^8.5.1" } }, "@polkadot/types-support": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-7.5.1.tgz", - "integrity": "sha512-6LrYMQVF6G9+r1mnYpSGX6irN0eG5OQQRb2YXX4wtYT3JIU+G9EK0NjLngSDf0KMMm80aD0hFKYF0DcuQSGk+A==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-7.12.1.tgz", + "integrity": "sha512-dlTRXJmBWIcRi3wryvaqPxGBv9vDfu+vWeyQF93CMRdCuBwKB25jeoh2n2xCMZ9c0TbziJzE+Qg2oGoKK2Dzeg==", "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/util": "^8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/util": "^8.5.1" } }, "@polkadot/util": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-8.3.3.tgz", - "integrity": "sha512-8u1NShSHrCFeFvxWL8WAyRN8y1/iPvijqYCDeeHziBxCNBrL3VKDc9GNF11skeay/EKQiCHBSBeAYyyQOpLebA==", - "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/x-bigint": "8.3.3", - "@polkadot/x-global": "8.3.3", - "@polkadot/x-textdecoder": "8.3.3", - "@polkadot/x-textencoder": "8.3.3", - "@types/bn.js": "^4.11.6", - "bn.js": "^4.12.0", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-8.5.1.tgz", + "integrity": "sha512-B+W3VdLo4ignLZXRTA/gAF7TwFe+kgW6XTt+BBWJL9dcjGVU66aL8xjTbohUNUtwlaD2p5kua6jJqTJC/3u3hQ==", + "requires": { + "@babel/runtime": "^7.17.2", + "@polkadot/x-bigint": "8.5.1", + "@polkadot/x-global": "8.5.1", + "@polkadot/x-textdecoder": "8.5.1", + "@polkadot/x-textencoder": "8.5.1", + "@types/bn.js": "^5.1.0", + "bn.js": "^5.2.0", "ip-regex": "^4.3.0" } }, "@polkadot/util-crypto": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-8.3.3.tgz", - "integrity": "sha512-kXaT2VTEbJq1wNiV0Dz5qJuVWy7pK+x1QLcyWC+6OFERYO+BCp1Y2bTOcLUeF/gyyR/ZaRMMdTyu0ZbHrwH0xg==", - "requires": { - "@babel/runtime": "^7.16.7", - "@noble/hashes": "0.5.7", - "@noble/secp256k1": "1.3.4", - "@polkadot/networks": "8.3.3", - "@polkadot/util": "8.3.3", - "@polkadot/wasm-crypto": "^4.5.1", - "@polkadot/x-bigint": "8.3.3", - "@polkadot/x-randomvalues": "8.3.3", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-8.5.1.tgz", + "integrity": "sha512-/+4Cwcd4vlIzvIVFXfNjNeoLWw4wSZY58OiXlq8apISrJly63u8KCa8DwV9SxxgMBU0xzpWi/4W1m7hihGh8RQ==", + "requires": { + "@babel/runtime": "^7.17.2", + "@noble/hashes": "1.0.0", + "@noble/secp256k1": "1.5.5", + "@polkadot/networks": "8.5.1", + "@polkadot/util": "8.5.1", + "@polkadot/wasm-crypto": "^4.6.1", + "@polkadot/x-bigint": "8.5.1", + "@polkadot/x-randomvalues": "8.5.1", + "@scure/base": "1.0.0", "ed2curve": "^0.3.0", - "micro-base": "^0.10.2", "tweetnacl": "^1.0.3" } }, "@polkadot/wasm-crypto": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto/-/wasm-crypto-4.5.1.tgz", - "integrity": "sha512-Cr21ais3Kq3aedIHZ3J1tjgeD/+K8FCiwEawr0oRywNBSJR8wyuZMePs4swR/6xm8wbBkpqoBVHz/UQHqqQJmA==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto/-/wasm-crypto-4.6.1.tgz", + "integrity": "sha512-2wEftBDxDG+TN8Ah6ogtvzjdZdcF0mAjU4UNNOfpmkBCxQYZOrAHB8HXhzo3noSsKkLX7PDX57NxvJ9OhoTAjw==", "requires": { - "@babel/runtime": "^7.16.3", - "@polkadot/wasm-crypto-asmjs": "^4.5.1", - "@polkadot/wasm-crypto-wasm": "^4.5.1" + "@babel/runtime": "^7.17.2", + "@polkadot/wasm-crypto-asmjs": "^4.6.1", + "@polkadot/wasm-crypto-wasm": "^4.6.1" } }, "@polkadot/wasm-crypto-asmjs": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-4.5.1.tgz", - "integrity": "sha512-DOdRiWhxVvmqTvp+E9z1j+Yr0zDOGsDvqnT/eNw0Dl1FVUOImsEa7FKns/urASmcxCVEE1jtUWSnij29jrORMQ==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-4.6.1.tgz", + "integrity": "sha512-1oHQjz2oEO1kCIcQniOP+dZ9N2YXf2yCLHLsKaKSvfXiWaetVCaBNB8oIHIVYvuLnVc8qlMi66O6xc1UublHsw==", "requires": { - "@babel/runtime": "^7.16.3" + "@babel/runtime": "^7.17.2" } }, "@polkadot/wasm-crypto-wasm": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-4.5.1.tgz", - "integrity": "sha512-hPwke85HxpgG/RAlwdCE8u5w7bThvWg399mlB+XjogXMxOUWBZSgq2XYbgzROUXx27inK9nStF4Pnc4zJnqs9A==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-4.6.1.tgz", + "integrity": "sha512-NI3JVwmLjrSYpSVuhu0yeQYSlsZrdpK41UC48sY3kyxXC71pi6OVePbtHS1K3xh3FFmDd9srSchExi3IwzKzMw==", "requires": { - "@babel/runtime": "^7.16.3" + "@babel/runtime": "^7.17.2" } }, "@polkadot/x-bigint": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-8.3.3.tgz", - "integrity": "sha512-2CT25f0zN/uhch3KpM38jtQfFJ1zJCNT41exg49ztsOvm4f6l+6hW91NLhNAZ313B/c6Z4Lm3DalsjAOdBZ8Nw==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-8.5.1.tgz", + "integrity": "sha512-6HaINISJYIf2t9FFnUh6aFC5/Zf8wifcuHpMQGTlfXGeK7egmTmkVE9fjkoDOOSt6jbJ+jvlPcWcPh9WdY4tkg==", "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/x-global": "8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/x-global": "8.5.1" } }, "@polkadot/x-fetch": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-8.3.3.tgz", - "integrity": "sha512-+ScnWnt0i1IF+fM9IC+OnjkTi5NonK+ji8q861hwkNCtK2ziibibcD3mGavCA6wZvij4wUTovWEsTc5Su0+KTA==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-8.5.1.tgz", + "integrity": "sha512-c3VytuvXPm5NLOCF6TTm8avJ6jO8nmyrmVR4IQlq1hhQM556bbAv1+/PSnzwO6Rhr8KWu6TdsTIbl+wyky96Jw==", "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/x-global": "8.3.3", - "@types/node-fetch": "^2.5.12", + "@babel/runtime": "^7.17.2", + "@polkadot/x-global": "8.5.1", + "@types/node-fetch": "^2.6.1", "node-fetch": "^2.6.7" } }, "@polkadot/x-global": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-8.3.3.tgz", - "integrity": "sha512-7DWjcNhTDIpYNiQmLq56o6xYOONr0i6WXdoPUxYrToxZWeWyj/FWaYMfttedLydABPcy87lmvIy8ECp7qCcnyw==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-8.5.1.tgz", + "integrity": "sha512-fjKivdI0fOrT86YyLZJHGFkAZSo7ZyrAos2CoJ/DPhSNYOYg6wwaqLloodDBx5awpt0383jns97MOPdkFu3n6A==", "requires": { - "@babel/runtime": "^7.16.7" + "@babel/runtime": "^7.17.2" } }, "@polkadot/x-randomvalues": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-8.3.3.tgz", - "integrity": "sha512-yxM6GWQholf+vY4dHxKVwtJwDzNUz4UJlL/iN3PA0cuhQ37gxmtJugnNAllcFd8LDNXEN47Ky6Ifw1OHHmZaVw==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-8.5.1.tgz", + "integrity": "sha512-4FRCiieOcHEsWoO95NpPLm/6bjyalYylPyKuMw16cEOTrbtGzYi9mYW34gLyR5vy08ZDOBBM5b1zRzmzAL7yQg==", "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/x-global": "8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/x-global": "8.5.1" } }, "@polkadot/x-textdecoder": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-8.3.3.tgz", - "integrity": "sha512-oEvFJv/F+fQ336ciRuJJgJFtfyOX6a2Nyr/5GCkiSQjkEIdnBUuO49yXpHNmQsNI0WndLWIEitiVVa9KuDslYw==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-8.5.1.tgz", + "integrity": "sha512-UVGMy8bibZDaF9BadwsNOHExHDyDp+f7chqqLEMVdu48l+gTqFmtqhGhegYz2ft23JBHIO0t93MYa8R3RwEEwA==", "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/x-global": "8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/x-global": "8.5.1" } }, "@polkadot/x-textencoder": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-8.3.3.tgz", - "integrity": "sha512-acVsJjmlQ7aluUq8JARY2wJAbf+6dvZNoUrvgzdX/jl5MqvqeIXmX3LX71MyidLt27Z537VDgNzWw8V/524AVQ==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-8.5.1.tgz", + "integrity": "sha512-c2ZD7mHxrz8rE87eF78QfN7d1IFcHsu4aRTuja/oXMf1MEebChP/XmjHUGog/Ib5W6Hn4+Bm8at2DTgxjYfROg==", "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/x-global": "8.3.3" + "@babel/runtime": "^7.17.2", + "@polkadot/x-global": "8.5.1" } }, "@polkadot/x-ws": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-8.3.3.tgz", - "integrity": "sha512-Dd0kscZSb7MULVqo5isPZyqvErvgE7lYIwZ4IA0rNdgUWi3mrJWeeWrzVMxC6nbg6q1ahIEGxxZLMVzeI3u/Ew==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-8.5.1.tgz", + "integrity": "sha512-61TT3dMt9J0JihaprZo/8Lr75qIGr0A/TKuflCBnHw24kRbaamnCYUAtyJC1uL3X50LDqtGRybvpKPGOnzl5sQ==", "requires": { - "@babel/runtime": "^7.16.7", - "@polkadot/x-global": "8.3.3", - "@types/websocket": "^1.0.4", + "@babel/runtime": "^7.17.2", + "@polkadot/x-global": "8.5.1", + "@types/websocket": "^1.0.5", "websocket": "^1.0.34" } }, + "@scure/base": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.0.0.tgz", + "integrity": "sha512-gIVaYhUsy+9s58m/ETjSJVKHhKTBMmcRb9cEV5/5dwvfDlfORjKrFsDeDHWRrm6RjcPvCLZFwGJjAjLj1gg4HA==" + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" }, + "@substrate/ss58-registry": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/@substrate/ss58-registry/-/ss58-registry-1.16.0.tgz", + "integrity": "sha512-z88145A9NE0mnDbIYRP1SlHndDtm6Jd1cRnG2InRCA/M7UprFRc0zrtaTWj1KBHfcVc2uYUMggGXuenQPBQ8yQ==" + }, "@szmarczak/http-timer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", @@ -8683,6 +10796,11 @@ "defer-to-connect": "^1.0.1" } }, + "@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" + }, "@tsconfig/node10": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", @@ -8708,9 +10826,9 @@ "dev": true }, "@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", + "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", "requires": { "@types/node": "*" } @@ -8747,7 +10865,8 @@ "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true }, "@types/minimist": { "version": "1.2.2", @@ -8756,19 +10875,19 @@ "dev": true }, "@types/mocha": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.0.0.tgz", - "integrity": "sha512-scN0hAWyLVAvLR9AyW7HoFF5sJZglyBsbPuHO4fv7JRvfmPBMfp1ozWqOf/e4wwPNxezBZXRfWzMb6iFLgEVRA==" + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.0.tgz", + "integrity": "sha512-QCWHkbMv4Y5U9oW10Uxbr45qMMSzl4OzijsozynUAgx3kEHUdXB00udx2dWDQ7f2TU2a2uuiFaRZjCe3unPpeg==" }, "@types/node": { - "version": "17.0.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.9.tgz", - "integrity": "sha512-5dNBXu/FOER+EXnyah7rn8xlNrfMOQb/qXnw4NQgLkCygKBKhdmF/CA5oXVOKZLBEahw8s2WP9LxIcN/oDDRgQ==" + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==" }, "@types/node-fetch": { - "version": "2.5.12", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.12.tgz", - "integrity": "sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA==", "requires": { "@types/node": "*", "form-data": "^3.0.0" @@ -8783,9 +10902,9 @@ } }, "@types/ramda": { - "version": "0.27.64", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.27.64.tgz", - "integrity": "sha512-EDf++ss/JoMiDpvT1MuA8oi88OwpvmqVE+o8Ojm5v/5bdJEPZ6eIQd/XYAeQ0imlwG6Tf0Npfq4Z9w3hAKBk9Q==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.28.1.tgz", + "integrity": "sha512-8wnJK5aPaGL7AYhQSe7olwxjhIB9GO4GOCxd6JjYlVNe128DHJDOu7Kyve4kx4uazeKJdnOS3N5TVRv0z1bb1g==", "requires": { "ts-toolbelt": "^6.15.1" } @@ -8807,14 +10926,14 @@ } }, "@typescript-eslint/eslint-plugin": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.10.1.tgz", - "integrity": "sha512-xN3CYqFlyE/qOcy978/L0xLR2HlcAGIyIK5sMOasxaaAPfQRj/MmMV6OC3I7NZO84oEUdWCOju34Z9W8E0pFDQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.15.0.tgz", + "integrity": "sha512-u6Db5JfF0Esn3tiAKELvoU5TpXVSkOpZ78cEGn/wXtT2RVqs2vkt4ge6N8cRCyw7YVKhmmLDbwI2pg92mlv7cA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.10.1", - "@typescript-eslint/type-utils": "5.10.1", - "@typescript-eslint/utils": "5.10.1", + "@typescript-eslint/scope-manager": "5.15.0", + "@typescript-eslint/type-utils": "5.15.0", + "@typescript-eslint/utils": "5.15.0", "debug": "^4.3.2", "functional-red-black-tree": "^1.0.1", "ignore": "^5.1.8", @@ -8833,52 +10952,52 @@ } }, "@typescript-eslint/parser": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.10.1.tgz", - "integrity": "sha512-GReo3tjNBwR5RnRO0K2wDIDN31cM3MmDtgyQ85oAxAmC5K3j/g85IjP+cDfcqDsDDBf1HNKQAD0WqOYL8jXqUA==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.15.0.tgz", + "integrity": "sha512-NGAYP/+RDM2sVfmKiKOCgJYPstAO40vPAgACoWPO/+yoYKSgAXIFaBKsV8P0Cc7fwKgvj27SjRNX4L7f4/jCKQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.10.1", - "@typescript-eslint/types": "5.10.1", - "@typescript-eslint/typescript-estree": "5.10.1", + "@typescript-eslint/scope-manager": "5.15.0", + "@typescript-eslint/types": "5.15.0", + "@typescript-eslint/typescript-estree": "5.15.0", "debug": "^4.3.2" } }, "@typescript-eslint/scope-manager": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.10.1.tgz", - "integrity": "sha512-Lyvi559Gvpn94k7+ElXNMEnXu/iundV5uFmCUNnftbFrUbAJ1WBoaGgkbOBm07jVZa682oaBU37ao/NGGX4ZDg==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.15.0.tgz", + "integrity": "sha512-EFiZcSKrHh4kWk0pZaa+YNJosvKE50EnmN4IfgjkA3bTHElPtYcd2U37QQkNTqwMCS7LXeDeZzEqnsOH8chjSg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.10.1", - "@typescript-eslint/visitor-keys": "5.10.1" + "@typescript-eslint/types": "5.15.0", + "@typescript-eslint/visitor-keys": "5.15.0" } }, "@typescript-eslint/type-utils": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.10.1.tgz", - "integrity": "sha512-AfVJkV8uck/UIoDqhu+ptEdBoQATON9GXnhOpPLzkQRJcSChkvD//qsz9JVffl2goxX+ybs5klvacE9vmrQyCw==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.15.0.tgz", + "integrity": "sha512-KGeDoEQ7gHieLydujGEFLyLofipe9PIzfvA/41urz4hv+xVxPEbmMQonKSynZ0Ks2xDhJQ4VYjB3DnRiywvKDA==", "dev": true, "requires": { - "@typescript-eslint/utils": "5.10.1", + "@typescript-eslint/utils": "5.15.0", "debug": "^4.3.2", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.10.1.tgz", - "integrity": "sha512-ZvxQ2QMy49bIIBpTqFiOenucqUyjTQ0WNLhBM6X1fh1NNlYAC6Kxsx8bRTY3jdYsYg44a0Z/uEgQkohbR0H87Q==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.15.0.tgz", + "integrity": "sha512-yEiTN4MDy23vvsIksrShjNwQl2vl6kJeG9YkVJXjXZnkJElzVK8nfPsWKYxcsGWG8GhurYXP4/KGj3aZAxbeOA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.1.tgz", - "integrity": "sha512-PwIGnH7jIueXv4opcwEbVGDATjGPO1dx9RkUl5LlHDSe+FXxPwFL5W/qYd5/NHr7f6lo/vvTrAzd0KlQtRusJQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.15.0.tgz", + "integrity": "sha512-Hb0e3dGc35b75xLzixM3cSbG1sSbrTBQDfIScqdyvrfJZVEi4XWAT+UL/HMxEdrJNB8Yk28SKxPLtAhfCbBInA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.10.1", - "@typescript-eslint/visitor-keys": "5.10.1", + "@typescript-eslint/types": "5.15.0", + "@typescript-eslint/visitor-keys": "5.15.0", "debug": "^4.3.2", "globby": "^11.0.4", "is-glob": "^4.0.3", @@ -8898,39 +11017,44 @@ } }, "@typescript-eslint/utils": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.10.1.tgz", - "integrity": "sha512-RRmlITiUbLuTRtn/gcPRi4202niF+q7ylFLCKu4c+O/PcpRvZ/nAUwQ2G00bZgpWkhrNLNnvhZLbDn8Ml0qsQw==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.15.0.tgz", + "integrity": "sha512-081rWu2IPKOgTOhHUk/QfxuFog8m4wxW43sXNOMSCdh578tGJ1PAaWPsj42LOa7pguh173tNlMigsbrHvh/mtA==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.10.1", - "@typescript-eslint/types": "5.10.1", - "@typescript-eslint/typescript-estree": "5.10.1", + "@typescript-eslint/scope-manager": "5.15.0", + "@typescript-eslint/types": "5.15.0", + "@typescript-eslint/typescript-estree": "5.15.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" } }, "@typescript-eslint/visitor-keys": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.1.tgz", - "integrity": "sha512-NjQ0Xinhy9IL979tpoTRuLKxMc0zJC7QVSdeerXs2/QvOy2yRkzX5dRb10X5woNUdJgU8G3nYRDlI33sq1K4YQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.15.0.tgz", + "integrity": "sha512-+vX5FKtgvyHbmIJdxMJ2jKm9z2BIlXJiuewI8dsDYMp5LzPUcuTT78Ya5iwvQg3VqSVdmxyM8Anj1Jeq7733ZQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.10.1", + "@typescript-eslint/types": "5.15.0", "eslint-visitor-keys": "^3.0.0" } }, "@ungap/promise-all-settled": { "version": "1.1.2" }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" } }, "acorn": { @@ -8939,6 +11063,8 @@ }, "acorn-jsx": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "requires": {} }, @@ -8948,6 +11074,33 @@ "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "dev": true }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, + "agentkeepalive": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", + "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", + "requires": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, "ajv": { "version": "6.12.6", "requires": { @@ -8957,6 +11110,14 @@ "uri-js": "^4.2.2" } }, + "ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "requires": { + "string-width": "^4.1.0" + } + }, "ansi-colors": { "version": "4.1.1" }, @@ -8978,6 +11139,20 @@ "picomatch": "^2.0.4" } }, + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "are-we-there-yet": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz", + "integrity": "sha512-0GWpv50YSOcLXaN6/FAKY3vfRbllXWV2xvfA/oKJF8pzFhWXPV+yjhJXDBbjscDYowv7Yw1A3uigpzn5iEGTyw==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, "arg": { "version": "4.1.3", "dev": true @@ -8993,8 +11168,7 @@ "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" }, "arrify": { "version": "1.0.1", @@ -9019,6 +11193,13 @@ "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0", "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } } }, "assert": { @@ -9114,24 +11295,24 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" }, "body-parser": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz", - "integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==", + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", "requires": { - "bytes": "3.1.1", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.2", "http-errors": "1.8.1", "iconv-lite": "0.4.24", "on-finished": "~2.3.0", - "qs": "6.9.6", - "raw-body": "2.4.2", + "qs": "6.9.7", + "raw-body": "2.4.3", "type-is": "~1.6.18" }, "dependencies": { @@ -9143,6 +11324,14 @@ "ms": "2.0.0" } }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -9150,6 +11339,21 @@ } } }, + "boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + } + }, "brace-expansion": { "version": "1.1.11", "requires": { @@ -9159,6 +11363,8 @@ }, "braces": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "requires": { "fill-range": "^7.0.1" } @@ -9212,13 +11418,6 @@ "requires": { "bn.js": "^5.0.0", "randombytes": "^2.0.1" - }, - "dependencies": { - "bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" - } } }, "browserify-sign": { @@ -9235,24 +11434,17 @@ "parse-asn1": "^5.1.5", "readable-stream": "^3.6.0", "safe-buffer": "^5.2.0" - }, - "dependencies": { - "bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" - } } }, "browserslist": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz", - "integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==", + "version": "4.20.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz", + "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==", "requires": { - "caniuse-lite": "^1.0.30001286", - "electron-to-chromium": "^1.4.17", + "caniuse-lite": "^1.0.30001317", + "electron-to-chromium": "^1.4.84", "escalade": "^3.1.1", - "node-releases": "^2.0.1", + "node-releases": "^2.0.2", "picocolors": "^1.0.0" } }, @@ -9302,10 +11494,52 @@ "node-gyp-build": "^4.3.0" } }, + "builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=" + }, "bytes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", - "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "cacache": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.0.1.tgz", + "integrity": "sha512-tHPtfdZDqQpZ15eaEZeLspIqS5mK5fOBDZi6AjuqaIi53QNVXH3dQv6uKT3YuUu6uxV/8pjU9in0CoJ8fgaHqw==", + "requires": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.1.2", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^7.2.0", + "infer-owner": "^1.0.4", + "lru-cache": "^7.5.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.1.11", + "unique-filename": "^1.1.1" + }, + "dependencies": { + "lru-cache": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.5.1.tgz", + "integrity": "sha512-q1TS8IqKvcg3aScamKCHpepSrHF537Ww7nHahBOxhDu9D2YoBXAsj/7uFdZFj1xJr9LmyeJ62AdyofCHafUbIA==" + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + } + } }, "cacheable-request": { "version": "6.1.0", @@ -9345,15 +11579,17 @@ }, "callsites": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, "camelcase": { "version": "6.3.0" }, "caniuse-lite": { - "version": "1.0.30001299", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001299.tgz", - "integrity": "sha512-iujN4+x7QzqA2NCSrS5VUy+4gLmRd4xv6vbBBsmfVqTx8bLAD8097euLqQgKxSVLvxjSDcvF1T/i9ocgnUFexw==" + "version": "1.0.30001317", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001317.tgz", + "integrity": "sha512-xIZLh8gBm4dqNX0gkzrBeyI86J2eCjWzYAs40q88smG844YIrN4tVQl/RhquHvKEKImWWFIVh1Lxe5n1G/N+GQ==" }, "caseless": { "version": "0.12.0", @@ -9361,12 +11597,15 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "chai": { - "version": "4.3.4", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", + "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", "requires": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", "deep-eql": "^3.0.1", "get-func-name": "^2.0.0", + "loupe": "^2.3.1", "pathval": "^1.1.1", "type-detect": "^4.0.5" } @@ -9377,6 +11616,12 @@ "check-error": "^1.0.2" } }, + "chai-bn": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/chai-bn/-/chai-bn-0.3.1.tgz", + "integrity": "sha512-vuzEy0Cb+k8zqi2SHOmvZdRSbKcSOJfS1Nv8+6YDJIyCzfxkTCHLNRyjRIoRJ3WJtYb/c7OHjrvLoGeyO4A/gA==", + "requires": {} + }, "chalk": { "version": "4.1.2", "requires": { @@ -9396,24 +11641,29 @@ "version": "1.0.2" }, "chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "requires": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "readdirp": "~3.6.0" } }, "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" }, "cids": { "version": "0.7.5", @@ -9438,6 +11688,11 @@ } } }, + "cint": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/cint/-/cint-8.2.1.tgz", + "integrity": "sha1-cDhrG0jidz0NYxZqVa/5TvRFahI=" + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -9452,6 +11707,24 @@ "resolved": "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz", "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==" }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + }, + "cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==" + }, + "cli-table": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz", + "integrity": "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==", + "requires": { + "colors": "1.0.3" + } + }, "cliui": { "version": "7.0.4", "requires": { @@ -9487,6 +11760,16 @@ "color-name": { "version": "1.1.4" }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -9495,6 +11778,11 @@ "delayed-stream": "~1.0.0" } }, + "commander": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.0.0.tgz", + "integrity": "sha512-JJfP2saEKbQqvW+FI93OYUB4ByV5cizMpFMiiJI8xDbBvQvSkIk0VvQdn1CZ8mqAO8Loq2h0gYTYtDFUZUeERw==" + }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -9503,6 +11791,34 @@ "concat-map": { "version": "0.0.1" }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + } + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, "content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -9542,9 +11858,9 @@ } }, "cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" }, "cookie-signature": { "version": "1.0.6", @@ -9571,12 +11887,12 @@ } }, "crc-32": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", - "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.1.tgz", + "integrity": "sha512-Dn/xm/1vFFgs3nfrpEVScHoIslO9NZRITWGz/1E/St6u4xw99vfZzVkW0OSnzx2h9egej9xwMCEut6sqwokM/w==", "requires": { "exit-on-epipe": "~1.0.1", - "printj": "~1.1.0" + "printj": "~1.3.1" } }, "create-ecdh": { @@ -9586,6 +11902,13 @@ "requires": { "bn.js": "^4.1.0", "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } } }, "create-hash": { @@ -9644,6 +11967,11 @@ "randomfill": "^1.0.3" } }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" + }, "d": { "version": "1.0.1", "requires": { @@ -9660,10 +11988,14 @@ } }, "dateformat": { - "version": "4.6.3" + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==" }, "debug": { - "version": "4.3.2", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "requires": { "ms": "2.1.2" }, @@ -9695,6 +12027,11 @@ "type-detect": "^4.0.0" } }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, "deep-is": { "version": "0.1.4", "dev": true @@ -9715,6 +12052,11 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -9745,13 +12087,19 @@ "bn.js": "^4.1.0", "miller-rabin": "^4.0.0", "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } } }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, "requires": { "path-type": "^4.0.0" } @@ -9768,6 +12116,14 @@ "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "requires": { + "is-obj": "^2.0.0" + } + }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -9796,9 +12152,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { - "version": "1.4.44", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.44.tgz", - "integrity": "sha512-tHGWiUUmY7GABK8+DNcr474cnZDTzD8x1736SlDosVH8+/vRJeqfaIBAEHFtMjddz/0T4rKKYsxEc8BwQRdBpw==" + "version": "1.4.85", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.85.tgz", + "integrity": "sha512-K9AsQ41WS2bjZUFpRWfvaS4RjEcRCamEkBJN1Z1TQILBfP1H8QnJ9ti0wiLiMv0sRjX3EHKzgs9jDnmGFx2jXg==" }, "elliptic": { "version": "6.5.4", @@ -9812,6 +12168,13 @@ "inherits": "^2.0.4", "minimalistic-assert": "^1.0.1", "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } } }, "emoji-regex": { @@ -9822,6 +12185,15 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "requires": { + "iconv-lite": "^0.6.2" + } + }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -9830,6 +12202,16 @@ "once": "^1.4.0" } }, + "env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==" + }, + "err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" + }, "es-abstract": { "version": "1.19.1", "requires": { @@ -9893,19 +12275,26 @@ "escalade": { "version": "3.1.1" }, + "escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==" + }, "escape-html": { - "version": "1.0.3" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, "escape-string-regexp": { "version": "4.0.0" }, "eslint": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.7.0.tgz", - "integrity": "sha512-ifHYzkBGrzS2iDU7KjhCAVMGCvF6M3Xfs8X8b37cgrUlDt6bWRTpRh6T/gtSXv1HJ/BUGgmjvNvOEGu85Iif7w==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.11.0.tgz", + "integrity": "sha512-/KRpd9mIRg2raGxHRGwW9ZywYNAClZrHjdueHcrVDuO3a6bj83eoTirCCk0M0yPwOjWYKHwRVRid+xK4F/GHgA==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.0.5", + "@eslint/eslintrc": "^1.2.1", "@humanwhocodes/config-array": "^0.9.2", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -9913,10 +12302,10 @@ "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.0", + "eslint-scope": "^7.1.1", "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.2.0", - "espree": "^9.3.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -9943,7 +12332,9 @@ }, "dependencies": { "eslint-scope": { - "version": "7.1.0", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", "dev": true, "requires": { "esrecurse": "^4.3.0", @@ -9952,6 +12343,8 @@ }, "estraverse": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true }, "glob-parent": { @@ -9960,6 +12353,15 @@ "requires": { "is-glob": "^4.0.3" } + }, + "globals": { + "version": "13.13.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", + "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } } } }, @@ -9992,18 +12394,20 @@ } }, "eslint-visitor-keys": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz", - "integrity": "sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", "dev": true }, "espree": { - "version": "9.3.0", + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", + "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", "dev": true, "requires": { "acorn": "^8.7.0", "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.1.0" + "eslint-visitor-keys": "^3.3.0" } }, "esquery": { @@ -10021,6 +12425,8 @@ }, "esrecurse": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "requires": { "estraverse": "^5.2.0" @@ -10028,6 +12434,8 @@ "dependencies": { "estraverse": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true } } @@ -10074,6 +12482,13 @@ "servify": "^0.1.12", "ws": "^3.0.0", "xhr-request-promise": "^0.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } } }, "ethereum-bloom-filters": { @@ -10107,30 +12522,15 @@ } }, "ethereumjs-util": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.3.tgz", - "integrity": "sha512-y+82tEbyASO0K0X1/SRhbJJoAlfcvq8JbrG4a5cjrOks7HS/36efU/0j2flxCPOUM++HFahk33kr/ZxyC4vNuw==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.4.tgz", + "integrity": "sha512-p6KmuPCX4mZIqsQzXfmSx9Y0l2hqf+VkAiwSisW3UKUFdk8ZkAt+AYaor83z2nSi6CU2zSsXMlD80hAbNEGM0A==", "requires": { "@types/bn.js": "^5.1.0", "bn.js": "^5.1.2", "create-hash": "^1.1.2", "ethereum-cryptography": "^0.1.3", "rlp": "^2.2.4" - }, - "dependencies": { - "@types/bn.js": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", - "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", - "requires": { - "@types/node": "*" - } - }, - "bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" - } } }, "ethjs-unit": { @@ -10169,16 +12569,16 @@ "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==" }, "express": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.2.tgz", - "integrity": "sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg==", + "version": "4.17.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", + "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", "requires": { - "accepts": "~1.3.7", + "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.1", + "body-parser": "1.19.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.1", + "cookie": "0.4.2", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "~1.1.2", @@ -10193,7 +12593,7 @@ "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.7", - "qs": "6.9.6", + "qs": "6.9.7", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.17.2", @@ -10248,7 +12648,6 @@ "version": "3.2.11", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -10264,15 +12663,24 @@ "version": "2.0.6", "dev": true }, + "fast-memoize": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz", + "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==" + }, "fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, "requires": { "reusify": "^1.0.4" } }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==" + }, "file-entry-cache": { "version": "6.0.1", "dev": true, @@ -10282,6 +12690,8 @@ }, "fill-range": { "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "requires": { "to-regex-range": "^5.0.1" } @@ -10370,13 +12780,20 @@ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" }, + "fp-and-or": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/fp-and-or/-/fp-and-or-0.1.3.tgz", + "integrity": "sha512-wJaE62fLaB3jCYvY2ZHjZvmKK2iiLiiehX38rz5QZxtdN8fVPJDeZUiVvJrHStdTc+23LHlyZuSEKgFc0pxi2g==" + }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, "fs-extra": { - "version": "10.0.0", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", + "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", "requires": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -10384,11 +12801,11 @@ } }, "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "requires": { - "minipass": "^2.6.0" + "minipass": "^3.0.0" } }, "fs.realpath": { @@ -10401,7 +12818,9 @@ "optional": true }, "fsu": { - "version": "1.1.1" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fsu/-/fsu-1.1.1.tgz", + "integrity": "sha512-xQVsnjJ/5pQtcKh+KjUoZGzVWn4uNkchxTF6Lwjr4Gf7nQr8fmUfhKJ62zE77+xQg9xnxi5KUps7XGs+VC986A==" }, "function-bind": { "version": "1.1.1" @@ -10410,6 +12829,21 @@ "version": "1.0.1", "dev": true }, + "gauge": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.3.tgz", + "integrity": "sha512-ICw1DhAwMtb22rYFwEHgJcx1JCwJGv3x6G0OQUq56Nge+H4Q8JEwr8iveS0XFlsUNSI67F5ffMGK25bK4Pmskw==", + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + } + }, "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -10429,6 +12863,11 @@ "has-symbols": "^1.0.1" } }, + "get-stdin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==" + }, "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -10453,8 +12892,9 @@ } }, "glob": { - "version": "7.1.7", - "dev": true, + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -10466,6 +12906,8 @@ }, "glob-parent": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "requires": { "is-glob": "^4.0.1" } @@ -10479,18 +12921,30 @@ "process": "^0.11.10" } }, - "globals": { - "version": "13.12.0", - "dev": true, + "global-dirs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", + "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", "requires": { - "type-fest": "^0.20.2" + "ini": "2.0.0" + }, + "dependencies": { + "ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==" + } } }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + }, "globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, "requires": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -10584,6 +13038,16 @@ "has-symbols": "^1.0.2" } }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==" + }, "hash-base": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", @@ -10616,6 +13080,14 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, "http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", @@ -10638,6 +13110,16 @@ "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", "integrity": "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=" }, + "http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "requires": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + } + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -10648,12 +13130,30 @@ "sshpk": "^1.7.0" } }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "requires": { + "ms": "^2.0.0" + } + }, "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "idna-uts46-hx": { @@ -10677,20 +13177,43 @@ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { - "version": "5.2.0", - "dev": true + "version": "5.2.0" + }, + "ignore-walk": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-4.0.1.tgz", + "integrity": "sha512-rzDQLaW4jQbh2YrOFlJdCtX8qgJTehFRYiUB2r1osqTeDzV/3+Jh8fz1oAPzUThf3iku8Ds4IDqawI5d8mUiQw==", + "requires": { + "minimatch": "^3.0.4" + } }, "import-fresh": { "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" + }, "imurmurhash": { - "version": "0.1.4", - "dev": true + "version": "0.1.4" + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" }, "inflight": { "version": "1.0.6", @@ -10702,6 +13225,11 @@ "inherits": { "version": "2.0.4" }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, "internal-slot": { "version": "1.0.3", "requires": { @@ -10710,6 +13238,11 @@ "side-channel": "^1.0.4" } }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, "ip-regex": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", @@ -10751,6 +13284,22 @@ "is-callable": { "version": "1.2.4" }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "requires": { + "has": "^1.0.3" + } + }, "is-date-object": { "version": "1.0.5", "requires": { @@ -10785,6 +13334,20 @@ "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" }, + "is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "requires": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + } + }, + "is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=" + }, "is-nan": { "version": "1.3.2", "dev": true, @@ -10796,8 +13359,15 @@ "is-negative-zero": { "version": "2.0.2" }, + "is-npm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==" + }, "is-number": { - "version": "7.0.0" + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, "is-number-object": { "version": "1.0.6", @@ -10805,11 +13375,21 @@ "has-tostringtag": "^1.0.0" } }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" + }, "is-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==" }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" + }, "is-plain-obj": { "version": "2.1.0" }, @@ -10866,12 +13446,22 @@ "is-typedarray": { "version": "1.0.0" }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==" + }, "is-weakref": { "version": "1.0.2", "requires": { "call-bind": "^1.0.2" } }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" + }, "isexe": { "version": "2.0.0" }, @@ -10894,6 +13484,11 @@ "is-object": "^1.0.1" } }, + "jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=" + }, "js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", @@ -10904,7 +13499,6 @@ }, "js-yaml": { "version": "4.1.0", - "dev": true, "requires": { "argparse": "^2.0.1" } @@ -10924,6 +13518,19 @@ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "json-parse-helpfulerror": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz", + "integrity": "sha1-E/FM4C7tTpgSl7ZOueO5MuLdE9w=", + "requires": { + "jju": "^1.1.0" + } + }, "json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", @@ -10943,17 +13550,30 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, "requires": { "minimist": "^1.2.0" } }, "jsonfile": { "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "requires": { "graceful-fs": "^4.1.6", "universalify": "^2.0.0" } }, + "jsonlines": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsonlines/-/jsonlines-0.1.1.tgz", + "integrity": "sha1-T80kbcXQ44aRkHxEqwAveC0dlMw=" + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" + }, "jsprim": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", @@ -10988,6 +13608,19 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" + }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "requires": { + "package-json": "^6.3.0" + } + }, "levn": { "version": "0.4.1", "dev": true, @@ -10996,17 +13629,74 @@ "type-check": "~0.4.0" } }, + "libnpmconfig": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/libnpmconfig/-/libnpmconfig-1.2.1.tgz", + "integrity": "sha512-9esX8rTQAHqarx6qeZqmGQKBNZR5OIbl/Ayr0qQDy3oXja2iFVQQI81R6GZ2a02bSNZ9p3YOGX1O6HHCb1X7kA==", + "requires": { + "figgy-pudding": "^3.5.1", + "find-up": "^3.0.0", + "ini": "^1.3.5" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + } + } + }, "locate-path": { "version": "6.0.0", "requires": { "p-locate": "^5.0.0" } }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "lodash.isempty": { "version": "4.4.0" }, "lodash.isfunction": { - "version": "3.0.9" + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" }, "lodash.isobject": { "version": "3.0.2" @@ -11024,19 +13714,30 @@ "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=" }, "log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "requires": { - "chalk": "^4.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" } }, "loose-envify": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "requires": { "js-tokens": "^3.0.0 || ^4.0.0" } }, + "loupe": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.1.tgz", + "integrity": "sha512-EN1D3jyVmaX4tnajVlfbREU4axL647hLec1h/PXAb8CPDMJiYitcWF2UeLVNttRqaIqQs4x+mRvXf+d+TlDrCA==", + "requires": { + "get-func-name": "^2.0.0" + } + }, "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -11044,7 +13745,6 @@ }, "lru-cache": { "version": "6.0.0", - "dev": true, "requires": { "yallist": "^4.0.0" } @@ -11069,6 +13769,36 @@ "version": "1.3.6", "dev": true }, + "make-fetch-happen": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.0.6.tgz", + "integrity": "sha512-4Gfh6lV3TLXmj7qz79hBFuvVqjYSMW6v2+sxtdX4LFQU0rK3V/txRjE0DoZb7X0IF3t9f8NO3CxPSWlvdckhVA==", + "requires": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.0.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.5.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.1.1", + "ssri": "^8.0.1" + }, + "dependencies": { + "lru-cache": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.5.1.tgz", + "integrity": "sha512-q1TS8IqKvcg3aScamKCHpepSrHF537Ww7nHahBOxhDu9D2YoBXAsj/7uFdZFj1xJr9LmyeJ62AdyofCHafUbIA==" + } + } + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -11092,24 +13822,17 @@ "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, - "micro-base": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/micro-base/-/micro-base-0.10.2.tgz", - "integrity": "sha512-lqqJrT7lfJtDmmiQ4zRLZuIJBk96t0RAc5pCrrWpL9zDeH5i/SUL85mku9HqzTI/OCZ8EQ3aicbMW+eK5Nyu5w==" - }, "micromatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, "requires": { "braces": "^3.0.1", "picomatch": "^2.2.3" @@ -11122,6 +13845,13 @@ "requires": { "bn.js": "^4.0.0", "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } } }, "mime": { @@ -11130,16 +13860,16 @@ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "requires": { - "mime-db": "1.51.0" + "mime-db": "1.52.0" } }, "mimic-response": { @@ -11160,44 +13890,89 @@ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" }, - "minimalistic-crypto-utils": { + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimatch": { + "version": "3.0.4", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "minipass": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", + "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", + "requires": { + "yallist": "^4.0.0" + } + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-fetch": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.0.3.tgz", + "integrity": "sha512-VA+eiiUtaIvpQJXISwE3OiMvQwAWrgKb97F0aXlCS1Ahikr8fEQq8m3Hf7Kv9KT3nokuHigJKsDMB6atU04olQ==", + "requires": { + "encoding": "^0.1.13", + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-json-stream": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" - }, - "minimatch": { - "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", + "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", "requires": { - "brace-expansion": "^1.1.7" + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" } }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "requires": { + "minipass": "^3.0.0" + } }, - "minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - }, - "dependencies": { - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - } + "minipass": "^3.0.0" } }, "minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "requires": { - "minipass": "^2.9.0" + "minipass": "^3.0.0", + "yallist": "^4.0.0" } }, "mkdirp": { @@ -11217,71 +13992,42 @@ } }, "mocha": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", - "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", + "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", "requires": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.5.1", - "debug": "4.3.1", + "chokidar": "3.5.3", + "debug": "4.3.3", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.1.6", + "glob": "7.2.0", "growl": "1.10.5", "he": "1.2.0", - "js-yaml": "4.0.0", - "log-symbols": "4.0.0", - "minimatch": "3.0.4", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "4.2.1", "ms": "2.1.3", - "nanoid": "3.1.20", - "serialize-javascript": "5.0.1", + "nanoid": "3.3.1", + "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.1.0", + "workerpool": "6.2.0", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" }, "dependencies": { - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "requires": { - "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" - } - }, - "js-yaml": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", - "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "minimatch": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", + "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", "requires": { - "argparse": "^2.0.1" + "brace-expansion": "^1.1.7" } } } @@ -11294,7 +14040,9 @@ "requires": {} }, "mochawesome": { - "version": "7.0.1", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/mochawesome/-/mochawesome-7.1.2.tgz", + "integrity": "sha512-kZBHRYoiV+zPrqMO0TU4LOiYDCMR5ciBZEE6fvS6RFMtB2MMndeOQ2LQEpFHtPG8yxFsqg1F6gym5qo3rPs/XA==", "requires": { "chalk": "^4.1.2", "diff": "^5.0.0", @@ -11303,13 +14051,15 @@ "lodash.isfunction": "^3.0.9", "lodash.isobject": "^3.0.2", "lodash.isstring": "^4.0.1", - "mochawesome-report-generator": "^6.0.1", + "mochawesome-report-generator": "^6.1.1", "strip-ansi": "^6.0.1", "uuid": "^8.3.2" } }, "mochawesome-report-generator": { - "version": "6.0.1", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/mochawesome-report-generator/-/mochawesome-report-generator-6.1.1.tgz", + "integrity": "sha512-wTYGAH2KHOSDi7eSvwniq+h4Wvrvt+Bd4mz8774HOHTcxRTECh5zjvG5fP+/VvPbhzsjOlIsylZaOVEdwZlfJg==", "requires": { "chalk": "^4.1.2", "dateformat": "^4.5.1", @@ -11327,6 +14077,8 @@ "dependencies": { "yargs": { "version": "17.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", + "integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==", "requires": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -11338,7 +14090,9 @@ } }, "yargs-parser": { - "version": "21.0.0" + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==" } } }, @@ -11399,18 +14153,18 @@ "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=" }, "nanoid": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", - "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==" + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==" }, "natural-compare": { "version": "1.4.0", "dev": true }, "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, "neo-async": { "version": "2.6.2", @@ -11421,9 +14175,9 @@ "version": "1.0.0" }, "nock": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.2.2.tgz", - "integrity": "sha512-PcBHuvl9i6zfaJ50A7LS55oU+nFLv8htXIhffJO+FxyfibdZ4jEvd9kTuvkrJireBFIGMZ+oUIRpMK5gU9h//g==", + "version": "13.2.4", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.2.4.tgz", + "integrity": "sha512-8GPznwxcPNCH/h8B+XZcKjYPXnUV5clOKCjAqyjsiqA++MpNx9E9+t8YPp0MbThO+KauRo7aZJ1WuIZmOrT2Ug==", "requires": { "debug": "^4.1.0", "json-stringify-safe": "^5.0.1", @@ -11444,13 +14198,84 @@ "whatwg-url": "^5.0.0" } }, + "node-gyp": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.0.0.tgz", + "integrity": "sha512-Ma6p4s+XCTPxCuAMrOA/IJRmVy16R8Sdhtwl4PrCr7IBlj4cPawF0vg/l7nOT1jPbuNS7lIRJpBSvVsXwEZuzw==", + "requires": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^10.0.3", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, "node-gyp-build": { "version": "4.3.0" }, "node-releases": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", - "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", + "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==" + }, + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.0.tgz", + "integrity": "sha512-m+GL22VXJKkKbw62ZaBBjv8u6IE3UI4Mh5QakIqs3fWiKe0Xyi6L97hakwZK41/LD4R/2ly71Bayx0NLMwLA/g==", + "requires": { + "hosted-git-info": "^5.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "dependencies": { + "hosted-git-info": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.0.0.tgz", + "integrity": "sha512-rRnjWu0Bxj+nIfUOkz0695C0H6tRrN5iYIzYejb0tDEefe2AekHu/U5Kn9pEie5vsJqpNQU02az7TGSH3qpz4Q==", + "requires": { + "lru-cache": "^7.5.1" + }, + "dependencies": { + "lru-cache": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.5.1.tgz", + "integrity": "sha512-q1TS8IqKvcg3aScamKCHpepSrHF537Ww7nHahBOxhDu9D2YoBXAsj/7uFdZFj1xJr9LmyeJ62AdyofCHafUbIA==" + } + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } }, "normalize-path": { "version": "3.0.0", @@ -11462,6 +14287,191 @@ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==" }, + "npm-bundled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", + "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-check-updates": { + "version": "12.5.3", + "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-12.5.3.tgz", + "integrity": "sha512-siFg/+Un+j4tLA6GJCnk6hz2YU4Yc5bftDnOoiSRLKL6NeAS3FScB32mtKNBtITMJf2nsoZSr8vH+wdUGeP19g==", + "requires": { + "chalk": "^4.1.2", + "cint": "^8.2.1", + "cli-table": "^0.3.11", + "commander": "^9.0.0", + "fast-memoize": "^2.5.2", + "find-up": "5.0.0", + "fp-and-or": "^0.1.3", + "get-stdin": "^8.0.0", + "globby": "^11.0.4", + "hosted-git-info": "^4.1.0", + "json-parse-helpfulerror": "^1.0.3", + "jsonlines": "^0.1.1", + "libnpmconfig": "^1.2.1", + "lodash": "^4.17.21", + "minimatch": "^5.0.1", + "p-map": "^4.0.0", + "pacote": "^13.0.3", + "parse-github-url": "^1.0.2", + "progress": "^2.0.3", + "prompts": "^2.4.2", + "rc-config-loader": "^4.0.0", + "remote-git-tags": "^3.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "semver-utils": "^1.1.4", + "source-map-support": "^0.5.21", + "spawn-please": "^1.0.0", + "update-notifier": "^5.1.0", + "yaml": "^1.10.2" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "npm-install-checks": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-4.0.0.tgz", + "integrity": "sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==", + "requires": { + "semver": "^7.1.1" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + }, + "npm-package-arg": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.0.1.tgz", + "integrity": "sha512-Xs9wznfEAmZAR61qsYH3iN24V/qMYYkvAR5CRQNMvC6PjN2fHtO8y9XP/xdp5K+Icx+u1wMBMgWRPCmAEChSog==", + "requires": { + "hosted-git-info": "^5.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.0.0.tgz", + "integrity": "sha512-rRnjWu0Bxj+nIfUOkz0695C0H6tRrN5iYIzYejb0tDEefe2AekHu/U5Kn9pEie5vsJqpNQU02az7TGSH3qpz4Q==", + "requires": { + "lru-cache": "^7.5.1" + }, + "dependencies": { + "lru-cache": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.5.1.tgz", + "integrity": "sha512-q1TS8IqKvcg3aScamKCHpepSrHF537Ww7nHahBOxhDu9D2YoBXAsj/7uFdZFj1xJr9LmyeJ62AdyofCHafUbIA==" + } + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "npm-packlist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-4.0.0.tgz", + "integrity": "sha512-gL6XC/iw9YSmqArmZOGSkyy+yIZf2f7uH0p4Vmxef/irn73vd9/rDkCtvm+a9rh/QK2xGYfCAMOghM06ymzC0A==", + "requires": { + "glob": "^7.2.0", + "ignore-walk": "^4.0.1", + "npm-bundled": "^1.1.2", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-pick-manifest": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-7.0.0.tgz", + "integrity": "sha512-njM1AcdioFaKd0JSGtLO09YA1WRwctjGQJbnHGmKS+u+uwP8oFvtZtOQWPYdxrnY5eJud3wn8OpH4sEIx6+GEQ==", + "requires": { + "npm-install-checks": "^4.0.0", + "npm-normalize-package-bin": "^1.0.1", + "npm-package-arg": "^9.0.0", + "semver": "^7.3.5" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "npm-registry-fetch": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-13.0.1.tgz", + "integrity": "sha512-Ak+LXVtSrCLOdscFW/apUw67OPNph8waHsPKM9UOJosL7i59EF5XoSWQMEsXEOeifM9Bb4/2+WrQC4t/pd8DGg==", + "requires": { + "make-fetch-happen": "^10.0.3", + "minipass": "^3.1.6", + "minipass-fetch": "^2.0.1", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^9.0.0", + "proc-log": "^2.0.0" + } + }, + "npmlog": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.1.tgz", + "integrity": "sha512-BTHDvY6nrRHuRfyjt1MAufLxYdVXZfd099H4+i1f0lPywNQyI4foeNXJRObB/uy+TYqUW0vAD9gbdSOXPst7Eg==", + "requires": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.0", + "set-blocking": "^2.0.0" + } + }, "number-to-bn": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", @@ -11484,7 +14494,9 @@ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" }, "object-assign": { - "version": "4.1.1" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-inspect": { "version": "1.12.0" @@ -11532,7 +14544,9 @@ } }, "opener": { - "version": "1.5.2" + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==" }, "optionator": { "version": "0.9.1", @@ -11568,6 +14582,14 @@ "p-limit": "^3.0.2" } }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "requires": { + "aggregate-error": "^3.0.0" + } + }, "p-timeout": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", @@ -11581,8 +14603,56 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + } + }, + "pacote": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-13.0.5.tgz", + "integrity": "sha512-6CYfot3/rUAn3qqzF2d/jrrXm5HlBtvaSgfmg0VtOUAdJ8fbSq21BJwftMGArkL71yXHIbUJ7Bt5B04547HELA==", + "requires": { + "@npmcli/git": "^3.0.0", + "@npmcli/installed-package-contents": "^1.0.7", + "@npmcli/promise-spawn": "^1.2.0", + "@npmcli/run-script": "^3.0.1", + "cacache": "^16.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "infer-owner": "^1.0.4", + "minipass": "^3.1.6", + "mkdirp": "^1.0.4", + "npm-package-arg": "^9.0.0", + "npm-packlist": "^4.0.0", + "npm-pick-manifest": "^7.0.0", + "npm-registry-fetch": "^13.0.1", + "proc-log": "^2.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^5.0.0", + "read-package-json-fast": "^2.0.3", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.1.11" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + } + } + }, "parent-module": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "requires": { "callsites": "^3.0.0" @@ -11600,10 +14670,15 @@ "safe-buffer": "^5.1.1" } }, + "parse-github-url": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz", + "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==" + }, "parse-headers": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.4.tgz", - "integrity": "sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz", + "integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==" }, "parseurl": { "version": "1.3.3", @@ -11628,8 +14703,7 @@ "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" }, "pathval": { "version": "1.1.1" @@ -11657,7 +14731,9 @@ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "picomatch": { - "version": "2.3.1" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, "pify": { "version": "4.0.1", @@ -11665,9 +14741,9 @@ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" }, "pirates": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.4.tgz", - "integrity": "sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw==" + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==" }, "pkg-dir": { "version": "3.0.0", @@ -11727,17 +14803,52 @@ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" }, "printj": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", - "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==" + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.3.1.tgz", + "integrity": "sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg==" + }, + "proc-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.0.tgz", + "integrity": "sha512-I/35MfCX2H8jBUhKN8JB8nmqvQo/nKdrBodBY7L3RhDSPPyvOHwLYNmPuhwuJq7a7C3vgFKWGQM+ecPStcvOHA==" }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + }, + "promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "requires": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + } + }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, "prop-types": { "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "requires": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -11774,6 +14885,13 @@ "parse-asn1": "^5.0.0", "randombytes": "^2.0.1", "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } } }, "pump": { @@ -11788,10 +14906,18 @@ "punycode": { "version": "2.1.1" }, + "pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "requires": { + "escape-goat": "^2.0.0" + } + }, "qs": { - "version": "6.9.6", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", - "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==" + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" }, "query-string": { "version": "5.1.1", @@ -11806,8 +14932,7 @@ "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" }, "ramda": { "version": "0.28.0", @@ -11827,28 +14952,99 @@ "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", + "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "requires": { + "bytes": "3.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + } + } + }, + "rc-config-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rc-config-loader/-/rc-config-loader-4.0.0.tgz", + "integrity": "sha512-//LRTblJEcqbmmro1GCmZ39qZXD+JqzuD8Y5/IZU3Dhp3A1Yr0Xn68ks8MQ6qKfKvYCWDveUmRDKDA40c+sCXw==", + "requires": { + "debug": "^4.1.1", + "js-yaml": "^4.0.0", + "json5": "^2.1.2", + "require-from-string": "^2.0.2" + }, + "dependencies": { + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "requires": { + "minimist": "^1.2.5" + } + } } }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, - "raw-body": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", - "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", + "read-package-json": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-5.0.0.tgz", + "integrity": "sha512-1cjk2MV5ONDMn34uxSID3X8NY7VKsXfJnjbcVdFMvHEnJOBzU6MJ7/3yg6QFVZDq5/1yFNrKBUK9kGnonyGP2Q==", "requires": { - "bytes": "3.1.1", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "glob": "^7.2.0", + "json-parse-even-better-errors": "^2.3.1", + "normalize-package-data": "^4.0.0", + "npm-normalize-package-bin": "^1.0.1" } }, - "react-is": { - "version": "16.13.1" + "read-package-json-fast": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz", + "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==", + "requires": { + "json-parse-even-better-errors": "^2.3.0", + "npm-normalize-package-bin": "^1.0.1" + } }, "readable-stream": { "version": "3.6.0", @@ -11861,20 +15057,43 @@ } }, "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "requires": { "picomatch": "^2.2.1" } }, "regenerator-runtime": { - "version": "0.13.9" + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" }, "regexpp": { "version": "3.2.0", "dev": true }, + "registry-auth-token": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", + "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", + "requires": { + "rc": "^1.2.8" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "requires": { + "rc": "^1.2.8" + } + }, + "remote-git-tags": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remote-git-tags/-/remote-git-tags-3.0.0.tgz", + "integrity": "sha512-C9hAO4eoEsX+OXA4rla66pXZQ+TLQ8T9dttgQj18yuKlPMTVkIkdYXvlMC55IuUsIkV6DpmQYi10JKFLaU+l7w==" + }, "request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", @@ -11927,8 +15146,15 @@ "require-directory": { "version": "2.1.1" }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + }, "resolve-from": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, "responselike": { @@ -11939,15 +15165,18 @@ "lowercase-keys": "^1.0.0" } }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" + }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" }, "rimraf": { "version": "3.0.2", - "dev": true, "requires": { "glob": "^7.1.3" } @@ -11967,28 +15196,20 @@ "integrity": "sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==", "requires": { "bn.js": "^5.2.0" - }, - "dependencies": { - "bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" - } } }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "requires": { "queue-microtask": "^1.2.2" } }, "rxjs": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.2.tgz", - "integrity": "sha512-PwDt186XaL3QN5qXj/H9DGyHhP3/RYYgZZwqBv9Tv8rsAaiwFH1IsJJlcgD37J7UW5a6O67qX0KWKS3/pu0m4w==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", + "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", "requires": { "tslib": "^2.1.0" } @@ -12021,6 +15242,19 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" }, + "semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "requires": { + "semver": "^6.3.0" + } + }, + "semver-utils": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/semver-utils/-/semver-utils-1.1.4.tgz", + "integrity": "sha512-EjnoLE5OGmDAVV/8YDoN5KiajNadjzIp9BAHOhYeQHt7j0UWxjmgsx4YD48wp4Ue1Qogq38F1GNUJNqF1kKKxA==" + }, "send": { "version": "0.17.2", "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", @@ -12059,9 +15293,9 @@ } }, "serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "requires": { "randombytes": "^2.1.0" } @@ -12089,6 +15323,11 @@ "xhr": "^2.3.3" } }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -12135,26 +15374,59 @@ "object-inspect": "^1.9.0" } }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, "simple-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" }, "simple-get": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", - "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.2.tgz", + "integrity": "sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw==", "requires": { "decompress-response": "^3.3.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" + }, + "socks": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", + "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.2.0" + } + }, + "socks-proxy-agent": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz", + "integrity": "sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==", + "requires": { + "agent-base": "^6.0.2", + "debug": "^4.3.1", + "socks": "^2.6.1" + } }, "source-map": { "version": "0.6.1" @@ -12166,6 +15438,39 @@ "source-map": "^0.6.0" } }, + "spawn-please": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/spawn-please/-/spawn-please-1.0.0.tgz", + "integrity": "sha512-Kz33ip6NRNKuyTRo3aDWyWxeGeM0ORDO552Fs6E1nj4pLWPkl37SrRtTnq+MEopVaqgmaO6bAvVS+v64BJ5M/A==" + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==" + }, "sshpk": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", @@ -12189,6 +15494,14 @@ } } }, + "ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "requires": { + "minipass": "^3.1.1" + } + }, "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -12238,7 +15551,8 @@ "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true }, "strip-hex-prefix": { "version": "1.0.0", @@ -12275,6 +15589,11 @@ "xhr-request": "^1.0.1" }, "dependencies": { + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, "fs-extra": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", @@ -12285,6 +15604,14 @@ "universalify": "^0.1.0" } }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "requires": { + "minipass": "^2.6.0" + } + }, "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", @@ -12324,6 +15651,23 @@ "graceful-fs": "^4.1.6" } }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "requires": { + "minipass": "^2.9.0" + } + }, "p-cancelable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", @@ -12334,6 +15678,20 @@ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" }, + "tar": { + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", + "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", + "requires": { + "chownr": "^1.1.4", + "fs-minipass": "^1.2.7", + "minipass": "^2.9.0", + "minizlib": "^1.3.3", + "mkdirp": "^0.5.5", + "safe-buffer": "^5.2.1", + "yallist": "^3.1.1" + } + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -12346,35 +15704,43 @@ "requires": { "prepend-http": "^1.0.1" } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" } } }, "tar": { - "version": "4.4.19", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", - "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", - "requires": { - "chownr": "^1.1.4", - "fs-minipass": "^1.2.7", - "minipass": "^2.9.0", - "minizlib": "^1.3.3", - "mkdirp": "^0.5.5", - "safe-buffer": "^5.2.1", - "yallist": "^3.1.1" + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" }, "dependencies": { - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" } } }, "tcomb": { - "version": "3.2.29" + "version": "3.2.29", + "resolved": "https://registry.npmjs.org/tcomb/-/tcomb-3.2.29.tgz", + "integrity": "sha512-di2Hd1DB2Zfw6StGv861JoAF5h/uQVu/QJp2g8KVbtfKnoHdBQl5M32YWq6mnSYBQ1vFFrns5B1haWJL7rKaOQ==" }, "tcomb-validation": { "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tcomb-validation/-/tcomb-validation-3.4.1.tgz", + "integrity": "sha512-urVVMQOma4RXwiVCa2nM2eqrAomHROHvWPuj6UkDGz/eb5kcy0x6P0dVt6kzpUZtYMNoAqJLWmz1BPtxrtjtrA==", "requires": { "tcomb": "^3.0.0" } @@ -12400,6 +15766,8 @@ }, "to-regex-range": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "requires": { "is-number": "^7.0.0" } @@ -12424,9 +15792,9 @@ "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" }, "ts-mocha": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/ts-mocha/-/ts-mocha-8.0.0.tgz", - "integrity": "sha512-Kou1yxTlubLnD5C3unlCVO7nh0HERTezjoVhVw/M5S1SqoUec0WgllQvPk3vzPMc6by8m6xD1uR1yRf8lnVUbA==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/ts-mocha/-/ts-mocha-9.0.2.tgz", + "integrity": "sha512-WyQjvnzwrrubl0JT7EC1yWmNpcsU3fOuBFfdps30zbmFBgKniSaSOyZMZx+Wq7kytUs5CY+pEbSYEbGfIKnXTw==", "dev": true, "requires": { "ts-node": "7.0.1", @@ -12464,9 +15832,9 @@ } }, "ts-node": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz", - "integrity": "sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==", + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", + "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", "dev": true, "requires": { "@cspotcode/source-map-support": "0.7.0", @@ -12480,6 +15848,7 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.0", "yn": "3.1.1" }, "dependencies": { @@ -12495,9 +15864,10 @@ "integrity": "sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==" }, "tsconfig-paths": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", - "integrity": "sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.0.tgz", + "integrity": "sha512-cg/1jAZoL57R39+wiw4u/SCC6Ic9Q5NqjBOb+9xISedOYurfog9ZNmKJSxAnb2m/5Bq4lE9lhUcau33Ml8DM0g==", + "dev": true, "requires": { "@types/json5": "^0.0.29", "json5": "^1.0.1", @@ -12554,8 +15924,7 @@ "version": "4.0.8" }, "type-fest": { - "version": "0.20.2", - "dev": true + "version": "0.20.2" }, "type-is": { "version": "1.6.18", @@ -12573,7 +15942,9 @@ } }, "typescript": { - "version": "4.5.4", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", + "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", "dev": true }, "uglify-js": { @@ -12596,14 +15967,71 @@ "which-boxed-primitive": "^1.0.2" } }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "requires": { + "crypto-random-string": "^2.0.0" + } + }, "universalify": { - "version": "2.0.0" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, + "update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "requires": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, "uri-js": { "version": "4.4.1", "requires": { @@ -12667,8 +16095,33 @@ "version": "2.3.0", "dev": true }, + "v8-compile-cache-lib": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz", + "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "requires": { + "builtins": "^1.0.3" + } + }, "validator": { - "version": "13.7.0" + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==" }, "varint": { "version": "5.0.2", @@ -12691,23 +16144,23 @@ } }, "web3": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3/-/web3-1.7.0.tgz", - "integrity": "sha512-n39O7QQNkpsjhiHMJ/6JY6TaLbdX+2FT5iGs8tb3HbIWOhPm4+a7UDbr5Lkm+gLa9aRKWesZs5D5hWyEvg4aJA==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.7.1.tgz", + "integrity": "sha512-RKVdyZ5FuVEykj62C1o2tc0teJciSOh61jpVB9yb344dBHO3ZV4XPPP24s/PPqIMXmVFN00g2GD9M/v1SoHO/A==", "requires": { - "web3-bzz": "1.7.0", - "web3-core": "1.7.0", - "web3-eth": "1.7.0", - "web3-eth-personal": "1.7.0", - "web3-net": "1.7.0", - "web3-shh": "1.7.0", - "web3-utils": "1.7.0" + "web3-bzz": "1.7.1", + "web3-core": "1.7.1", + "web3-eth": "1.7.1", + "web3-eth-personal": "1.7.1", + "web3-net": "1.7.1", + "web3-shh": "1.7.1", + "web3-utils": "1.7.1" } }, "web3-bzz": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.7.0.tgz", - "integrity": "sha512-XPhTWUnZa8gnARfiqaag3jJ9+6+a66Li8OikgBUJoMUqPuQTCJPncTbGYqOJIfRFGavEAdlMnfYXx9lvgv2ZPw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.7.1.tgz", + "integrity": "sha512-sVeUSINx4a4pfdnT+3ahdRdpDPvZDf4ZT/eBF5XtqGWq1mhGTl8XaQAk15zafKVm6Onq28vN8abgB/l+TrG8kA==", "requires": { "@types/node": "^12.12.6", "got": "9.6.0", @@ -12715,58 +16168,66 @@ }, "dependencies": { "@types/node": { - "version": "12.20.42", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.42.tgz", - "integrity": "sha512-aI3/oo5DzyiI5R/xAhxxRzfZlWlsbbqdgxfTPkqu/Zt+23GXiJvMCyPJT4+xKSXOnLqoL8jJYMLTwvK2M3a5hw==" + "version": "12.20.47", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.47.tgz", + "integrity": "sha512-BzcaRsnFuznzOItW1WpQrDHM7plAa7GIDMZ6b5pnMbkqEtM/6WCOhvZar39oeMQP79gwvFUWjjptE7/KGcNqFg==" } } }, "web3-core": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.7.0.tgz", - "integrity": "sha512-U/CRL53h3T5KHl8L3njzCBT7fCaHkbE6BGJe3McazvFldRbfTDEHXkUJCyM30ZD0RoLi3aDfTVeFIusmEyCctA==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.7.1.tgz", + "integrity": "sha512-HOyDPj+4cNyeNPwgSeUkhtS0F+Pxc2obcm4oRYPW5ku6jnTO34pjaij0us+zoY3QEusR8FfAKVK1kFPZnS7Dzw==", "requires": { "@types/bn.js": "^4.11.5", "@types/node": "^12.12.6", "bignumber.js": "^9.0.0", - "web3-core-helpers": "1.7.0", - "web3-core-method": "1.7.0", - "web3-core-requestmanager": "1.7.0", - "web3-utils": "1.7.0" + "web3-core-helpers": "1.7.1", + "web3-core-method": "1.7.1", + "web3-core-requestmanager": "1.7.1", + "web3-utils": "1.7.1" }, "dependencies": { + "@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "requires": { + "@types/node": "*" + } + }, "@types/node": { - "version": "12.20.42", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.42.tgz", - "integrity": "sha512-aI3/oo5DzyiI5R/xAhxxRzfZlWlsbbqdgxfTPkqu/Zt+23GXiJvMCyPJT4+xKSXOnLqoL8jJYMLTwvK2M3a5hw==" + "version": "12.20.47", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.47.tgz", + "integrity": "sha512-BzcaRsnFuznzOItW1WpQrDHM7plAa7GIDMZ6b5pnMbkqEtM/6WCOhvZar39oeMQP79gwvFUWjjptE7/KGcNqFg==" } } }, "web3-core-helpers": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.7.0.tgz", - "integrity": "sha512-kFiqsZFHJliKF8VKZNjt2JvKu3gu7h3N1/ke3EPhdp9Li/rLmiyzFVr6ApryZ1FSjbSx6vyOkibG3m6xQ5EHJA==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.7.1.tgz", + "integrity": "sha512-xn7Sx+s4CyukOJdlW8bBBDnUCWndr+OCJAlUe/dN2wXiyaGRiCWRhuQZrFjbxLeBt1fYFH7uWyYHhYU6muOHgw==", "requires": { - "web3-eth-iban": "1.7.0", - "web3-utils": "1.7.0" + "web3-eth-iban": "1.7.1", + "web3-utils": "1.7.1" } }, "web3-core-method": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.7.0.tgz", - "integrity": "sha512-43Om+kZX8wU5u1pJ28TltF9e9pSTRph6b8wrOb6wgXAfPHqMulq6UTBJWjXXIRVN46Eiqv0nflw35hp9bbgnbA==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.7.1.tgz", + "integrity": "sha512-383wu5FMcEphBFl5jCjk502JnEg3ugHj7MQrsX7DY76pg5N5/dEzxeEMIJFCN6kr5Iq32NINOG3VuJIyjxpsEg==", "requires": { "@ethersproject/transactions": "^5.0.0-beta.135", - "web3-core-helpers": "1.7.0", - "web3-core-promievent": "1.7.0", - "web3-core-subscriptions": "1.7.0", - "web3-utils": "1.7.0" + "web3-core-helpers": "1.7.1", + "web3-core-promievent": "1.7.1", + "web3-core-subscriptions": "1.7.1", + "web3-utils": "1.7.1" } }, "web3-core-promievent": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.7.0.tgz", - "integrity": "sha512-xPH66XeC0K0k29GoRd0vyPQ07yxERPRd4yVPrbMzGAz/e9E4M3XN//XK6+PdfGvGw3fx8VojS+tNIMiw+PujbQ==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.7.1.tgz", + "integrity": "sha512-Vd+CVnpPejrnevIdxhCkzMEywqgVbhHk/AmXXceYpmwA6sX41c5a65TqXv1i3FWRJAz/dW7oKz9NAzRIBAO/kA==", "requires": { "eventemitter3": "4.0.4" }, @@ -12779,24 +16240,24 @@ } }, "web3-core-requestmanager": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.7.0.tgz", - "integrity": "sha512-rA3dBTBPrt+eIfTAQ2/oYNTN/2wbZaYNR3pFZGqG8+2oCK03+7oQyz4sWISKy/nYQhURh4GK01rs9sN4o/Tq9w==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.7.1.tgz", + "integrity": "sha512-/EHVTiMShpZKiq0Jka0Vgguxi3vxq1DAHKxg42miqHdUsz4/cDWay2wGALDR2x3ofDB9kqp7pb66HsvQImQeag==", "requires": { "util": "^0.12.0", - "web3-core-helpers": "1.7.0", - "web3-providers-http": "1.7.0", - "web3-providers-ipc": "1.7.0", - "web3-providers-ws": "1.7.0" + "web3-core-helpers": "1.7.1", + "web3-providers-http": "1.7.1", + "web3-providers-ipc": "1.7.1", + "web3-providers-ws": "1.7.1" } }, "web3-core-subscriptions": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.7.0.tgz", - "integrity": "sha512-6giF8pyJrPmWrRpc2WLoVCvQdMMADp20ZpAusEW72axauZCNlW1XfTjs0i4QHQBfdd2lFp65qad9IuATPhuzrQ==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.7.1.tgz", + "integrity": "sha512-NZBsvSe4J+Wt16xCf4KEtBbxA9TOwSVr8KWfUQ0tC2KMdDYdzNswl0Q9P58xaVuNlJ3/BH+uDFZJJ5E61BSA1Q==", "requires": { "eventemitter3": "4.0.4", - "web3-core-helpers": "1.7.0" + "web3-core-helpers": "1.7.1" }, "dependencies": { "eventemitter3": { @@ -12807,37 +16268,37 @@ } }, "web3-eth": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.7.0.tgz", - "integrity": "sha512-3uYwjMjn/MZjKIzXCt4YL9ja/k9X5shfa4lKparZhZE6uesmu+xmSmrEFXA/e9qcveF50jkV7frjkT8H+cLYtw==", - "requires": { - "web3-core": "1.7.0", - "web3-core-helpers": "1.7.0", - "web3-core-method": "1.7.0", - "web3-core-subscriptions": "1.7.0", - "web3-eth-abi": "1.7.0", - "web3-eth-accounts": "1.7.0", - "web3-eth-contract": "1.7.0", - "web3-eth-ens": "1.7.0", - "web3-eth-iban": "1.7.0", - "web3-eth-personal": "1.7.0", - "web3-net": "1.7.0", - "web3-utils": "1.7.0" + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.7.1.tgz", + "integrity": "sha512-Uz3gO4CjTJ+hMyJZAd2eiv2Ur1uurpN7sTMATWKXYR/SgG+SZgncnk/9d8t23hyu4lyi2GiVL1AqVqptpRElxg==", + "requires": { + "web3-core": "1.7.1", + "web3-core-helpers": "1.7.1", + "web3-core-method": "1.7.1", + "web3-core-subscriptions": "1.7.1", + "web3-eth-abi": "1.7.1", + "web3-eth-accounts": "1.7.1", + "web3-eth-contract": "1.7.1", + "web3-eth-ens": "1.7.1", + "web3-eth-iban": "1.7.1", + "web3-eth-personal": "1.7.1", + "web3-net": "1.7.1", + "web3-utils": "1.7.1" } }, "web3-eth-abi": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.7.0.tgz", - "integrity": "sha512-heqR0bWxgCJwjWIhq2sGyNj9bwun5+Xox/LdZKe+WMyTSy0cXDXEAgv3XKNkXC4JqdDt/ZlbTEx4TWak4TRMSg==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.7.1.tgz", + "integrity": "sha512-8BVBOoFX1oheXk+t+uERBibDaVZ5dxdcefpbFTWcBs7cdm0tP8CD1ZTCLi5Xo+1bolVHNH2dMSf/nEAssq5pUA==", "requires": { "@ethersproject/abi": "5.0.7", - "web3-utils": "1.7.0" + "web3-utils": "1.7.1" } }, "web3-eth-accounts": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.7.0.tgz", - "integrity": "sha512-Zwm7TlQXdXGRuS6+ib1YsR5fQwpfnFyL6UAZg1zERdrUrs3IkCZSL3yCP/8ZYbAjdTEwWljoott2iSqXNH09ug==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.7.1.tgz", + "integrity": "sha512-3xGQ2bkTQc7LFoqGWxp5cQDrKndlX05s7m0rAFVoyZZODMqrdSGjMPMqmWqHzJRUswNEMc+oelqSnGBubqhguQ==", "requires": { "@ethereumjs/common": "^2.5.0", "@ethereumjs/tx": "^3.3.2", @@ -12846,12 +16307,17 @@ "ethereumjs-util": "^7.0.10", "scrypt-js": "^3.0.1", "uuid": "3.3.2", - "web3-core": "1.7.0", - "web3-core-helpers": "1.7.0", - "web3-core-method": "1.7.0", - "web3-utils": "1.7.0" + "web3-core": "1.7.1", + "web3-core-helpers": "1.7.1", + "web3-core-method": "1.7.1", + "web3-utils": "1.7.1" }, "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "eth-lib": { "version": "0.2.8", "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", @@ -12870,99 +16336,116 @@ } }, "web3-eth-contract": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.7.0.tgz", - "integrity": "sha512-2LY1Xwxu5rx468nqHuhvupQAIpytxIUj3mGL9uexszkhrQf05THVe3i4OnUCzkeN6B2cDztNOqLT3j9SSnVQDg==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.7.1.tgz", + "integrity": "sha512-HpnbkPYkVK3lOyos2SaUjCleKfbF0SP3yjw7l551rAAi5sIz/vwlEzdPWd0IHL7ouxXbO0tDn7jzWBRcD3sTbA==", "requires": { "@types/bn.js": "^4.11.5", - "web3-core": "1.7.0", - "web3-core-helpers": "1.7.0", - "web3-core-method": "1.7.0", - "web3-core-promievent": "1.7.0", - "web3-core-subscriptions": "1.7.0", - "web3-eth-abi": "1.7.0", - "web3-utils": "1.7.0" + "web3-core": "1.7.1", + "web3-core-helpers": "1.7.1", + "web3-core-method": "1.7.1", + "web3-core-promievent": "1.7.1", + "web3-core-subscriptions": "1.7.1", + "web3-eth-abi": "1.7.1", + "web3-utils": "1.7.1" + }, + "dependencies": { + "@types/bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "requires": { + "@types/node": "*" + } + } } }, "web3-eth-ens": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.7.0.tgz", - "integrity": "sha512-I1bikYJJWQ/FJZIAvwsGOvzAgcRIkosWG4s1L6veRoXaU8OEJFeh4s00KcfHDxg7GWZZGbUSbdbzKpwRbWnvkg==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.7.1.tgz", + "integrity": "sha512-DVCF76i9wM93DrPQwLrYiCw/UzxFuofBsuxTVugrnbm0SzucajLLNftp3ITK0c4/lV3x9oo5ER/wD6RRMHQnvw==", "requires": { "content-hash": "^2.5.2", "eth-ens-namehash": "2.0.8", - "web3-core": "1.7.0", - "web3-core-helpers": "1.7.0", - "web3-core-promievent": "1.7.0", - "web3-eth-abi": "1.7.0", - "web3-eth-contract": "1.7.0", - "web3-utils": "1.7.0" + "web3-core": "1.7.1", + "web3-core-helpers": "1.7.1", + "web3-core-promievent": "1.7.1", + "web3-eth-abi": "1.7.1", + "web3-eth-contract": "1.7.1", + "web3-utils": "1.7.1" } }, "web3-eth-iban": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.7.0.tgz", - "integrity": "sha512-1PFE/Og+sPZaug+M9TqVUtjOtq0HecE+SjDcsOOysXSzslNC2CItBGkcRwbvUcS+LbIkA7MFsuqYxOL0IV/gyA==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.7.1.tgz", + "integrity": "sha512-XG4I3QXuKB/udRwZdNEhdYdGKjkhfb/uH477oFVMLBqNimU/Cw8yXUI5qwFKvBHM+hMQWfzPDuSDEDKC2uuiMg==", "requires": { "bn.js": "^4.11.9", - "web3-utils": "1.7.0" + "web3-utils": "1.7.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } } }, "web3-eth-personal": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.7.0.tgz", - "integrity": "sha512-Dr9RZTNOR80PhrPKGdktDUXpOgExEcCcosBj080lKCJFU1paSPj9Zfnth3u6BtIOXyKsVFTrpqekqUDyAwXnNw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.7.1.tgz", + "integrity": "sha512-02H6nFBNfNmFjMGZL6xcDi0r7tUhxrUP91FTFdoLyR94eIJDadPp4rpXfG7MVES873i1PReh4ep5pSCHbc3+Pg==", "requires": { "@types/node": "^12.12.6", - "web3-core": "1.7.0", - "web3-core-helpers": "1.7.0", - "web3-core-method": "1.7.0", - "web3-net": "1.7.0", - "web3-utils": "1.7.0" + "web3-core": "1.7.1", + "web3-core-helpers": "1.7.1", + "web3-core-method": "1.7.1", + "web3-net": "1.7.1", + "web3-utils": "1.7.1" }, "dependencies": { "@types/node": { - "version": "12.20.42", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.42.tgz", - "integrity": "sha512-aI3/oo5DzyiI5R/xAhxxRzfZlWlsbbqdgxfTPkqu/Zt+23GXiJvMCyPJT4+xKSXOnLqoL8jJYMLTwvK2M3a5hw==" + "version": "12.20.47", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.47.tgz", + "integrity": "sha512-BzcaRsnFuznzOItW1WpQrDHM7plAa7GIDMZ6b5pnMbkqEtM/6WCOhvZar39oeMQP79gwvFUWjjptE7/KGcNqFg==" } } }, "web3-net": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.7.0.tgz", - "integrity": "sha512-8pmfU1Se7DmG40Pu8nOCKlhuI12VsVzCtdFDnLAai0zGVAOUuuOCK71B2aKm6u9amWBJjtOlyrCwvsG+QEd6dw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.7.1.tgz", + "integrity": "sha512-8yPNp2gvjInWnU7DCoj4pIPNhxzUjrxKlODsyyXF8j0q3Z2VZuQp+c63gL++r2Prg4fS8t141/HcJw4aMu5sVA==", "requires": { - "web3-core": "1.7.0", - "web3-core-method": "1.7.0", - "web3-utils": "1.7.0" + "web3-core": "1.7.1", + "web3-core-method": "1.7.1", + "web3-utils": "1.7.1" } }, "web3-providers-http": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.7.0.tgz", - "integrity": "sha512-Y9reeEiApfvQKLUUtrU4Z0c+H6b7BMWcsxjgoXndI1C5NB297mIUfltXxfXsh5C/jk5qn4Q3sJp3SwQTyVjH7Q==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.7.1.tgz", + "integrity": "sha512-dmiO6G4dgAa3yv+2VD5TduKNckgfR97VI9YKXVleWdcpBoKXe2jofhdvtafd42fpIoaKiYsErxQNcOC5gI/7Vg==", "requires": { - "web3-core-helpers": "1.7.0", + "web3-core-helpers": "1.7.1", "xhr2-cookies": "1.1.0" } }, "web3-providers-ipc": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.7.0.tgz", - "integrity": "sha512-U5YLXgu6fvAK4nnMYqo9eoml3WywgTym0dgCdVX/n1UegLIQ4nctTubBAuWQEJzmAzwh+a6ValGcE7ZApTRI7Q==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.7.1.tgz", + "integrity": "sha512-uNgLIFynwnd5M9ZC0lBvRQU5iLtU75hgaPpc7ZYYR+kjSk2jr2BkEAQhFVJ8dlqisrVmmqoAPXOEU0flYZZgNQ==", "requires": { "oboe": "2.1.5", - "web3-core-helpers": "1.7.0" + "web3-core-helpers": "1.7.1" } }, "web3-providers-ws": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.7.0.tgz", - "integrity": "sha512-0a8+lVV3JBf+eYnGOsdzOpftK1kis5X7s35QAdoaG5SDapnEylXFlR4xDSSSU88ZwMwvse8hvng2xW6A7oeWxw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.7.1.tgz", + "integrity": "sha512-Uj0n5hdrh0ESkMnTQBsEUS2u6Unqdc7Pe4Zl+iZFb7Yn9cIGsPJBl7/YOP4137EtD5ueXAv+MKwzcelpVhFiFg==", "requires": { "eventemitter3": "4.0.4", - "web3-core-helpers": "1.7.0", + "web3-core-helpers": "1.7.1", "websocket": "^1.0.32" }, "dependencies": { @@ -12974,20 +16457,20 @@ } }, "web3-shh": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.7.0.tgz", - "integrity": "sha512-RZhxcevALIPK178VZCpwMBvQeW+IoWtRJ4EMdegpbnETeZaC3aRUcs6vKnrf0jXJjm4J/E2Dt438Y1Ord/1IMw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.7.1.tgz", + "integrity": "sha512-NO+jpEjo8kYX6c7GiaAm57Sx93PLYkWYUCWlZmUOW7URdUcux8VVluvTWklGPvdM9H1WfDrol91DjuSW+ykyqg==", "requires": { - "web3-core": "1.7.0", - "web3-core-method": "1.7.0", - "web3-core-subscriptions": "1.7.0", - "web3-net": "1.7.0" + "web3-core": "1.7.1", + "web3-core-method": "1.7.1", + "web3-core-subscriptions": "1.7.1", + "web3-net": "1.7.1" } }, "web3-utils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.7.0.tgz", - "integrity": "sha512-O8Tl4Ky40Sp6pe89Olk2FsaUkgHyb5QAXuaKo38ms3CxZZ4d3rPGfjP9DNKGm5+IUgAZBNpF1VmlSmNCqfDI1w==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.7.1.tgz", + "integrity": "sha512-fef0EsqMGJUgiHPdX+KN9okVWshbIumyJPmR+btnD1HgvoXijKEkuKBv0OmUqjbeqmLKP2/N9EiXKJel5+E1Dw==", "requires": { "bn.js": "^4.11.9", "ethereum-bloom-filters": "^1.0.6", @@ -12996,6 +16479,13 @@ "number-to-bn": "1.7.0", "randombytes": "^2.1.0", "utf8": "3.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } } }, "webidl-conversions": { @@ -13062,40 +16552,19 @@ } }, "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", "requires": { - "string-width": "^1.0.2 || 2" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" - } - } + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "requires": { + "string-width": "^4.0.0" } }, "word-wrap": { @@ -13108,9 +16577,9 @@ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" }, "workerpool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", - "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==" + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", + "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==" }, "wrap-ansi": { "version": "7.0.0", @@ -13123,6 +16592,17 @@ "wrappy": { "version": "1.0.2" }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, "ws": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", @@ -13140,6 +16620,11 @@ } } }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" + }, "xhr": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", @@ -13193,8 +16678,12 @@ "version": "0.0.6" }, "yallist": { - "version": "4.0.0", - "dev": true + "version": "4.0.0" + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" }, "yargs": { "version": "16.2.0", diff --git a/integration-tests/runtime-tests/package.json b/integration-tests/runtime-tests/package.json index a8928b60715..b2933038036 100644 --- a/integration-tests/runtime-tests/package.json +++ b/integration-tests/runtime-tests/package.json @@ -1,63 +1,71 @@ { "name": "picasso-integration-tester", - "version": "0.0.2", + "version": "1.0.0", "description": "Runs various integration tests for the composable picasso parachain.", - "main": "src/main.js", + "main": "src/main.ts", "type": "commonjs", "scripts": { - "compile": "tsc --declaration", - "lint": "eslint src/**/*.ts --fix-dry-run", + "compile": "tsc -p . --declaration", + "live_compile": "tsc -p . -w", + "lint": "eslint test/**/*.ts src/**/*.ts --fix-dry-run", "prepare": "npm run compile", - "init": "node src/initializeState.js", - "init_and_test": "npm run init && mocha src/test.js --reporter mochawesome", - "test": "ts-mocha --paths -p tsconfig.json src/test.ts", + "init": "ts-node -r tsconfig-paths/register src/main.ts", + "init_and_test": "npm run init && npm run test", + "test": "ts-mocha --paths -p tsconfig.json", "gen": "npm run gen:defs && npm run gen:meta", "gen:defs": "ts-node --skip-project node_modules/.bin/polkadot-types-from-defs --package @composable/types/interfaces --input ./src/types/interfaces", - "gen:meta": "ts-node --skip-project node_modules/.bin/polkadot-types-from-chain --package @composable/types/interfaces --endpoint ws://localhost:9988 --output src/types/interfaces/" + "gen:meta": "ts-node --skip-project node_modules/.bin/polkadot-types-from-chain --package @composable/types/interfaces --endpoint ws://localhost:9988 --output src/types/interfaces/", + "check_dep_updates": "npx npm-check-updates", + "delete_js_artifacts": "find ./src -name '*.js' -type f -delete && find ./test -name '*.js' -type f -delete" }, "directories": { - "src": "./src", - "test": "./src" + "src": [ + "./src", + "./test" + ], + "test": "./test" }, "keywords": [], "author": "Composable.Finance", - "license": "GNU AGPLv3", + "license": "Public Domain", "devDependencies": { "@types/chai": "^4.3.0", "@types/minimist": "^1.2.2", - "@typescript-eslint/eslint-plugin": "^5.10.0", - "@typescript-eslint/parser": "^5.10.0", + "@typescript-eslint/eslint-plugin": "^5.15.0", + "@typescript-eslint/parser": "^5.15.0", "assert": "^2.0.0", - "eslint": "^8.7.0", + "eslint": "^8.11.0", "eslint-config-google": "^0.14.0", "mocha-prepare": "^0.1.0", - "ts-mocha": "^8.0.0", - "ts-node": "^10.4.0", - "typescript": "^4.5.4" + "ts-mocha": "^9.0.2", + "ts-node": "^10.7.0", + "tsconfig-paths": "^3.14.0", + "typescript": "^4.6.2" }, "engines": { "node": ">=12.0.0" }, "dependencies": { - "@polkadot/api": "^7.4.1", + "@polkadot/api": "^7.12.1", "@polkadot/ts": "^0.4.22", - "@polkadot/typegen": "^7.4.1", - "@polkadot/types": "^7.4.1", - "@polkadot/types-augment": "^7.4.1", - "@polkadot/types-codec": "^7.4.1", - "@polkadot/types-create": "^7.4.1", - "@polkadot/types-known": "^7.4.1", - "@polkadot/types-support": "^7.4.1", - "@types/mocha": "^9.0.0", - "@types/node": "^17.0.9", - "@types/ramda": "^0.27.64", - "chai": "^4.3.4", + "@polkadot/typegen": "^7.12.1", + "@polkadot/types": "^7.12.1", + "@polkadot/types-augment": "^7.12.1", + "@polkadot/types-codec": "^7.12.1", + "@polkadot/types-create": "^7.12.1", + "@polkadot/types-known": "^7.12.1", + "@polkadot/types-support": "^7.12.1", + "@types/mocha": "^9.1.0", + "@types/node": "^17.0.21", + "@types/ramda": "^0.28.1", + "chai": "^4.3.6", "chai-as-promised": "^7.1.1", + "chai-bn": "^0.3.1", "minimist": "^1.2.5", - "mocha": "^8.4.0", - "mochawesome": "^7.0.1", + "mocha": "^9.2.2", + "mochawesome": "^7.1.2", + "npm-check-updates": "^12.5.3", "ramda": "^0.28.0", - "tsconfig-paths": "^3.12.0", - "web3": "^1.7.0" + "web3": "^1.7.1" } } diff --git a/integration-tests/runtime-tests/src/generators/exampleGenerators/testTransactionGenerator.ts b/integration-tests/runtime-tests/src/generators/exampleGenerators/testTransactionGenerator.ts index 08d7943c0af..56208899a55 100644 --- a/integration-tests/runtime-tests/src/generators/exampleGenerators/testTransactionGenerator.ts +++ b/integration-tests/runtime-tests/src/generators/exampleGenerators/testTransactionGenerator.ts @@ -1,9 +1,4 @@ import { ApiPromise, Keyring, WsProvider } from '@polkadot/api'; -import { KeyringPair } from '@polkadot/keyring/types'; -import * as R from 'ramda'; -import minimist from 'minimist'; -import { args } from '../../utils/args'; - /** * Generates a test transaction. @@ -13,6 +8,8 @@ export class testTransactionGenerator { /** * Sends test transaction from Alice to Bob. * @param {ApiPromise} api Connected API Promise. + * @param {Keyring} walletSender Wallet sending asset. + * @param {Keyring} walletReceiverAddress Wallet receiving asset. **/ public static async testTransaction(api: ApiPromise, walletSender, walletReceiverAddress) { const transfer = api.tx.assets.transferNative(walletReceiverAddress, 12345678910, true); @@ -22,7 +19,7 @@ export class testTransactionGenerator { } async function main() { - const endpoint = `ws://${args.h}:${args.p}`; + const endpoint = `ws://${process.env.ENDPOINT}`; // Instantiate the API const provider = new WsProvider(endpoint); const api = await ApiPromise.create({ provider: provider }); @@ -31,10 +28,10 @@ async function main() { const walletAlice = keyring.addFromUri('//Alice'); const walletBob = keyring.addFromUri('//Bob'); await testTransactionGenerator.testTransaction(api, walletAlice, walletBob.address); - process.exit(0); + console.info("setStartBalance finished!"); + await api.disconnect(); } if (require.main === module) { - main(); + main().catch(console.error).finally(() => process.exit()); } - diff --git a/integration-tests/runtime-tests/src/generators/setBalance/setStartBalance.ts b/integration-tests/runtime-tests/src/generators/setBalance/setStartBalance.ts new file mode 100644 index 00000000000..19076920e87 --- /dev/null +++ b/integration-tests/runtime-tests/src/generators/setBalance/setStartBalance.ts @@ -0,0 +1,46 @@ +import { ApiPromise, Keyring, WsProvider } from '@polkadot/api'; +import {expect} from "chai"; +import {sendAndWaitForSuccess} from "@composable/utils/polkadotjs"; + + +/** + * Mints balance for specified wallets. + **/ +export class startBalanceGenerator { + /** + * Sends test transaction from Alice to Bob. + * @param {ApiPromise} api Connected API Promise. + * @param {Keyring} sudoKey Sudo key minting asset. + * @param {Keyring} walletReceiverAddress Wallet receiving asset. + **/ + public static async setBalance(api: ApiPromise, sudoKey, walletReceiverAddress) { + const {data: [result1],} = await sendAndWaitForSuccess( + api, + sudoKey, + api.events.sudo.Sudid.is, + api.tx.sudo.sudo( + api.tx.assets.mintInto(1, walletReceiverAddress.publicKey, 555555555555) + ) + ); + expect(result1.isOk).to.be.true; + } +} + +async function main() { + const endpoint = `ws://${process.env.ENDPOINT}`; + // Instantiate the API + const provider = new WsProvider(endpoint); + const api = await ApiPromise.create({ provider: provider }); + // Constuct the keyring after the API (crypto has an async init) + const keyring = new Keyring({ type: 'sr25519' }); + const walletAlice = keyring.addFromUri('//Alice'); + const walletBob = keyring.addFromUri('//Bob'); + await startBalanceGenerator.setBalance(api, walletAlice, walletAlice.address); + await startBalanceGenerator.setBalance(api, walletAlice, walletBob.address); + console.info("setStartBalance finished!"); + await api.disconnect(); +} + +if (require.main === module) { + main().catch(console.error).finally(() => process.exit()); +} diff --git a/integration-tests/runtime-tests/src/initializeState.ts b/integration-tests/runtime-tests/src/main.ts similarity index 86% rename from integration-tests/runtime-tests/src/initializeState.ts rename to integration-tests/runtime-tests/src/main.ts index 54c42a52ab3..05c6a1f4ca4 100644 --- a/integration-tests/runtime-tests/src/initializeState.ts +++ b/integration-tests/runtime-tests/src/main.ts @@ -1,11 +1,10 @@ -/* eslint-disable no-trailing-spaces */ -/* eslint-disable max-len */ /** * Inserts default values into the devnet for development. **/ import { ApiPromise, Keyring, WsProvider } from '@polkadot/api'; import { KeyringPair } from '@polkadot/keyring/types'; import { testTransactionGenerator } from './generators/exampleGenerators/testTransactionGenerator'; +import {startBalanceGenerator} from "@composable/generators/setBalance/setStartBalance"; // ToDo: Change endpoint to be read from env variables or run parameters. @@ -27,6 +26,10 @@ async function createDefaultData(api: ApiPromise, sudoKey: KeyringPair) { await testTransactionGenerator.testTransaction(api, walletAlice, walletBob.address); // ToDo: Add additional data generator calls here. // Consider splitting it up into groups of similiar generators, to keep it clean. + + // Setting start balance for alice and bob accounts. + await startBalanceGenerator.setBalance(api, sudoKey, walletAlice.address); + await startBalanceGenerator.setBalance(api, sudoKey, walletBob.address); } /** @@ -53,7 +56,7 @@ async function main() { await createDefaultData(api, walletAlice); console.info('Finished creating dummy data.'); - api.disconnect(); + await api.disconnect(); } if (require.main === module) { diff --git a/integration-tests/runtime-tests/src/test.ts b/integration-tests/runtime-tests/src/test.ts deleted file mode 100644 index 7d752b82529..00000000000 --- a/integration-tests/runtime-tests/src/test.ts +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Defines the tests to be run on the picasso parachain node. - * All tests can be found in the ./tests/ folder. - **/ - -import { QueryCrowdloanRewardsTests } from './tests/query/crowdloanRewards/queryCrowdloanRewardsTests'; -import { TxCrowdloanRewardsTests } from './tests/tx/crowdloanRewards/txCrowdloanRewardsTests'; -import { TxBondedFinanceTests } from "@composable/tests/tx/bondedFinance/txBondedFinanceTests"; -import { runBefore, runAfter } from "@composable/utils/testSetup"; -import { TxOracleTests } from "@composable/tests/tx/oracle/txOracleTests"; - - -describe('Picasso Runtime Tests', function() { - before(async function () { - // Set timeout to 1 minute. - this.timeout(60*1000); - await runBefore(); - }); - - after(async function() { - // Set timeout to 1 minute. - this.timeout(60*1000); - await runAfter(); - }); - - // Query Tests - describe('Query Tests', function() { - // Query Crowdloan Rewards Tests - QueryCrowdloanRewardsTests.runQueryCrowdloanRewardsTests(); - }); - - // TX Tests - describe('TX Tests', function () { - // TX Crowdloan Rewards Tests - TxCrowdloanRewardsTests.runTxCrowdloanRewardsTests(); - - // TX bondedFinance Tests - TxBondedFinanceTests.runTxBondedFinanceTests(); - - // TX Oracle Tests - TxOracleTests.runTxOracleTests(); - }); - - // RPC Tests - describe('RPC Tests', function () { - // No RPC tests implemented yet! - }); -}); - - - - diff --git a/integration-tests/runtime-tests/src/tests/examples/querySystemAccountTests.ts b/integration-tests/runtime-tests/src/tests/examples/querySystemAccountTests.ts deleted file mode 100644 index 69071e9cbeb..00000000000 --- a/integration-tests/runtime-tests/src/tests/examples/querySystemAccountTests.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* eslint-disable no-trailing-spaces */ -import { expect } from 'chai'; - - -export class QuerySystemAccountTests { - /** - * Example Test - * Just checking if provided wallet balance >0. - */ - static runQuerySystemAccountTests() { - describe('query.system.account Tests', function () { - it('Wallet balance check should result >0', async () => { - await QuerySystemAccountTests.checkBalance(global.api, global.walletAlice.address); - }); - }); - } - - /** - * Tests by checking the balance of the supplied account is >0 - * @param {ApiPromise} api Connected API Promise. - * @param {string} walletAddress wallet public key - */ - private static async checkBalance(api, walletAddress:string) { - const {nonce, data: balance} = await api.query.system.account(walletAddress); - expect(parseInt(balance.free)).to.be.a('number'); - expect(parseInt(nonce)).to.be.a('number'); - expect(parseInt(balance.free)).to.be.greaterThan(0); - } -} \ No newline at end of file diff --git a/integration-tests/runtime-tests/src/tests/query/council/queryCouncilTests.ts b/integration-tests/runtime-tests/src/tests/query/council/queryCouncilTests.ts deleted file mode 100644 index fc4a617cd55..00000000000 --- a/integration-tests/runtime-tests/src/tests/query/council/queryCouncilTests.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Keyring } from "@polkadot/api"; - -/** - * -**/ -export class QueryCouncilTests { - - // ToDo (D. Roth): STUB -} \ No newline at end of file diff --git a/integration-tests/runtime-tests/src/tests/query/crowdloanRewards/queryCrowdloanRewardsTests.ts b/integration-tests/runtime-tests/src/tests/query/crowdloanRewards/queryCrowdloanRewardsTests.ts deleted file mode 100644 index 6fc2cdd0d6b..00000000000 --- a/integration-tests/runtime-tests/src/tests/query/crowdloanRewards/queryCrowdloanRewardsTests.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* eslint-disable no-trailing-spaces */ -import { expect } from 'chai'; - -/** - * Contains all Query tests for the pallet: - * crowdloanRewards - * - * ToDo: Add additional checks. - */ -export class QueryCrowdloanRewardsTests { - public static runQueryCrowdloanRewardsTests() { - describe('query.crowdloanRewards.account Tests', function() { - // Set timeout to 1 minute. - this.timeout(60*1000); - it('query.crowdloanRewards.claimedRewards Tests', async function() { - await QueryCrowdloanRewardsTests.queryCrowdloanRewardsClaimedRewardsTest(); - }); - - it('query.crowdloanRewards.totalContributors Tests', async function() { - await QueryCrowdloanRewardsTests.queryCrowdloanRewardsTotalContributorsTest(); - }); - - it('query.crowdloanRewards.totalRewards Tests', async function() { - await QueryCrowdloanRewardsTests.queryCrowdloanRewardsTotalRewardsTest(); - }); - }); - } - - /** - * Checks for a successful return of - * query.crowdloanRewards.claimedRewards() - */ - private static async queryCrowdloanRewardsClaimedRewardsTest() { - const claimedRewards = await api.query.crowdloanRewards.claimedRewards(); - expect(claimedRewards.toNumber()).to.be.a('number'); - } - - /** - * Checks for a successful return of - * query.crowdloanRewards.totalContributors() - */ - private static async queryCrowdloanRewardsTotalContributorsTest() { - const totalContributors = await api.query.crowdloanRewards.totalContributors(); - expect(totalContributors.toNumber()).to.be.a('number'); - } - - /** - * Checks for a successful return of - * query.crowdloanRewards.totalRewards() - */ - private static async queryCrowdloanRewardsTotalRewardsTest() { - const totalRewards = await api.query.crowdloanRewards.totalRewards(); - expect(totalRewards.toNumber()).to.be.a('number'); - } -} - -// Uncomment to debug -// QueryCrowdloanRewardsTests.runQueryCrowdloanRewardsTests(); diff --git a/integration-tests/runtime-tests/src/tests/rpc/crowdloanRewards/rpcCrowdloanRewardsTests.ts b/integration-tests/runtime-tests/src/tests/rpc/crowdloanRewards/rpcCrowdloanRewardsTests.ts deleted file mode 100644 index 22f8579deeb..00000000000 --- a/integration-tests/runtime-tests/src/tests/rpc/crowdloanRewards/rpcCrowdloanRewardsTests.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* eslint-disable no-trailing-spaces */ -import { ApiPromise } from '@polkadot/api'; -import { expect } from 'chai'; - - -export class RpcCrowdloanRewardsTests { - /** - * - */ - public static runRpcCrowdloanRewardsTests() { - describe('query.crowdloanRewards.account Tests', function () { - it('STUB', async () => { - RpcCrowdloanRewardsTests.rpcCrowdloanRewardsTest(); - }); - }); - } - - /** - * - */ - private static async rpcCrowdloanRewardsTest() { - // ToDo (D. Roth): STUB - expect(true).to.equal(true); - } -} - -// Uncomment to debug -// RpcCrowdloanRewardsTests.runRpcCrowdloanRewardsTests(); \ No newline at end of file diff --git a/integration-tests/runtime-tests/src/tests/tx/bondedFinance/txBondedFinanceTests.ts b/integration-tests/runtime-tests/src/tests/tx/bondedFinance/txBondedFinanceTests.ts deleted file mode 100644 index cf1b79bbc07..00000000000 --- a/integration-tests/runtime-tests/src/tests/tx/bondedFinance/txBondedFinanceTests.ts +++ /dev/null @@ -1,178 +0,0 @@ -/* eslint-disable no-trailing-spaces */ -import {expect} from "chai"; -import { - txBondedFinanceCancelSudoSuccessTest, - txBondedFinanceCancelFailureTest, - txBondedFinanceCancelSuccessTest -} from '@composable/tests/tx/bondedFinance/testHandlers/cancelTests'; -import { - txBondedFinanceOfferFailureTest, - txBondedFinanceOfferSuccessTest -} from "@composable/tests/tx/bondedFinance/testHandlers/offerTests"; -import {txBondedFinanceBondSuccessTest} from "@composable/tests/tx/bondedFinance/testHandlers/bondTests"; - -/** - * Contains all TX tests for the pallet: - * bondedFinance - */ -export class TxBondedFinanceTests { - /** - * Runs all tx tests for the bondedFinance pallet. - * - * ToDo (D. Roth): The tests assume you're running them on a fresh chain. Instead of assuming, use the test returns. - */ - public static runTxBondedFinanceTests() { - describe('tx.bondedFinance Tests', function() { - /** - * bondedFinance.offer(...) Success Tests - */ - describe('tx.bondedFinance.offer & .bond Success Tests', function () { - // Timeout set to 2 minutes - this.timeout(2*60*1000); - // #1 Create offer using Alice's wallet. - it('Can create a new offer', async function () { - const requestParameters = { - beneficiary: walletAlice.publicKey, - asset: api.createType('u128', 1), - bondPrice: api.consts.bondedFinance.stake, - nbOfBonds: api.createType('u128', 10), - maturity: { Finite: { returnIn: api.createType('u32', 16) } }, - reward: { - asset: api.createType('u128', 1), - amount: api.consts.bondedFinance.minReward, - maturity: api.createType('u32', 1) - } - }; - const { data: [result], } = await txBondedFinanceOfferSuccessTest(walletAlice, requestParameters); - expect(result.toNumber()).to.be.a('number'); - }); - - // #2 Create offer using Bob's wallet. - it('Can create a second new offer', async function () { - const requestParameters = { - beneficiary: walletBob.publicKey, - asset: api.createType('u128', 1), - bondPrice: api.consts.bondedFinance.stake, - nbOfBonds: api.createType('u128', 10), - maturity: { Finite: { returnIn: api.createType('u32', 16) } }, - reward: { - asset: api.createType('u128', 1), - amount: api.consts.bondedFinance.minReward, - maturity: api.createType('u32', 1) - } - }; - const { data: [result], } = await txBondedFinanceOfferSuccessTest(walletBob, requestParameters); - expect(result.toNumber()).to.be.a('number'); - }); - - /** - * bondedFinance.bond(offerId:u64, nbOfBonds:u128) Tests - */ - // #3 Bob can bond to the offer Alice has created. - it('Can bond to newly created offer', async function () { - const offerId = api.createType('u64', 1); - const nbOfBonds = api.createType('u128', 1); - await txBondedFinanceBondSuccessTest(walletBob, offerId, nbOfBonds); - }); - }); - - /** - * Runs all tx FAILURE tests for the bondedFinance pallet. - */ - describe('tx.bondedFinance.offer Failure Tests', function () { - // Timeout set to 2 minutes - this.timeout(2*60*1000); - // #4 Alice can't create am offer with the bond price too low. - it('Should not be able to create offer (bondPrice < MIN_VESTED_TRANSFER)', async function () { - const requestParameters = { - beneficiary: walletAlice.publicKey, - asset: api.createType('u128', 1), - bondPrice: api.createType('u128', api.consts.bondedFinance.stake.toNumber()-1), - nbOfBonds: api.createType('u128', 10), - maturity: {Finite: {returnIn: api.createType('u32', 16)}}, - reward: { - asset: api.createType('u128', 1), - amount: api.consts.bondedFinance.minReward, - maturity: api.createType('u32', 1) - } - }; - const {data: [result],} = await txBondedFinanceOfferFailureTest(walletAlice, requestParameters); - expect(result.toNumber()).to.be.a('number'); - }); - - // #5 Alice can't create offer with the reward amount too low. - it('Should not be able to create offer (reward.amount < MinReward)', async function () { - const requestParameters = { - beneficiary: walletAlice.publicKey, - asset: api.createType('u128', 1), - bondPrice: api.consts.bondedFinance.stake, - nbOfBonds: api.createType('u128', 10), - maturity: {Finite: {returnIn: api.createType('u32', 16)}}, - reward: { - asset: api.createType('u128', 1), - amount: api.createType('u128', api.consts.bondedFinance.minReward.toNumber()-1), - maturity: api.createType('u32', 1) - } - }; - const {data: [result],} = await txBondedFinanceOfferFailureTest(walletAlice, requestParameters); - expect(result.toNumber()).to.be.a('number'); - }); - - // #5 Alice can't create offer with the reward amount too low. - it('Should not be able to create offer (reward.asset does not exist)', async function () { - const requestParameters = { - beneficiary: walletAlice.publicKey, - asset: api.createType('u128', 1), - bondPrice: api.consts.bondedFinance.stake, - nbOfBonds: api.createType('u128', 10), - maturity: {Finite: {returnIn: api.createType('u32', 16)}}, - reward: { - asset: api.createType('u128', 1337), - amount: api.consts.bondedFinance.minReward, - maturity: api.createType('u32', 1) - } - }; - const {data: [result],} = await txBondedFinanceOfferFailureTest(walletAlice, requestParameters); - expect(result.toNumber()).to.be.a('number'); - }); - }); - - /** - * Runs FAILURE tests for bondedFinance.cancel(offerId) - */ - describe('tx.bondedFinance.cancel Failure Tests', function () { - // Timeout set to 2 minutes - this.timeout(2*60*1000); - it('Should not be able to cancel offer that doesn\'t exist', async function () { - const offerId = 1337; - const { data: [result], } = await txBondedFinanceCancelFailureTest(walletAlice, offerId); - expect(result.toNumber()).to.be.a('number'); - }); - }); - - /** - * Runs SUCCESS tests for bondedFinance.cancel(offerId) - */ - describe('tx.bondedFinance.cancel Success Tests', function () { - // Timeout set to 2 minutes - this.timeout(2*60*1000); - // #6 Alice should be able to cancel her offer. - it('Can cancel offer created in first bondedFinance.offer test by creator', async function () { - const offerId = 1; - const { data: [result], } = await txBondedFinanceCancelSuccessTest(walletAlice, offerId); - expect(result.toNumber()).to.be.a('number'); - }); - - // #7 A sudo command should be able to cancel an offer. - it('Can sudo (diff. account) cancel offer created in second bondedFinance.offer', async function () { - const offerId = 2; - const { data: [result], } = await txBondedFinanceCancelSudoSuccessTest(walletAlice, offerId); - expect(result.isOk).to.be.true; - }); - }); - }); - } -} - -// Uncomment to debug -//TxBondedFinanceTests.runTxBondedFinanceTests(); diff --git a/integration-tests/runtime-tests/src/tests/tx/crowdloanRewards/txCrowdloanRewardsTests.ts b/integration-tests/runtime-tests/src/tests/tx/crowdloanRewards/txCrowdloanRewardsTests.ts deleted file mode 100644 index a370a0ad665..00000000000 --- a/integration-tests/runtime-tests/src/tests/tx/crowdloanRewards/txCrowdloanRewardsTests.ts +++ /dev/null @@ -1,130 +0,0 @@ -/* eslint-disable no-trailing-spaces */ -import R from 'ramda'; -import { PalletCrowdloanRewardsModelsRemoteAccount } from '@composable/types/interfaces'; -import { sendAndWaitForSuccess, sendUnsignedAndWaitForSuccess } from '@composable/utils/polkadotjs'; -import { u128, u32 } from '@polkadot/types-codec'; -import { expect } from 'chai'; -import { IKeyringPair } from '@polkadot/types/types'; -import {KeyringPair} from "@polkadot/keyring/types"; - -const toHexString = bytes => - Array.prototype.map.call(bytes, x => ('0' + (x & 0xFF).toString(16)).slice(-2)).join(''); - -// The prefix is defined as pallet config -const proofMessage = (account: IKeyringPair, isEth=false) => - (isEth ? "picasso-" : "picasso-") + toHexString(account.publicKey) + (isEth ? "" : ""); - -const ethAccount = (seed: number) => - web3.eth.accounts.privateKeyToAccount("0x" + seed.toString(16).padStart(64, '0')) - -export class TxCrowdloanRewardsTests { - /** - * Task order list: - * * Populate the list of contributors - * * Initialize the crowdloan - * * Associate a picassso account - */ - public static runTxCrowdloanRewardsTests() { - describe('CrowdloanRewards Tests', function() { - // 2 minutes timeout - this.timeout(60 * 2 * 1000); - it('Can populate the list of contributors', async function() { - const sudoWallet = walletAlice; - const { data: [result], } = await TxCrowdloanRewardsTests.txCrowdloanRewardsPopulateTest(sudoWallet); - expect(result.isOk).to.be.true; - }); - - it('Can initialize the crowdloan', async function() { - const sudoWallet = walletAlice; - const { data: [result], } = await TxCrowdloanRewardsTests.txCrowdloanRewardsInitializeTest(sudoWallet); - expect(result.isOk).to.be.true; - }); - - it('Can associate a picasso account', async function() { - const wallet = walletAlice; - await Promise.all([ - TxCrowdloanRewardsTests.txCrowdloanRewardsEthAssociateTests(wallet), - TxCrowdloanRewardsTests.txCrowdloanRewardsRelayAssociateTests(wallet), - ]); - }); - }); - } - - /** - * tx.crowdloanRewards.populate - */ - private static txCrowdloanRewardsInitializeTest(sudoKey:KeyringPair) { - return sendAndWaitForSuccess( - api, - sudoKey, - api.events.sudo.Sudid.is, - api.tx.sudo.sudo( - api.tx.crowdloanRewards.initialize() - ) - ); - } - - /** - * - */ - private static async txCrowdloanRewardsPopulateTest(sudoKey:KeyringPair) { - const vesting48weeks = api.createType('u32', 100800); - const reward = api.createType('u128', 1_000_000_000_000); - const relay_accounts = - R.unfold(n => n > 50 ? false : [[ - api.createType( - 'PalletCrowdloanRewardsModelsRemoteAccount', - { RelayChain: walletAlice.derive("/contributor-" + n.toString()).publicKey } - ), - reward, - vesting48weeks, - ], n + 1], 1); - const eth_accounts = - R.unfold(n => n > 50 ? false : [[ - api.createType( - 'PalletCrowdloanRewardsModelsRemoteAccount', - { Ethereum: ethAccount(n).address } - ), - reward, - vesting48weeks, - ], n + 1], 1); - const accounts = relay_accounts.concat(eth_accounts); - return await sendAndWaitForSuccess( - api, - sudoKey, - api.events.sudo.Sudid.is, api.tx.sudo.sudo( - api.tx.crowdloanRewards.populate(accounts) - ) - ); - } - - private static async txCrowdloanRewardsRelayAssociateTests(wallet:KeyringPair) { - const contributor = wallet.derive("/contributor-1"); - // arbitrary, user defined reward account - const contributorRewardAccount = contributor.derive("/reward"); - const proof = contributor.sign(proofMessage(contributorRewardAccount)); - return await sendUnsignedAndWaitForSuccess( - api, - api.events.crowdloanRewards.Associated.is, - api.tx.crowdloanRewards.associate( - contributorRewardAccount.publicKey, - { RelayChain: [contributor.publicKey, { Sr25519: proof }] } - ) - ); - } - - private static async txCrowdloanRewardsEthAssociateTests(wallet:KeyringPair) { - const contributor = ethAccount(1); - // arbitrary, user defined reward account - const contributorRewardAccount = wallet.derive("/reward-eth-1"); - const proof = contributor.sign(proofMessage(contributorRewardAccount, true)); - return await sendUnsignedAndWaitForSuccess( - api, - api.events.crowdloanRewards.Associated.is, - api.tx.crowdloanRewards.associate( - contributorRewardAccount.publicKey, - { Ethereum: proof.signature } - ) - ); - } -} diff --git a/integration-tests/runtime-tests/src/tests/tx/oracle/txOracleTests.ts b/integration-tests/runtime-tests/src/tests/tx/oracle/txOracleTests.ts deleted file mode 100644 index 2489e6a2f6e..00000000000 --- a/integration-tests/runtime-tests/src/tests/tx/oracle/txOracleTests.ts +++ /dev/null @@ -1,204 +0,0 @@ -/* eslint-disable no-trailing-spaces */ -import {expect} from "chai"; -import {txOracleSubmitPriceSuccessTest} from "@composable/tests/tx/oracle/testHandlers/submitPriceTests"; -import {txOracleAddAssetAndInfoSuccessTest} from "@composable/tests/tx/oracle/testHandlers/addAssetAndInfoTests"; -import { - runBeforeTxOracleSetSigner, - txOracleSetSignerSuccessTest -} from "@composable/tests/tx/oracle/testHandlers/setSignerTests"; -import {KeyringPair} from "@polkadot/keyring/types"; -import { - runBeforeTxOracleAddStake, - txOracleAddStakeSuccessTest -} from "@composable/tests/tx/oracle/testHandlers/addStakeTests"; -import {txOracleReclaimStakeSuccessTest} from "@composable/tests/tx/oracle/testHandlers/reclaimStakeTests"; -import {txOracleRemoveStakeSuccessTest} from "@composable/tests/tx/oracle/testHandlers/removeStakeTests"; - -/** - * Contains all TX tests for the pallet: - * Oracle - */ -function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -export class TxOracleTests { - /** - * Runs all tx tests for the Oracle pallet. - */ - public static runTxOracleTests() { - let assetsCountStart:number; - let newAsset1:number; - let signedWallet: KeyringPair; - let controllerWallet: KeyringPair; - - describe('tx.oracle Tests', function () { - before(async function() { - // Getting the id for the about to be created asset. - assetsCountStart = (await api.query.oracle.assetsCount()).toNumber(); - newAsset1=assetsCountStart+1; - - signedWallet = walletAlice.derive('/oracleSigner'); - controllerWallet = walletAlice; - }); - /** - * oracle.addAssetAndInfo Success Tests - * - * Sudo command success is checked with `.isOk`. - */ - describe('tx.addAssetAndInfo Success Test', function () { - // Timeout set to 2 minutes - this.timeout(2 * 60 * 1000); - it('Can add new asset and info', async function () { - const assetId = api.createType('u128', newAsset1); - const threshold = api.createType('Percent', 50); - const minAnswers = api.createType('u32', 2); - const maxAnswers = api.createType('u32', 5); - const blockInterval = api.createType('u32', 6); - const reward = api.createType('u128', 150000000000); - const slash = api.createType('u128', 100000000000); - const {data: [result],} = await txOracleAddAssetAndInfoSuccessTest( - controllerWallet, - assetId, - threshold, - minAnswers, - maxAnswers, - blockInterval, - reward, - slash - ); - if (result.isErr) - console.debug(result.asErr.toString()); - expect(result.isOk).to.be.true; - }); - }); - - /** - * oracle.setSigner Success Tests - * To be called by controller. - * - * In `before` we give the signer wallet enough funds to become a signer. - * - * We get 2 results here. - * resultAccount0: The signer wallets public key. - * resultAccount1: The controller wallets public key. - */ - describe('tx.setSigner Success Test', function () { - // Timeout set to 2 minutes - this.timeout(2 * 60 * 1000); - before(async function() { - const sudoKey = walletAlice; - const {data: [result],} = await runBeforeTxOracleSetSigner(sudoKey, signedWallet); - expect(result.isOk).to.be.true; - }); - it('Can set signer', async function () { - const {data: [resultAccount0, resultAccount1],} = await txOracleSetSignerSuccessTest(controllerWallet, signedWallet).catch(function(exc) { - return {data:[exc]}; // We can't call this.skip() from here. - }); - if (resultAccount0.message == "oracle.SignerUsed: This signer is already in use" || - resultAccount0.message == "oracle.ControllerUsed: This controller is already in use") - return this.skip(); // If the test is run a second time on the same chain, we already have a signer set. - expect(resultAccount0).to.not.be.an('Error'); - expect(resultAccount1).to.not.be.an('Error'); - expect(resultAccount0.toString()).to.be.equal(api.createType('AccountId32', signedWallet.publicKey).toString()); - expect(resultAccount1.toString()).to.be.equal(api.createType('AccountId32', controllerWallet.publicKey).toString()); - }); - }); - - /** - * oracle.addStake Success Tests - * To be called by controller. - * - * Result is the signer wallets public key. - */ - describe('tx.addStake Success Test', function () { - // Timeout set to 2 minutes - this.timeout(2 * 60 * 1000); - before(async function() { - const sudoKey = walletAlice; - await runBeforeTxOracleAddStake(sudoKey, controllerWallet, signedWallet); - }); - it('Can add stake from creator/controller', async function () { - const stake = api.createType('u128', 250000000000); - const {data: [result],} = await txOracleAddStakeSuccessTest(controllerWallet, stake); - expect(result).to.not.be.an('Error'); - expect(result.toString()).to.be - .equal(api.createType('AccountId32', signedWallet.publicKey).toString()); - }); - }); - - /** - * oracle.submitPrice Success Tests - * To be called by signer or controller. - * - * Result is the signer wallets public key. - */ - describe('tx.submitPrice Success Test', function () { - // Timeout set to 2 minutes - this.timeout(2 * 60 * 1000); - it('Can submit new price by signer', async function () { - const price = api.createType('u128', 10000); - const assetId = api.createType('u128', newAsset1); - const {data: [result],} = await txOracleSubmitPriceSuccessTest(signedWallet, price, assetId); - expect(result).to.not.be.an('Error'); - expect(result.toString()).to.be - .equal(api.createType('AccountId32', signedWallet.publicKey).toString()); - }); - }); - - /** - * oracle.removeStake Success Tests - * To be called by controller. - * - * Result is the signer wallets public key. - */ - describe('tx.removeStake Success Test', function () { - // Timeout set to 2 minutes - this.timeout(2 * 60 * 1000); - it('Can remove stake', async function () { - const controllerWallet = walletAlice; - const {data: [result],} = await txOracleRemoveStakeSuccessTest(controllerWallet); - expect(result).to.not.be.an('Error'); - expect(result.toString()).to.be - .equal(api.createType('AccountId32', signedWallet.publicKey).toString()); - }); - }); - - /** - * oracle.reclaimStake Success Tests - * To be called by controller. - * Can only work after a successful removeStake(), and waiting for unblockBlock to be reached. - * - * Result is the signer wallets public key. - */ - describe('tx.reclaimStake Success Test', function () { - let unlockBlock; - // Timeout set to 15 minutes - this.timeout(15 * 60 * 1000); - before(async function() { - // Get the block number at which the funds are unlocked. - const result = await api.query.oracle.declaredWithdraws(signedWallet.address); - unlockBlock = result.unwrap().unlockBlock; - expect(unlockBlock.toNumber()).to.be.a('Number'); - }); - - it('Can reclaim stake', async function () { - let currentBlock = await api.query.system.number(); - // Taking a nap until we reach the unlocking block. - while (unlockBlock.toNumber() >= currentBlock.toNumber()) { - await sleep(9000); - currentBlock = await api.query.system.number(); - } - const controllerWallet = walletAlice; // Controller - const {data: [result],} = await txOracleReclaimStakeSuccessTest(controllerWallet); - expect(result).to.not.be.an('Error'); - expect(result.toString()).to.be - .equal(api.createType('AccountId32', signedWallet.publicKey).toString()); - }); - }); - }); - } -} - -// Uncomment to debug -//TxOracleTests.runTxOracleTests(); diff --git a/integration-tests/runtime-tests/src/types/interfaces/assets/definitions.ts b/integration-tests/runtime-tests/src/types/interfaces/assets/definitions.ts new file mode 100644 index 00000000000..e67a07f107f --- /dev/null +++ b/integration-tests/runtime-tests/src/types/interfaces/assets/definitions.ts @@ -0,0 +1,27 @@ +export default { + rpc: { + balanceOf: { + description: "Balance available for the specified account for the specified asset.", + params: [ + { + name: "asset", + type: "CurrencyId" + }, + { + name: "account", + type: "AccountId32" + }, + { + name: "at", + type: "Hash", + isOptional: true, + }, + ], + type: "AssetsBalance" + }, + }, + types: { + CurrencyId: "u128", + AssetsBalance: "u128", + }, +}; diff --git a/integration-tests/runtime-tests/src/types/interfaces/default/index.ts b/integration-tests/runtime-tests/src/types/interfaces/assets/index.ts similarity index 100% rename from integration-tests/runtime-tests/src/types/interfaces/default/index.ts rename to integration-tests/runtime-tests/src/types/interfaces/assets/index.ts diff --git a/integration-tests/runtime-tests/src/types/interfaces/assets/types.ts b/integration-tests/runtime-tests/src/types/interfaces/assets/types.ts new file mode 100644 index 00000000000..7766ed204ea --- /dev/null +++ b/integration-tests/runtime-tests/src/types/interfaces/assets/types.ts @@ -0,0 +1,12 @@ +// Auto-generated via `yarn polkadot-types-from-defs`, do not edit +/* eslint-disable */ + +import type { u128 } from '@polkadot/types-codec'; + +/** @name AssetsBalance */ +export interface AssetsBalance extends u128 {} + +/** @name CurrencyId */ +export interface CurrencyId extends u128 {} + +export type PHANTOM_ASSETS = 'assets'; diff --git a/integration-tests/runtime-tests/src/types/interfaces/augment-api-consts.ts b/integration-tests/runtime-tests/src/types/interfaces/augment-api-consts.ts index 404fe6d2eae..b712b8df1d4 100644 --- a/integration-tests/runtime-tests/src/types/interfaces/augment-api-consts.ts +++ b/integration-tests/runtime-tests/src/types/interfaces/augment-api-consts.ts @@ -2,13 +2,20 @@ /* eslint-disable */ import type { ApiTypes } from '@polkadot/api-base/types'; -import type { Bytes, Vec, bool, u128, u16, u32, u64, u8 } from '@polkadot/types-codec'; +import type { Bytes, Option, Vec, bool, u128, u16, u32, u64, u8 } from '@polkadot/types-codec'; import type { Codec } from '@polkadot/types-codec/types'; -import type { Perbill, Permill } from '@polkadot/types/interfaces/runtime'; +import type { AccountId32, Perbill, Permill } from '@polkadot/types/interfaces/runtime'; import type { FrameSupportPalletId, FrameSupportWeightsRuntimeDbWeight, FrameSupportWeightsWeightToFeeCoefficient, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, SpVersionRuntimeVersion, XcmV1MultiLocation } from '@polkadot/types/lookup'; declare module '@polkadot/api-base/types/consts' { export interface AugmentedConsts { + assets: { + nativeAssetId: u128 & AugmentedConst; + /** + * Generic const + **/ + [key: string]: Codec; + }; authorship: { /** * The number of blocks back we should accept uncles. @@ -60,19 +67,41 @@ declare module '@polkadot/api-base/types/consts' { **/ [key: string]: Codec; }; + callFilter: { + maxStringSize: u32 & AugmentedConst; + /** + * Generic const + **/ + [key: string]: Codec; + }; + constantProductDex: { + palletId: FrameSupportPalletId & AugmentedConst; + /** + * Generic const + **/ + [key: string]: Codec; + }; crowdloanRewards: { + /** + * The AccountId of this pallet. + **/ + accountId: AccountId32 & AugmentedConst; /** * The upfront liquidity unlocked at first claim. **/ initialPayment: Perbill & AugmentedConst; + /** + * The unique identifier of this pallet. + **/ + palletId: FrameSupportPalletId & AugmentedConst; /** * The arbitrary prefix used for the proof **/ prefix: Bytes & AugmentedConst; /** - * The number of blocks a fragment of the reward is vested. + * The time you have to wait to unlock another part of your reward. **/ - vestingStep: u32 & AugmentedConst; + vestingStep: u64 & AugmentedConst; /** * Generic const **/ @@ -147,16 +176,6 @@ declare module '@polkadot/api-base/types/consts' { **/ [key: string]: Codec; }; - factory: { - /** - * The initial currency id from which we are able to generate the next. - **/ - dynamicCurrencyIdInitial: u128 & AugmentedConst; - /** - * Generic const - **/ - [key: string]: Codec; - }; identity: { /** * The amount held on deposit for a registered identity @@ -201,6 +220,79 @@ declare module '@polkadot/api-base/types/consts' { **/ [key: string]: Codec; }; + lending: { + /** + * Minimal price of borrow asset in Oracle price required to create. + * Examples, 100 USDC. + * Creators puts that amount and it is staked under Vault account. + * So he does not owns it anymore. + * So borrow is both stake and tool to create market. + * + * # Why not pure borrow amount minimum? + * + * Borrow may have very small price. Will imbalance some markets on creation. + * + * # Why not native parachain token? + * + * Possible option. But I doubt closing market as easy as transferring back rent. So it is + * not exactly platform rent only. + * + * # Why borrow amount priced by Oracle? + * + * We depend on Oracle to price in Lending. So we know price anyway. + * We normalized price over all markets and protect from spam all possible pairs equally. + * Locking borrow amount ensures manager can create market wit borrow assets, and we force + * him to really create it. + * + * This solution forces to have amount before creating market. + * Vault can take that amount if reconfigured so, but that may be changed during runtime + * upgrades. + **/ + oracleMarketCreationStake: u128 & AugmentedConst; + palletId: FrameSupportPalletId & AugmentedConst; + /** + * Generic const + **/ + [key: string]: Codec; + }; + liquidityBootstrapping: { + /** + * Maximum initial weight. + **/ + maxInitialWeight: Permill & AugmentedConst; + /** + * Maximum duration for a sale. + **/ + maxSaleDuration: u32 & AugmentedConst; + /** + * Minimum final weight. + **/ + minFinalWeight: Permill & AugmentedConst; + /** + * Minimum duration for a sale. + **/ + minSaleDuration: u32 & AugmentedConst; + palletId: FrameSupportPalletId & AugmentedConst; + /** + * Generic const + **/ + [key: string]: Codec; + }; + mosaic: { + /** + * The minimum period for which we lock outgoing/incoming funds. + **/ + minimumTimeLockPeriod: u32 & AugmentedConst; + /** + * The minimum time to live before a relayer account rotation. + **/ + minimumTTL: u32 & AugmentedConst; + timelockPeriod: u32 & AugmentedConst; + /** + * Generic const + **/ + [key: string]: Codec; + }; multisig: { /** * The base amount of currency needed to reserve for creating a multisig execution or to @@ -226,6 +318,14 @@ declare module '@polkadot/api-base/types/consts' { **/ [key: string]: Codec; }; + oracle: { + maxHistory: u32 & AugmentedConst; + maxPrePrices: u32 & AugmentedConst; + /** + * Generic const + **/ + [key: string]: Codec; + }; scheduler: { /** * The maximum weight that may be scheduled per block for any dispatchables of less @@ -242,6 +342,13 @@ declare module '@polkadot/api-base/types/consts' { **/ [key: string]: Codec; }; + stableSwapDex: { + palletId: FrameSupportPalletId & AugmentedConst; + /** + * Generic const + **/ + [key: string]: Codec; + }; system: { /** * Maximum number of block number to block hash mappings to keep (oldest pruned first). @@ -341,6 +448,8 @@ declare module '@polkadot/api-base/types/consts' { burn: Permill & AugmentedConst; /** * The maximum number of approvals that can wait in the spending queue. + * + * NOTE: This parameter is also used within the Bounties Pallet extension if enabled. **/ maxApprovals: u32 & AugmentedConst; /** @@ -352,6 +461,10 @@ declare module '@polkadot/api-base/types/consts' { * An accepted proposal gets these back. A rejected proposal does not. **/ proposalBond: Permill & AugmentedConst; + /** + * Maximum amount of funds that should be placed in a deposit for making a proposal. + **/ + proposalBondMaximum: Option & AugmentedConst; /** * Minimum amount of funds that should be placed in a deposit for making a proposal. **/ diff --git a/integration-tests/runtime-tests/src/types/interfaces/augment-api-errors.ts b/integration-tests/runtime-tests/src/types/interfaces/augment-api-errors.ts index da915f5d6ef..59ccf164a86 100644 --- a/integration-tests/runtime-tests/src/types/interfaces/augment-api-errors.ts +++ b/integration-tests/runtime-tests/src/types/interfaces/augment-api-errors.ts @@ -6,7 +6,6 @@ import type { ApiTypes } from '@polkadot/api-base/types'; declare module '@polkadot/api-base/types/errors' { export interface AugmentedErrors { assets: { - BadOrigin: AugmentedError; CannotSetNewCurrencyToRegistry: AugmentedError; /** * Generic error @@ -15,7 +14,9 @@ declare module '@polkadot/api-base/types/errors' { }; assetsRegistry: { ForeignAssetIdAlreadyUsed: AugmentedError; + ForeignAssetIdNotFound: AugmentedError; LocalAssetIdAlreadyUsed: AugmentedError; + LocalAssetIdNotFound: AugmentedError; OnlyAllowedForAdmins: AugmentedError; /** * Generic error @@ -172,6 +173,19 @@ declare module '@polkadot/api-base/types/errors' { **/ [key: string]: AugmentedError; }; + constantProductDex: { + CannotRespectMinimumRequested: AugmentedError; + InvalidAmount: AugmentedError; + InvalidFees: AugmentedError; + InvalidPair: AugmentedError; + MissingAmount: AugmentedError; + PairMismatch: AugmentedError; + PoolNotFound: AugmentedError; + /** + * Generic error + **/ + [key: string]: AugmentedError; + }; council: { /** * Members are already initialized! @@ -235,11 +249,14 @@ declare module '@polkadot/api-base/types/errors' { crowdloanRewards: { AlreadyAssociated: AugmentedError; AlreadyInitialized: AugmentedError; + BackToTheFuture: AugmentedError; InvalidClaim: AugmentedError; InvalidProof: AugmentedError; NotAssociated: AugmentedError; + NotClaimableYet: AugmentedError; NothingToClaim: AugmentedError; NotInitialized: AugmentedError; + RewardsNotFunded: AugmentedError; /** * Generic error **/ @@ -251,6 +268,12 @@ declare module '@polkadot/api-base/types/errors' { **/ [key: string]: AugmentedError; }; + currencyFactory: { + /** + * Generic error + **/ + [key: string]: AugmentedError; + }; democracy: { /** * Cannot cancel the same proposal twice @@ -385,6 +408,7 @@ declare module '@polkadot/api-base/types/errors' { [key: string]: AugmentedError; }; dutchAuction: { + NotEnoughNativeCurrentyToPayForAuction: AugmentedError; OrderNotFound: AugmentedError; OrderParametersIsInvalid: AugmentedError; RequestedOrderDoesNotExists: AugmentedError; @@ -395,12 +419,6 @@ declare module '@polkadot/api-base/types/errors' { **/ [key: string]: AugmentedError; }; - factory: { - /** - * Generic error - **/ - [key: string]: AugmentedError; - }; governanceRegistry: { /** * Not found @@ -507,6 +525,94 @@ declare module '@polkadot/api-base/types/errors' { **/ [key: string]: AugmentedError; }; + lending: { + /** + * Only assets for which we can track price are supported + **/ + AssetNotSupportedByOracle: AugmentedError; + AssetPriceNotFound: AugmentedError; + BorrowAndRepayInSameBlockIsNotSupported: AugmentedError; + BorrowDoesNotExist: AugmentedError; + BorrowerDataCalculationFailed: AugmentedError; + BorrowIndexDoesNotExist: AugmentedError; + BorrowRateDoesNotExist: AugmentedError; + CannotRepayMoreThanBorrowAmount: AugmentedError; + CannotWithdrawFromProvidedBorrowAccount: AugmentedError; + CollateralDepositFailed: AugmentedError; + CollateralFactorIsLessOrEqualOne: AugmentedError; + ExceedLendingCount: AugmentedError; + InvalidTimestampOnBorrowRequest: AugmentedError; + LiquidationFailed: AugmentedError; + MarketAndAccountPairNotFound: AugmentedError; + MarketCollateralWasNotDepositedByAccount: AugmentedError; + /** + * The market could not be found + **/ + MarketDoesNotExist: AugmentedError; + MarketIsClosing: AugmentedError; + NotEnoughBorrowAsset: AugmentedError; + NotEnoughCollateral: AugmentedError; + NotEnoughCollateralToBorrowAmount: AugmentedError; + NotEnoughRent: AugmentedError; + Overflow: AugmentedError; + /** + * borrow assets should have enough value as per oracle + **/ + PriceOfInitialBorrowVaultShouldBeGreaterThanZero: AugmentedError; + RepayAmountMustBeGraterThanZero: AugmentedError; + TransferFailed: AugmentedError; + Unauthorized: AugmentedError; + Underflow: AugmentedError; + /** + * vault provided does not exist + **/ + VaultNotFound: AugmentedError; + /** + * Generic error + **/ + [key: string]: AugmentedError; + }; + liquidations: { + NoLiquidationEngineFound: AugmentedError; + /** + * Generic error + **/ + [key: string]: AugmentedError; + }; + liquidityBootstrapping: { + CannotRespectMinimumRequested: AugmentedError; + InvalidAmount: AugmentedError; + InvalidSaleState: AugmentedError; + MustBeOwner: AugmentedError; + PairMismatch: AugmentedError; + PoolNotFound: AugmentedError; + /** + * Generic error + **/ + [key: string]: AugmentedError; + }; + mosaic: { + AmountMismatch: AugmentedError; + AssetNotMapped: AugmentedError; + BadTimelockPeriod: AugmentedError; + BadTTL: AugmentedError; + BelowMinTransferSize: AugmentedError; + ExceedsMaxTransferSize: AugmentedError; + InsufficientBudget: AugmentedError; + NetworkDisabled: AugmentedError; + NoClaimableTx: AugmentedError; + NoOutgoingTx: AugmentedError; + NoStaleTransactions: AugmentedError; + Overflow: AugmentedError; + RelayerNotSet: AugmentedError; + TxStillLocked: AugmentedError; + UnsupportedAsset: AugmentedError; + UnsupportedNetwork: AugmentedError; + /** + * Generic error + **/ + [key: string]: AugmentedError; + }; multisig: { /** * Call is already approved by this signatory. @@ -620,6 +726,8 @@ declare module '@polkadot/api-base/types/errors' { **/ InvalidMinAnswers: AugmentedError; MaxAnswersLessThanMinAnswers: AugmentedError; + MaxHistory: AugmentedError; + MaxPrePrices: AugmentedError; /** * Max prices already reached **/ @@ -720,6 +828,36 @@ declare module '@polkadot/api-base/types/errors' { **/ [key: string]: AugmentedError; }; + preimage: { + /** + * Preimage has already been noted on-chain. + **/ + AlreadyNoted: AugmentedError; + /** + * The user is not authorized to perform this action. + **/ + NotAuthorized: AugmentedError; + /** + * The preimage cannot be removed since it has not yet been noted. + **/ + NotNoted: AugmentedError; + /** + * The preimage request cannot be removed since no outstanding requests exist. + **/ + NotRequested: AugmentedError; + /** + * A preimage may not be removed when there are outstanding requests. + **/ + Requested: AugmentedError; + /** + * Preimage is too large to store on-chain. + **/ + TooLarge: AugmentedError; + /** + * Generic error + **/ + [key: string]: AugmentedError; + }; relayerXcm: { /** * The location is invalid since it already has a subscription from us. @@ -829,6 +967,19 @@ declare module '@polkadot/api-base/types/errors' { **/ [key: string]: AugmentedError; }; + stableSwapDex: { + AmpFactorMustBeGreaterThanZero: AugmentedError; + AssetAmountMustBePositiveNumber: AugmentedError; + CannotRespectMinimumRequested: AugmentedError; + InvalidFees: AugmentedError; + InvalidPair: AugmentedError; + PairMismatch: AugmentedError; + PoolNotFound: AugmentedError; + /** + * Generic error + **/ + [key: string]: AugmentedError; + }; sudo: { /** * Sender must be the Sudo account @@ -1073,6 +1224,10 @@ declare module '@polkadot/api-base/types/errors' { * This account have too many vesting schedules **/ TooManyVestingSchedules: AugmentedError; + /** + * Trying to vest to ourselves + **/ + TryingToSelfVest: AugmentedError; /** * Vesting period is zero **/ @@ -1087,6 +1242,10 @@ declare module '@polkadot/api-base/types/errors' { [key: string]: AugmentedError; }; xcmpQueue: { + /** + * Bad overweight index. + **/ + BadOverweightIndex: AugmentedError; /** * Bad XCM data. **/ @@ -1099,6 +1258,10 @@ declare module '@polkadot/api-base/types/errors' { * Failed to send XCM message. **/ FailedToSend: AugmentedError; + /** + * Provided weight is possibly not enough to execute the message. + **/ + WeightOverLimit: AugmentedError; /** * Generic error **/ @@ -1109,6 +1272,10 @@ declare module '@polkadot/api-base/types/errors' { * Asset has no reserve location. **/ AssetHasNoReserve: AugmentedError; + /** + * The specified index does not exist in a MultiAssets struct. + **/ + AssetIndexNonExistent: AugmentedError; /** * The version of the `Versioned` value used is not able to be * interpreted. @@ -1124,18 +1291,22 @@ declare module '@polkadot/api-base/types/errors' { **/ DestinationNotInvertible: AugmentedError; /** - * The fee MultiAsset is of different type than the asset to transfer. + * We tried sending distinct asset and fee but they have different + * reserve chains. **/ - DistincAssetAndFeeId: AugmentedError; + DistinctReserveForAssetAndFee: AugmentedError; /** - * The fee amount was zero when the fee specification extrinsic is - * being used. + * Fee is not enough. **/ - FeeCannotBeZero: AugmentedError; + FeeNotEnough: AugmentedError; /** * Could not get ancestry of asset reserve location. **/ InvalidAncestry: AugmentedError; + /** + * The MultiAsset is invalid. + **/ + InvalidAsset: AugmentedError; /** * Invalid transfer destination. **/ @@ -1149,9 +1320,9 @@ declare module '@polkadot/api-base/types/errors' { **/ NotCrossChainTransferableCurrency: AugmentedError; /** - * Not fungible asset. + * The number of assets to be sent is over the maximum. **/ - NotFungible: AugmentedError; + TooManyAssetsBeingSent: AugmentedError; /** * The message's weight could not be determined. **/ @@ -1160,6 +1331,14 @@ declare module '@polkadot/api-base/types/errors' { * XCM execution failed. **/ XcmExecutionFailed: AugmentedError; + /** + * The transfering asset amount is zero. + **/ + ZeroAmount: AugmentedError; + /** + * The fee is zero. + **/ + ZeroFee: AugmentedError; /** * Generic error **/ diff --git a/integration-tests/runtime-tests/src/types/interfaces/augment-api-events.ts b/integration-tests/runtime-tests/src/types/interfaces/augment-api-events.ts index 1ca01b2168b..d006528198f 100644 --- a/integration-tests/runtime-tests/src/types/interfaces/augment-api-events.ts +++ b/integration-tests/runtime-tests/src/types/interfaces/augment-api-events.ts @@ -1,17 +1,18 @@ // Auto-generated via `yarn polkadot-types-from-chain`, do not edit /* eslint-disable */ -import type { ComposableTraitsAssetsXcmAssetLocation, ComposableTraitsCallFilterCallFilterEntry, ComposableTraitsVestingVestingSchedule, PalletCrowdloanRewardsModelsRemoteAccount, PalletDemocracyVoteThreshold, PalletDutchAuctionSellOrder } from '@composable/types/interfaces/default'; +import type { CommonMosaicRemoteAssetId, ComposableTraitsCallFilterCallFilterEntry, ComposableTraitsDefiCurrencyPair, ComposableTraitsLendingUpdateInput, ComposableTraitsVestingVestingSchedule, FrameSupportScheduleLookupError, PalletCrowdloanRewardsModelsRemoteAccount, PalletCurrencyFactoryRangesRange, PalletDemocracyVoteAccountVote, PalletDemocracyVoteThreshold, PalletDutchAuctionSellOrder, PalletMosaicDecayBudgetPenaltyDecayer, PalletMosaicNetworkInfo } from '@composable/types/interfaces/crowdloanRewards'; import type { ApiTypes } from '@polkadot/api-base/types'; import type { Bytes, Null, Option, Result, U8aFixed, Vec, bool, u128, u32, u64, u8 } from '@polkadot/types-codec'; import type { ITuple } from '@polkadot/types-codec/types'; import type { AccountId32, H256, Percent } from '@polkadot/types/interfaces/runtime'; -import type { FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchInfo, PalletMultisigTimepoint, SpRuntimeDispatchError, XcmV1MultiAsset, XcmV1MultiLocation, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation } from '@polkadot/types/lookup'; +import type { FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchInfo, PalletMultisigTimepoint, SpRuntimeDispatchError, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetMultiAssets, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation } from '@polkadot/types/lookup'; declare module '@polkadot/api-base/types/events' { export interface AugmentedEvents { assetsRegistry: { - AssetsMappingCandidateUpdated: AugmentedEvent; + AssetMetadataUpdated: AugmentedEvent; + AssetsMappingCandidateUpdated: AugmentedEvent; ForeignAdminUpdated: AugmentedEvent; LocalAdminUpdated: AugmentedEvent; /** @@ -71,19 +72,19 @@ declare module '@polkadot/api-base/types/events' { /** * A new bond has been registered. **/ - NewBond: AugmentedEvent; + NewBond: AugmentedEvent; /** * A new offer has been created. **/ - NewOffer: AugmentedEvent; + NewOffer: AugmentedEvent; /** * An offer has been cancelled by the `AdminOrigin`. **/ - OfferCancelled: AugmentedEvent; + OfferCancelled: AugmentedEvent; /** * An offer has been completed. **/ - OfferCompleted: AugmentedEvent; + OfferCompleted: AugmentedEvent; /** * Generic event **/ @@ -114,6 +115,28 @@ declare module '@polkadot/api-base/types/events' { **/ [key: string]: AugmentedEvent; }; + constantProductDex: { + /** + * Liquidity added into the pool `T::PoolId` by `T::AccountId`. + **/ + LiquidityAdded: AugmentedEvent; + /** + * Liquidity removed from pool `T::PoolId` by `T::AccountId` in balanced way. + **/ + LiquidityRemoved: AugmentedEvent; + /** + * Pool with specified id `T::PoolId` was created successfully by `T::AccountId`. + **/ + PoolCreated: AugmentedEvent; + /** + * Token exchange happened. + **/ + Swapped: AugmentedEvent; + /** + * Generic event + **/ + [key: string]: AugmentedEvent; + }; council: { /** * A motion was approved by the required threshold. @@ -183,6 +206,7 @@ declare module '@polkadot/api-base/types/events' { crowdloanRewards: { Associated: AugmentedEvent; Claimed: AugmentedEvent; + Initialized: AugmentedEvent; /** * Generic event **/ @@ -209,6 +233,13 @@ declare module '@polkadot/api-base/types/events' { **/ [key: string]: AugmentedEvent; }; + currencyFactory: { + RangeCreated: AugmentedEvent; + /** + * Generic event + **/ + [key: string]: AugmentedEvent; + }; democracy: { /** * A proposal_hash has been blacklisted permanently. @@ -262,6 +293,10 @@ declare module '@polkadot/api-base/types/events' { * A motion has been proposed by a public account. **/ Proposed: AugmentedEvent; + /** + * An account has secconded a proposal + **/ + Seconded: AugmentedEvent; /** * A referendum has begun. **/ @@ -278,6 +313,10 @@ declare module '@polkadot/api-base/types/events' { * An external proposal has been vetoed. **/ Vetoed: AugmentedEvent; + /** + * An account has voted in a referendum + **/ + Voted: AugmentedEvent; /** * Generic event **/ @@ -327,12 +366,6 @@ declare module '@polkadot/api-base/types/events' { **/ [key: string]: AugmentedEvent; }; - factory: { - /** - * Generic event - **/ - [key: string]: AugmentedEvent; - }; governanceRegistry: { GrantRoot: AugmentedEvent; Remove: AugmentedEvent; @@ -407,6 +440,130 @@ declare module '@polkadot/api-base/types/events' { **/ [key: string]: AugmentedEvent; }; + lending: { + /** + * Event emitted when user borrows from given market. + **/ + Borrowed: AugmentedEvent; + /** + * Event emitted when collateral is deposited. + **/ + CollateralDeposited: AugmentedEvent; + /** + * Event emitted when collateral is withdrawed. + **/ + CollateralWithdrawn: AugmentedEvent; + /** + * Event emitted when a liquidation is initiated for a loan. + **/ + LiquidationInitiated: AugmentedEvent]>; + /** + * Event emitted when new lending market is created. + **/ + MarketCreated: AugmentedEvent; + MarketUpdated: AugmentedEvent; + /** + * Event emitted when user repays borrow of beneficiary in given market. + **/ + RepaidBorrow: AugmentedEvent; + /** + * Event emitted to warn that loan may go under collaterized soon. + **/ + SoonMayUnderCollaterized: AugmentedEvent; + /** + * Generic event + **/ + [key: string]: AugmentedEvent; + }; + liquidations: { + PositionWasSentToLiquidation: AugmentedEvent; + /** + * Generic event + **/ + [key: string]: AugmentedEvent; + }; + liquidityBootstrapping: { + /** + * Liquidity added into the pool `T::PoolId`. + **/ + LiquidityAdded: AugmentedEvent; + /** + * Pool with specified id `T::PoolId` was created successfully by `T::AccountId`. + **/ + PoolCreated: AugmentedEvent; + /** + * The sale ended, the funds repatriated and the pool deleted. + **/ + PoolDeleted: AugmentedEvent; + /** + * Token exchange happened. + **/ + Swapped: AugmentedEvent; + /** + * Generic event + **/ + [key: string]: AugmentedEvent; + }; + mosaic: { + /** + * An asset mapping has been created. + **/ + AssetMappingCreated: AugmentedEvent; + /** + * An existing asset mapping has been deleted. + **/ + AssetMappingDeleted: AugmentedEvent; + /** + * An existing asset mapping has been updated. + **/ + AssetMappingUpdated: AugmentedEvent; + BudgetUpdated: AugmentedEvent; + /** + * The `NetworkInfos` `network_info` was updated for `network_id`. + **/ + NetworksUpdated: AugmentedEvent; + /** + * The relayer partially accepted the user's `OutgoingTransaction`. + **/ + PartialTransferAccepted: AugmentedEvent; + /** + * The relayer has been rotated to `account_id`. + **/ + RelayerRotated: AugmentedEvent; + /** + * The account of the relayer has been set. + **/ + RelayerSet: AugmentedEvent; + /** + * User claimed outgoing tx that was not (yet) picked up by the relayer + **/ + StaleTxClaimed: AugmentedEvent; + /** + * The relayer accepted the user's `OutgoingTransaction`. + **/ + TransferAccepted: AugmentedEvent; + /** + * The user claims his `IncomingTransaction` and unlocks the locked amount. + **/ + TransferClaimed: AugmentedEvent; + /** + * An incoming tx is created and waiting for the user to claim. + **/ + TransferInto: AugmentedEvent; + /** + * When we have finality issues occur on the Ethereum chain, + * we burn the locked `IncomingTransaction` for which we know that it is invalid. + **/ + TransferIntoRescined: AugmentedEvent; + /** + * An outgoing tx is created, and locked in the outgoing tx pool. + **/ + TransferOut: AugmentedEvent; + /** + * Generic event + **/ + [key: string]: AugmentedEvent; + }; multisig: { /** * A multisig operation has been approved by someone. @@ -504,6 +661,24 @@ declare module '@polkadot/api-base/types/events' { **/ [key: string]: AugmentedEvent; }; + preimage: { + /** + * A preimage has ben cleared. + **/ + Cleared: AugmentedEvent; + /** + * A preimage has been noted. + **/ + Noted: AugmentedEvent; + /** + * A preimage has been requested. + **/ + Requested: AugmentedEvent; + /** + * Generic event + **/ + [key: string]: AugmentedEvent; + }; relayerXcm: { /** * Some assets have been placed in an asset trap. @@ -628,15 +803,19 @@ declare module '@polkadot/api-base/types/events' { }; scheduler: { /** - * Canceled some task. \[when, index\] + * The call for the provided hash was not found so the task has been aborted. + **/ + CallLookupFailed: AugmentedEvent, Option, FrameSupportScheduleLookupError]>; + /** + * Canceled some task. **/ Canceled: AugmentedEvent; /** - * Dispatched some task. \[task, id, result\] + * Dispatched some task. **/ Dispatched: AugmentedEvent, Option, Result]>; /** - * Scheduled some task. \[when, index\] + * Scheduled some task. **/ Scheduled: AugmentedEvent; /** @@ -655,11 +834,33 @@ declare module '@polkadot/api-base/types/events' { **/ [key: string]: AugmentedEvent; }; + stableSwapDex: { + /** + * Liquidity added into the pool `T::PoolId` by `T::AccountId`. + **/ + LiquidityAdded: AugmentedEvent; + /** + * Liquidity removed from pool `T::PoolId` by `T::AccountId` in balanced way. + **/ + LiquidityRemoved: AugmentedEvent; + /** + * Pool with specified id `T::PoolId` was created successfully by `T::AccountId`. + **/ + PoolCreated: AugmentedEvent; + /** + * Token exchange happened. + **/ + Swapped: AugmentedEvent; + /** + * Generic event + **/ + [key: string]: AugmentedEvent; + }; sudo: { /** - * The \[sudoer\] just switched identity; the old key is supplied. + * The \[sudoer\] just switched identity; the old key is supplied if one existed. **/ - KeyChanged: AugmentedEvent; + KeyChanged: AugmentedEvent]>; /** * A sudo just took place. \[result\] **/ @@ -679,23 +880,23 @@ declare module '@polkadot/api-base/types/events' { **/ CodeUpdated: AugmentedEvent; /** - * An extrinsic failed. \[error, info\] + * An extrinsic failed. **/ ExtrinsicFailed: AugmentedEvent; /** - * An extrinsic completed successfully. \[info\] + * An extrinsic completed successfully. **/ ExtrinsicSuccess: AugmentedEvent; /** - * An \[account\] was reaped. + * An account was reaped. **/ KilledAccount: AugmentedEvent; /** - * A new \[account\] was created. + * A new account was created. **/ NewAccount: AugmentedEvent; /** - * On on-chain remark happened. \[origin, remark_hash\] + * On on-chain remark happened. **/ Remarked: AugmentedEvent; /** @@ -705,38 +906,33 @@ declare module '@polkadot/api-base/types/events' { }; tokens: { /** - * A balance was set by root. \[who, free, reserved\] + * A balance was set by root. **/ BalanceSet: AugmentedEvent; /** * An account was removed whose balance was non-zero but below - * ExistentialDeposit, resulting in an outright loss. \[currency_id, - * account, balance\] + * ExistentialDeposit, resulting in an outright loss. **/ DustLost: AugmentedEvent; /** - * An account was created with some free balance. \[currency_id, - * account, free_balance\] + * An account was created with some free balance. **/ Endowed: AugmentedEvent; /** * Some reserved balance was repatriated (moved from reserved to * another account). - * \[currency_id, from, to, amount_actually_moved, status\] **/ RepatriatedReserve: AugmentedEvent; /** * Some balance was reserved (moved from free to reserved). - * \[currency_id, who, value\] **/ Reserved: AugmentedEvent; /** - * Transfer succeeded. \[currency_id, from, to, value\] + * Transfer succeeded. **/ Transfer: AugmentedEvent; /** * Some balance was unreserved (moved from reserved to free). - * \[currency_id, who, value\] **/ Unreserved: AugmentedEvent; /** @@ -746,32 +942,31 @@ declare module '@polkadot/api-base/types/events' { }; treasury: { /** - * Some funds have been allocated. \[proposal_index, award, beneficiary\] + * Some funds have been allocated. **/ Awarded: AugmentedEvent; /** - * Some of our funds have been burnt. \[burn\] + * Some of our funds have been burnt. **/ Burnt: AugmentedEvent; /** - * Some funds have been deposited. \[deposit\] + * Some funds have been deposited. **/ Deposit: AugmentedEvent; /** - * New proposal. \[proposal_index\] + * New proposal. **/ Proposed: AugmentedEvent; /** - * A proposal was rejected; funds were slashed. \[proposal_index, slashed\] + * A proposal was rejected; funds were slashed. **/ Rejected: AugmentedEvent; /** * Spending has finished; this is the amount that rolls over until next spend. - * \[budget_remaining\] **/ Rollover: AugmentedEvent; /** - * We have ended a spend period and will now allocate funds. \[budget_remaining\] + * We have ended a spend period and will now allocate funds. **/ Spending: AugmentedEvent; /** @@ -781,11 +976,11 @@ declare module '@polkadot/api-base/types/events' { }; unknownTokens: { /** - * Deposit success. [asset, to] + * Deposit success. **/ Deposited: AugmentedEvent; /** - * Withdraw success. [asset, from] + * Withdraw success. **/ Withdrawn: AugmentedEvent; /** @@ -804,7 +999,7 @@ declare module '@polkadot/api-base/types/events' { **/ BatchInterrupted: AugmentedEvent; /** - * A call was dispatched. \[result\] + * A call was dispatched. **/ DispatchedAs: AugmentedEvent]>; /** @@ -874,6 +1069,14 @@ declare module '@polkadot/api-base/types/events' { * Some XCM failed. **/ Fail: AugmentedEvent, XcmV2TraitsError]>; + /** + * An XCM exceeded the individual message weight budget. + **/ + OverweightEnqueued: AugmentedEvent; + /** + * An XCM from the overweight queue was executed with the given actual weight used. + **/ + OverweightServiced: AugmentedEvent; /** * Some XCM was executed ok. **/ @@ -893,21 +1096,9 @@ declare module '@polkadot/api-base/types/events' { }; xTokens: { /** - * Transferred. \[sender, currency_id, amount, dest\] - **/ - Transferred: AugmentedEvent; - /** - * Transferred `MultiAsset`. \[sender, asset, dest\] - **/ - TransferredMultiAsset: AugmentedEvent; - /** - * Transferred `MultiAsset` with fee. \[sender, asset, fee, dest\] - **/ - TransferredMultiAssetWithFee: AugmentedEvent; - /** - * Transferred with fee. \[sender, currency_id, amount, fee, dest\] + * Transferred `MultiAsset` with fee. **/ - TransferredWithFee: AugmentedEvent; + TransferredMultiAssets: AugmentedEvent; /** * Generic event **/ diff --git a/integration-tests/runtime-tests/src/types/interfaces/augment-api-query.ts b/integration-tests/runtime-tests/src/types/interfaces/augment-api-query.ts index c68045b75dc..b6428c8fb22 100644 --- a/integration-tests/runtime-tests/src/types/interfaces/augment-api-query.ts +++ b/integration-tests/runtime-tests/src/types/interfaces/augment-api-query.ts @@ -1,7 +1,7 @@ // Auto-generated via `yarn polkadot-types-from-chain`, do not edit /* eslint-disable */ -import type { ComposableTraitsAssetsXcmAssetLocation, ComposableTraitsBondedFinanceBondOffer, ComposableTraitsCallFilterCallFilterEntry, ComposableTraitsGovernanceSignedRawOrigin, ComposableTraitsVestingVestingSchedule, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundStatus, CumulusPalletXcmpQueueOutboundStatus, CumulusPalletXcmpQueueQueueConfigData, DaliRuntimeOpaqueSessionKeys, OrmlTokensAccountData, OrmlTokensBalanceLock, PalletAssetsRegistryCandidateStatus, PalletCollatorSelectionCandidateInfo, PalletCrowdloanRewardsModelsRemoteAccount, PalletCrowdloanRewardsReward, PalletDemocracyPreimageStatus, PalletDemocracyReferendumInfo, PalletDemocracyReleases, PalletDemocracyVoteThreshold, PalletDemocracyVoteVoting, PalletDutchAuctionSellOrder, PalletDutchAuctionTakeOrder, PalletIdentityRegistrarInfo, PalletIdentityRegistration, PalletOracleAssetInfo, PalletOraclePrePrice, PalletOraclePrice, PalletOracleWithdraw, PalletSchedulerReleases, PalletSchedulerScheduledV2, PalletTreasuryProposal, PalletVaultModelsStrategyOverview, PalletVaultModelsVaultInfo, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV1AbridgedHostConfiguration, PolkadotPrimitivesV1PersistedValidationData, SpConsensusAuraSr25519AppSr25519Public } from '@composable/types/interfaces/default'; +import type { CommonMosaicRemoteAssetId, ComposableTraitsAssetsXcmAssetLocation, ComposableTraitsBondedFinanceBondOffer, ComposableTraitsCallFilterCallFilterEntry, ComposableTraitsDexConstantProductPoolInfo, ComposableTraitsDexStableSwapPoolInfo, ComposableTraitsGovernanceSignedRawOrigin, ComposableTraitsLendingMarketConfig, ComposableTraitsOraclePrice, ComposableTraitsVestingVestingSchedule, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueQueueConfigData, DaliRuntimeOpaqueSessionKeys, OrmlTokensAccountData, OrmlTokensBalanceLock, PalletAssetsRegistryCandidateStatus, PalletAssetsRegistryForeignMetadata, PalletCollatorSelectionCandidateInfo, PalletCrowdloanRewardsModelsRemoteAccount, PalletCrowdloanRewardsModelsReward, PalletCurrencyFactoryRanges, PalletDemocracyPreimageStatus, PalletDemocracyReferendumInfo, PalletDemocracyReleases, PalletDemocracyVoteThreshold, PalletDemocracyVoteVoting, PalletDutchAuctionSellOrder, PalletDutchAuctionTakeOrder, PalletIdentityRegistrarInfo, PalletIdentityRegistration, PalletLiquidationsLiquidationStrategyConfiguration, PalletLiquidityBootstrappingPool, PalletMosaicAssetInfo, PalletMosaicNetworkInfo, PalletMosaicRelayerStaleRelayer, PalletOracleAssetInfo, PalletOraclePrePrice, PalletOracleWithdraw, PalletPreimageRequestStatus, PalletSchedulerScheduledV3, PalletTreasuryProposal, PalletVaultModelsStrategyOverview, PalletVaultModelsVaultInfo, PolkadotPrimitivesV1AbridgedHostConfiguration, PolkadotPrimitivesV1PersistedValidationData, SpConsensusAuraSr25519AppSr25519Public } from '@composable/types/interfaces/crowdloanRewards'; import type { ApiTypes } from '@polkadot/api-base/types'; import type { Data } from '@polkadot/types'; import type { BTreeMap, Bytes, Null, Option, U8aFixed, Vec, WrapperKeepOpaque, bool, u128, u16, u32, u64 } from '@polkadot/types-codec'; @@ -22,23 +22,35 @@ declare module '@polkadot/api-base/types/storage' { /** * Mapping (local asset, foreign asset) to candidate status. **/ - assetsMappingCandidates: AugmentedQuery | [u128 | AnyNumber | Uint8Array, ComposableTraitsAssetsXcmAssetLocation | { parents?: any; interior?: any } | string | Uint8Array]) => Observable>, [ITuple<[u128, ComposableTraitsAssetsXcmAssetLocation]>]> & QueryableStorageEntry]>; + assetsMappingCandidates: AugmentedQuery | [u128 | AnyNumber | Uint8Array, u128 | AnyNumber | Uint8Array]) => Observable>, [ITuple<[u128, u128]>]> & QueryableStorageEntry]>; /** * Foreign admin account **/ - foreignAdmin: AugmentedQuery Observable, []> & QueryableStorageEntry; + foreignAdmin: AugmentedQuery Observable>, []> & QueryableStorageEntry; + /** + * Mapping foreign asset to foreign location. + **/ + foreignAssetLocation: AugmentedQuery Observable>, [u128]> & QueryableStorageEntry; + /** + * Mapping local asset to foreign asset metadata. + **/ + foreignAssetMetadata: AugmentedQuery Observable>, [u128]> & QueryableStorageEntry; /** * Mapping foreign asset to local asset. **/ - foreignToLocal: AugmentedQuery Observable>, [ComposableTraitsAssetsXcmAssetLocation]> & QueryableStorageEntry; + foreignToLocal: AugmentedQuery Observable>, [u128]> & QueryableStorageEntry; + /** + * Mapping foreign location to foreign asset. + **/ + fromForeignAssetLocation: AugmentedQuery Observable>, [ComposableTraitsAssetsXcmAssetLocation]> & QueryableStorageEntry; /** * Local admin account **/ - localAdmin: AugmentedQuery Observable, []> & QueryableStorageEntry; + localAdmin: AugmentedQuery Observable>, []> & QueryableStorageEntry; /** * Mapping local asset to foreign asset. **/ - localToForeign: AugmentedQuery Observable>, [u128]> & QueryableStorageEntry; + localToForeign: AugmentedQuery Observable>, [u128]> & QueryableStorageEntry; /** * Generic query **/ @@ -80,8 +92,29 @@ declare module '@polkadot/api-base/types/storage' { }; balances: { /** - * The balance of an account. + * The Balances pallet example of storing the balance of an account. + * + * # Example * + * ```nocompile + * impl pallet_balances::Config for Runtime { + * type AccountStore = StorageMapShim, frame_system::Provider, AccountId, Self::AccountData> + * } + * ``` + * + * You can also store the balance of an account in the `System` pallet. + * + * # Example + * + * ```nocompile + * impl pallet_balances::Config for Runtime { + * type AccountStore = System + * } + * ``` + * + * But this comes with tradeoffs, storing account balances in the system pallet stores + * `frame_system` data alongside the account data contrary to storing account balances in the + * `Balances` pallet, which uses a `StorageMap` to store balances data only. * NOTE: This is only used in the case that this pallet is used to store balances. **/ account: AugmentedQuery Observable, [AccountId32]> & QueryableStorageEntry; @@ -113,11 +146,11 @@ declare module '@polkadot/api-base/types/storage' { /** * The counter used to uniquely identify bond offers within this pallet. **/ - bondOfferCount: AugmentedQuery Observable, []> & QueryableStorageEntry; + bondOfferCount: AugmentedQuery Observable, []> & QueryableStorageEntry; /** * A mapping from offer ID to the pair: (issuer, offer) **/ - bondOffers: AugmentedQuery Observable>>, [u64]> & QueryableStorageEntry; + bondOffers: AugmentedQuery Observable>>, [u128]> & QueryableStorageEntry; /** * Generic query **/ @@ -126,8 +159,6 @@ declare module '@polkadot/api-base/types/storage' { callFilter: { /** * The list of disabled extrinsics. - * - * CallFilterEntry -> () **/ disabledCalls: AugmentedQuery Observable>, [ComposableTraitsCallFilterCallFilterEntry]> & QueryableStorageEntry; /** @@ -137,7 +168,9 @@ declare module '@polkadot/api-base/types/storage' { }; collatorSelection: { /** - * Fixed deposit bond for each candidate. + * Fixed amount to deposit to become a collator. + * + * When a collator calls `leave_intent` they immediately receive the deposit back. **/ candidacyBond: AugmentedQuery Observable, []> & QueryableStorageEntry; /** @@ -163,6 +196,20 @@ declare module '@polkadot/api-base/types/storage' { **/ [key: string]: QueryableStorageEntry; }; + constantProductDex: { + /** + * Current number of pools (also ID for the next created pool) + **/ + poolCount: AugmentedQuery Observable, []> & QueryableStorageEntry; + /** + * Existing pools + **/ + pools: AugmentedQuery Observable>, [u128]> & QueryableStorageEntry; + /** + * Generic query + **/ + [key: string]: QueryableStorageEntry; + }; council: { /** * The current members of the collective. This is stored sorted (just by value). @@ -216,7 +263,7 @@ declare module '@polkadot/api-base/types/storage' { * The rewards claimed so far. **/ claimedRewards: AugmentedQuery Observable, []> & QueryableStorageEntry; - rewards: AugmentedQuery Observable>, [PalletCrowdloanRewardsModelsRemoteAccount]> & QueryableStorageEntry; + rewards: AugmentedQuery Observable>, [PalletCrowdloanRewardsModelsRemoteAccount]> & QueryableStorageEntry; /** * The total number of contributors. **/ @@ -228,7 +275,14 @@ declare module '@polkadot/api-base/types/storage' { /** * The block at which the users are able to claim their rewards. **/ - vestingBlockStart: AugmentedQuery Observable>, []> & QueryableStorageEntry; + vestingTimeStart: AugmentedQuery Observable>, []> & QueryableStorageEntry; + /** + * Generic query + **/ + [key: string]: QueryableStorageEntry; + }; + currencyFactory: { + assetIdRanges: AugmentedQuery Observable, []> & QueryableStorageEntry; /** * Generic query **/ @@ -255,13 +309,6 @@ declare module '@polkadot/api-base/types/storage' { * proposal. **/ lastTabledWasExternal: AugmentedQuery Observable, []> & QueryableStorageEntry; - /** - * Accounts for which there are locks in action which may be removed at some point in the - * future. The value is the block number at which the lock expires and may be removed. - * - * TWOX-NOTE: OK ― `AccountId` is a secure hash. - **/ - locks: AugmentedQuery Observable>, [AccountId32]> & QueryableStorageEntry; /** * The lowest referendum index representing an unbaked referendum. Equal to * `ReferendumCount` if there isn't a unbaked referendum. @@ -350,16 +397,6 @@ declare module '@polkadot/api-base/types/storage' { **/ [key: string]: QueryableStorageEntry; }; - factory: { - /** - * The counter that track the latest generated currency id. - **/ - currencyCounter: AugmentedQuery Observable, []> & QueryableStorageEntry; - /** - * Generic query - **/ - [key: string]: QueryableStorageEntry; - }; governanceRegistry: { originsByAssetId: AugmentedQuery Observable>, [u128]> & QueryableStorageEntry; /** @@ -409,6 +446,84 @@ declare module '@polkadot/api-base/types/storage' { **/ [key: string]: QueryableStorageEntry; }; + lending: { + /** + * (Market, Account) -> Collateral + **/ + accountCollateral: AugmentedQuery Observable>, [u32, AccountId32]> & QueryableStorageEntry; + /** + * market borrow index + **/ + borrowIndex: AugmentedQuery Observable, [u32]> & QueryableStorageEntry; + borrowRent: AugmentedQuery Observable>, [u32, AccountId32]> & QueryableStorageEntry; + /** + * Latest timestamp at which account borrowed from market. + **/ + borrowTimestamp: AugmentedQuery Observable>, [u32, AccountId32]> & QueryableStorageEntry; + /** + * at which lending index account did borrowed. + **/ + debtIndex: AugmentedQuery Observable>, [u32, AccountId32]> & QueryableStorageEntry; + /** + * Original debt values are on balances. + * Debt token allows to simplify some debt management and implementation of features + **/ + debtMarkets: AugmentedQuery Observable, [u32]> & QueryableStorageEntry; + /** + * The timestamp of the previous block or defaults to timestamp at genesis. + **/ + lastBlockTimestamp: AugmentedQuery Observable, []> & QueryableStorageEntry; + /** + * Lending instances counter + **/ + lendingCount: AugmentedQuery Observable, []> & QueryableStorageEntry; + /** + * Indexed lending instances + **/ + markets: AugmentedQuery Observable>, [u32]> & QueryableStorageEntry; + /** + * Generic query + **/ + [key: string]: QueryableStorageEntry; + }; + liquidations: { + defaultStrategyIndex: AugmentedQuery Observable, []> & QueryableStorageEntry; + strategies: AugmentedQuery Observable>, [u32]> & QueryableStorageEntry; + strategyIndex: AugmentedQuery Observable, []> & QueryableStorageEntry; + /** + * Generic query + **/ + [key: string]: QueryableStorageEntry; + }; + liquidityBootstrapping: { + poolCount: AugmentedQuery Observable, []> & QueryableStorageEntry; + pools: AugmentedQuery Observable>, [u128]> & QueryableStorageEntry; + /** + * Generic query + **/ + [key: string]: QueryableStorageEntry; + }; + mosaic: { + assetsInfo: AugmentedQuery Observable>, [u128]> & QueryableStorageEntry; + /** + * Locked incoming tx into Picasso that the user needs to claim. + **/ + incomingTransactions: AugmentedQuery Observable>>, [AccountId32, u128]> & QueryableStorageEntry; + localToRemoteAsset: AugmentedQuery Observable>, [u128, u32]> & QueryableStorageEntry; + networkInfos: AugmentedQuery Observable>, [u32]> & QueryableStorageEntry; + nonce: AugmentedQuery Observable, []> & QueryableStorageEntry; + /** + * Locked outgoing tx out of Picasso, that a relayer needs to process. + **/ + outgoingTransactions: AugmentedQuery Observable>>, [AccountId32, u128]> & QueryableStorageEntry; + relayer: AugmentedQuery Observable>, []> & QueryableStorageEntry; + remoteToLocalAsset: AugmentedQuery Observable>, [CommonMosaicRemoteAssetId, u32]> & QueryableStorageEntry; + timeLockPeriod: AugmentedQuery Observable, []> & QueryableStorageEntry; + /** + * Generic query + **/ + [key: string]: QueryableStorageEntry; + }; multisig: { calls: AugmentedQuery Observable, AccountId32, u128]>>>, [U8aFixed]> & QueryableStorageEntry; /** @@ -452,11 +567,11 @@ declare module '@polkadot/api-base/types/storage' { /** * Price for an asset and blocknumber asset was updated at **/ - priceHistory: AugmentedQuery Observable>, [u128]> & QueryableStorageEntry; + priceHistory: AugmentedQuery Observable>, [u128]> & QueryableStorageEntry; /** * Price for an asset and blocknumber asset was updated at **/ - prices: AugmentedQuery Observable, [u128]> & QueryableStorageEntry; + prices: AugmentedQuery Observable, [u128]> & QueryableStorageEntry; /** * Mapping signing key to controller key **/ @@ -483,6 +598,12 @@ declare module '@polkadot/api-base/types/storage' { * The next authorized upgrade, if there is one. **/ authorizedUpgrade: AugmentedQuery Observable>, []> & QueryableStorageEntry; + /** + * A custom head data that should be returned as result of `validate_block`. + * + * See [`Pallet::set_custom_validation_head_data`] for more information. + **/ + customValidationHeadData: AugmentedQuery Observable>, []> & QueryableStorageEntry; /** * Were the validation data set to notify the relay chain? **/ @@ -596,6 +717,20 @@ declare module '@polkadot/api-base/types/storage' { **/ [key: string]: QueryableStorageEntry; }; + preimage: { + /** + * The preimages stored by this pallet. + **/ + preimageFor: AugmentedQuery Observable>, [H256]> & QueryableStorageEntry; + /** + * The request status of a given hash. + **/ + statusFor: AugmentedQuery Observable>, [H256]> & QueryableStorageEntry; + /** + * Generic query + **/ + [key: string]: QueryableStorageEntry; + }; randomnessCollectiveFlip: { /** * Series of block headers from the last 81 blocks that acts as random seed material. This @@ -612,17 +747,11 @@ declare module '@polkadot/api-base/types/storage' { /** * Items to be executed, indexed by the block number that they should be executed on. **/ - agenda: AugmentedQuery Observable>>, [u32]> & QueryableStorageEntry; + agenda: AugmentedQuery Observable>>, [u32]> & QueryableStorageEntry; /** * Lookup from identity to the block number and index of the task. **/ lookup: AugmentedQuery Observable>>, [Bytes]> & QueryableStorageEntry; - /** - * Storage version of the pallet. - * - * New networks start with last version. - **/ - storageVersion: AugmentedQuery Observable, []> & QueryableStorageEntry; /** * Generic query **/ @@ -668,11 +797,25 @@ declare module '@polkadot/api-base/types/storage' { **/ [key: string]: QueryableStorageEntry; }; + stableSwapDex: { + /** + * Current number of pools (also ID for the next created pool) + **/ + poolCount: AugmentedQuery Observable, []> & QueryableStorageEntry; + /** + * Existing pools + **/ + pools: AugmentedQuery Observable>, [u128]> & QueryableStorageEntry; + /** + * Generic query + **/ + [key: string]: QueryableStorageEntry; + }; sudo: { /** * The `AccountId` of the sudo key. **/ - key: AugmentedQuery Observable, []> & QueryableStorageEntry; + key: AugmentedQuery Observable>, []> & QueryableStorageEntry; /** * Generic query **/ @@ -892,7 +1035,7 @@ declare module '@polkadot/api-base/types/storage' { /** * Status of the inbound XCMP channels. **/ - inboundXcmpStatus: AugmentedQuery Observable>]>>>, []> & QueryableStorageEntry; + inboundXcmpStatus: AugmentedQuery Observable>, []> & QueryableStorageEntry; /** * The messages outbound in a given XCMP channel. **/ @@ -905,11 +1048,27 @@ declare module '@polkadot/api-base/types/storage' { * case of the need to send a high-priority signal message this block. * The bool is true if there is a signal message waiting to be sent. **/ - outboundXcmpStatus: AugmentedQuery Observable>>, []> & QueryableStorageEntry; + outboundXcmpStatus: AugmentedQuery Observable>, []> & QueryableStorageEntry; + /** + * The messages that exceeded max individual message weight budget. + * + * These message stay in this storage map until they are manually dispatched via + * `service_overweight`. + **/ + overweight: AugmentedQuery Observable>>, [u64]> & QueryableStorageEntry; + /** + * The number of overweight messages ever recorded in `Overweight`. Also doubles as the next + * available free overweight index. + **/ + overweightCount: AugmentedQuery Observable, []> & QueryableStorageEntry; /** * The configuration which controls the dynamics of the outbound queue. **/ queueConfig: AugmentedQuery Observable, []> & QueryableStorageEntry; + /** + * Whether or not the XCMP queue is suspended from executing incoming XCMs or not. + **/ + queueSuspended: AugmentedQuery Observable, []> & QueryableStorageEntry; /** * Any signal messages waiting to be sent. **/ diff --git a/integration-tests/runtime-tests/src/types/interfaces/augment-api-rpc.ts b/integration-tests/runtime-tests/src/types/interfaces/augment-api-rpc.ts index 0c7a5cc5d17..fac6ea908e6 100644 --- a/integration-tests/runtime-tests/src/types/interfaces/augment-api-rpc.ts +++ b/integration-tests/runtime-tests/src/types/interfaces/augment-api-rpc.ts @@ -1,6 +1,7 @@ // Auto-generated via `yarn polkadot-types-from-chain`, do not edit /* eslint-disable */ +import type { AssetsBalance, CurrencyId } from '@composable/types/interfaces/assets'; import type { AugmentedRpc } from '@polkadot/rpc-core/types'; import type { Metadata, StorageKey } from '@polkadot/types'; import type { Bytes, HashMap, Json, Null, Option, Text, U256, U64, Vec, bool, u32, u64 } from '@polkadot/types-codec'; @@ -11,7 +12,7 @@ import type { BeefySignedCommitment } from '@polkadot/types/interfaces/beefy'; import type { BlockHash } from '@polkadot/types/interfaces/chain'; import type { PrefixedStorageKey } from '@polkadot/types/interfaces/childstate'; import type { AuthorityId } from '@polkadot/types/interfaces/consensus'; -import type { ContractCallRequest, ContractExecResult, ContractInstantiateResult, InstantiateRequest } from '@polkadot/types/interfaces/contracts'; +import type { CodeUploadRequest, CodeUploadResult, ContractCallRequest, ContractExecResult, ContractInstantiateResult, InstantiateRequest } from '@polkadot/types/interfaces/contracts'; import type { CreatedBlock } from '@polkadot/types/interfaces/engine'; import type { EthAccount, EthCallRequest, EthFilter, EthFilterChanges, EthLog, EthReceipt, EthRichBlock, EthSubKind, EthSubParams, EthSyncStatus, EthTransaction, EthTransactionRequest, EthWork } from '@polkadot/types/interfaces/eth'; import type { Extrinsic } from '@polkadot/types/interfaces/extrinsics'; @@ -20,13 +21,19 @@ import type { MmrLeafProof } from '@polkadot/types/interfaces/mmr'; import type { StorageKind } from '@polkadot/types/interfaces/offchain'; import type { FeeDetails, RuntimeDispatchInfo } from '@polkadot/types/interfaces/payment'; import type { RpcMethods } from '@polkadot/types/interfaces/rpc'; -import type { AccountId, BlockNumber, H160, H256, H64, Hash, Header, Index, Justification, KeyValue, SignedBlock, StorageData } from '@polkadot/types/interfaces/runtime'; +import type { AccountId, AccountId32, Balance, BlockNumber, H160, H256, H64, Hash, Header, Index, Justification, KeyValue, SignedBlock, StorageData } from '@polkadot/types/interfaces/runtime'; import type { ReadProof, RuntimeVersion, TraceBlockResponse } from '@polkadot/types/interfaces/state'; import type { ApplyExtrinsicResult, ChainProperties, ChainType, Health, NetworkState, NodeRole, PeerInfo, SyncState } from '@polkadot/types/interfaces/system'; import type { IExtrinsic, Observable } from '@polkadot/types/types'; declare module '@polkadot/rpc-core/types/jsonrpc' { export interface RpcInterface { + assets: { + /** + * Balance available for the specified account for the specified asset. + **/ + balanceOf: AugmentedRpc<(asset: CurrencyId | AnyNumber | Uint8Array, account: AccountId32 | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable>; + }; author: { /** * Returns true if the keystore has private keys for the given public key and key type. @@ -68,6 +75,10 @@ declare module '@polkadot/rpc-core/types/jsonrpc' { epochAuthorship: AugmentedRpc<() => Observable>>; }; beefy: { + /** + * Returns hash of the latest BEEFY finalized block as seen by this client. + **/ + getFinalizedHead: AugmentedRpc<() => Observable>; /** * Returns the block most recently finalized by BEEFY, alongside side its justification. **/ @@ -146,6 +157,16 @@ declare module '@polkadot/rpc-core/types/jsonrpc' { * Returns the projected time a given contract will be able to sustain paying its rent **/ rentProjection: AugmentedRpc<(address: AccountId | string | Uint8Array, at?: BlockHash | string | Uint8Array) => Observable>>; + /** + * Upload new code without instantiating a contract from it + **/ + uploadCode: AugmentedRpc<(uploadRequest: CodeUploadRequest | { origin?: any; code?: any; storageDepositLimit?: any } | string | Uint8Array, at?: BlockHash | string | Uint8Array) => Observable>; + }; + crowdloanRewards: { + /** + * The unclaimed amount + **/ + amountAvailableToClaimFor: AugmentedRpc<(accountId: AccountId | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable>; }; engine: { /** @@ -325,9 +346,9 @@ declare module '@polkadot/rpc-core/types/jsonrpc' { }; grandpa: { /** - * Prove finality for the range (begin; end] hash. + * Prove finality for the given block number, returning the Justification for the last block in the set. **/ - proveFinality: AugmentedRpc<(begin: BlockHash | string | Uint8Array, end: BlockHash | string | Uint8Array, authoritiesSetId?: u64 | AnyNumber | Uint8Array) => Observable>>; + proveFinality: AugmentedRpc<(blockNumber: BlockNumber | AnyNumber | Uint8Array) => Observable>>; /** * Returns the state of the current best round state as well as the ongoing background rounds **/ diff --git a/integration-tests/runtime-tests/src/types/interfaces/augment-api-tx.ts b/integration-tests/runtime-tests/src/types/interfaces/augment-api-tx.ts index 061463026f4..47e80d25587 100644 --- a/integration-tests/runtime-tests/src/types/interfaces/augment-api-tx.ts +++ b/integration-tests/runtime-tests/src/types/interfaces/augment-api-tx.ts @@ -1,12 +1,12 @@ // Auto-generated via `yarn polkadot-types-from-chain`, do not edit /* eslint-disable */ -import type { ComposableTraitsAssetsXcmAssetLocation, ComposableTraitsBondedFinanceBondOffer, ComposableTraitsCallFilterCallFilterEntry, ComposableTraitsDefiSell, ComposableTraitsDefiTake, ComposableTraitsTimeTimeReleaseFunction, ComposableTraitsVaultVaultConfig, ComposableTraitsVestingVestingSchedule, CumulusPrimitivesParachainInherentParachainInherentData, DaliRuntimeOpaqueSessionKeys, DaliRuntimeOriginCaller, PalletCrowdloanRewardsModelsProof, PalletCrowdloanRewardsModelsRemoteAccount, PalletDemocracyConviction, PalletDemocracyVoteAccountVote, PalletIdentityBitFlags, PalletIdentityIdentityInfo, PalletIdentityJudgement, XcmVersionedMultiAsset } from '@composable/types/interfaces/default'; +import type { CommonMosaicRemoteAssetId, ComposableTraitsAssetsXcmAssetLocation, ComposableTraitsBondedFinanceBondOffer, ComposableTraitsCallFilterCallFilterEntry, ComposableTraitsDefiCurrencyPair, ComposableTraitsDefiSell, ComposableTraitsDefiTake, ComposableTraitsLendingCreateInput, ComposableTraitsLendingUpdateInput, ComposableTraitsTimeTimeReleaseFunction, ComposableTraitsVaultVaultConfig, ComposableTraitsVestingVestingSchedule, CumulusPrimitivesParachainInherentParachainInherentData, DaliRuntimeOpaqueSessionKeys, DaliRuntimeOriginCaller, FrameSupportScheduleMaybeHashed, PalletAssetsRegistryForeignMetadata, PalletCrowdloanRewardsModelsProof, PalletCrowdloanRewardsModelsRemoteAccount, PalletDemocracyConviction, PalletDemocracyVoteAccountVote, PalletIdentityBitFlags, PalletIdentityIdentityInfo, PalletIdentityJudgement, PalletLiquidationsLiquidationStrategyConfiguration, PalletLiquidityBootstrappingPool, PalletMosaicDecayBudgetPenaltyDecayer, PalletMosaicNetworkInfo, XcmVersionedMultiAsset } from '@composable/types/interfaces/crowdloanRewards'; import type { ApiTypes } from '@polkadot/api-base/types'; import type { Data } from '@polkadot/types'; import type { Bytes, Compact, Option, U8aFixed, Vec, WrapperKeepOpaque, bool, u128, u16, u32, u64, u8 } from '@polkadot/types-codec'; import type { AnyNumber, ITuple } from '@polkadot/types-codec/types'; -import type { AccountId32, Call, H256, MultiAddress, Perbill, Percent } from '@polkadot/types/interfaces/runtime'; +import type { AccountId32, Call, H256, MultiAddress, Perbill, Percent, Permill } from '@polkadot/types/interfaces/runtime'; import type { PalletMultisigTimepoint, SpRuntimeHeader, XcmV1MultiLocation, XcmV2WeightLimit, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup'; declare module '@polkadot/api-base/types/submittable' { @@ -95,9 +95,10 @@ declare module '@polkadot/api-base/types/submittable' { [key: string]: SubmittableExtrinsicFunction; }; assetsRegistry: { - approveAssetsMappingCandidate: AugmentedSubmittable<(localAssetId: u128 | AnyNumber | Uint8Array, foreignAssetId: ComposableTraitsAssetsXcmAssetLocation | { parents?: any; interior?: any } | string | Uint8Array) => SubmittableExtrinsic, [u128, ComposableTraitsAssetsXcmAssetLocation]>; + approveAssetsMappingCandidate: AugmentedSubmittable<(localAssetId: u128 | AnyNumber | Uint8Array, foreignAssetId: u128 | AnyNumber | Uint8Array, location: ComposableTraitsAssetsXcmAssetLocation | { parents?: any; interior?: any } | string | Uint8Array, decimals: u8 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u128, u128, ComposableTraitsAssetsXcmAssetLocation, u8]>; setForeignAdmin: AugmentedSubmittable<(foreignAdmin: AccountId32 | string | Uint8Array) => SubmittableExtrinsic, [AccountId32]>; setLocalAdmin: AugmentedSubmittable<(localAdmin: AccountId32 | string | Uint8Array) => SubmittableExtrinsic, [AccountId32]>; + setMetadata: AugmentedSubmittable<(localAssetId: u128 | AnyNumber | Uint8Array, metadata: PalletAssetsRegistryForeignMetadata | { decimals?: any } | string | Uint8Array) => SubmittableExtrinsic, [u128, PalletAssetsRegistryForeignMetadata]>; /** * Generic tx **/ @@ -133,7 +134,7 @@ declare module '@polkadot/api-base/types/submittable' { * Set the balances of a given account. * * This will alter `FreeBalance` and `ReservedBalance` in storage. it will - * also decrease the total issuance of the system (`TotalIssuance`). + * also alter the total issuance of the system (`TotalIssuance`) appropriately. * If the new free or reserved balance is below the existential deposit, * it will reset the account nonce (`frame_system::AccountNonce`). * @@ -144,7 +145,6 @@ declare module '@polkadot/api-base/types/submittable' { * Transfer some liquid free balance to another account. * * `transfer` will set the `FreeBalance` of the sender and receiver. - * It will decrease the total issuance of the system by the `TransferFee`. * If the sender's account is below the existential deposit as a result * of the transfer, the account will be reaped. * @@ -206,31 +206,39 @@ declare module '@polkadot/api-base/types/submittable' { bondedFinance: { /** * Bond to an offer. + * And user should provide the number of contracts she is willing to buy. + * On offer completion (a.k.a. no more contract on the offer), the `stake` put by the + * creator is refunded. * * The dispatch origin for this call must be _Signed_ and the sender must have the * appropriate funds. * + * Allow the bonder to ask for his account to be kept alive using the `keep_alive` + * parameter. + * * Emits a `NewBond`. * Possibily Emits a `OfferCompleted`. **/ - bond: AugmentedSubmittable<(offerId: u64 | AnyNumber | Uint8Array, nbOfBonds: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u64, u128]>; + bond: AugmentedSubmittable<(offerId: u128 | AnyNumber | Uint8Array, nbOfBonds: u128 | AnyNumber | Uint8Array, keepAlive: bool | boolean | Uint8Array) => SubmittableExtrinsic, [u128, u128, bool]>; /** - * Cancel an offer. - * + * Cancel a running offer. Blocking further bond but not cancelling the + * currently vested rewards. The `stake` put by the creator is refunded. * The dispatch origin for this call must be _Signed_ and the sender must be `AdminOrigin` * * Emits a `OfferCancelled`. **/ - cancel: AugmentedSubmittable<(offerId: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u64]>; + cancel: AugmentedSubmittable<(offerId: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u128]>; /** - * Create a new offer. + * Create a new offer. So later can `bond` it. * * The dispatch origin for this call must be _Signed_ and the sender must have the * appropriate funds. + * Allow the issuer to ask for his account to be kept alive using the `keep_alive` + * parameter. * * Emits a `NewOffer`. **/ - offer: AugmentedSubmittable<(offer: ComposableTraitsBondedFinanceBondOffer | { beneficiary?: any; asset?: any; bondPrice?: any; nbOfBonds?: any; maturity?: any; reward?: any } | string | Uint8Array) => SubmittableExtrinsic, [ComposableTraitsBondedFinanceBondOffer]>; + offer: AugmentedSubmittable<(offer: ComposableTraitsBondedFinanceBondOffer | { beneficiary?: any; asset?: any; bondPrice?: any; nbOfBonds?: any; maturity?: any; reward?: any } | string | Uint8Array, keepAlive: bool | boolean | Uint8Array) => SubmittableExtrinsic, [ComposableTraitsBondedFinanceBondOffer, bool]>; /** * Generic tx **/ @@ -261,16 +269,92 @@ declare module '@polkadot/api-base/types/submittable' { [key: string]: SubmittableExtrinsicFunction; }; collatorSelection: { + /** + * Deregister `origin` as a collator candidate. Note that the collator can only leave on + * session change. The `CandidacyBond` will be unreserved immediately. + * + * This call will fail if the total number of candidates would drop below `MinCandidates`. + * + * This call is not available to `Invulnerable` collators. + **/ leaveIntent: AugmentedSubmittable<() => SubmittableExtrinsic, []>; + /** + * Register this account as a collator candidate. The account must (a) already have + * registered session keys and (b) be able to reserve the `CandidacyBond`. + * + * This call is not available to `Invulnerable` collators. + **/ registerAsCandidate: AugmentedSubmittable<() => SubmittableExtrinsic, []>; + /** + * Set the candidacy bond amount. + **/ setCandidacyBond: AugmentedSubmittable<(bond: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u128]>; + /** + * Set the ideal number of collators (not including the invulnerables). + * If lowering this number, then the number of running collators could be higher than this figure. + * Aside from that edge case, there should be no other way to have more collators than the desired number. + **/ setDesiredCandidates: AugmentedSubmittable<(max: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u32]>; + /** + * Set the list of invulnerable (fixed) collators. + **/ setInvulnerables: AugmentedSubmittable<(updated: Vec | (AccountId32 | string | Uint8Array)[]) => SubmittableExtrinsic, [Vec]>; /** * Generic tx **/ [key: string]: SubmittableExtrinsicFunction; }; + constantProductDex: { + /** + * Add liquidity to a constant_product pool. + * + * Emits `LiquidityAdded` event when successful. + **/ + addLiquidity: AugmentedSubmittable<(poolId: u128 | AnyNumber | Uint8Array, baseAmount: u128 | AnyNumber | Uint8Array, quoteAmount: u128 | AnyNumber | Uint8Array, minMintAmount: u128 | AnyNumber | Uint8Array, keepAlive: bool | boolean | Uint8Array) => SubmittableExtrinsic, [u128, u128, u128, u128, bool]>; + /** + * Execute a buy order on a pool. + * + * The `base_amount` always represent the base asset amount (A/B => A). + * + * Emits `Swapped` event when successful. + **/ + buy: AugmentedSubmittable<(poolId: u128 | AnyNumber | Uint8Array, assetId: u128 | AnyNumber | Uint8Array, amount: u128 | AnyNumber | Uint8Array, keepAlive: bool | boolean | Uint8Array) => SubmittableExtrinsic, [u128, u128, u128, bool]>; + /** + * Create a new pool. + * + * Emits `PoolCreated` even when successful. + **/ + create: AugmentedSubmittable<(pair: ComposableTraitsDefiCurrencyPair | { base?: any; quote?: any } | string | Uint8Array, fee: Permill | AnyNumber | Uint8Array, ownerFee: Permill | AnyNumber | Uint8Array) => SubmittableExtrinsic, [ComposableTraitsDefiCurrencyPair, Permill, Permill]>; + /** + * Remove liquidity from constant_product pool. + * + * Emits `LiquidityRemoved` event when successful. + **/ + removeLiquidity: AugmentedSubmittable<(poolId: u128 | AnyNumber | Uint8Array, lpAmount: u128 | AnyNumber | Uint8Array, minBaseAmount: u128 | AnyNumber | Uint8Array, minQuoteAmount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u128, u128, u128, u128]>; + /** + * Execute a sell order on a pool. + * + * The `base_amount` always represent the base asset amount (A/B => A). + * + * Emits `Swapped` event when successful. + **/ + sell: AugmentedSubmittable<(poolId: u128 | AnyNumber | Uint8Array, assetId: u128 | AnyNumber | Uint8Array, amount: u128 | AnyNumber | Uint8Array, keepAlive: bool | boolean | Uint8Array) => SubmittableExtrinsic, [u128, u128, u128, bool]>; + /** + * Execute a specific swap operation. + * + * Buy operation if the pair is the original pool pair (A/B). + * Sell operation if the pair is the original pool pair swapped (B/A). + * + * The `quote_amount` is always the quote asset amount (A/B => B), (B/A => A). + * + * Emits `Swapped` event when successful. + **/ + swap: AugmentedSubmittable<(poolId: u128 | AnyNumber | Uint8Array, pair: ComposableTraitsDefiCurrencyPair | { base?: any; quote?: any } | string | Uint8Array, quoteAmount: u128 | AnyNumber | Uint8Array, minReceive: u128 | AnyNumber | Uint8Array, keepAlive: bool | boolean | Uint8Array) => SubmittableExtrinsic, [u128, ComposableTraitsDefiCurrencyPair, u128, u128, bool]>; + /** + * Generic tx + **/ + [key: string]: SubmittableExtrinsicFunction; + }; council: { /** * Close a vote that is either approved, disapproved or whose voting period has ended. @@ -502,12 +586,16 @@ declare module '@polkadot/api-base/types/submittable' { * Initialize the pallet at the current transaction block. **/ initialize: AugmentedSubmittable<() => SubmittableExtrinsic, []>; + /** + * Initialize the pallet at the given transaction block. + **/ + initializeAt: AugmentedSubmittable<(at: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u64]>; /** * Populate pallet by adding more rewards. * Can be called multiple times. Idempotent. * Can only be called before `initialize`. **/ - populate: AugmentedSubmittable<(rewards: Vec> | ([PalletCrowdloanRewardsModelsRemoteAccount | { RelayChain: any } | { Ethereum: any } | string | Uint8Array, u128 | AnyNumber | Uint8Array, u32 | AnyNumber | Uint8Array])[]) => SubmittableExtrinsic, [Vec>]>; + populate: AugmentedSubmittable<(rewards: Vec> | ([PalletCrowdloanRewardsModelsRemoteAccount | { RelayChain: any } | { Ethereum: any } | string | Uint8Array, u128 | AnyNumber | Uint8Array, u64 | AnyNumber | Uint8Array])[]) => SubmittableExtrinsic, [Vec>]>; /** * Generic tx **/ @@ -1296,6 +1384,209 @@ declare module '@polkadot/api-base/types/submittable' { **/ [key: string]: SubmittableExtrinsicFunction; }; + lending: { + /** + * Borrow asset against deposited collateral. + * - `origin` : Sender of this extrinsic. (Also the user who wants to borrow from market.) + * - `market_id` : Market index from which user wants to borrow. + * - `amount_to_borrow` : Amount which user wants to borrow. + **/ + borrow: AugmentedSubmittable<(marketId: u32 | AnyNumber | Uint8Array, amountToBorrow: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u32, u128]>; + /** + * Create a new lending market. + * - `origin` : Sender of this extrinsic. Manager for new market to be created. Can pause + * borrow operations. + * - `input` : Borrow & deposits of assets, persentages. + * + * `origin` irreversibly pays `T::OracleMarketCreationStake`. + **/ + createMarket: AugmentedSubmittable<(input: ComposableTraitsLendingCreateInput | { updatable?: any; currencyPair?: any; reservedFactor?: any } | string | Uint8Array) => SubmittableExtrinsic, [ComposableTraitsLendingCreateInput]>; + /** + * Deposit collateral to market. + * - `origin` : Sender of this extrinsic. + * - `market` : Market index to which collateral will be deposited. + * - `amount` : Amount of collateral to be deposited. + **/ + depositCollateral: AugmentedSubmittable<(marketId: u32 | AnyNumber | Uint8Array, amount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u32, u128]>; + /** + * Check if borrow for `borrower` account is required to be liquidated, initiate + * liquidation. + * - `origin` : Sender of this extrinsic. + * - `market_id` : Market index from which `borrower` has taken borrow. + **/ + liquidate: AugmentedSubmittable<(marketId: u32 | AnyNumber | Uint8Array, borrowers: Vec | (AccountId32 | string | Uint8Array)[]) => SubmittableExtrinsic, [u32, Vec]>; + /** + * Repay borrow for beneficiary account. + * - `origin` : Sender of this extrinsic. (Also the user who repays beneficiary's borrow.) + * - `market_id` : Market index to which user wants to repay borrow. + * - `beneficiary` : AccountId which has borrowed asset. (This can be same or different + * than + * origin). + * - `repay_amount` : Amount which user wants to borrow. + **/ + repayBorrow: AugmentedSubmittable<(marketId: u32 | AnyNumber | Uint8Array, beneficiary: AccountId32 | string | Uint8Array, repayAmount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u32, AccountId32, u128]>; + /** + * owner must be very careful calling this + **/ + updateMarket: AugmentedSubmittable<(marketId: u32 | AnyNumber | Uint8Array, input: ComposableTraitsLendingUpdateInput | { collateralFactor?: any; underCollaterizedWarnPercent?: any; liquidators?: any; interestRateModel?: any } | string | Uint8Array) => SubmittableExtrinsic, [u32, ComposableTraitsLendingUpdateInput]>; + /** + * Withdraw collateral from market. + * - `origin` : Sender of this extrinsic. + * - `market_id` : Market index from which collateral will be withdraw. + * - `amount` : Amount of collateral to be withdrawed. + **/ + withdrawCollateral: AugmentedSubmittable<(marketId: u32 | AnyNumber | Uint8Array, amount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u32, u128]>; + /** + * Generic tx + **/ + [key: string]: SubmittableExtrinsicFunction; + }; + liquidations: { + addLiquidationStrategy: AugmentedSubmittable<(configuraiton: PalletLiquidationsLiquidationStrategyConfiguration | { DutchAuction: any } | { UniswapV2: any } | { XcmDex: any } | string | Uint8Array) => SubmittableExtrinsic, [PalletLiquidationsLiquidationStrategyConfiguration]>; + /** + * Generic tx + **/ + [key: string]: SubmittableExtrinsicFunction; + }; + liquidityBootstrapping: { + /** + * Add liquidity to an LBP pool. + * + * Only possible before the sale started. + * + * Emits `LiquidityAdded` event when successful. + **/ + addLiquidity: AugmentedSubmittable<(poolId: u128 | AnyNumber | Uint8Array, baseAmount: u128 | AnyNumber | Uint8Array, quoteAmount: u128 | AnyNumber | Uint8Array, keepAlive: bool | boolean | Uint8Array) => SubmittableExtrinsic, [u128, u128, u128, bool]>; + /** + * Execute a buy order on a pool. + * + * Emits `Swapped` event when successful. + **/ + buy: AugmentedSubmittable<(poolId: u128 | AnyNumber | Uint8Array, assetId: u128 | AnyNumber | Uint8Array, amount: u128 | AnyNumber | Uint8Array, keepAlive: bool | boolean | Uint8Array) => SubmittableExtrinsic, [u128, u128, u128, bool]>; + /** + * Create a new pool. + * + * Emits `PoolCreated` event when successful. + **/ + create: AugmentedSubmittable<(pool: PalletLiquidityBootstrappingPool | { owner?: any; pair?: any; sale?: any; fee?: any } | string | Uint8Array) => SubmittableExtrinsic, [PalletLiquidityBootstrappingPool]>; + /** + * Withdraw the remaining liquidity and destroy the pool. + * + * Emits `PoolDeleted` event when successful. + **/ + removeLiquidity: AugmentedSubmittable<(poolId: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u128]>; + /** + * Execute a sell order on a pool. + * + * Emits `Swapped` event when successful. + **/ + sell: AugmentedSubmittable<(poolId: u128 | AnyNumber | Uint8Array, assetId: u128 | AnyNumber | Uint8Array, amount: u128 | AnyNumber | Uint8Array, keepAlive: bool | boolean | Uint8Array) => SubmittableExtrinsic, [u128, u128, u128, bool]>; + /** + * Execute a specific swap operation. + * + * Buy operation if the pair is the original pool pair (A/B). + * Sell operation if the pair is the original pool pair swapped (B/A). + * + * The `quote_amount` is always the quote asset amount (A/B => B), (B/A => A). + * + * Emits `Swapped` event when successful. + **/ + swap: AugmentedSubmittable<(poolId: u128 | AnyNumber | Uint8Array, pair: ComposableTraitsDefiCurrencyPair | { base?: any; quote?: any } | string | Uint8Array, quoteAmount: u128 | AnyNumber | Uint8Array, minReceive: u128 | AnyNumber | Uint8Array, keepAlive: bool | boolean | Uint8Array) => SubmittableExtrinsic, [u128, ComposableTraitsDefiCurrencyPair, u128, u128, bool]>; + /** + * Generic tx + **/ + [key: string]: SubmittableExtrinsicFunction; + }; + mosaic: { + /** + * Called by the relayer to confirm that it will relay a transaction, disabling the user + * from reclaiming their tokens. + * + * # Restrictions + * - Origin must be relayer + * - Outgoing transaction must exist for the user + * - Amount must be equal or lower than what the user has locked + * + * # Note + * - Reclaim period is not reset if not all the funds are moved; menaing that the clock + * remains ticking for the relayer to pick up the rest of the transaction. + **/ + acceptTransfer: AugmentedSubmittable<(from: AccountId32 | string | Uint8Array, networkId: u32 | AnyNumber | Uint8Array, remoteAssetId: CommonMosaicRemoteAssetId | { EthereumTokenAddress: any } | string | Uint8Array, amount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [AccountId32, u32, CommonMosaicRemoteAssetId, u128]>; + /** + * Claims user funds from the `OutgoingTransactions`, in case that the relayer has not + * picked them up. + **/ + claimStaleTo: AugmentedSubmittable<(assetId: u128 | AnyNumber | Uint8Array, to: AccountId32 | string | Uint8Array) => SubmittableExtrinsic, [u128, AccountId32]>; + /** + * Collects funds deposited by the relayer into the owner's account + **/ + claimTo: AugmentedSubmittable<(assetId: u128 | AnyNumber | Uint8Array, to: AccountId32 | string | Uint8Array) => SubmittableExtrinsic, [u128, AccountId32]>; + /** + * Burns funds waiting in incoming_transactions that are still unclaimed. May be used by + * the relayer in case of finality issues on the other side of the bridge. + **/ + rescindTimelockedMint: AugmentedSubmittable<(networkId: u32 | AnyNumber | Uint8Array, remoteAssetId: CommonMosaicRemoteAssetId | { EthereumTokenAddress: any } | string | Uint8Array, account: AccountId32 | string | Uint8Array, untrustedAmount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u32, CommonMosaicRemoteAssetId, AccountId32, u128]>; + /** + * Rotates the Relayer Account + * + * # Restrictions + * - Only callable by the current relayer. + * - TTL must be sufficiently long. + **/ + rotateRelayer: AugmentedSubmittable<(updated: AccountId32 | string | Uint8Array, validatedTtl: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [AccountId32, u32]>; + /** + * Sets the relayer budget for _incoming_ transactions for specific assets. Does not reset + * the current `penalty`. + * + * # Restrictions + * - Only callable by root + **/ + setBudget: AugmentedSubmittable<(assetId: u128 | AnyNumber | Uint8Array, amount: u128 | AnyNumber | Uint8Array, decay: PalletMosaicDecayBudgetPenaltyDecayer | { Linear: any } | string | Uint8Array) => SubmittableExtrinsic, [u128, u128, PalletMosaicDecayBudgetPenaltyDecayer]>; + /** + * Sets supported networks and maximum transaction sizes accepted by the relayer. + **/ + setNetwork: AugmentedSubmittable<(networkId: u32 | AnyNumber | Uint8Array, networkInfo: PalletMosaicNetworkInfo | { enabled?: any; minTransferSize?: any; maxTransferSize?: any } | string | Uint8Array) => SubmittableExtrinsic, [u32, PalletMosaicNetworkInfo]>; + /** + * Sets the current relayer configuration. This is enacted immediately and invalidates + * inflight, incoming transactions from the previous relayer. Budgets remain in place + * however. + **/ + setRelayer: AugmentedSubmittable<(relayer: AccountId32 | string | Uint8Array) => SubmittableExtrinsic, [AccountId32]>; + setTimelockDuration: AugmentedSubmittable<(period: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u32]>; + /** + * Mints new tokens into the pallet's wallet, ready for the user to be picked up after + * `lock_time` blocks have expired. + **/ + timelockedMint: AugmentedSubmittable<(networkId: u32 | AnyNumber | Uint8Array, remoteAssetId: CommonMosaicRemoteAssetId | { EthereumTokenAddress: any } | string | Uint8Array, to: AccountId32 | string | Uint8Array, amount: u128 | AnyNumber | Uint8Array, lockTime: u32 | AnyNumber | Uint8Array, id: H256 | string | Uint8Array) => SubmittableExtrinsic, [u32, CommonMosaicRemoteAssetId, AccountId32, u128, u32, H256]>; + /** + * Creates an outgoing transaction request, locking the funds locally until picked up by + * the relayer. + * + * # Restrictions + * - Network must be supported. + * - AssetId must be supported. + * - Amount must be lower than the networks `max_transfer_size`. + * - Origin must have sufficient funds. + * - Transfers near Balance::max may result in overflows, which are caught and returned as + * an error. + **/ + transferTo: AugmentedSubmittable<(networkId: u32 | AnyNumber | Uint8Array, assetId: u128 | AnyNumber | Uint8Array, address: U8aFixed | string | Uint8Array, amount: u128 | AnyNumber | Uint8Array, keepAlive: bool | boolean | Uint8Array) => SubmittableExtrinsic, [u32, u128, U8aFixed, u128, bool]>; + /** + * Update a network asset mapping. + * + * The caller must be `ControlOrigin`. + * + * Possibly emits one of: + * - `AssetMappingCreated` + * - `AssetMappingDeleted` + * - `AssetMappingUpdated` + **/ + updateAssetMapping: AugmentedSubmittable<(assetId: u128 | AnyNumber | Uint8Array, networkId: u32 | AnyNumber | Uint8Array, remoteAssetId: Option | null | object | string | Uint8Array) => SubmittableExtrinsic, [u128, u32, Option]>; + /** + * Generic tx + **/ + [key: string]: SubmittableExtrinsicFunction; + }; multisig: { /** * Register approval for a dispatch to be made from a deterministic composite account if @@ -1516,6 +1807,36 @@ declare module '@polkadot/api-base/types/submittable' { **/ [key: string]: SubmittableExtrinsicFunction; }; + preimage: { + /** + * Register a preimage on-chain. + * + * If the preimage was previously requested, no fees or deposits are taken for providing + * the preimage. Otherwise, a deposit is taken proportional to the size of the preimage. + **/ + notePreimage: AugmentedSubmittable<(bytes: Bytes | string | Uint8Array) => SubmittableExtrinsic, [Bytes]>; + /** + * Request a preimage be uploaded to the chain without paying any fees or deposits. + * + * If the preimage requests has already been provided on-chain, we unreserve any deposit + * a user may have paid, and take the control of the preimage out of their hands. + **/ + requestPreimage: AugmentedSubmittable<(hash: H256 | string | Uint8Array) => SubmittableExtrinsic, [H256]>; + /** + * Clear an unrequested preimage from the runtime storage. + **/ + unnotePreimage: AugmentedSubmittable<(hash: H256 | string | Uint8Array) => SubmittableExtrinsic, [H256]>; + /** + * Clear a previously made request for a preimage. + * + * NOTE: THIS MUST NOT BE CALLED ON `hash` MORE TIMES THAN `request_preimage`. + **/ + unrequestPreimage: AugmentedSubmittable<(hash: H256 | string | Uint8Array) => SubmittableExtrinsic, [H256]>; + /** + * Generic tx + **/ + [key: string]: SubmittableExtrinsicFunction; + }; relayerXcm: { /** * Execute an XCM message from a local, signed, origin. @@ -1594,8 +1915,8 @@ declare module '@polkadot/api-base/types/submittable' { * an `AccountId32` value. * - `assets`: The assets to be withdrawn. The first item should be the currency used to to pay the fee on the * `dest` side. May not be empty. - * - `dest_weight`: Equal to the total weight on `dest` of the XCM message - * `Teleport { assets, effects: [ BuyExecution{..}, DepositAsset{..} ] }`. + * - `fee_asset_item`: The index into `assets` of the item which should be used to pay + * fees. * - `weight_limit`: The remote-side weight limit, if any, for the XCM fee purchase. **/ limitedTeleportAssets: AugmentedSubmittable<(dest: XcmVersionedMultiLocation | { V0: any } | { V1: any } | string | Uint8Array, beneficiary: XcmVersionedMultiLocation | { V0: any } | { V1: any } | string | Uint8Array, assets: XcmVersionedMultiAssets | { V0: any } | { V1: any } | string | Uint8Array, feeAssetItem: u32 | AnyNumber | Uint8Array, weightLimit: XcmV2WeightLimit | { Unlimited: any } | { Limited: any } | string | Uint8Array) => SubmittableExtrinsic, [XcmVersionedMultiLocation, XcmVersionedMultiLocation, XcmVersionedMultiAssets, u32, XcmV2WeightLimit]>; @@ -1633,8 +1954,8 @@ declare module '@polkadot/api-base/types/submittable' { * an `AccountId32` value. * - `assets`: The assets to be withdrawn. The first item should be the currency used to to pay the fee on the * `dest` side. May not be empty. - * - `dest_weight`: Equal to the total weight on `dest` of the XCM message - * `Teleport { assets, effects: [ BuyExecution{..}, DepositAsset{..} ] }`. + * - `fee_asset_item`: The index into `assets` of the item which should be used to pay + * fees. **/ teleportAssets: AugmentedSubmittable<(dest: XcmVersionedMultiLocation | { V0: any } | { V1: any } | string | Uint8Array, beneficiary: XcmVersionedMultiLocation | { V0: any } | { V1: any } | string | Uint8Array, assets: XcmVersionedMultiAssets | { V0: any } | { V1: any } | string | Uint8Array, feeAssetItem: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [XcmVersionedMultiLocation, XcmVersionedMultiLocation, XcmVersionedMultiAssets, u32]>; /** @@ -1654,7 +1975,7 @@ declare module '@polkadot/api-base/types/submittable' { /** * Anonymously schedule a task. **/ - schedule: AugmentedSubmittable<(when: u32 | AnyNumber | Uint8Array, maybePeriodic: Option> | null | object | string | Uint8Array, priority: u8 | AnyNumber | Uint8Array, call: Call | { callIndex?: any; args?: any } | string | Uint8Array) => SubmittableExtrinsic, [u32, Option>, u8, Call]>; + schedule: AugmentedSubmittable<(when: u32 | AnyNumber | Uint8Array, maybePeriodic: Option> | null | object | string | Uint8Array, priority: u8 | AnyNumber | Uint8Array, call: FrameSupportScheduleMaybeHashed | { Value: any } | { Hash: any } | string | Uint8Array) => SubmittableExtrinsic, [u32, Option>, u8, FrameSupportScheduleMaybeHashed]>; /** * Anonymously schedule a task after a delay. * @@ -1662,11 +1983,11 @@ declare module '@polkadot/api-base/types/submittable' { * Same as [`schedule`]. * # **/ - scheduleAfter: AugmentedSubmittable<(after: u32 | AnyNumber | Uint8Array, maybePeriodic: Option> | null | object | string | Uint8Array, priority: u8 | AnyNumber | Uint8Array, call: Call | { callIndex?: any; args?: any } | string | Uint8Array) => SubmittableExtrinsic, [u32, Option>, u8, Call]>; + scheduleAfter: AugmentedSubmittable<(after: u32 | AnyNumber | Uint8Array, maybePeriodic: Option> | null | object | string | Uint8Array, priority: u8 | AnyNumber | Uint8Array, call: FrameSupportScheduleMaybeHashed | { Value: any } | { Hash: any } | string | Uint8Array) => SubmittableExtrinsic, [u32, Option>, u8, FrameSupportScheduleMaybeHashed]>; /** * Schedule a named task. **/ - scheduleNamed: AugmentedSubmittable<(id: Bytes | string | Uint8Array, when: u32 | AnyNumber | Uint8Array, maybePeriodic: Option> | null | object | string | Uint8Array, priority: u8 | AnyNumber | Uint8Array, call: Call | { callIndex?: any; args?: any } | string | Uint8Array) => SubmittableExtrinsic, [Bytes, u32, Option>, u8, Call]>; + scheduleNamed: AugmentedSubmittable<(id: Bytes | string | Uint8Array, when: u32 | AnyNumber | Uint8Array, maybePeriodic: Option> | null | object | string | Uint8Array, priority: u8 | AnyNumber | Uint8Array, call: FrameSupportScheduleMaybeHashed | { Value: any } | { Hash: any } | string | Uint8Array) => SubmittableExtrinsic, [Bytes, u32, Option>, u8, FrameSupportScheduleMaybeHashed]>; /** * Schedule a named task after a delay. * @@ -1674,7 +1995,7 @@ declare module '@polkadot/api-base/types/submittable' { * Same as [`schedule_named`](Self::schedule_named). * # **/ - scheduleNamedAfter: AugmentedSubmittable<(id: Bytes | string | Uint8Array, after: u32 | AnyNumber | Uint8Array, maybePeriodic: Option> | null | object | string | Uint8Array, priority: u8 | AnyNumber | Uint8Array, call: Call | { callIndex?: any; args?: any } | string | Uint8Array) => SubmittableExtrinsic, [Bytes, u32, Option>, u8, Call]>; + scheduleNamedAfter: AugmentedSubmittable<(id: Bytes | string | Uint8Array, after: u32 | AnyNumber | Uint8Array, maybePeriodic: Option> | null | object | string | Uint8Array, priority: u8 | AnyNumber | Uint8Array, call: FrameSupportScheduleMaybeHashed | { Value: any } | { Hash: any } | string | Uint8Array) => SubmittableExtrinsic, [Bytes, u32, Option>, u8, FrameSupportScheduleMaybeHashed]>; /** * Generic tx **/ @@ -1722,6 +2043,50 @@ declare module '@polkadot/api-base/types/submittable' { **/ [key: string]: SubmittableExtrinsicFunction; }; + stableSwapDex: { + /** + * Add liquidity to a stable-swap pool. + * + * Emits `LiquidityAdded` event when successful. + **/ + addLiquidity: AugmentedSubmittable<(poolId: u128 | AnyNumber | Uint8Array, baseAmount: u128 | AnyNumber | Uint8Array, quoteAmount: u128 | AnyNumber | Uint8Array, minMintAmount: u128 | AnyNumber | Uint8Array, keepAlive: bool | boolean | Uint8Array) => SubmittableExtrinsic, [u128, u128, u128, u128, bool]>; + /** + * Execute a buy order on pool. + * + * Emits `Swapped` event when successful. + **/ + buy: AugmentedSubmittable<(poolId: u128 | AnyNumber | Uint8Array, assetId: u128 | AnyNumber | Uint8Array, amount: u128 | AnyNumber | Uint8Array, keepAlive: bool | boolean | Uint8Array) => SubmittableExtrinsic, [u128, u128, u128, bool]>; + /** + * Create a new pool. + * + * Emits `PoolCreated` event when successful. + **/ + create: AugmentedSubmittable<(pair: ComposableTraitsDefiCurrencyPair | { base?: any; quote?: any } | string | Uint8Array, amplificationCoefficient: u16 | AnyNumber | Uint8Array, fee: Permill | AnyNumber | Uint8Array, ownerFee: Permill | AnyNumber | Uint8Array) => SubmittableExtrinsic, [ComposableTraitsDefiCurrencyPair, u16, Permill, Permill]>; + /** + * Remove liquidity from stable-swap pool. + * + * Emits `LiquidityRemoved` event when successful. + **/ + removeLiquidity: AugmentedSubmittable<(poolId: u128 | AnyNumber | Uint8Array, lpAmount: u128 | AnyNumber | Uint8Array, minBaseAmount: u128 | AnyNumber | Uint8Array, minQuoteAmount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u128, u128, u128, u128]>; + /** + * Execute a sell order on pool. + * + * Emits `Swapped` event when successful. + **/ + sell: AugmentedSubmittable<(poolId: u128 | AnyNumber | Uint8Array, assetId: u128 | AnyNumber | Uint8Array, amount: u128 | AnyNumber | Uint8Array, keepAlive: bool | boolean | Uint8Array) => SubmittableExtrinsic, [u128, u128, u128, bool]>; + /** + * Execute a specific swap operation. + * + * The `quote_amount` is always the quote asset amount (A/B => B), (B/A => A). + * + * Emits `Swapped` event when successful. + **/ + swap: AugmentedSubmittable<(poolId: u128 | AnyNumber | Uint8Array, pair: ComposableTraitsDefiCurrencyPair | { base?: any; quote?: any } | string | Uint8Array, quoteAmount: u128 | AnyNumber | Uint8Array, minReceive: u128 | AnyNumber | Uint8Array, keepAlive: bool | boolean | Uint8Array) => SubmittableExtrinsic, [u128, ComposableTraitsDefiCurrencyPair, u128, u128, bool]>; + /** + * Generic tx + **/ + [key: string]: SubmittableExtrinsicFunction; + }; sudo: { /** * Authenticates the current sudo key and sets the given AccountId (`new`) as the new sudo @@ -1807,11 +2172,6 @@ declare module '@polkadot/api-base/types/submittable' { remark: AugmentedSubmittable<(remark: Bytes | string | Uint8Array) => SubmittableExtrinsic, [Bytes]>; /** * Make some on-chain remark and emit event. - * - * # - * - `O(b)` where b is the length of the remark. - * - 1 event. - * # **/ remarkWithEvent: AugmentedSubmittable<(remark: Bytes | string | Uint8Array) => SubmittableExtrinsic, [Bytes]>; /** @@ -2166,14 +2526,91 @@ declare module '@polkadot/api-base/types/submittable' { vesting: { claim: AugmentedSubmittable<(asset: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u128]>; claimFor: AugmentedSubmittable<(dest: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, asset: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [MultiAddress, u128]>; - updateVestingSchedules: AugmentedSubmittable<(who: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, asset: u128 | AnyNumber | Uint8Array, vestingSchedules: Vec | (ComposableTraitsVestingVestingSchedule | { start?: any; period?: any; periodCount?: any; perPeriod?: any } | string | Uint8Array)[]) => SubmittableExtrinsic, [MultiAddress, u128, Vec]>; - vestedTransfer: AugmentedSubmittable<(dest: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, asset: u128 | AnyNumber | Uint8Array, schedule: ComposableTraitsVestingVestingSchedule | { start?: any; period?: any; periodCount?: any; perPeriod?: any } | string | Uint8Array) => SubmittableExtrinsic, [MultiAddress, u128, ComposableTraitsVestingVestingSchedule]>; + updateVestingSchedules: AugmentedSubmittable<(who: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, asset: u128 | AnyNumber | Uint8Array, vestingSchedules: Vec | (ComposableTraitsVestingVestingSchedule | { window?: any; periodCount?: any; perPeriod?: any } | string | Uint8Array)[]) => SubmittableExtrinsic, [MultiAddress, u128, Vec]>; + vestedTransfer: AugmentedSubmittable<(from: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, beneficiary: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array, asset: u128 | AnyNumber | Uint8Array, schedule: ComposableTraitsVestingVestingSchedule | { window?: any; periodCount?: any; perPeriod?: any } | string | Uint8Array) => SubmittableExtrinsic, [MultiAddress, MultiAddress, u128, ComposableTraitsVestingVestingSchedule]>; /** * Generic tx **/ [key: string]: SubmittableExtrinsicFunction; }; xcmpQueue: { + /** + * Resumes all XCM executions for the XCMP queue. + * + * Note that this function doesn't change the status of the in/out bound channels. + * + * - `origin`: Must pass `ControllerOrigin`. + **/ + resumeXcmExecution: AugmentedSubmittable<() => SubmittableExtrinsic, []>; + /** + * Services a single overweight XCM. + * + * - `origin`: Must pass `ExecuteOverweightOrigin`. + * - `index`: The index of the overweight XCM to service + * - `weight_limit`: The amount of weight that XCM execution may take. + * + * Errors: + * - `BadOverweightIndex`: XCM under `index` is not found in the `Overweight` storage map. + * - `BadXcm`: XCM under `index` cannot be properly decoded into a valid XCM format. + * - `WeightOverLimit`: XCM execution may use greater `weight_limit`. + * + * Events: + * - `OverweightServiced`: On success. + **/ + serviceOverweight: AugmentedSubmittable<(index: u64 | AnyNumber | Uint8Array, weightLimit: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u64, u64]>; + /** + * Suspends all XCM executions for the XCMP queue, regardless of the sender's origin. + * + * - `origin`: Must pass `ControllerOrigin`. + **/ + suspendXcmExecution: AugmentedSubmittable<() => SubmittableExtrinsic, []>; + /** + * Overwrites the number of pages of messages which must be in the queue after which we drop any further + * messages from the channel. + * + * - `origin`: Must pass `Root`. + * - `new`: Desired value for `QueueConfigData.drop_threshold` + **/ + updateDropThreshold: AugmentedSubmittable<(updated: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u32]>; + /** + * Overwrites the number of pages of messages which the queue must be reduced to before it signals that + * message sending may recommence after it has been suspended. + * + * - `origin`: Must pass `Root`. + * - `new`: Desired value for `QueueConfigData.resume_threshold` + **/ + updateResumeThreshold: AugmentedSubmittable<(updated: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u32]>; + /** + * Overwrites the number of pages of messages which must be in the queue for the other side to be told to + * suspend their sending. + * + * - `origin`: Must pass `Root`. + * - `new`: Desired value for `QueueConfigData.suspend_value` + **/ + updateSuspendThreshold: AugmentedSubmittable<(updated: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u32]>; + /** + * Overwrites the amount of remaining weight under which we stop processing messages. + * + * - `origin`: Must pass `Root`. + * - `new`: Desired value for `QueueConfigData.threshold_weight` + **/ + updateThresholdWeight: AugmentedSubmittable<(updated: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u64]>; + /** + * Overwrites the speed to which the available weight approaches the maximum weight. + * A lower number results in a faster progression. A value of 1 makes the entire weight available initially. + * + * - `origin`: Must pass `Root`. + * - `new`: Desired value for `QueueConfigData.weight_restrict_decay`. + **/ + updateWeightRestrictDecay: AugmentedSubmittable<(updated: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u64]>; + /** + * Overwrite the maximum amount of weight any individual message may consume. + * Messages above this weight go into the overweight queue and may only be serviced explicitly. + * + * - `origin`: Must pass `Root`. + * - `new`: Desired value for `QueueConfigData.xcmp_max_individual_weight`. + **/ + updateXcmpMaxIndividualWeight: AugmentedSubmittable<(updated: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u64]>; /** * Generic tx **/ @@ -2210,6 +2647,24 @@ declare module '@polkadot/api-base/types/submittable' { * messages correctly. **/ transferMultiasset: AugmentedSubmittable<(asset: XcmVersionedMultiAsset | { V0: any } | { V1: any } | string | Uint8Array, dest: XcmVersionedMultiLocation | { V0: any } | { V1: any } | string | Uint8Array, destWeight: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [XcmVersionedMultiAsset, XcmVersionedMultiLocation, u64]>; + /** + * Transfer several `MultiAsset` specifying the item to be used as fee + * + * `dest_weight` is the weight for XCM execution on the dest chain, and + * it would be charged from the transferred assets. If set below + * requirements, the execution may fail and assets wouldn't be + * received. + * + * `fee_item` is index of the MultiAssets that we want to use for + * payment + * + * It's a no-op if any error on local XCM execution or message sending. + * Note sending assets out per se doesn't guarantee they would be + * received. Receiving depends on if the XCM message could be delivered + * by the network, and if the receiving chain would handle + * messages correctly. + **/ + transferMultiassets: AugmentedSubmittable<(assets: XcmVersionedMultiAssets | { V0: any } | { V1: any } | string | Uint8Array, feeItem: u32 | AnyNumber | Uint8Array, dest: XcmVersionedMultiLocation | { V0: any } | { V1: any } | string | Uint8Array, destWeight: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [XcmVersionedMultiAssets, u32, XcmVersionedMultiLocation, u64]>; /** * Transfer `MultiAsset` specifying the fee and amount as separate. * @@ -2234,6 +2689,24 @@ declare module '@polkadot/api-base/types/submittable' { * messages correctly. **/ transferMultiassetWithFee: AugmentedSubmittable<(asset: XcmVersionedMultiAsset | { V0: any } | { V1: any } | string | Uint8Array, fee: XcmVersionedMultiAsset | { V0: any } | { V1: any } | string | Uint8Array, dest: XcmVersionedMultiLocation | { V0: any } | { V1: any } | string | Uint8Array, destWeight: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [XcmVersionedMultiAsset, XcmVersionedMultiAsset, XcmVersionedMultiLocation, u64]>; + /** + * Transfer several currencies specifying the item to be used as fee + * + * `dest_weight` is the weight for XCM execution on the dest chain, and + * it would be charged from the transferred assets. If set below + * requirements, the execution may fail and assets wouldn't be + * received. + * + * `fee_item` is index of the currencies tuple that we want to use for + * payment + * + * It's a no-op if any error on local XCM execution or message sending. + * Note sending assets out per se doesn't guarantee they would be + * received. Receiving depends on if the XCM message could be delivered + * by the network, and if the receiving chain would handle + * messages correctly. + **/ + transferMulticurrencies: AugmentedSubmittable<(currencies: Vec> | ([u128 | AnyNumber | Uint8Array, u128 | AnyNumber | Uint8Array])[], feeItem: u32 | AnyNumber | Uint8Array, dest: XcmVersionedMultiLocation | { V0: any } | { V1: any } | string | Uint8Array, destWeight: u64 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [Vec>, u32, XcmVersionedMultiLocation, u64]>; /** * Transfer native currencies specifying the fee and amount as * separate. diff --git a/integration-tests/runtime-tests/src/types/interfaces/augment-types.ts b/integration-tests/runtime-tests/src/types/interfaces/augment-types.ts index 857a1703901..2c6a616067d 100644 --- a/integration-tests/runtime-tests/src/types/interfaces/augment-types.ts +++ b/integration-tests/runtime-tests/src/types/interfaces/augment-types.ts @@ -1,10 +1,10 @@ // Auto-generated via `yarn polkadot-types-from-defs`, do not edit /* eslint-disable */ -import type { ComposableTraitsAssetsXcmAssetLocation, ComposableTraitsAuctionAuctionStepFunction, ComposableTraitsBondedFinanceBondOffer, ComposableTraitsCallFilterCallFilterEntry, ComposableTraitsDefiSell, ComposableTraitsDefiTake, ComposableTraitsGovernanceSignedRawOrigin, ComposableTraitsTimeTimeReleaseFunction, ComposableTraitsVaultVaultConfig, ComposableTraitsVestingVestingSchedule, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundStatus, CumulusPalletXcmpQueueOutboundStatus, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, DaliRuntimeOpaqueSessionKeys, DaliRuntimeOriginCaller, OrmlTokensAccountData, OrmlTokensBalanceLock, PalletAssetsRegistryCandidateStatus, PalletCollatorSelectionCandidateInfo, PalletCrowdloanRewardsModelsProof, PalletCrowdloanRewardsModelsRemoteAccount, PalletCrowdloanRewardsReward, PalletDemocracyConviction, PalletDemocracyPreimageStatus, PalletDemocracyReferendumInfo, PalletDemocracyReleases, PalletDemocracyVoteAccountVote, PalletDemocracyVoteThreshold, PalletDemocracyVoteVoting, PalletDutchAuctionSellOrder, PalletDutchAuctionTakeOrder, PalletIdentityBitFlags, PalletIdentityIdentityInfo, PalletIdentityJudgement, PalletIdentityRegistrarInfo, PalletIdentityRegistration, PalletOracleAssetInfo, PalletOraclePrePrice, PalletOraclePrice, PalletOracleWithdraw, PalletSchedulerReleases, PalletSchedulerScheduledV2, PalletTreasuryProposal, PalletVaultModelsStrategyOverview, PalletVaultModelsVaultInfo, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV1AbridgedHostConfiguration, PolkadotPrimitivesV1PersistedValidationData, SpConsensusAuraSr25519AppSr25519Public, XcmVersionedMultiAsset } from '@composable/types/interfaces/default'; +import type { AssetsBalance, CurrencyId } from '@composable/types/interfaces/assets'; +import type { CommonMosaicRemoteAssetId, ComposableTraitsAssetsXcmAssetLocation, ComposableTraitsAuctionAuctionStepFunction, ComposableTraitsBondedFinanceBondDuration, ComposableTraitsBondedFinanceBondOffer, ComposableTraitsBondedFinanceBondOfferReward, ComposableTraitsCallFilterCallFilterEntry, ComposableTraitsDefiCurrencyPair, ComposableTraitsDefiSell, ComposableTraitsDefiTake, ComposableTraitsDexConsantProductPoolInfo, ComposableTraitsDexConstantProductPoolInfo, ComposableTraitsDexStableSwapPoolInfo, ComposableTraitsGovernanceSignedRawOrigin, ComposableTraitsLendingCreateInput, ComposableTraitsLendingMarketConfig, ComposableTraitsLendingUpdateInput, ComposableTraitsOraclePrice, ComposableTraitsTimeTimeReleaseFunction, ComposableTraitsVaultVaultConfig, ComposableTraitsVestingVestingSchedule, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundStatus, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundStatus, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, DaliRuntimeOpaqueSessionKeys, DaliRuntimeOriginCaller, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, OrmlTokensAccountData, OrmlTokensBalanceLock, PalletAssetsRegistryCandidateStatus, PalletAssetsRegistryForeignMetadata, PalletCollatorSelectionCandidateInfo, PalletCrowdloanRewardsModelsEcdsaSignature, PalletCrowdloanRewardsModelsProof, PalletCrowdloanRewardsModelsRemoteAccount, PalletCrowdloanRewardsModelsReward, PalletCrowdloanRewardsReward, PalletCurrencyFactoryRanges, PalletCurrencyFactoryRangesRange, PalletDemocracyConviction, PalletDemocracyPreimageStatus, PalletDemocracyReferendumInfo, PalletDemocracyReleases, PalletDemocracyVoteAccountVote, PalletDemocracyVoteThreshold, PalletDemocracyVoteVoting, PalletDutchAuctionSellOrder, PalletDutchAuctionTakeOrder, PalletIdentityBitFlags, PalletIdentityIdentityInfo, PalletIdentityJudgement, PalletIdentityRegistrarInfo, PalletIdentityRegistration, PalletLiquidationsLiquidationStrategyConfiguration, PalletLiquidityBootstrappingPool, PalletMosaicAssetInfo, PalletMosaicDecayBudgetPenaltyDecayer, PalletMosaicNetworkInfo, PalletMosaicRelayerStaleRelayer, PalletOracleAssetInfo, PalletOraclePrePrice, PalletOraclePrice, PalletOracleWithdraw, PalletPreimageRequestStatus, PalletSchedulerReleases, PalletSchedulerScheduledV2, PalletSchedulerScheduledV3, PalletTreasuryProposal, PalletVaultModelsStrategyOverview, PalletVaultModelsVaultInfo, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV1AbridgedHostConfiguration, PolkadotPrimitivesV1PersistedValidationData, SpConsensusAuraSr25519AppSr25519Public, XcmVersionedMultiAsset } from '@composable/types/interfaces/crowdloanRewards'; import type { Data, StorageKey } from '@polkadot/types'; import type { BitVec, Bool, Bytes, I128, I16, I256, I32, I64, I8, Json, Null, Raw, Text, Type, U128, U16, U256, U32, U64, U8, USize, bool, i128, i16, i256, i32, i64, i8, u128, u16, u256, u32, u64, u8, usize } from '@polkadot/types-codec'; -import type { AssetApproval, AssetApprovalKey, AssetBalance, AssetDestroyWitness, AssetDetails, AssetMetadata, TAssetBalance, TAssetDepositBalance } from '@polkadot/types/interfaces/assets'; import type { BlockAttestations, IncludedBlocks, MoreAttestations } from '@polkadot/types/interfaces/attestations'; import type { RawAuraPreDigest } from '@polkadot/types/interfaces/aura'; import type { ExtrinsicOrHash, ExtrinsicStatus } from '@polkadot/types/interfaces/author'; @@ -18,7 +18,7 @@ import type { PrefixedStorageKey } from '@polkadot/types/interfaces/childstate'; import type { StatementKind } from '@polkadot/types/interfaces/claims'; import type { CollectiveOrigin, MemberCount, ProposalIndex, Votes, VotesTo230 } from '@polkadot/types/interfaces/collective'; import type { AuthorityId, RawVRFOutput } from '@polkadot/types/interfaces/consensus'; -import type { AliveContractInfo, CodeHash, ContractCallFlags, ContractCallRequest, ContractExecResult, ContractExecResultErr, ContractExecResultErrModule, ContractExecResultOk, ContractExecResultResult, ContractExecResultSuccessTo255, ContractExecResultSuccessTo260, ContractExecResultTo255, ContractExecResultTo260, ContractExecResultTo267, ContractInfo, ContractInstantiateResult, ContractInstantiateResultTo267, ContractReturnFlags, ContractStorageKey, DeletedContract, ExecReturnValue, Gas, HostFnWeights, HostFnWeightsTo264, InstantiateRequest, InstantiateReturnValue, InstantiateReturnValueTo267, InstructionWeights, Limits, LimitsTo264, PrefabWasmModule, RentProjection, Schedule, ScheduleTo212, ScheduleTo258, ScheduleTo264, SeedOf, StorageDeposit, TombstoneContractInfo, TrieId } from '@polkadot/types/interfaces/contracts'; +import type { AliveContractInfo, CodeHash, CodeSource, CodeUploadRequest, CodeUploadResult, CodeUploadResultValue, ContractCallFlags, ContractCallRequest, ContractExecResult, ContractExecResultErr, ContractExecResultErrModule, ContractExecResultOk, ContractExecResultResult, ContractExecResultSuccessTo255, ContractExecResultSuccessTo260, ContractExecResultTo255, ContractExecResultTo260, ContractExecResultTo267, ContractInfo, ContractInstantiateResult, ContractInstantiateResultTo267, ContractInstantiateResultTo299, ContractReturnFlags, ContractStorageKey, DeletedContract, ExecReturnValue, Gas, HostFnWeights, HostFnWeightsTo264, InstantiateRequest, InstantiateRequestV1, InstantiateRequestV2, InstantiateReturnValue, InstantiateReturnValueOk, InstantiateReturnValueTo267, InstructionWeights, Limits, LimitsTo264, PrefabWasmModule, RentProjection, Schedule, ScheduleTo212, ScheduleTo258, ScheduleTo264, SeedOf, StorageDeposit, TombstoneContractInfo, TrieId } from '@polkadot/types/interfaces/contracts'; import type { ContractConstructorSpecLatest, ContractConstructorSpecV0, ContractConstructorSpecV1, ContractConstructorSpecV2, ContractConstructorSpecV3, ContractContractSpecV0, ContractContractSpecV1, ContractContractSpecV2, ContractContractSpecV3, ContractCryptoHasher, ContractDiscriminant, ContractDisplayName, ContractEventParamSpecLatest, ContractEventParamSpecV0, ContractEventParamSpecV2, ContractEventSpecLatest, ContractEventSpecV0, ContractEventSpecV1, ContractEventSpecV2, ContractLayoutArray, ContractLayoutCell, ContractLayoutEnum, ContractLayoutHash, ContractLayoutHashingStrategy, ContractLayoutKey, ContractLayoutStruct, ContractLayoutStructField, ContractMessageParamSpecLatest, ContractMessageParamSpecV0, ContractMessageParamSpecV2, ContractMessageSpecLatest, ContractMessageSpecV0, ContractMessageSpecV1, ContractMessageSpecV2, ContractMetadata, ContractMetadataLatest, ContractMetadataV0, ContractMetadataV1, ContractMetadataV2, ContractMetadataV3, ContractProject, ContractProjectContract, ContractProjectInfo, ContractProjectSource, ContractProjectV0, ContractSelector, ContractStorageLayout, ContractTypeSpec } from '@polkadot/types/interfaces/contractsAbi'; import type { FundIndex, FundInfo, LastContribution, TrieIndex } from '@polkadot/types/interfaces/crowdloan'; import type { ConfigData, MessageId, OverweightIndex, PageCounter, PageIndexData } from '@polkadot/types/interfaces/cumulus'; @@ -38,7 +38,7 @@ import type { ErrorMetadataLatest, ErrorMetadataV10, ErrorMetadataV11, ErrorMeta import type { MmrLeafProof } from '@polkadot/types/interfaces/mmr'; import type { StorageKind } from '@polkadot/types/interfaces/offchain'; import type { DeferredOffenceOf, Kind, OffenceDetails, Offender, OpaqueTimeSlot, ReportIdOf, Reporter } from '@polkadot/types/interfaces/offences'; -import type { AbridgedCandidateReceipt, AbridgedHostConfiguration, AbridgedHrmpChannel, AssignmentId, AssignmentKind, AttestedCandidate, AuctionIndex, AuthorityDiscoveryId, AvailabilityBitfield, AvailabilityBitfieldRecord, BackedCandidate, Bidder, BufferedSessionChange, CandidateCommitments, CandidateDescriptor, CandidateHash, CandidateInfo, CandidatePendingAvailability, CandidateReceipt, CollatorId, CollatorSignature, CommittedCandidateReceipt, CoreAssignment, CoreIndex, CoreOccupied, DisputeLocation, DisputeResult, DisputeState, DisputeStatement, DisputeStatementSet, DoubleVoteReport, DownwardMessage, ExplicitDisputeStatement, GlobalValidationData, GlobalValidationSchedule, GroupIndex, HeadData, HostConfiguration, HrmpChannel, HrmpChannelId, HrmpOpenChannelRequest, InboundDownwardMessage, InboundHrmpMessage, InboundHrmpMessages, IncomingParachain, IncomingParachainDeploy, IncomingParachainFixed, InvalidDisputeStatementKind, LeasePeriod, LeasePeriodOf, LocalValidationData, MessageIngestionType, MessageQueueChain, MessagingStateSnapshot, MessagingStateSnapshotEgressEntry, MultiDisputeStatementSet, NewBidder, OutboundHrmpMessage, ParaGenesisArgs, ParaId, ParaInfo, ParaLifecycle, ParaPastCodeMeta, ParaScheduling, ParaValidatorIndex, ParachainDispatchOrigin, ParachainInherentData, ParachainProposal, ParachainsInherentData, ParathreadClaim, ParathreadClaimQueue, ParathreadEntry, PersistedValidationData, QueuedParathread, RegisteredParachainInfo, RelayBlockNumber, RelayChainBlockNumber, RelayChainHash, RelayHash, Remark, ReplacementTimes, Retriable, Scheduling, ServiceQuality, SessionInfo, SessionInfoValidatorGroup, SignedAvailabilityBitfield, SignedAvailabilityBitfields, SigningContext, SlotRange, Statement, SubId, SystemInherentData, TransientValidationData, UpgradeGoAhead, UpgradeRestriction, UpwardMessage, ValidDisputeStatementKind, ValidationCode, ValidationCodeHash, ValidationData, ValidationDataType, ValidationFunctionParams, ValidatorSignature, ValidityAttestation, VecInboundHrmpMessage, WinnersData, WinnersDataTuple, WinningData, WinningDataEntry } from '@polkadot/types/interfaces/parachains'; +import type { AbridgedCandidateReceipt, AbridgedHostConfiguration, AbridgedHrmpChannel, AssignmentId, AssignmentKind, AttestedCandidate, AuctionIndex, AuthorityDiscoveryId, AvailabilityBitfield, AvailabilityBitfieldRecord, BackedCandidate, Bidder, BufferedSessionChange, CandidateCommitments, CandidateDescriptor, CandidateHash, CandidateInfo, CandidatePendingAvailability, CandidateReceipt, CollatorId, CollatorSignature, CommittedCandidateReceipt, CoreAssignment, CoreIndex, CoreOccupied, DisputeLocation, DisputeResult, DisputeState, DisputeStatement, DisputeStatementSet, DoubleVoteReport, DownwardMessage, ExplicitDisputeStatement, GlobalValidationData, GlobalValidationSchedule, GroupIndex, HeadData, HostConfiguration, HrmpChannel, HrmpChannelId, HrmpOpenChannelRequest, InboundDownwardMessage, InboundHrmpMessage, InboundHrmpMessages, IncomingParachain, IncomingParachainDeploy, IncomingParachainFixed, InvalidDisputeStatementKind, LeasePeriod, LeasePeriodOf, LocalValidationData, MessageIngestionType, MessageQueueChain, MessagingStateSnapshot, MessagingStateSnapshotEgressEntry, MultiDisputeStatementSet, NewBidder, OutboundHrmpMessage, ParaGenesisArgs, ParaId, ParaInfo, ParaLifecycle, ParaPastCodeMeta, ParaScheduling, ParaValidatorIndex, ParachainDispatchOrigin, ParachainInherentData, ParachainProposal, ParachainsInherentData, ParathreadClaim, ParathreadClaimQueue, ParathreadEntry, PersistedValidationData, QueuedParathread, RegisteredParachainInfo, RelayBlockNumber, RelayChainBlockNumber, RelayChainHash, RelayHash, Remark, ReplacementTimes, Retriable, Scheduling, ServiceQuality, SessionInfo, SessionInfoValidatorGroup, SignedAvailabilityBitfield, SignedAvailabilityBitfields, SigningContext, SlotRange, SlotRange10, Statement, SubId, SystemInherentData, TransientValidationData, UpgradeGoAhead, UpgradeRestriction, UpwardMessage, ValidDisputeStatementKind, ValidationCode, ValidationCodeHash, ValidationData, ValidationDataType, ValidationFunctionParams, ValidatorSignature, ValidityAttestation, VecInboundHrmpMessage, WinnersData, WinnersData10, WinnersDataTuple, WinnersDataTuple10, WinningData, WinningData10, WinningDataEntry } from '@polkadot/types/interfaces/parachains'; import type { FeeDetails, InclusionFee, RuntimeDispatchInfo } from '@polkadot/types/interfaces/payment'; import type { Approvals } from '@polkadot/types/interfaces/poll'; import type { ProxyAnnouncement, ProxyDefinition, ProxyType } from '@polkadot/types/interfaces/proxy'; @@ -97,18 +97,13 @@ declare module '@polkadot/types/types/registry' { ApprovalFlag: ApprovalFlag; Approvals: Approvals; ArithmeticError: ArithmeticError; - AssetApproval: AssetApproval; - AssetApprovalKey: AssetApprovalKey; - AssetBalance: AssetBalance; - AssetDestroyWitness: AssetDestroyWitness; - AssetDetails: AssetDetails; AssetId: AssetId; AssetInstance: AssetInstance; AssetInstanceV0: AssetInstanceV0; AssetInstanceV1: AssetInstanceV1; AssetInstanceV2: AssetInstanceV2; - AssetMetadata: AssetMetadata; AssetOptions: AssetOptions; + AssetsBalance: AssetsBalance; AssignmentId: AssignmentId; AssignmentKind: AssignmentKind; AttestedCandidate: AttestedCandidate; @@ -198,10 +193,15 @@ declare module '@polkadot/types/types/registry' { ClassMetadata: ClassMetadata; CodecHash: CodecHash; CodeHash: CodeHash; + CodeSource: CodeSource; + CodeUploadRequest: CodeUploadRequest; + CodeUploadResult: CodeUploadResult; + CodeUploadResultValue: CodeUploadResultValue; CollatorId: CollatorId; CollatorSignature: CollatorSignature; CollectiveOrigin: CollectiveOrigin; CommittedCandidateReceipt: CommittedCandidateReceipt; + CommonMosaicRemoteAssetId: CommonMosaicRemoteAssetId; CompactAssignments: CompactAssignments; CompactAssignmentsTo257: CompactAssignmentsTo257; CompactAssignmentsTo265: CompactAssignmentsTo265; @@ -211,11 +211,21 @@ declare module '@polkadot/types/types/registry' { CompactScoreCompact: CompactScoreCompact; ComposableTraitsAssetsXcmAssetLocation: ComposableTraitsAssetsXcmAssetLocation; ComposableTraitsAuctionAuctionStepFunction: ComposableTraitsAuctionAuctionStepFunction; + ComposableTraitsBondedFinanceBondDuration: ComposableTraitsBondedFinanceBondDuration; ComposableTraitsBondedFinanceBondOffer: ComposableTraitsBondedFinanceBondOffer; + ComposableTraitsBondedFinanceBondOfferReward: ComposableTraitsBondedFinanceBondOfferReward; ComposableTraitsCallFilterCallFilterEntry: ComposableTraitsCallFilterCallFilterEntry; + ComposableTraitsDefiCurrencyPair: ComposableTraitsDefiCurrencyPair; ComposableTraitsDefiSell: ComposableTraitsDefiSell; ComposableTraitsDefiTake: ComposableTraitsDefiTake; + ComposableTraitsDexConsantProductPoolInfo: ComposableTraitsDexConsantProductPoolInfo; + ComposableTraitsDexConstantProductPoolInfo: ComposableTraitsDexConstantProductPoolInfo; + ComposableTraitsDexStableSwapPoolInfo: ComposableTraitsDexStableSwapPoolInfo; ComposableTraitsGovernanceSignedRawOrigin: ComposableTraitsGovernanceSignedRawOrigin; + ComposableTraitsLendingCreateInput: ComposableTraitsLendingCreateInput; + ComposableTraitsLendingMarketConfig: ComposableTraitsLendingMarketConfig; + ComposableTraitsLendingUpdateInput: ComposableTraitsLendingUpdateInput; + ComposableTraitsOraclePrice: ComposableTraitsOraclePrice; ComposableTraitsTimeTimeReleaseFunction: ComposableTraitsTimeTimeReleaseFunction; ComposableTraitsVaultVaultConfig: ComposableTraitsVaultVaultConfig; ComposableTraitsVestingVestingSchedule: ComposableTraitsVestingVestingSchedule; @@ -257,6 +267,7 @@ declare module '@polkadot/types/types/registry' { ContractInfo: ContractInfo; ContractInstantiateResult: ContractInstantiateResult; ContractInstantiateResultTo267: ContractInstantiateResultTo267; + ContractInstantiateResultTo299: ContractInstantiateResultTo299; ContractLayoutArray: ContractLayoutArray; ContractLayoutCell: ContractLayoutCell; ContractLayoutEnum: ContractLayoutEnum; @@ -297,10 +308,13 @@ declare module '@polkadot/types/types/registry' { CumulusPalletDmpQueueConfigData: CumulusPalletDmpQueueConfigData; CumulusPalletDmpQueuePageIndexData: CumulusPalletDmpQueuePageIndexData; CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot: CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot; + CumulusPalletXcmpQueueInboundChannelDetails: CumulusPalletXcmpQueueInboundChannelDetails; CumulusPalletXcmpQueueInboundStatus: CumulusPalletXcmpQueueInboundStatus; + CumulusPalletXcmpQueueOutboundChannelDetails: CumulusPalletXcmpQueueOutboundChannelDetails; CumulusPalletXcmpQueueOutboundStatus: CumulusPalletXcmpQueueOutboundStatus; CumulusPalletXcmpQueueQueueConfigData: CumulusPalletXcmpQueueQueueConfigData; CumulusPrimitivesParachainInherentParachainInherentData: CumulusPrimitivesParachainInherentParachainInherentData; + CurrencyId: CurrencyId; DaliRuntimeOpaqueSessionKeys: DaliRuntimeOpaqueSessionKeys; DaliRuntimeOriginCaller: DaliRuntimeOriginCaller; Data: Data; @@ -447,6 +461,8 @@ declare module '@polkadot/types/types/registry' { Forcing: Forcing; ForkTreePendingChange: ForkTreePendingChange; ForkTreePendingChangeNode: ForkTreePendingChangeNode; + FrameSupportScheduleLookupError: FrameSupportScheduleLookupError; + FrameSupportScheduleMaybeHashed: FrameSupportScheduleMaybeHashed; FullIdentification: FullIdentification; FunctionArgumentMetadataLatest: FunctionArgumentMetadataLatest; FunctionArgumentMetadataV10: FunctionArgumentMetadataV10; @@ -542,7 +558,10 @@ declare module '@polkadot/types/types/registry' { InstanceId: InstanceId; InstanceMetadata: InstanceMetadata; InstantiateRequest: InstantiateRequest; + InstantiateRequestV1: InstantiateRequestV1; + InstantiateRequestV2: InstantiateRequestV2; InstantiateReturnValue: InstantiateReturnValue; + InstantiateReturnValueOk: InstantiateReturnValueOk; InstantiateReturnValueTo267: InstantiateReturnValueTo267; InstructionV2: InstructionV2; InstructionWeights: InstructionWeights; @@ -686,14 +705,19 @@ declare module '@polkadot/types/types/registry' { PageCounter: PageCounter; PageIndexData: PageIndexData; PalletAssetsRegistryCandidateStatus: PalletAssetsRegistryCandidateStatus; + PalletAssetsRegistryForeignMetadata: PalletAssetsRegistryForeignMetadata; PalletCallMetadataLatest: PalletCallMetadataLatest; PalletCallMetadataV14: PalletCallMetadataV14; PalletCollatorSelectionCandidateInfo: PalletCollatorSelectionCandidateInfo; PalletConstantMetadataLatest: PalletConstantMetadataLatest; PalletConstantMetadataV14: PalletConstantMetadataV14; + PalletCrowdloanRewardsModelsEcdsaSignature: PalletCrowdloanRewardsModelsEcdsaSignature; PalletCrowdloanRewardsModelsProof: PalletCrowdloanRewardsModelsProof; PalletCrowdloanRewardsModelsRemoteAccount: PalletCrowdloanRewardsModelsRemoteAccount; + PalletCrowdloanRewardsModelsReward: PalletCrowdloanRewardsModelsReward; PalletCrowdloanRewardsReward: PalletCrowdloanRewardsReward; + PalletCurrencyFactoryRanges: PalletCurrencyFactoryRanges; + PalletCurrencyFactoryRangesRange: PalletCurrencyFactoryRangesRange; PalletDemocracyConviction: PalletDemocracyConviction; PalletDemocracyPreimageStatus: PalletDemocracyPreimageStatus; PalletDemocracyReferendumInfo: PalletDemocracyReferendumInfo; @@ -713,14 +737,22 @@ declare module '@polkadot/types/types/registry' { PalletIdentityJudgement: PalletIdentityJudgement; PalletIdentityRegistrarInfo: PalletIdentityRegistrarInfo; PalletIdentityRegistration: PalletIdentityRegistration; + PalletLiquidationsLiquidationStrategyConfiguration: PalletLiquidationsLiquidationStrategyConfiguration; + PalletLiquidityBootstrappingPool: PalletLiquidityBootstrappingPool; PalletMetadataLatest: PalletMetadataLatest; PalletMetadataV14: PalletMetadataV14; + PalletMosaicAssetInfo: PalletMosaicAssetInfo; + PalletMosaicDecayBudgetPenaltyDecayer: PalletMosaicDecayBudgetPenaltyDecayer; + PalletMosaicNetworkInfo: PalletMosaicNetworkInfo; + PalletMosaicRelayerStaleRelayer: PalletMosaicRelayerStaleRelayer; PalletOracleAssetInfo: PalletOracleAssetInfo; PalletOraclePrePrice: PalletOraclePrePrice; PalletOraclePrice: PalletOraclePrice; PalletOracleWithdraw: PalletOracleWithdraw; + PalletPreimageRequestStatus: PalletPreimageRequestStatus; PalletSchedulerReleases: PalletSchedulerReleases; PalletSchedulerScheduledV2: PalletSchedulerScheduledV2; + PalletSchedulerScheduledV3: PalletSchedulerScheduledV3; PalletsOrigin: PalletsOrigin; PalletStorageMetadataLatest: PalletStorageMetadataLatest; PalletStorageMetadataV14: PalletStorageMetadataV14; @@ -960,6 +992,7 @@ declare module '@polkadot/types/types/registry' { Slot: Slot; SlotNumber: SlotNumber; SlotRange: SlotRange; + SlotRange10: SlotRange10; SocietyJudgement: SocietyJudgement; SocietyVote: SocietyVote; SolutionOrSnapshotSize: SolutionOrSnapshotSize; @@ -1025,8 +1058,6 @@ declare module '@polkadot/types/types/registry' { SystemOrigin: SystemOrigin; Tally: Tally; TaskAddress: TaskAddress; - TAssetBalance: TAssetBalance; - TAssetDepositBalance: TAssetDepositBalance; Text: Text; Timepoint: Timepoint; TokenError: TokenError; @@ -1127,8 +1158,11 @@ declare module '@polkadot/types/types/registry' { WildMultiAssetV1: WildMultiAssetV1; WildMultiAssetV2: WildMultiAssetV2; WinnersData: WinnersData; + WinnersData10: WinnersData10; WinnersDataTuple: WinnersDataTuple; + WinnersDataTuple10: WinnersDataTuple10; WinningData: WinningData; + WinningData10: WinningData10; WinningDataEntry: WinningDataEntry; WithdrawReasons: WithdrawReasons; Xcm: Xcm; diff --git a/integration-tests/runtime-tests/src/types/interfaces/crowdloanRewards/definitions.ts b/integration-tests/runtime-tests/src/types/interfaces/crowdloanRewards/definitions.ts new file mode 100644 index 00000000000..b232d15bf64 --- /dev/null +++ b/integration-tests/runtime-tests/src/types/interfaces/crowdloanRewards/definitions.ts @@ -0,0 +1,151 @@ +import { DefinitionRpc } from "@polkadot/types/types"; + +export default { + rpc: { + amountAvailableToClaimFor: { + description: "The unclaimed amount", + params: [ + { + name: "accountId", + type: "AccountId" + }, + { + name: "at", + type: "Hash", + isOptional: true, + } + ], + type: "Balance" + }, + }, + types: { + ComposableTraitsAssetsXcmAssetLocation: "Null", + PalletCrowdloanRewardsModelsReward: "Null", + PalletCrowdloanRewardsModelsRemoteAccount: { + _enum: { + RelayChain: 'AccountId32', + Ethereum: 'EthereumAccountId' + } + }, + ComposableTraitsCallFilterCallFilterEntry: "Null", + PalletAssetsRegistryCandidateStatus: "Null", + SpConsensusAuraSr25519AppSr25519Public: "Null", + ComposableTraitsBondedFinanceBondOffer: { + beneficiary: "AccountId32", + asset: "u128", + bondPrice: "u128", + nbOfBonds: "u128", + maturity: "ComposableTraitsBondedFinanceBondDuration", + reward: "ComposableTraitsBondedFinanceBondOfferReward", + keepAlive: "bool" + }, + ComposableTraitsBondedFinanceBondDuration: { + Finite: {returnIn: "u32"} + }, + ComposableTraitsBondedFinanceBondOfferReward: { + asset: "u128", + amount: "u128", + maturity: "u32" + }, + PalletCollatorSelectionCandidateInfo: "Null", + PalletCrowdloanRewardsReward: "Null", + PalletDemocracyVoteThreshold: "Null", + PalletDemocracyPreimageStatus: "Null", + PalletDemocracyReferendumInfo: "Null", + PalletPreimageRequestStatus: "Null", + PalletDemocracyReleases: "Null", + PalletDemocracyVoteVoting: "Null", + CumulusPalletDmpQueueConfigData: "Null", + PalletDutchAuctionSellOrder: "Null", + ComposableTraitsVestingVestingSchedule: "Null", + CumulusPalletDmpQueuePageIndexData: "Null", + PalletDutchAuctionTakeOrder: "Null", + ComposableTraitsGovernanceSignedRawOrigin: "Null", + PalletIdentityRegistration: "Null", + PalletIdentityRegistrarInfo: "Null", + PalletOracleAssetInfo: "Null", + PalletOracleWithdraw: { + stake: 'u128', + unlockBlock: 'u32' + }, + PalletOraclePrePrice: "Null", + PalletOraclePrice: "Null", + PolkadotPrimitivesV1AbridgedHostConfiguration: "Null", + CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot: "Null", + PolkadotPrimitivesV1PersistedValidationData: "PersistedValidationData", + PalletSchedulerScheduledV2: "Null", + PalletSchedulerReleases: "Null", + PalletSchedulerScheduledV3: "Null", + DaliRuntimeOpaqueSessionKeys: "Null", + OrmlTokensAccountData: { + free: 'u128', + reserved: 'u128', + frozen: 'u128' + }, + OrmlTokensBalanceLock: "Null", + PalletTreasuryProposal: "Null", + PalletVaultModelsStrategyOverview: "Null", + PalletVaultModelsVaultInfo: "Null", + CumulusPalletXcmpQueueInboundStatus: "Null", + CumulusPalletXcmpQueueInboundChannelDetails: "Null", + PolkadotParachainPrimitivesXcmpMessageFormat: "Null", + CumulusPalletXcmpQueueOutboundStatus: "Null", + CumulusPalletXcmpQueueQueueConfigData: "Null", + CumulusPalletXcmpQueueOutboundChannelDetails: "Null", + PalletCrowdloanRewardsModelsProof: { + _enum: { + RelayChain: '(AccountId32, MultiSignature)', + Ethereum: 'PalletCrowdloanRewardsModelsEcdsaSignature' + } + }, + PalletCrowdloanRewardsModelsEcdsaSignature: "EcdsaSignature", + PalletDemocracyConviction: "Null", + PalletDemocracyVoteAccountVote: "Null", + ComposableTraitsDefiSell: "Null", + ComposableTraitsAuctionAuctionStepFunction: "Null", + ComposableTraitsDefiTake: "Null", + ComposableTraitsTimeTimeReleaseFunction: "Null", + PalletIdentityJudgement: "Null", + PalletIdentityBitFlags: "Null", + PalletIdentityIdentityInfo: "Null", + CumulusPrimitivesParachainInherentParachainInherentData: 'ParachainInherentData', + DaliRuntimeOriginCaller: "Null", + ComposableTraitsVaultVaultConfig: "Null", + XcmVersionedMultiAsset: "Null", + PalletMosaicNetworkInfo: { + enabled: "bool", + maxTransferSize: "Balance" + }, + PalletMosaicDecayBudgetPenaltyDecayer: "Null", + PalletAssetsRegistryForeignMetadata: "Null", + PalletMosaicAssetInfo: "Null", + PalletMosaicRelayerStaleRelayer: "Null", + FrameSupportScheduleMaybeHashed: "Null", + FrameSupportScheduleLookupError: "Null", + PalletCurrencyFactoryRanges: "Null", + PalletCurrencyFactoryRangesRange: "Null", + PalletLiquidationsLiquidationStrategyConfiguration: "Null", + ComposableTraitsDefiCurrencyPair: { + base: "u128", + quote: "u128" + }, + CommonMosaicRemoteAssetId: "Null", + ComposableTraitsDexConsantProductPoolInfo: "Null", + ComposableTraitsLendingMarketConfig: "Null", + ComposableTraitsLendingCreateInput: "Null", + ComposableTraitsLendingUpdateInput: "Null", + ComposableTraitsDexStableSwapPoolInfo: "Null", + ComposableTraitsOraclePrice: "Null", + PalletLiquidityBootstrappingPool: "Null", + ComposableTraitsDexConstantProductPoolInfo: { + owner: "AccountId32", + pair: { + base: "u128", + quote: "u128" + }, + lpToken: "u128", + fee: "Permill", + ownerFee: "Permill" + }, + }, +}; diff --git a/integration-tests/runtime-tests/src/types/interfaces/crowdloanRewards/index.ts b/integration-tests/runtime-tests/src/types/interfaces/crowdloanRewards/index.ts new file mode 100644 index 00000000000..2d307291c39 --- /dev/null +++ b/integration-tests/runtime-tests/src/types/interfaces/crowdloanRewards/index.ts @@ -0,0 +1,4 @@ +// Auto-generated via `yarn polkadot-types-from-defs`, do not edit +/* eslint-disable */ + +export * from './types'; diff --git a/integration-tests/runtime-tests/src/types/interfaces/default/types.ts b/integration-tests/runtime-tests/src/types/interfaces/crowdloanRewards/types.ts similarity index 60% rename from integration-tests/runtime-tests/src/types/interfaces/default/types.ts rename to integration-tests/runtime-tests/src/types/interfaces/crowdloanRewards/types.ts index 78dcce5616a..36aad1480c7 100644 --- a/integration-tests/runtime-tests/src/types/interfaces/default/types.ts +++ b/integration-tests/runtime-tests/src/types/interfaces/crowdloanRewards/types.ts @@ -1,12 +1,15 @@ // Auto-generated via `yarn polkadot-types-from-defs`, do not edit /* eslint-disable */ -import type { Enum, Null, Struct, u128, u32 } from '@polkadot/types-codec'; +import type { Enum, Null, Struct, bool, u128, u32 } from '@polkadot/types-codec'; import type { ITuple } from '@polkadot/types-codec/types'; import type { EthereumAccountId } from '@polkadot/types/interfaces/eth'; import type { EcdsaSignature, MultiSignature } from '@polkadot/types/interfaces/extrinsics'; import type { ParachainInherentData, PersistedValidationData } from '@polkadot/types/interfaces/parachains'; -import type { AccountId32 } from '@polkadot/types/interfaces/runtime'; +import type { AccountId32, Balance, Permill } from '@polkadot/types/interfaces/runtime'; + +/** @name CommonMosaicRemoteAssetId */ +export interface CommonMosaicRemoteAssetId extends Null {} /** @name ComposableTraitsAssetsXcmAssetLocation */ export interface ComposableTraitsAssetsXcmAssetLocation extends Null {} @@ -14,21 +17,79 @@ export interface ComposableTraitsAssetsXcmAssetLocation extends Null {} /** @name ComposableTraitsAuctionAuctionStepFunction */ export interface ComposableTraitsAuctionAuctionStepFunction extends Null {} +/** @name ComposableTraitsBondedFinanceBondDuration */ +export interface ComposableTraitsBondedFinanceBondDuration extends Struct { + readonly Finite: { + readonly returnIn: u32; + } & Struct; +} + /** @name ComposableTraitsBondedFinanceBondOffer */ -export interface ComposableTraitsBondedFinanceBondOffer extends Null {} +export interface ComposableTraitsBondedFinanceBondOffer extends Struct { + readonly beneficiary: AccountId32; + readonly asset: u128; + readonly bondPrice: u128; + readonly nbOfBonds: u128; + readonly maturity: ComposableTraitsBondedFinanceBondDuration; + readonly reward: ComposableTraitsBondedFinanceBondOfferReward; + readonly keepAlive: bool; +} + +/** @name ComposableTraitsBondedFinanceBondOfferReward */ +export interface ComposableTraitsBondedFinanceBondOfferReward extends Struct { + readonly asset: u128; + readonly amount: u128; + readonly maturity: u32; +} /** @name ComposableTraitsCallFilterCallFilterEntry */ export interface ComposableTraitsCallFilterCallFilterEntry extends Null {} +/** @name ComposableTraitsDefiCurrencyPair */ +export interface ComposableTraitsDefiCurrencyPair extends Struct { + readonly base: u128; + readonly quote: u128; +} + /** @name ComposableTraitsDefiSell */ export interface ComposableTraitsDefiSell extends Null {} /** @name ComposableTraitsDefiTake */ export interface ComposableTraitsDefiTake extends Null {} +/** @name ComposableTraitsDexConsantProductPoolInfo */ +export interface ComposableTraitsDexConsantProductPoolInfo extends Null {} + +/** @name ComposableTraitsDexConstantProductPoolInfo */ +export interface ComposableTraitsDexConstantProductPoolInfo extends Struct { + readonly owner: AccountId32; + readonly pair: { + readonly base: u128; + readonly quote: u128; + } & Struct; + readonly lpToken: u128; + readonly fee: Permill; + readonly ownerFee: Permill; +} + +/** @name ComposableTraitsDexStableSwapPoolInfo */ +export interface ComposableTraitsDexStableSwapPoolInfo extends Null {} + /** @name ComposableTraitsGovernanceSignedRawOrigin */ export interface ComposableTraitsGovernanceSignedRawOrigin extends Null {} +/** @name ComposableTraitsLendingCreateInput */ +export interface ComposableTraitsLendingCreateInput extends Null {} + +/** @name ComposableTraitsLendingMarketConfig */ +export interface ComposableTraitsLendingMarketConfig extends Null {} + +/** @name ComposableTraitsLendingUpdateInput */ +export interface ComposableTraitsLendingUpdateInput extends Null {} + +/** @name ComposableTraitsOraclePrice */ +export interface ComposableTraitsOraclePrice extends Null {} + /** @name ComposableTraitsTimeTimeReleaseFunction */ export interface ComposableTraitsTimeTimeReleaseFunction extends Null {} @@ -47,9 +108,15 @@ export interface CumulusPalletDmpQueuePageIndexData extends Null {} /** @name CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot */ export interface CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot extends Null {} +/** @name CumulusPalletXcmpQueueInboundChannelDetails */ +export interface CumulusPalletXcmpQueueInboundChannelDetails extends Null {} + /** @name CumulusPalletXcmpQueueInboundStatus */ export interface CumulusPalletXcmpQueueInboundStatus extends Null {} +/** @name CumulusPalletXcmpQueueOutboundChannelDetails */ +export interface CumulusPalletXcmpQueueOutboundChannelDetails extends Null {} + /** @name CumulusPalletXcmpQueueOutboundStatus */ export interface CumulusPalletXcmpQueueOutboundStatus extends Null {} @@ -65,8 +132,18 @@ export interface DaliRuntimeOpaqueSessionKeys extends Null {} /** @name DaliRuntimeOriginCaller */ export interface DaliRuntimeOriginCaller extends Null {} +/** @name FrameSupportScheduleLookupError */ +export interface FrameSupportScheduleLookupError extends Null {} + +/** @name FrameSupportScheduleMaybeHashed */ +export interface FrameSupportScheduleMaybeHashed extends Null {} + /** @name OrmlTokensAccountData */ -export interface OrmlTokensAccountData extends Null {} +export interface OrmlTokensAccountData extends Struct { + readonly free: u128; + readonly reserved: u128; + readonly frozen: u128; +} /** @name OrmlTokensBalanceLock */ export interface OrmlTokensBalanceLock extends Null {} @@ -74,15 +151,21 @@ export interface OrmlTokensBalanceLock extends Null {} /** @name PalletAssetsRegistryCandidateStatus */ export interface PalletAssetsRegistryCandidateStatus extends Null {} +/** @name PalletAssetsRegistryForeignMetadata */ +export interface PalletAssetsRegistryForeignMetadata extends Null {} + /** @name PalletCollatorSelectionCandidateInfo */ export interface PalletCollatorSelectionCandidateInfo extends Null {} +/** @name PalletCrowdloanRewardsModelsEcdsaSignature */ +export interface PalletCrowdloanRewardsModelsEcdsaSignature extends EcdsaSignature {} + /** @name PalletCrowdloanRewardsModelsProof */ export interface PalletCrowdloanRewardsModelsProof extends Enum { readonly isRelayChain: boolean; readonly asRelayChain: ITuple<[AccountId32, MultiSignature]>; readonly isEthereum: boolean; - readonly asEthereum: EcdsaSignature; + readonly asEthereum: PalletCrowdloanRewardsModelsEcdsaSignature; readonly type: 'RelayChain' | 'Ethereum'; } @@ -95,9 +178,18 @@ export interface PalletCrowdloanRewardsModelsRemoteAccount extends Enum { readonly type: 'RelayChain' | 'Ethereum'; } +/** @name PalletCrowdloanRewardsModelsReward */ +export interface PalletCrowdloanRewardsModelsReward extends Null {} + /** @name PalletCrowdloanRewardsReward */ export interface PalletCrowdloanRewardsReward extends Null {} +/** @name PalletCurrencyFactoryRanges */ +export interface PalletCurrencyFactoryRanges extends Null {} + +/** @name PalletCurrencyFactoryRangesRange */ +export interface PalletCurrencyFactoryRangesRange extends Null {} + /** @name PalletDemocracyConviction */ export interface PalletDemocracyConviction extends Null {} @@ -140,6 +232,27 @@ export interface PalletIdentityRegistrarInfo extends Null {} /** @name PalletIdentityRegistration */ export interface PalletIdentityRegistration extends Null {} +/** @name PalletLiquidationsLiquidationStrategyConfiguration */ +export interface PalletLiquidationsLiquidationStrategyConfiguration extends Null {} + +/** @name PalletLiquidityBootstrappingPool */ +export interface PalletLiquidityBootstrappingPool extends Null {} + +/** @name PalletMosaicAssetInfo */ +export interface PalletMosaicAssetInfo extends Null {} + +/** @name PalletMosaicDecayBudgetPenaltyDecayer */ +export interface PalletMosaicDecayBudgetPenaltyDecayer extends Null {} + +/** @name PalletMosaicNetworkInfo */ +export interface PalletMosaicNetworkInfo extends Struct { + readonly enabled: bool; + readonly maxTransferSize: Balance; +} + +/** @name PalletMosaicRelayerStaleRelayer */ +export interface PalletMosaicRelayerStaleRelayer extends Null {} + /** @name PalletOracleAssetInfo */ export interface PalletOracleAssetInfo extends Null {} @@ -155,12 +268,18 @@ export interface PalletOracleWithdraw extends Struct { readonly unlockBlock: u32; } +/** @name PalletPreimageRequestStatus */ +export interface PalletPreimageRequestStatus extends Null {} + /** @name PalletSchedulerReleases */ export interface PalletSchedulerReleases extends Null {} /** @name PalletSchedulerScheduledV2 */ export interface PalletSchedulerScheduledV2 extends Null {} +/** @name PalletSchedulerScheduledV3 */ +export interface PalletSchedulerScheduledV3 extends Null {} + /** @name PalletTreasuryProposal */ export interface PalletTreasuryProposal extends Null {} @@ -185,4 +304,4 @@ export interface SpConsensusAuraSr25519AppSr25519Public extends Null {} /** @name XcmVersionedMultiAsset */ export interface XcmVersionedMultiAsset extends Null {} -export type PHANTOM_DEFAULT = 'default'; +export type PHANTOM_CROWDLOANREWARDS = 'crowdloanRewards'; diff --git a/integration-tests/runtime-tests/src/types/interfaces/definitions.ts b/integration-tests/runtime-tests/src/types/interfaces/definitions.ts index e33ff1a2fad..81fe2c7247c 100644 --- a/integration-tests/runtime-tests/src/types/interfaces/definitions.ts +++ b/integration-tests/runtime-tests/src/types/interfaces/definitions.ts @@ -1,71 +1,2 @@ -export default { - types: { - ComposableTraitsAssetsXcmAssetLocation: "Null", - PalletCrowdloanRewardsModelsRemoteAccount: { - _enum: { - RelayChain: 'AccountId32', - Ethereum: 'EthereumAccountId' - } - }, - ComposableTraitsCallFilterCallFilterEntry: "Null", - PalletAssetsRegistryCandidateStatus: "Null", - SpConsensusAuraSr25519AppSr25519Public: "Null", - ComposableTraitsBondedFinanceBondOffer: "Null", - PalletCollatorSelectionCandidateInfo: "Null", - PalletCrowdloanRewardsReward: "Null", - PalletDemocracyVoteThreshold: "Null", - PalletDemocracyPreimageStatus: "Null", - PalletDemocracyReferendumInfo: "Null", - PalletDemocracyReleases: "Null", - PalletDemocracyVoteVoting: "Null", - CumulusPalletDmpQueueConfigData: "Null", - PalletDutchAuctionSellOrder: "Null", - ComposableTraitsVestingVestingSchedule: "Null", - CumulusPalletDmpQueuePageIndexData: "Null", - PalletDutchAuctionTakeOrder: "Null", - ComposableTraitsGovernanceSignedRawOrigin: "Null", - PalletIdentityRegistration: "Null", - PalletIdentityRegistrarInfo: "Null", - PalletOracleAssetInfo: "Null", - PalletOracleWithdraw: { - stake: 'u128', - unlockBlock: 'u32' - }, - PalletOraclePrePrice: "Null", - PalletOraclePrice: "Null", - PolkadotPrimitivesV1AbridgedHostConfiguration: "Null", - CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot: "Null", - PolkadotPrimitivesV1PersistedValidationData: "PersistedValidationData", - PalletSchedulerScheduledV2: "Null", - PalletSchedulerReleases: "Null", - DaliRuntimeOpaqueSessionKeys: "Null", - OrmlTokensAccountData: "Null", - OrmlTokensBalanceLock: "Null", - PalletTreasuryProposal: "Null", - PalletVaultModelsStrategyOverview: "Null", - PalletVaultModelsVaultInfo: "Null", - CumulusPalletXcmpQueueInboundStatus: "Null", - PolkadotParachainPrimitivesXcmpMessageFormat: "Null", - CumulusPalletXcmpQueueOutboundStatus: "Null", - CumulusPalletXcmpQueueQueueConfigData: "Null", - PalletCrowdloanRewardsModelsProof: { - _enum: { - RelayChain: '(AccountId32, MultiSignature)', - Ethereum: 'EcdsaSignature' - } - }, - PalletDemocracyConviction: "Null", - PalletDemocracyVoteAccountVote: "Null", - ComposableTraitsDefiSell: "Null", - ComposableTraitsAuctionAuctionStepFunction: "Null", - ComposableTraitsDefiTake: "Null", - ComposableTraitsTimeTimeReleaseFunction: "Null", - PalletIdentityJudgement: "Null", - PalletIdentityBitFlags: "Null", - PalletIdentityIdentityInfo: "Null", - CumulusPrimitivesParachainInherentParachainInherentData: 'ParachainInherentData', - DaliRuntimeOriginCaller: "Null", - ComposableTraitsVaultVaultConfig: "Null", - XcmVersionedMultiAsset: "Null", - } -}; +export { default as crowdloanRewards } from "./crowdloanRewards/definitions"; +export { default as assets } from "./assets/definitions"; \ No newline at end of file diff --git a/integration-tests/runtime-tests/src/types/interfaces/types.ts b/integration-tests/runtime-tests/src/types/interfaces/types.ts index d8d4cf80d33..f582241cf01 100644 --- a/integration-tests/runtime-tests/src/types/interfaces/types.ts +++ b/integration-tests/runtime-tests/src/types/interfaces/types.ts @@ -1,4 +1,5 @@ // Auto-generated via `yarn polkadot-types-from-defs`, do not edit /* eslint-disable */ -export * from './default/types'; +export * from './crowdloanRewards/types'; +export * from './assets/types'; diff --git a/integration-tests/runtime-tests/src/utils/args.ts b/integration-tests/runtime-tests/src/utils/args.ts deleted file mode 100644 index 49a5e779ebd..00000000000 --- a/integration-tests/runtime-tests/src/utils/args.ts +++ /dev/null @@ -1,6 +0,0 @@ -import minimist from "minimist"; - - -export const args = minimist(process.argv.slice(2), - { default: { p: 9988, h: '127.0.0.1', w: true } }); -console.debug(`args parser: Host(${args.h}), Port(${args.p})`); diff --git a/integration-tests/runtime-tests/src/utils/mintingHelper.ts b/integration-tests/runtime-tests/src/utils/mintingHelper.ts new file mode 100644 index 00000000000..d03e1a27a7a --- /dev/null +++ b/integration-tests/runtime-tests/src/utils/mintingHelper.ts @@ -0,0 +1,27 @@ +import {sendAndWaitForSuccess} from "@composable/utils/polkadotjs"; +import {expect} from "chai"; + +/*** + * This mints all specified assets to a specified wallet. + * The best way would be to make a list of all transactions, and sending them at once. + * But due to issues with our current handler when sending transactions at the same time (Priority to low event), + * we send them one after another. Check [CU-20jc9ug] + * + * @param wallet The wallet receiving the assets. + * @param sudoKey The sudo key making the transaction. + * @param assetIDs All assets to be minted to wallet. + * @param amount Mint amount. + */ +export async function mintAssetsToWallet(wallet, sudoKey, assetIDs:number[], amount=999999999999999) { + for (const asset of assetIDs) { + const {data: [result]} = await sendAndWaitForSuccess( + api, + sudoKey, + api.events.sudo.Sudid.is, + api.tx.sudo.sudo( + api.tx.assets.mintInto(asset, wallet.publicKey, amount) + ) + ) + expect(result.isOk).to.be.true; + } +} diff --git a/integration-tests/runtime-tests/src/utils/polkadotjs.ts b/integration-tests/runtime-tests/src/utils/polkadotjs.ts index 95e6eb862c5..1eec8550216 100644 --- a/integration-tests/runtime-tests/src/utils/polkadotjs.ts +++ b/integration-tests/runtime-tests/src/utils/polkadotjs.ts @@ -1,6 +1,7 @@ import { ApiPromise } from '@polkadot/api'; import { AnyTuple, IEvent } from '@polkadot/types/types'; import { SubmittableExtrinsic, AddressOrPair } from '@polkadot/api/types'; +import {expect} from "chai"; export async function sendUnsignedAndWaitForSuccess( api: ApiPromise, @@ -21,6 +22,28 @@ export async function sendAndWaitForSuccess( return await sendAndWaitFor(api, sender, filter, call, intendedToFail); } +export async function waitForBlocks(n=1) { + return await waitForBlockHandler(n); +} + +/** + * Helper to wait for n blocks. + * @param n Block wait duration. + */ +export async function waitForBlockHandler(n) { + const originBlock = await api.query.system.number(); + let currentBlock = await api.query.system.number(); + while(currentBlock.toNumber() < originBlock.toNumber()+n) { + await sleep(3000); + currentBlock = await api.query.system.number(); + } + return currentBlock; +} + +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + /** * Sends the given unsigned `call` and waits for an event that fits `filter`. * @param {ApiPromise} api api object @@ -83,13 +106,13 @@ export function sendAndWaitFor( ): Promise> { return new Promise>(function (resolve, reject) { call - .signAndSend(sender, { nonce: -1 }, function (res) { - const { dispatchError, status } = res; + .signAndSend(sender, {nonce: -1}, function (res) { + const {dispatchError, status} = res; if (dispatchError) { if (dispatchError.isModule) { // for module errors, we have the section indexed, lookup const decoded = api.registry.findMetaError(dispatchError.asModule); - const { docs, name, section } = decoded; + const {docs, name, section} = decoded; if (intendedToFail) { const event = res.events.find(e => filter(e.event)).event; if (filter(event)) @@ -122,12 +145,24 @@ export function sendAndWaitFor( if (filter(event)) resolve(event); } - reject(Error("Event record not found")); + reject(Error("1014: Priority is too low:")); } } }) - .catch(function (e) { - reject(Error(e.stack)); + .catch(async function (e) { + if (e.message.contains("1014: Priority is too low:")) { + // This happens when we send 2 transaction from the same wallet, at the same time. + // We solve it by waiting 2 seconds and retrying it. + await sleep(2000); + const {data: [result],} = await sendAndWaitFor(api, sender, filter, call, intendedToFail).catch(function (exc) { + reject(exc); + return {data:[exc]}; + }); + expect(result).to.not.be.an('Error'); + resolve(result); + } + else + reject(Error(e.stack)); }); }); } diff --git a/integration-tests/runtime-tests/src/utils/testSetup.ts b/integration-tests/runtime-tests/src/utils/testSetup.ts index 1da004e82b2..6b4bc1e2854 100644 --- a/integration-tests/runtime-tests/src/utils/testSetup.ts +++ b/integration-tests/runtime-tests/src/utils/testSetup.ts @@ -1,43 +1,54 @@ /* eslint-disable no-var */ -import '@composable/types/interfaces/augment-api'; -import '@composable/types/interfaces/augment-types'; -import * as definitions from '@composable/types/interfaces/definitions'; +import '@composable/../../src/types/interfaces/augment-api'; +import '@composable/../../src/types/interfaces/augment-types'; +import * as definitions from '@composable/../../src/types/interfaces/definitions'; import { ApiPromise, Keyring, WsProvider } from "@polkadot/api"; +import { ApiOptions } from '@polkadot/api/types'; import Web3 from 'web3'; -import { args } from "./args"; + +import chai_bn from "chai-bn"; +import BN from "bn.js"; +import chai from "chai"; global.useTestnetWallets = true; global.testSudoCommands = true; // ToDo (D. Roth): Read public/private keys from external file to be usable in live environment. // and ability to specify keys using env variables or using run parameters. -export async function runBefore() { - // extract all types from definitions - fast and dirty approach, flatted on 'types' - const types = Object.values(definitions).reduce((res, {types}): object => ({...res, ...types}), {}); - global.endpoint = `ws://${args.h}:${args.p}`; +exports.mochaHooks = { + async beforeAll() { + this.timeout(5*60*1000); +// Enable and inject BN dependency + chai.use(chai_bn(BN)); + const rpc = Object.keys(definitions).reduce((accumulator, key) => ({ ...accumulator, [key]: definitions[key].rpc }), {}); + const types = Object.values(definitions).reduce((accumulator, { types }) => ({ ...accumulator, ...types }), {}); + + global.endpoint = 'ws://' + (process.env.ENDPOINT ?? '127.0.0.1:9988'); const provider = new WsProvider(global.endpoint); console.debug(`Establishing connection to ${global.endpoint}...`); - // async or Promise-returning functions allowed - global.api = await ApiPromise.create({provider, types}); + const apiOptions: ApiOptions = { + provider, types, rpc + }; + global.api = await ApiPromise.create(apiOptions); + global.web3 = new Web3(); // do something before every test, // then run the next hook in this array - global.keyring = new Keyring({type: 'sr25519'}); - - if (global.useTestnetWallets === true) { - global.walletAlice = global.keyring.addFromUri('//Alice'); - global.walletBob = global.keyring.addFromUri('//Bob'); - global.walletCharlie = global.keyring.addFromUri('//Charlie'); - global.walletDave = global.keyring.addFromUri('//Dave'); - global.walletEve = global.keyring.addFromUri('//Eve'); - global.walletFerdie = global.keyring.addFromUri('//Ferdie'); - } - return; -} + global.keyring = new Keyring({ type: 'sr25519' }); -export async function runAfter () { - await global.api.disconnect(); -} + if (global.useTestnetWallets === true) { + global.walletAlice = global.keyring.addFromUri('//Alice'); + global.walletBob = global.keyring.addFromUri('//Bob'); + global.walletCharlie = global.keyring.addFromUri('//Charlie'); + global.walletDave = global.keyring.addFromUri('//Dave'); + global.walletEve = global.keyring.addFromUri('//Eve'); + global.walletFerdie = global.keyring.addFromUri('//Ferdie'); + } + }, + async afterAll() { + return await global.api.disconnect(); + } +} \ No newline at end of file diff --git a/integration-tests/runtime-tests/src/globals.ts b/integration-tests/runtime-tests/test/globals.ts similarity index 94% rename from integration-tests/runtime-tests/src/globals.ts rename to integration-tests/runtime-tests/test/globals.ts index 4053ff6d45b..babf007d1b2 100644 --- a/integration-tests/runtime-tests/src/globals.ts +++ b/integration-tests/runtime-tests/test/globals.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-var */ import { ApiPromise, Keyring } from '@polkadot/api'; import { KeyringPair } from '@polkadot/keyring/types'; import Web3 from 'web3'; diff --git a/integration-tests/runtime-tests/test/tests/assets/rpcAssetsTests.ts b/integration-tests/runtime-tests/test/tests/assets/rpcAssetsTests.ts new file mode 100644 index 00000000000..4ec728079a6 --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/assets/rpcAssetsTests.ts @@ -0,0 +1,23 @@ +import { CurrencyId } from '@composable/types/interfaces'; +import { AnyNumber } from '@polkadot/types-codec/types'; +import { expect } from 'chai'; +import testConfiguration from './test_configuration.json'; + +describe('rpc.assets Tests', function () { + if (!testConfiguration.enabledTests.rpc.enabled) + return; + it('rpc.assets.balanceOf Tests', async function () { + if (!testConfiguration.enabledTests.rpc.balanceOf__success) + this.skip(); + const asset_id = api.createType('CurrencyId', '123456789123456789'); + const publicKey = walletAlice.address; + const result = await RpcAssetsTests.rpcAssetsTest(asset_id, publicKey); + expect(result).to.be.a["bignumber"].that.equals('0'); + }); +}); + +export class RpcAssetsTests { + public static async rpcAssetsTest(asset_id: CurrencyId | AnyNumber, publicKey: string | Uint8Array) { + return await api.rpc.assets.balanceOf(asset_id, publicKey); + } +} diff --git a/integration-tests/runtime-tests/test/tests/assets/test_configuration.json b/integration-tests/runtime-tests/test/tests/assets/test_configuration.json new file mode 100644 index 00000000000..f07d1934c9f --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/assets/test_configuration.json @@ -0,0 +1,8 @@ +{ + "enabledTests": { + "rpc": { + "enabled": true, + "balanceOf__success": true + } + } +} \ No newline at end of file diff --git a/integration-tests/runtime-tests/src/tests/tx/bondedFinance/testHandlers/bondTests.ts b/integration-tests/runtime-tests/test/tests/bondedFinance/testHandlers/bondTests.ts similarity index 88% rename from integration-tests/runtime-tests/src/tests/tx/bondedFinance/testHandlers/bondTests.ts rename to integration-tests/runtime-tests/test/tests/bondedFinance/testHandlers/bondTests.ts index 801cf29e9f7..6c9fa669c54 100644 --- a/integration-tests/runtime-tests/src/tests/tx/bondedFinance/testHandlers/bondTests.ts +++ b/integration-tests/runtime-tests/test/tests/bondedFinance/testHandlers/bondTests.ts @@ -12,7 +12,7 @@ export async function txBondedFinanceBondSuccessTest(wallet: IKeyringPair, offer api, wallet, api.events.bondedFinance.NewBond.is, - api.tx.bondedFinance.bond(offerId, nbOfBonds), + api.tx.bondedFinance.bond(offerId, nbOfBonds, true), ); } @@ -27,7 +27,7 @@ export async function txBondedFinanceBondFailureTest(wallet: IKeyringPair, offer api, wallet, api.events.system.ExtrinsicFailed.is, - api.tx.bondedFinance.bond(offerId, nbOfBonds), + api.tx.bondedFinance.bond(offerId, nbOfBonds, true), true ); } \ No newline at end of file diff --git a/integration-tests/runtime-tests/src/tests/tx/bondedFinance/testHandlers/cancelTests.ts b/integration-tests/runtime-tests/test/tests/bondedFinance/testHandlers/cancelTests.ts similarity index 100% rename from integration-tests/runtime-tests/src/tests/tx/bondedFinance/testHandlers/cancelTests.ts rename to integration-tests/runtime-tests/test/tests/bondedFinance/testHandlers/cancelTests.ts diff --git a/integration-tests/runtime-tests/src/tests/tx/bondedFinance/testHandlers/offerTests.ts b/integration-tests/runtime-tests/test/tests/bondedFinance/testHandlers/offerTests.ts similarity index 88% rename from integration-tests/runtime-tests/src/tests/tx/bondedFinance/testHandlers/offerTests.ts rename to integration-tests/runtime-tests/test/tests/bondedFinance/testHandlers/offerTests.ts index 21e65bbcb22..3c1fc07face 100644 --- a/integration-tests/runtime-tests/src/tests/tx/bondedFinance/testHandlers/offerTests.ts +++ b/integration-tests/runtime-tests/test/tests/bondedFinance/testHandlers/offerTests.ts @@ -11,7 +11,7 @@ export async function txBondedFinanceOfferSuccessTest(wallet: IKeyringPair, requ api, wallet, api.events.bondedFinance.NewOffer.is, - api.tx.bondedFinance.offer(requestParameters), + api.tx.bondedFinance.offer(requestParameters, true), ); } @@ -25,7 +25,7 @@ export async function txBondedFinanceOfferFailureTest(wallet: IKeyringPair, requ api, wallet, api.events.system.ExtrinsicFailed.is, - api.tx.bondedFinance.offer(requestParameters), + api.tx.bondedFinance.offer(requestParameters, true), true ); } \ No newline at end of file diff --git a/integration-tests/runtime-tests/test/tests/bondedFinance/test_configuration.json b/integration-tests/runtime-tests/test/tests/bondedFinance/test_configuration.json new file mode 100644 index 00000000000..9b92d451534 --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/bondedFinance/test_configuration.json @@ -0,0 +1,26 @@ +{ + "enabledTests": { + "enabled": true, + "offer_bond__success": { + "enabled": true, + "create1": true, + "create2": true, + "bond": true + }, + "offer_bond__failure": { + "enabled": true, + "create_offer_price_lt_MIN_VESTED_TRANSFER": true, + "create_offer_reward_amt_lt_MinReward": true, + "create_offer_reward_asset_not_exist": true + }, + "cancel_failure": { + "enabled": true, + "cancel_offer_not_exist": true + }, + "cancel_success": { + "enabled": true, + "cancel_by_creator": true, + "cancel_by_sudo": true + } + } +} \ No newline at end of file diff --git a/integration-tests/runtime-tests/test/tests/bondedFinance/txBondedFinanceTests.ts b/integration-tests/runtime-tests/test/tests/bondedFinance/txBondedFinanceTests.ts new file mode 100644 index 00000000000..2b05a08df48 --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/bondedFinance/txBondedFinanceTests.ts @@ -0,0 +1,204 @@ +import {expect} from "chai"; +import testConfiguration from './test_configuration.json'; +import { + txBondedFinanceOfferFailureTest, + txBondedFinanceOfferSuccessTest +} from "@composabletests/tests/bondedFinance/testHandlers/offerTests"; +import {txBondedFinanceBondSuccessTest} from "@composabletests/tests/bondedFinance/testHandlers/bondTests"; +import { + txBondedFinanceCancelFailureTest, + txBondedFinanceCancelSuccessTest, txBondedFinanceCancelSudoSuccessTest +} from "@composabletests/tests/bondedFinance/testHandlers/cancelTests"; + + +let bondOfferId1:number, bondOfferId2:number; +/** + * Contains all TX tests for the pallet: + * bondedFinance + */ +describe('tx.bondedFinance Tests', function() { + if (!testConfiguration.enabledTests.enabled) + return; + /** + * bondedFinance.offer(...) Success Tests + */ + describe('tx.bondedFinance.offer & .bond Success Tests', function () { + if (!testConfiguration.enabledTests.offer_bond__success.enabled) + return; + + // Timeout set to 2 minutes + this.timeout(2*60*1000); + // #1 Create offer using Alice's wallet. + it('Can create a new offer', async function () { + if (!testConfiguration.enabledTests.offer_bond__success.create1) + this.skip(); + const requestParameters = { + beneficiary: walletAlice.publicKey, + asset: api.createType('u128', 1), + bondPrice: api.consts.bondedFinance.stake, + nbOfBonds: api.createType('u128', 10), + maturity: { Finite: { returnIn: api.createType('u32', 16) } }, + reward: { + asset: api.createType('u128', 1), + amount: api.consts.bondedFinance.minReward, + maturity: api.createType('u32', 1) + } + }; + const { data: [result], } = await txBondedFinanceOfferSuccessTest(walletAlice, requestParameters); + expect(result.toNumber()).to.be.a('number'); + bondOfferId1 = result.toNumber(); + }); + + // #2 Create offer using Bob's wallet. + it('Can create a second new offer', async function () { + if (!testConfiguration.enabledTests.offer_bond__success.create2) + this.skip(); + const requestParameters = { + beneficiary: walletBob.publicKey, + asset: api.createType('u128', 1), + bondPrice: api.consts.bondedFinance.stake, + nbOfBonds: api.createType('u128', 10), + maturity: { Finite: { returnIn: api.createType('u32', 16) } }, + reward: { + asset: api.createType('u128', 1), + amount: api.consts.bondedFinance.minReward, + maturity: api.createType('u32', 1) + } + }; + const { data: [result], } = await txBondedFinanceOfferSuccessTest(walletBob, requestParameters); + expect(result.toNumber()).to.be.a('number'); + bondOfferId2 = result.toNumber(); + }); + + /** + * bondedFinance.bond(offerId:u64, nbOfBonds:u128) Tests + */ + // #3 Bob can bond to the offer Alice has created. + it('Can bond to newly created offer', async function () { + if (!testConfiguration.enabledTests.offer_bond__success.bond) + this.skip(); + const offerId = api.createType('u64', bondOfferId1); + const nbOfBonds = api.createType('u128', 1); + const { data:[result], } = await txBondedFinanceBondSuccessTest(walletBob, offerId, nbOfBonds); + expect(result.toNumber()).to.be + .equal(bondOfferId1); + }); + }); + + /** + * Runs all tx FAILURE tests for the bondedFinance pallet. + */ + describe('tx.bondedFinance.offer Failure Tests', function () { + if (!testConfiguration.enabledTests.offer_bond__failure.enabled) + return; + // Timeout set to 2 minutes + this.timeout(2*60*1000); + // #4 Alice can't create am offer with the bond price too low. + it('Should not be able to create offer (bondPrice < MIN_VESTED_TRANSFER)', async function () { + if (!testConfiguration.enabledTests.offer_bond__failure.create_offer_price_lt_MIN_VESTED_TRANSFER) + this.skip(); + const requestParameters = { + beneficiary: walletAlice.publicKey, + asset: api.createType('u128', 1), + bondPrice: api.createType('u128', api.consts.bondedFinance.stake.toNumber()-1), + nbOfBonds: api.createType('u128', 10), + maturity: {Finite: {returnIn: api.createType('u32', 16)}}, + reward: { + asset: api.createType('u128', 1), + amount: api.consts.bondedFinance.minReward, + maturity: api.createType('u32', 1) + } + }; + const {data: [result],} = await txBondedFinanceOfferFailureTest(walletAlice, requestParameters); + // !Note: Doesn't provide failure message, and instead returns the same result as a successful call. + // E.g. on a clean chain it returns `3`, because it would have been the third offer. + expect(result.toNumber()).to.be.a('Number'); + }); + + // #5 Alice can't create offer with the reward amount too low. + it('Should not be able to create offer (reward.amount < MinReward)', async function () { + if (!testConfiguration.enabledTests.offer_bond__failure.create_offer_reward_amt_lt_MinReward) + this.skip(); + const requestParameters = { + beneficiary: walletAlice.publicKey, + asset: api.createType('u128', 1), + bondPrice: api.consts.bondedFinance.stake, + nbOfBonds: api.createType('u128', 10), + maturity: {Finite: {returnIn: api.createType('u32', 16)}}, + reward: { + asset: api.createType('u128', 1), + amount: api.createType('u128', api.consts.bondedFinance.minReward.toNumber()-1), + maturity: api.createType('u32', 1) + } + }; + const {data: [result],} = await txBondedFinanceOfferFailureTest(walletAlice, requestParameters); + expect(result.toNumber()).to.be.a('number'); + }); + + // #5 Alice can't create offer with the reward amount too low. + it('Should not be able to create offer (reward.asset does not exist)', async function () { + if (!testConfiguration.enabledTests.offer_bond__failure.create_offer_reward_asset_not_exist) + this.skip(); + const requestParameters = { + beneficiary: walletAlice.publicKey, + asset: api.createType('u128', 1), + bondPrice: api.consts.bondedFinance.stake, + nbOfBonds: api.createType('u128', 10), + maturity: {Finite: {returnIn: api.createType('u32', 16)}}, + reward: { + asset: api.createType('u128', 1337), + amount: api.consts.bondedFinance.minReward, + maturity: api.createType('u32', 1) + } + }; + const {data: [result],} = await txBondedFinanceOfferFailureTest(walletAlice, requestParameters); + expect(result.toNumber()).to.be.a('number'); + }); + }); + + /** + * Runs FAILURE tests for bondedFinance.cancel(offerId) + */ + describe('tx.bondedFinance.cancel Failure Tests', function () { + if (!testConfiguration.enabledTests.cancel_failure.enabled) + return; + // Timeout set to 2 minutes + this.timeout(2*60*1000); + it('Should not be able to cancel offer that doesn\'t exist', async function () { + if (!testConfiguration.enabledTests.cancel_failure.cancel_offer_not_exist) + this.skip(); + const offerId = 1337; + const { data: [result], } = await txBondedFinanceCancelFailureTest(walletAlice, offerId); + expect(result.toNumber()).to.be.a('number'); + }); + }); + + /** + * Runs SUCCESS tests for bondedFinance.cancel(offerId) + */ + describe('tx.bondedFinance.cancel Success Tests', function () { + if (!testConfiguration.enabledTests.cancel_success.enabled) + return; + // Timeout set to 2 minutes + this.timeout(2*60*1000); + // #6 Alice should be able to cancel her offer. + it('Can cancel offer created in first bondedFinance.offer test by creator', async function () { + if (!testConfiguration.enabledTests.cancel_success.cancel_by_creator) + this.skip(); + const offerId = bondOfferId1; + const { data: [result], } = await txBondedFinanceCancelSuccessTest(walletAlice, offerId); + expect(result.toNumber()).to.be.a('number'); + expect(result.toNumber()).to.be + .equal(bondOfferId1); + }); + + // #7 A sudo command should be able to cancel an offer. + it('Can sudo (diff. account) cancel offer created in second bondedFinance.offer', async function () { + if (!testConfiguration.enabledTests.cancel_success.cancel_by_sudo) + this.skip(); + const offerId = bondOfferId2; + const { data: [result], } = await txBondedFinanceCancelSudoSuccessTest(walletAlice, offerId); + expect(result.isOk).to.be.true; + }); + }); +}); diff --git a/integration-tests/runtime-tests/test/tests/crowdloanRewards/queryCrowdloanRewardsTests.ts b/integration-tests/runtime-tests/test/tests/crowdloanRewards/queryCrowdloanRewardsTests.ts new file mode 100644 index 00000000000..574985c2db5 --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/crowdloanRewards/queryCrowdloanRewardsTests.ts @@ -0,0 +1,54 @@ +/* eslint-disable no-trailing-spaces */ +import { expect } from 'chai'; + + +describe('query.crowdloanRewards.account Tests', function() { + // Set timeout to 1 minute. + this.timeout(60*1000); + it('query.crowdloanRewards.claimedRewards Tests', async function() { + await QueryCrowdloanRewardsTests.queryCrowdloanRewardsClaimedRewardsTest(); + }); + + it('query.crowdloanRewards.totalContributors Tests', async function() { + await QueryCrowdloanRewardsTests.queryCrowdloanRewardsTotalContributorsTest(); + }); + + it('query.crowdloanRewards.totalRewards Tests', async function() { + await QueryCrowdloanRewardsTests.queryCrowdloanRewardsTotalRewardsTest(); + }); +}); + +/** + * Contains all Query tests for the pallet: + * crowdloanRewards + * + * ToDo: Add additional checks. + */ +export class QueryCrowdloanRewardsTests { + /** + * Checks for a successful return of + * query.crowdloanRewards.claimedRewards() + */ + public static async queryCrowdloanRewardsClaimedRewardsTest() { + const claimedRewards = await api.query.crowdloanRewards.claimedRewards(); + expect(claimedRewards.toNumber()).to.be.a('number'); + } + + /** + * Checks for a successful return of + * query.crowdloanRewards.totalContributors() + */ + public static async queryCrowdloanRewardsTotalContributorsTest() { + const totalContributors = await api.query.crowdloanRewards.totalContributors(); + expect(totalContributors.toNumber()).to.be.a('number'); + } + + /** + * Checks for a successful return of + * query.crowdloanRewards.totalRewards() + */ + public static async queryCrowdloanRewardsTotalRewardsTest() { + const totalRewards = await api.query.crowdloanRewards.totalRewards(); + expect(totalRewards.toNumber()).to.be.a('number'); + } +} diff --git a/integration-tests/runtime-tests/test/tests/crowdloanRewards/rpcCrowdloanRewardsTests.ts b/integration-tests/runtime-tests/test/tests/crowdloanRewards/rpcCrowdloanRewardsTests.ts new file mode 100644 index 00000000000..00bfe170159 --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/crowdloanRewards/rpcCrowdloanRewardsTests.ts @@ -0,0 +1,22 @@ +import { expect } from 'chai'; +import testConfiguration from './test_configuration.json'; + +describe('rpc.crowdloanRewards Tests', function () { + if (!testConfiguration.enabledTests.rpc.enabled) + return; + it('rpc.crowdloanRewards.account Tests', async function () { + if (!testConfiguration.enabledTests.rpc.account__success) + this.skip(); + const accountId = walletAlice.derive('/contributor-1/reward').publicKey; + const result = await RpcCrowdloanRewardsTests.rpcCrowdloanRewardsTest(accountId); + expect(result).to.be.a["bignumber"].that.equals('0'); + }); +}); + +export class RpcCrowdloanRewardsTests { + public static async rpcCrowdloanRewardsTest(accountId: string | Uint8Array) { + return await api.rpc.crowdloanRewards.amountAvailableToClaimFor( + accountId, + ); + } +} diff --git a/integration-tests/runtime-tests/test/tests/crowdloanRewards/test_configuration.json b/integration-tests/runtime-tests/test/tests/crowdloanRewards/test_configuration.json new file mode 100644 index 00000000000..bfa012c1d7d --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/crowdloanRewards/test_configuration.json @@ -0,0 +1,57 @@ +{ + "enabledTests": { + "query": { + "enabled": true, + "addAssetAndInfo_success": { + "enabled": true, + "add1": true + }, + "setSigner_success": { + "enabled": true, + "set1": true + }, + "addStake_success": { + "enabled": true, + "add1": true + }, + "submitPrice_success": { + "enabled": true, + "submit1": true + }, + "removeStake_success": { + "enabled": true, + "remove1": true + }, + "reclaimStake_success": { + "enabled": true, + "reclaim1": true + } + }, + "tx": { + "enabled": true, + "setup": { + "provideAssets": true + }, + "populate_success": { + "enabled": true, + "populate1": true + }, + "initialize_success": { + "enabled": true, + "initialize1": true + }, + "associate_success": { + "enabled": true, + "associate1": true + }, + "claim_success": { + "enabled": true, + "claim1": true + } + }, + "rpc": { + "enabled": true, + "account__success": true + } + } +} \ No newline at end of file diff --git a/integration-tests/runtime-tests/test/tests/crowdloanRewards/txCrowdloanRewardsTests.ts b/integration-tests/runtime-tests/test/tests/crowdloanRewards/txCrowdloanRewardsTests.ts new file mode 100644 index 00000000000..e9d30622812 --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/crowdloanRewards/txCrowdloanRewardsTests.ts @@ -0,0 +1,292 @@ +import R from 'ramda'; +import { PalletCrowdloanRewardsModelsRemoteAccount } from '@composable/types/interfaces'; +import { u128, u32 } from '@polkadot/types-codec'; +import { expect } from 'chai'; +import { IKeyringPair } from '@polkadot/types/types'; +import {KeyringPair} from "@polkadot/keyring/types"; +import testConfiguration from './test_configuration.json'; +import {sendAndWaitForSuccess, sendUnsignedAndWaitForSuccess} from "@composable/utils/polkadotjs"; +import {mintAssetsToWallet} from "@composable/utils/mintingHelper"; + +const toHexString = bytes => + Array.prototype.map.call(bytes, x => ('0' + (x & 0xFF).toString(16)).slice(-2)).join(''); + +// The prefix is defined as pallet config +const proofMessage = (account: IKeyringPair, isEth=false) => + (isEth ? "picasso-" : "picasso-") + toHexString(account.publicKey) + (isEth ? "" : ""); + +const ethAccount = (seed: number) => + web3.eth.accounts.privateKeyToAccount("0x" + seed.toString(16).padStart(64, '0')); + + +/** + * Task order list: + * 1. Provide funds to crowdloan pallet + * 2. Populate the list of contributors + * 3. Initialize the crowdloan + * 4. Associate a picassso account (which also claims) + * 5. Claiming more rewards. + */ +describe('CrowdloanRewards Tests', function() { + if (!testConfiguration.enabledTests.tx.enabled) + return; + + let wallet: KeyringPair, + sudoKey: KeyringPair, + contributor: KeyringPair, + contributorRewardAccount: KeyringPair, + contributorEth, + contributorEthRewardAccount: KeyringPair; + + let onExistingChain = false; + + /** + * We mainly set up some variables here. + * + * We also identify if this chain had already tests run on it. + * And if so, we skip the populate() and initialize() tests. + */ + before('Initializing Variables', async function() { + sudoKey = walletAlice; + wallet = walletAlice; + let associationExisting = true; + let i = 1; + while (associationExisting) { + contributor = wallet.derive("/contributor-" + i); + contributorEth = ethAccount(i); + // arbitrary, user defined reward account + contributorRewardAccount = contributor.derive("/reward"); + contributorEthRewardAccount = wallet.derive("/reward-eth-" + i); + const existingAssociations = await api.query.crowdloanRewards.associations(contributorRewardAccount.publicKey); + if (existingAssociations.toString() == "") { + associationExisting = false; + } else { + onExistingChain = true; + } + i++; + } + if (onExistingChain) + console.info("tx.crowdloanRewards Tests: Detected already configured chain! " + + "Skipping populate() & initialize().") + }); + + before('Providing funds to crowdloan pallet', async function() { + if (!testConfiguration.enabledTests.tx.setup.provideAssets) + this.skip(); + // 2 minutes timeout + this.timeout(60 * 2 * 1000); + const {data: [resultAccountId1, resultAccountId2, resultNumber],} + = await TxCrowdloanRewardsTests.beforeCrowdlownTestsProvideFunds(sudoKey); + expect(resultAccountId1.toString()).to.be + .equal(api.createType('AccountId32', walletAlice.publicKey).toString()); + expect(resultNumber).to.be.a.bignumber; + }); + + /** + * Here we populate the crowdloan pallet with a random generated list of contributors. + * + * This is a SUDO call and is checked with `.isOk`. + */ + it('Can populate the list of contributors', async function() { + if (!testConfiguration.enabledTests.tx.populate_success.populate1 || onExistingChain) + this.skip(); + // 2 minutes timeout + this.timeout(60 * 2 * 1000); + const { data: [result,], } = await TxCrowdloanRewardsTests.txCrowdloanRewardsPopulateTest(sudoKey, walletAlice); + expect(result.isOk).to.be.true; + }); + + /** + * Here we initialize the crowdloan with our populated list of contributors. + * + * This is a SUDO call and is checked with `.isOk`. + */ + it('Can initialize the crowdloan', async function() { + if (!testConfiguration.enabledTests.tx.initialize_success.initialize1 || onExistingChain) + this.skip(); + // 2 minutes timeout + this.timeout(60 * 2 * 1000); + const { data: [result], } = await TxCrowdloanRewardsTests.txCrowdloanRewardsInitializeTest(sudoKey); + expect(result.isOk).to.be.true; + }); + + /*** + * Here we associate our picasso account with our ETH & RelayChain wallets. + * + * Here we send 2 transactions at the same time, therefore we have 2 results, + * though with the exact same result structure. + * + * Results: + * 1. The public key of the remote wallet. + * 2. The public key of the transacting wallet. + */ + it('Can associate a picasso account', async function() { + if (!testConfiguration.enabledTests.tx.associate_success.associate1) + this.skip(); + // 2 minutes timeout + this.timeout(60 * 20 * 1000); + await Promise.all([ + TxCrowdloanRewardsTests.txCrowdloanRewardsEthAssociateTest( + contributorEth, + contributorEthRewardAccount + ), + TxCrowdloanRewardsTests.txCrowdloanRewardsRelayAssociateTests( + contributor, + contributorRewardAccount + ), + ]).then(function([result, result2]) { + expect(result.data[1].toString()).to.be + .equal(api.createType('AccountId32', contributorEthRewardAccount.publicKey).toString()); + expect(result2.data[1].toString()).to.be + .equal(api.createType('AccountId32', contributorRewardAccount.publicKey).toString()); + }); + }); + + /** + * Can we finally claim the crowdloan reward? + * We're gonna find out! + * + * Results are: + * 1. The public key of the remote account. + * 2. The public key of the transacting wallet. + * 3. The claimed amount. + */ + it('Can claim the crowdloan reward', async function() { + if (!testConfiguration.enabledTests.tx.claim_success.claim1 || onExistingChain) + this.skip(); + // 2 minutes timeout + this.timeout(60 * 2 * 1000); + const { data: [resultRemoteAccountId, resultAccountId, resultClaimedAmount], } + = await TxCrowdloanRewardsTests.txCrowdloanRewardsClaimTest(contributorRewardAccount); + expect(resultClaimedAmount).to.be.a.bignumber; + expect(resultAccountId.toString()).to.be + .equal(api.createType('AccountId32', contributorRewardAccount.publicKey).toString()) + }); +}); + +export class TxCrowdloanRewardsTests { + /** + * Providing the crowdloan pallet with funds + * + * Unfortunately we can't directly mint into the pallet therefore, + * we mint into the Alice wallet and transfer funds from there. + * + * @param {KeyringPair} sudoKey Wallet with sudo rights. + */ + public static async beforeCrowdlownTestsProvideFunds(sudoKey:KeyringPair) { + const palletPublicKey = api.consts.crowdloanRewards.accountId; + await mintAssetsToWallet(sudoKey, sudoKey, [1]); + return await sendAndWaitForSuccess( + api, + sudoKey, + api.events.balances.Transfer.is, + api.tx.balances.transfer(palletPublicKey, 100000000000000) + ); + } + + /** + * tx.crowdloanRewards.initialize + * + * @param {KeyringPair} sudoKey Wallet with sudo rights. + */ + public static txCrowdloanRewardsInitializeTest(sudoKey:KeyringPair) { + return sendAndWaitForSuccess( + api, + sudoKey, + api.events.sudo.Sudid.is, + api.tx.sudo.sudo( + api.tx.crowdloanRewards.initialize() + ) + ); + } + + /** + * tx.crowdloanRewards.populate + * + * @param {KeyringPair} sudoKey Wallet with sudo rights. + * @param {KeyringPair} contributor The picasso wallet of which the contributor wallets are derived from. + */ + public static async txCrowdloanRewardsPopulateTest(sudoKey:KeyringPair, contributor:KeyringPair) { + const vesting48weeks = api.createType('u32', 100800); + const reward = api.createType('u128', 1_000_000_000_000); + const relay_accounts = + R.unfold(n => n > 50 ? false : [[ + api.createType( + 'PalletCrowdloanRewardsModelsRemoteAccount', + { RelayChain: contributor.derive("/contributor-" + n.toString()).publicKey } + ), + reward, + vesting48weeks, + ], n + 1], 1); + const eth_accounts = + R.unfold(n => n > 50 ? false : [[ + api.createType( + 'PalletCrowdloanRewardsModelsRemoteAccount', + { Ethereum: ethAccount(n).address } + ), + reward, + vesting48weeks, + ], n + 1], 1); + const accounts = relay_accounts.concat(eth_accounts); + return await sendAndWaitForSuccess( + api, + sudoKey, + api.events.sudo.Sudid.is, + api.tx.sudo.sudo( + api.tx.crowdloanRewards.populate(accounts) + ) + ); + } + + /** + * tx.crowdloanRewards.associate RelayChain + * + * @param {KeyringPair} contributor The contributor relay chain wallet public key. + * @param {KeyringPair} contributorRewardAccount The wallet the contributor wants to receive their PICA to. + */ + public static async txCrowdloanRewardsRelayAssociateTests(contributor:KeyringPair, contributorRewardAccount) { + // arbitrary, user defined reward account + const proof = contributor.sign(proofMessage(contributorRewardAccount)); + return await sendUnsignedAndWaitForSuccess( + api, + api.events.crowdloanRewards.Associated.is, + api.tx.crowdloanRewards.associate( + contributorRewardAccount.publicKey, + api.createType('PalletCrowdloanRewardsModelsProof', + { RelayChain: [contributor.publicKey, { Sr25519: proof }] }) + ) + ); + } + + /** + * tx.crowdloanRewards.associate ETH Chain + * + * @param {KeyringPair} contributor The contributor ETH chain wallet public key. + * @param {KeyringPair} contributorRewardAccount The wallet the contributor wants to receive their PICA to. + */ + public static async txCrowdloanRewardsEthAssociateTest(contributor, contributorRewardAccount) { + const proof = contributor.sign(proofMessage(contributorRewardAccount, true)); + return await sendUnsignedAndWaitForSuccess( + api, + api.events.crowdloanRewards.Associated.is, + api.tx.crowdloanRewards.associate( + contributorRewardAccount.publicKey, + api.createType('PalletCrowdloanRewardsModelsProof', { Ethereum: proof.signature }) + ) + ); + } + + /** + * tx.crowdloanRewards.claim + * + * @param { KeyringPair } wallet The reward account which tries to claim. + */ + public static async txCrowdloanRewardsClaimTest(wallet:KeyringPair) { + return await sendAndWaitForSuccess( + api, + wallet, + api.events.crowdloanRewards.Claimed.is, + api.tx.crowdloanRewards.claim() + ); + } +} diff --git a/integration-tests/runtime-tests/test/tests/dexTests/constantProductDex/constantProductTests.ts b/integration-tests/runtime-tests/test/tests/dexTests/constantProductDex/constantProductTests.ts new file mode 100644 index 00000000000..507fd9f8602 --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/dexTests/constantProductDex/constantProductTests.ts @@ -0,0 +1,167 @@ +import testConfiguration from './test_configuration.json'; +import {expect} from "chai"; +import {KeyringPair} from "@polkadot/keyring/types"; +import { addFundstoThePool, buyFromPool, createPool, getOwnerFee, getUserTokens, removeLiquidityFromPool, sellToPool, swapTokenPairs } from './testHandlers/constantProductDexHelper'; +import { mintAssetsToWallet } from '@composable/utils/mintingHelper'; + +/** + * This suite includes tests for the constantProductDex Pallet. + * Tested functionalities are: + * Create - AddLiquidity - Buy - Sell - Swap - RemoveLiquidity with basic calculations with constantProductFormula and OwnerFee. + * Mainly consists of happy path testing. +*/ +describe('tx.constantProductDex Tests', function () { + + let walletId1: KeyringPair, + walletId2: KeyringPair; + let poolId: number, + baseAssetId: number, + quoteAssetId: number, + wallet1LpTokens: number, + baseAmount: number, + quoteAmount: number, + ownerFee: number, + walletId1Account: string, + walletId2Account: string; + + before('Initialize variables', function() { + walletId1 = walletEve.derive("/test/constantProductDex/walletId1"); + walletId2 = walletBob.derive("/test/constantProductDex/walletId2"); + walletId1Account = api.createType('AccountId32', walletId1.address).toString(); + walletId2Account = api.createType('AccountId32', walletId2.address).toString(); + baseAssetId = 2; + quoteAssetId = 3; + baseAmount = 2500; + quoteAmount = 2500; + //sets the owner fee to 1.00%/Type Permill + ownerFee = 10000; + }); + + before('Minting assets', async function() { + this.timeout(8*60*1000); + await mintAssetsToWallet(walletId1, walletAlice, [1, baseAssetId, quoteAssetId]); + await mintAssetsToWallet(walletId2, walletAlice, [1, baseAssetId, quoteAssetId]); + }); + + describe('tx.constantProductDex Success Tests', function() { + if(!testConfiguration.enabledTests.successTests.enabled){ + return; + } + + it('Users can create a constantProduct pool', async function() { + if(!testConfiguration.enabledTests.successTests.createPool.enabled){ + return; + } + this.timeout(2*60*1000); + poolId = await createPool(walletId1, + baseAssetId, + quoteAssetId, + ownerFee + ); + let returnedOwnerFee = await getOwnerFee(poolId); + //verify if the pool is created + expect(poolId).to.be.a('number'); + //Verify if the pool is created with specified owner Fee + expect(returnedOwnerFee).to.be.equal(ownerFee); + }) + + it('Given that users has sufficient balance, User1 can send funds to pool', async function(){ + if(!testConfiguration.enabledTests.successTests.addLiquidityTests.enabled){ + return; + } + this.timeout(2*60*1000); + const result = await addFundstoThePool(walletId1, + baseAmount, + quoteAmount + ); + //Once funds added to the pool, User is deposited with LP Tokens. + wallet1LpTokens = result.returnedLPTokens.toNumber(); + expect(result.baseAdded.toNumber()).to.be.equal(baseAmount); + expect(result.quoteAdded.toNumber()).to.be.equal(quoteAmount); + expect(result.walletIdResult.toString()).to.be.equal(walletId1Account); + }); + + it('User2 can send funds to pool and router adjusts deposited amounts based on constantProductFormula to prevent arbitrage', async function(){ + if(!testConfiguration.enabledTests.successTests.addLiquidityTests.enabled){ + return; + } + this.timeout(2*60*1000); + const assetAmount = 30; + const quoteAmount = 100; + const result = await addFundstoThePool(walletId2, assetAmount, quoteAmount); + //The deposited amount should be maintained by the dex router hence should maintain 1:1. + expect(result.quoteAdded.toNumber()).to.be.equal(assetAmount); + expect(result.walletIdResult.toString()).to.be.equal(walletId2Account); + }); + + it("Given the pool has the sufficient funds, User1 can't completely drain the funds", async function(){ + if(!testConfiguration.enabledTests.successTests.poolDrainTest.enabled){ + return; + } + this.timeout(2*60*1000); + await buyFromPool(walletId1, baseAssetId, 2800).catch(error=>{ + expect(error.message).to.contain('arithmetic'); + }); + }); + + it('User1 can buy from the pool and router respects the constantProductFormula', async function() { + if(!testConfiguration.enabledTests.successTests.buyTest.enabled){ + return; + } + this.timeout(2 * 60 * 1000); + const result = await buyFromPool(walletId1, baseAssetId, 30); + expect(result.accountId.toString()).to.be.equal(walletId1Account); + //Expected amount is calculated based on the constantProductFormula which is 1:1 for this case. + expect(result.quoteAmount.toNumber()).to.be.equal(result.expectedConversion); + }); + + it('User1 can sell on the pool', async function(){ + if(!testConfiguration.enabledTests.successTests.sellTest.enabled){ + return; + } + this.timeout(2*60*1000); + const accountIdSeller = await sellToPool(walletId1, baseAssetId, 20); + expect(accountIdSeller).to.be.equal(walletId1Account); + }); + + it('User2 can swap from the pool', async function(){ + if(!testConfiguration.enabledTests.successTests.swapTest.enabled){ + return; + } + this.timeout(2*60*1000); + const quotedAmount = 12; + const result = await swapTokenPairs(walletId2, + baseAssetId, + quoteAssetId, + quotedAmount, + ); + expect(result.returnedQuoteAmount.toNumber()).to.be.equal(quotedAmount); + }); + + it('Owner of the pool receives owner fee on the transactions happened in the pool', async function(){ + if(!testConfiguration.enabledTests.successTests.ownerFeeTest.enabled){ + return; + } + this.timeout(2*60*1000); + let ownerInitialTokens = await getUserTokens(walletId1, quoteAssetId); + const result = await buyFromPool(walletId2, baseAssetId, 500); + let ownerAfterTokens = await getUserTokens(walletId1, quoteAssetId); + //verifies the ownerFee to be added in the owner account. + expect(ownerAfterTokens).to.be.equal(ownerInitialTokens+(result.ownerFee.toNumber())) + }); + + it('User1 can remove liquidity from the pool by using LP Tokens', async function(){ + if(!testConfiguration.enabledTests.successTests.removeLiquidityTest.enabled){ + return; + } + this.timeout(2*60*1000); + //Randomly checks an integer value that is always < mintedLPTokens. + const result = await removeLiquidityFromPool(walletId1, Math.floor(Math.random()*wallet1LpTokens)); + expect(result.remainingLpTokens.toNumber()).to.be.equal(result.expectedLPTokens); + }); + }); +}) + + + + diff --git a/integration-tests/runtime-tests/test/tests/dexTests/constantProductDex/testHandlers/constantProductDexHelper.ts b/integration-tests/runtime-tests/test/tests/dexTests/constantProductDex/testHandlers/constantProductDexHelper.ts new file mode 100644 index 00000000000..18e3c07b0a3 --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/dexTests/constantProductDex/testHandlers/constantProductDexHelper.ts @@ -0,0 +1,152 @@ +import { sendAndWaitForSuccess } from '@composable/utils/polkadotjs'; +import {KeyringPair} from "@polkadot/keyring/types"; +import { u128 } from '@polkadot/types-codec'; + +/** + *Contains handler methods for the constantProductDex Tests. + */ +let poolId: number; +let constantProductk: number; +let baseAmountTotal: number; +let quoteAmountTotal: number; +let mintedLPTokens: number; +baseAmountTotal = 0; +quoteAmountTotal = 0; +mintedLPTokens = 0; + +export async function createPool(walletId: KeyringPair, baseAssetId: number, quoteAssetId: number, ownerFee: number){ + const pair = api.createType('ComposableTraitsDefiCurrencyPair', { + base: api.createType('u128', baseAssetId), + quote: api.createType('u128', quoteAssetId) + }); + const fee = api.createType('Permill', 0); + const ownerFees = api.createType('Permill', ownerFee); + const {data: [resultPoolId],} = await sendAndWaitForSuccess( + api, + walletId, + api.events.constantProductDex.PoolCreated.is, + api.tx.constantProductDex.create(pair, fee, ownerFees) + ); + poolId = resultPoolId.toNumber(); + return poolId; +} +export async function addFundstoThePool(walletId:KeyringPair, baseAmount:number, quoteAmount:number){ + const baseAmountParam = api.createType('u128', baseAmount); + const quoteAmountParam = api.createType('u128', quoteAmount); + const keepAliveParam = api.createType('bool', true); + const minMintAmountParam = api.createType('u128', 0); + const {data: [,walletIdResult,baseAdded, quoteAdded,returnedLPTokens]} =await sendAndWaitForSuccess( + api, + walletId, + api.events.constantProductDex.LiquidityAdded.is, + api.tx.constantProductDex.addLiquidity(poolId, + baseAmountParam, + quoteAmountParam, + minMintAmountParam, + keepAliveParam + ) + ); + mintedLPTokens += returnedLPTokens.toNumber(); + baseAmountTotal += baseAdded.toNumber(); + quoteAmountTotal += quoteAdded.toNumber(); + return {walletIdResult, baseAdded, quoteAdded, returnedLPTokens}; +} + +export async function buyFromPool(walletId: KeyringPair, assetId:number, amountToBuy: number){ + const poolIdParam = api.createType('u128', poolId); + const assetIdParam = api.createType('u128', assetId); + const amountParam = api.createType('u128', amountToBuy); + const keepAlive = api.createType('bool', true); + constantProductk = baseAmountTotal*quoteAmountTotal; + let expectedConversion = Math.floor((constantProductk/(baseAmountTotal-amountToBuy)))-quoteAmountTotal; + const {data: [accountId,poolArg,quoteArg,swapArg,amountgathered,quoteAmount,ownerFee] } = await sendAndWaitForSuccess( + api, + walletId, + api.events.constantProductDex.Swapped.is, + api.tx.constantProductDex.buy( + poolIdParam, + assetIdParam, + amountParam, + keepAlive + ) + ); + return {accountId, quoteAmount, expectedConversion, ownerFee}; +} + +export async function sellToPool(walletId: KeyringPair, assetId: number, amount:number){ + const poolIdParam = api.createType('u128', poolId); + const assetIdParam = api.createType('u128', assetId); + const amountParam = api.createType('u128', amount); + const keepAliveParam = api.createType('bool', false); + const {data: [result, ...rest]} = await sendAndWaitForSuccess( + api, + walletId, + api.events.constantProductDex.Swapped.is, + api.tx.constantProductDex.sell( + poolIdParam, + assetIdParam, + amountParam, + keepAliveParam + ) + ) + return result.toString(); +} + +export async function removeLiquidityFromPool(walletId: KeyringPair, lpTokens:number){ + const expectedLPTokens = mintedLPTokens-lpTokens; + const poolIdParam = api.createType('u128', poolId); + const lpTokenParam = api.createType('u128', lpTokens); + const minBaseParam = api.createType('u128', 0); + const minQuoteAmountParam = api.createType('u128', 0); + const {data: [resultPoolId,resultWallet,resultBase,resultQuote,remainingLpTokens]}=await sendAndWaitForSuccess( + api, + walletId, + api.events.constantProductDex.LiquidityRemoved.is, + api.tx.constantProductDex.removeLiquidity( + poolIdParam, + lpTokenParam, + minBaseParam, + minQuoteAmountParam + ) + ); + return {remainingLpTokens, expectedLPTokens} +} + +export async function swapTokenPairs(wallet: KeyringPair, + baseAssetId: number, + quoteAssetId:number, + quoteAmount: number, + minReceiveAmount: number = 0 + ){ + const poolIdParam = api.createType('u128', poolId); + const currencyPair = api.createType('ComposableTraitsDefiCurrencyPair', { + base: api.createType('u128', baseAssetId), + quote: api.createType('u128',quoteAssetId) + }); + const quoteAmountParam = api.createType('u128', quoteAmount); + const minReceiveParam = api.createType('u128', minReceiveAmount); + const keepAliveParam = api.createType('bool', true); + const {data: [resultPoolId,resultWallet,resultQuote,resultBase,resultBaseAmount,returnedQuoteAmount,]}= await sendAndWaitForSuccess( + api, + wallet, + api.events.constantProductDex.Swapped.is, + api.tx.constantProductDex.swap( + poolIdParam, + currencyPair, + quoteAmountParam, + minReceiveParam, + keepAliveParam + ) + ); + return {returnedQuoteAmount}; +} + +export async function getUserTokens(walletId: KeyringPair, assetId: number){ + const {free, reserved, frozen} = await api.query.tokens.accounts(walletId.address, assetId); + return free.toNumber(); +} + +export async function getOwnerFee(poolId: number){ + const result = await api.query.constantProductDex.pools(api.createType('u128', poolId)); + return result.unwrap().ownerFee.toNumber(); +} \ No newline at end of file diff --git a/integration-tests/runtime-tests/test/tests/dexTests/constantProductDex/test_configuration.json b/integration-tests/runtime-tests/test/tests/dexTests/constantProductDex/test_configuration.json new file mode 100644 index 00000000000..7ad92d3b661 --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/dexTests/constantProductDex/test_configuration.json @@ -0,0 +1,33 @@ +{ + "enabledTests": { + "enabled": true, + + "successTests": { + "enabled": true, + "createPool": { + "enabled": true + }, + "addLiquidityTests": { + "enabled": true + }, + "poolDrainTest": { + "enabled": true + }, + "buyTest": { + "enabled": true + }, + "sellTest": { + "enabled": true + }, + "swapTest": { + "enabled": true + }, + "ownerFeeTest": { + "enabled": true + }, + "removeLiquidityTest": { + "enabled": true + } + } + } +} \ No newline at end of file diff --git a/integration-tests/runtime-tests/test/tests/examples/querySystemAccountTests.ts b/integration-tests/runtime-tests/test/tests/examples/querySystemAccountTests.ts new file mode 100644 index 00000000000..cb483cea91f --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/examples/querySystemAccountTests.ts @@ -0,0 +1,41 @@ +import { expect } from 'chai'; +import {ApiPromise} from "@polkadot/api"; +import testConfiguration from './test_configuration.json'; + +/** + * Example Test + * Just checking if provided wallet balance >0. + */ +// describe(name, function) groups all query tests for the system pallet. +describe('query.system Tests', function () { + // Check if group of tests are enabled. + if (!testConfiguration.enabledTests.query.enabled) + return; + + // This describe groups all system.account query tests. + describe('query.system.account Tests', function() { + // Check if group of tests are enabled. + if (!testConfiguration.enabledTests.query.account__success.enabled) + return; + + // it(name, function) describes a single test. + it('Wallet balance check should be >0', async function () { + // Check if this test is enabled. + if (!testConfiguration.enabledTests.query.account__success.balanceGTZero1) + this.skip(); + await QuerySystemAccountTests.checkBalance(api, walletAlice.address); + }); + }); +}); + +export class QuerySystemAccountTests { + /** + * Tests by checking the balance of the supplied account is >0 + * @param {ApiPromise} api Connected API Promise. + * @param {string} walletAddress wallet public key + */ + public static async checkBalance(api:ApiPromise, walletAddress:string) { + const {data: balance} = await api.query.system.account(walletAddress); + expect(balance.free.toBigInt() > 0).to.be.true; // .to.be.greater(0) didn't work for some reason. + } +} diff --git a/integration-tests/runtime-tests/test/tests/examples/test_configuration.json b/integration-tests/runtime-tests/test/tests/examples/test_configuration.json new file mode 100644 index 00000000000..00174eea184 --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/examples/test_configuration.json @@ -0,0 +1,11 @@ +{ + "enabledTests": { + "query": { + "enabled": true, + "account__success": { + "enabled": true, + "balanceGTZero1": true + } + } + } +} \ No newline at end of file diff --git a/integration-tests/runtime-tests/src/tests/tx/oracle/testHandlers/addAssetAndInfoTests.ts b/integration-tests/runtime-tests/test/tests/oracle/testHandlers/addAssetAndInfoTests.ts similarity index 99% rename from integration-tests/runtime-tests/src/tests/tx/oracle/testHandlers/addAssetAndInfoTests.ts rename to integration-tests/runtime-tests/test/tests/oracle/testHandlers/addAssetAndInfoTests.ts index 510d2fecb2e..7e9d172db2b 100644 --- a/integration-tests/runtime-tests/src/tests/tx/oracle/testHandlers/addAssetAndInfoTests.ts +++ b/integration-tests/runtime-tests/test/tests/oracle/testHandlers/addAssetAndInfoTests.ts @@ -39,4 +39,4 @@ export async function txOracleAddAssetAndInfoSuccessTest( ), ) ); -} \ No newline at end of file +} diff --git a/integration-tests/runtime-tests/src/tests/tx/oracle/testHandlers/addStakeTests.ts b/integration-tests/runtime-tests/test/tests/oracle/testHandlers/addStakeTests.ts similarity index 99% rename from integration-tests/runtime-tests/src/tests/tx/oracle/testHandlers/addStakeTests.ts rename to integration-tests/runtime-tests/test/tests/oracle/testHandlers/addStakeTests.ts index a222a222ad8..12208a5e307 100644 --- a/integration-tests/runtime-tests/src/tests/tx/oracle/testHandlers/addStakeTests.ts +++ b/integration-tests/runtime-tests/test/tests/oracle/testHandlers/addStakeTests.ts @@ -1,6 +1,6 @@ -import {sendAndWaitForSuccess} from "@composable/utils/polkadotjs"; import {u128} from "@polkadot/types-codec"; import {expect} from "chai"; +import {sendAndWaitForSuccess} from "@composable/utils/polkadotjs"; export async function runBeforeTxOracleAddStake(sudoKey, wallet1, wallet2) { @@ -38,4 +38,4 @@ export async function txOracleAddStakeSuccessTest(sender, stake:u128) { api.tx.oracle.addStake(stake), false ); -} \ No newline at end of file +} diff --git a/integration-tests/runtime-tests/src/tests/tx/oracle/testHandlers/reclaimStakeTests.ts b/integration-tests/runtime-tests/test/tests/oracle/testHandlers/reclaimStakeTests.ts similarity index 99% rename from integration-tests/runtime-tests/src/tests/tx/oracle/testHandlers/reclaimStakeTests.ts rename to integration-tests/runtime-tests/test/tests/oracle/testHandlers/reclaimStakeTests.ts index bc26daf761c..5be63731d28 100644 --- a/integration-tests/runtime-tests/src/tests/tx/oracle/testHandlers/reclaimStakeTests.ts +++ b/integration-tests/runtime-tests/test/tests/oracle/testHandlers/reclaimStakeTests.ts @@ -1,9 +1,10 @@ -import {sendAndWaitForSuccess} from "@composable/utils/polkadotjs"; - /** * Tests tx.oracle.reclaimStake with provided parameters that should succeed. * @param controller KeyringPair which is a controller. */ +import {sendAndWaitForSuccess} from "@composable/utils/polkadotjs"; + + export async function txOracleReclaimStakeSuccessTest(controller) { return await sendAndWaitForSuccess( api, @@ -12,4 +13,4 @@ export async function txOracleReclaimStakeSuccessTest(controller) { api.tx.oracle.reclaimStake(), false ); -} \ No newline at end of file +} diff --git a/integration-tests/runtime-tests/src/tests/tx/oracle/testHandlers/removeStakeTests.ts b/integration-tests/runtime-tests/test/tests/oracle/testHandlers/removeStakeTests.ts similarity index 99% rename from integration-tests/runtime-tests/src/tests/tx/oracle/testHandlers/removeStakeTests.ts rename to integration-tests/runtime-tests/test/tests/oracle/testHandlers/removeStakeTests.ts index 289f98cbaf6..bd4d161a987 100644 --- a/integration-tests/runtime-tests/src/tests/tx/oracle/testHandlers/removeStakeTests.ts +++ b/integration-tests/runtime-tests/test/tests/oracle/testHandlers/removeStakeTests.ts @@ -1,9 +1,10 @@ -import {sendAndWaitForSuccess} from "@composable/utils/polkadotjs"; - /** * Tests tx.oracle.removeStake with provided parameters that should succeed. * @param controller KeyringPair which is a controller. */ +import {sendAndWaitForSuccess} from "@composable/utils/polkadotjs"; + + export async function txOracleRemoveStakeSuccessTest(controller) { return await sendAndWaitForSuccess( api, @@ -12,4 +13,4 @@ export async function txOracleRemoveStakeSuccessTest(controller) { api.tx.oracle.removeStake(), false ); -} \ No newline at end of file +} diff --git a/integration-tests/runtime-tests/src/tests/tx/oracle/testHandlers/setSignerTests.ts b/integration-tests/runtime-tests/test/tests/oracle/testHandlers/setSignerTests.ts similarity index 99% rename from integration-tests/runtime-tests/src/tests/tx/oracle/testHandlers/setSignerTests.ts rename to integration-tests/runtime-tests/test/tests/oracle/testHandlers/setSignerTests.ts index b217b9b85bd..7708fb231d5 100644 --- a/integration-tests/runtime-tests/src/tests/tx/oracle/testHandlers/setSignerTests.ts +++ b/integration-tests/runtime-tests/test/tests/oracle/testHandlers/setSignerTests.ts @@ -25,4 +25,4 @@ export async function txOracleSetSignerSuccessTest(controller, signer) { api.tx.oracle.setSigner(signer.address), false ); -} \ No newline at end of file +} diff --git a/integration-tests/runtime-tests/src/tests/tx/oracle/testHandlers/submitPriceTests.ts b/integration-tests/runtime-tests/test/tests/oracle/testHandlers/submitPriceTests.ts similarity index 99% rename from integration-tests/runtime-tests/src/tests/tx/oracle/testHandlers/submitPriceTests.ts rename to integration-tests/runtime-tests/test/tests/oracle/testHandlers/submitPriceTests.ts index 6438f9e5903..d334a2001fb 100644 --- a/integration-tests/runtime-tests/src/tests/tx/oracle/testHandlers/submitPriceTests.ts +++ b/integration-tests/runtime-tests/test/tests/oracle/testHandlers/submitPriceTests.ts @@ -1,12 +1,12 @@ -import {sendAndWaitForSuccess} from "@composable/utils/polkadotjs"; - - /** * Tests tx.oracle.submitPrice with provided parameters that should succeed. * @param signer Connected API Promise w/ sudo rights. * @param price Price to be submitted. * @param assetId Specifies asset id. */ +import {sendAndWaitForSuccess} from "@composable/utils/polkadotjs"; + + export async function txOracleSubmitPriceSuccessTest(signer, price, assetId) { return await sendAndWaitForSuccess( api, @@ -15,4 +15,4 @@ export async function txOracleSubmitPriceSuccessTest(signer, price, assetId) { api.tx.oracle.submitPrice(price, assetId), false ); -} \ No newline at end of file +} diff --git a/integration-tests/runtime-tests/test/tests/oracle/test_configuration.json b/integration-tests/runtime-tests/test/tests/oracle/test_configuration.json new file mode 100644 index 00000000000..492c0c6b7d7 --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/oracle/test_configuration.json @@ -0,0 +1,29 @@ +{ + "enabledTests": { + "enabled": true, + "addAssetAndInfo__success": { + "enabled": true, + "add1": true + }, + "setSigner__success": { + "enabled": true, + "set1": true + }, + "addStake__success": { + "enabled": true, + "add1": true + }, + "submitPrice__success": { + "enabled": true, + "submit1": true + }, + "removeStake__success": { + "enabled": true, + "remove1": true + }, + "reclaimStake__success": { + "enabled": true, + "reclaim1": true + } + } +} \ No newline at end of file diff --git a/integration-tests/runtime-tests/test/tests/oracle/txOracleTests.ts b/integration-tests/runtime-tests/test/tests/oracle/txOracleTests.ts new file mode 100644 index 00000000000..8e9b00e19c3 --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/oracle/txOracleTests.ts @@ -0,0 +1,207 @@ +import {expect} from "chai"; +import {KeyringPair} from "@polkadot/keyring/types"; +import testConfiguration from './test_configuration.json'; +import {txOracleAddAssetAndInfoSuccessTest} from "@composabletests/tests/oracle/testHandlers/addAssetAndInfoTests"; +import { + runBeforeTxOracleSetSigner, + txOracleSetSignerSuccessTest +} from "@composabletests/tests/oracle/testHandlers/setSignerTests"; +import { + runBeforeTxOracleAddStake, + txOracleAddStakeSuccessTest +} from "@composabletests/tests/oracle/testHandlers/addStakeTests"; +import {txOracleSubmitPriceSuccessTest} from "@composabletests/tests/oracle/testHandlers/submitPriceTests"; +import {txOracleRemoveStakeSuccessTest} from "@composabletests/tests/oracle/testHandlers/removeStakeTests"; +import {txOracleReclaimStakeSuccessTest} from "@composabletests/tests/oracle/testHandlers/reclaimStakeTests"; +import {waitForBlocks} from "@composable/utils/polkadotjs"; // Weird import, because I had compilation problems. + +/** + * Contains all TX tests for the pallet: + * Oracle + */ +describe('tx.oracle Tests', function () { + if (!testConfiguration.enabledTests.enabled) + return; + + let assetsCountStart:number; + let newAsset1:number; + let signedWallet: KeyringPair; + let controllerWallet: KeyringPair; + + before(async function() { + // Getting the id for the about to be created asset. + assetsCountStart = (await api.query.oracle.assetsCount()).toNumber(); + newAsset1=assetsCountStart+1; + + signedWallet = walletAlice.derive('/oracleSigner'); + controllerWallet = walletAlice; + }); + /** + * oracle.addAssetAndInfo Success Tests + * + * Sudo command success is checked with `.isOk`. + */ + describe('tx.addAssetAndInfo Success Test', function () { + if (!testConfiguration.enabledTests.addAssetAndInfo__success.enabled) + return; + // Timeout set to 2 minutes + this.timeout(2 * 60 * 1000); + it('Can add new asset and info', async function () { + if (!testConfiguration.enabledTests.addAssetAndInfo__success.add1) + this.skip(); + const assetId = api.createType('u128', newAsset1); + const threshold = api.createType('Percent', 50); + const minAnswers = api.createType('u32', 2); + const maxAnswers = api.createType('u32', 5); + const blockInterval = api.createType('u32', 6); + const reward = api.createType('u128', 150000000000); + const slash = api.createType('u128', 100000000000); + const {data: [result],} = await txOracleAddAssetAndInfoSuccessTest( + controllerWallet, + assetId, + threshold, + minAnswers, + maxAnswers, + blockInterval, + reward, + slash + ); + if (result.isErr) + console.debug(result.asErr.toString()); + expect(result.isOk).to.be.true; + }); + }); + + /** + * oracle.setSigner Success Tests + * To be called by controller. + * + * In `before` we give the signer wallet enough funds to become a signer. + * + * We get 2 results here. + * resultAccount0: The signer wallets public key. + * resultAccount1: The controller wallets public key. + */ + describe('tx.setSigner Success Test', function () { + if (!testConfiguration.enabledTests.setSigner__success.enabled) + return; + // Timeout set to 4 minutes + this.timeout(4 * 60 * 1000); + it('Can set signer', async function () { + if (!testConfiguration.enabledTests.setSigner__success.set1) + this.skip(); + const sudoKey = walletAlice; + const {data: [result],} = await runBeforeTxOracleSetSigner(sudoKey, signedWallet); // Making sure we have funds. + expect(result.isOk).to.be.true; + const {data: [resultAccount0, resultAccount1],} = await txOracleSetSignerSuccessTest(controllerWallet, signedWallet) + .catch(function(exc) { return {data:[exc]}; /* We can't call this.skip() from here. */ }); + if (resultAccount0.message == "oracle.SignerUsed: This signer is already in use" || + resultAccount0.message == "oracle.ControllerUsed: This controller is already in use") + return this.skip(); // If the test is run a second time on the same chain, we already have a signer set. + expect(resultAccount0).to.not.be.an('Error'); + expect(resultAccount1).to.not.be.an('Error'); + expect(resultAccount0.toString()).to.be.equal(api.createType('AccountId32', signedWallet.publicKey).toString()); + expect(resultAccount1.toString()).to.be.equal(api.createType('AccountId32', controllerWallet.publicKey).toString()); + }); + }); + + /** + * oracle.addStake Success Tests + * To be called by controller. + * + * Result is the signer wallets public key. + */ + describe('tx.addStake Success Test', function () { + if (!testConfiguration.enabledTests.addStake__success.enabled) + return; + // Timeout set to 4 minutes + this.timeout(4 * 60 * 1000); + it('Can add stake from creator/controller', async function () { + if (!testConfiguration.enabledTests.addStake__success.add1) + this.skip(); + const sudoKey = walletAlice; + await runBeforeTxOracleAddStake(sudoKey, controllerWallet, signedWallet); // Preparing the signer to have funds. + const stake = api.createType('u128', 250000000000); + const {data: [result],} = await txOracleAddStakeSuccessTest(controllerWallet, stake); + expect(result).to.not.be.an('Error'); + expect(result.toString()).to.be + .equal(api.createType('AccountId32', signedWallet.publicKey).toString()); + }); + }); + + /** + * oracle.submitPrice Success Tests + * To be called by signer or controller. + * + * Result is the signer wallets public key. + */ + describe('tx.submitPrice Success Test', function () { + if (!testConfiguration.enabledTests.submitPrice__success.enabled) + return; + // Timeout set to 4 minutes + this.timeout(4 * 60 * 1000); + it('Can submit new price by signer', async function () { + if (!testConfiguration.enabledTests.submitPrice__success.submit1) + this.skip(); + const price = api.createType('u128', 10000); + const assetId = api.createType('u128', newAsset1); + const {data: [result],} = await txOracleSubmitPriceSuccessTest(signedWallet, price, assetId); + expect(result).to.not.be.an('Error'); + expect(result.toString()).to.be + .equal(api.createType('AccountId32', signedWallet.publicKey).toString()); + }); + }); + + /** + * oracle.removeStake Success Tests + * To be called by controller. + * + * Result is the signer wallets public key. + */ + describe('tx.removeStake Success Test', function () { + if (!testConfiguration.enabledTests.removeStake__success.enabled) + return; + // Timeout set to 2 minutes + this.timeout(2 * 60 * 1000); + it('Can remove stake', async function () { + if (!testConfiguration.enabledTests.removeStake__success.remove1) + this.skip(); + const {data: [result],} = await txOracleRemoveStakeSuccessTest(controllerWallet); + expect(result).to.not.be.an('Error'); + expect(result.toString()).to.be + .equal(api.createType('AccountId32', signedWallet.publicKey).toString()); + }); + }); + + /** + * oracle.reclaimStake Success Tests + * To be called by controller. + * Can only work after a successful removeStake(), and waiting for unlockBlock to be reached. + * + * Result is the signer wallets public key. + */ + describe('tx.reclaimStake Success Test', function () { + if (!testConfiguration.enabledTests.reclaimStake__success.enabled) + return; + let unlockBlock; + // Timeout set to 15 minutes + this.timeout(15 * 60 * 1000); + this.slow(1200000); + it('Can reclaim stake', async function () { + if (!testConfiguration.enabledTests.reclaimStake__success.reclaim1) + this.skip(); + // Get the block number at which the funds are unlocked. + const declaredWithdrawsResult = await api.query.oracle.declaredWithdraws(signedWallet.address); + unlockBlock = declaredWithdrawsResult.unwrap().unlockBlock; + expect(unlockBlock.toNumber()).to.be.a('Number'); + const currentBlock = await api.query.system.number(); + expect(currentBlock.toNumber()).to.be.a('Number'); + // Taking a nap until we reach the unlocking block. + await waitForBlocks(unlockBlock.toNumber() - currentBlock.toNumber()); + const {data: [result],} = await txOracleReclaimStakeSuccessTest(controllerWallet); + expect(result).to.not.be.an('Error'); + expect(result.toString()).to.be + .equal(api.createType('AccountId32', signedWallet.publicKey).toString()); + }); + }); +}); diff --git a/integration-tests/runtime-tests/test/tests/xcmp/transfers.ts b/integration-tests/runtime-tests/test/tests/xcmp/transfers.ts new file mode 100644 index 00000000000..b33c3190d19 --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/xcmp/transfers.ts @@ -0,0 +1,6 @@ +// tests transfers to and from parachain +// +// scenario: +// 1. ensure root has account on relayer (either via faucet/airdrop or having root of relayer or bying some) +// 2. from relay send XCM via XCM executor pallet via reserve transfer amount from it to parachain +// 3. check after some block that parachain diff --git a/integration-tests/runtime-tests/tsconfig.json b/integration-tests/runtime-tests/tsconfig.json index fc85404a262..ac32cf9100b 100644 --- a/integration-tests/runtime-tests/tsconfig.json +++ b/integration-tests/runtime-tests/tsconfig.json @@ -3,9 +3,9 @@ "module": "commonjs", "target": "ES2021", "moduleResolution": "node", - "pretty": false, + "pretty": true, "noImplicitAny": false, - "removeComments": true, + "removeComments": false, "noImplicitReturns": false, "suppressImplicitAnyIndexErrors": true, "allowSyntheticDefaultImports": true, @@ -17,6 +17,9 @@ "@composable/*": [ "./src/*" ], + "@composabletests/*": [ + "./test/*" + ], "@polkadot/api/augment": [ "./src/types/interfaces/augment-api.ts" ], @@ -25,6 +28,16 @@ ] } }, - "include": ["src/**/*"], - "exclude": ["node_modules", "src/**/**.d.ts"] + "include": [ + "src", + "src/**/*.ts", + "test", + "test/**/*.ts", + "@types/**/*.d.ts" + ], + "exclude": [ + "node_modules", + "test/**/*.d.ts", + "src/**/*.d.ts" + ] } diff --git a/integration-tests/src/cross_chain_transfer.rs b/integration-tests/src/cross_chain_transfer.rs deleted file mode 100644 index 663127c7683..00000000000 --- a/integration-tests/src/cross_chain_transfer.rs +++ /dev/null @@ -1,413 +0,0 @@ -use crate::{env_logger_init, kusama_test_net::*}; -use codec::Encode; -use common::AccountId; -use composable_traits::assets::{RemoteAssetRegistry, XcmAssetLocation}; -use cumulus_primitives_core::ParaId; -use dali_runtime as picasso_runtime; -use orml_traits::currency::MultiCurrency; -use primitives::currency::*; -use sp_runtime::traits::AccountIdConversion; -use support::assert_ok; -use xcm::latest::prelude::*; -use xcm_emulator::TestExt; -use xcm_executor::XcmExecutor; - -/// assumes that our parachain has native relay token on relay account -/// and kusama can send xcm message to our network and transfer native token onto local network -#[test] -fn transfer_from_relay_chain() { - crate::kusama_test_net::KusamaNetwork::reset(); - env_logger_init(); - Picasso::execute_with(|| { - assert_ok!(picasso_runtime::AssetsRegistry::set_location( - CurrencyId::KSM, // KSM id as it is locally - // if we get tokens from parent chain, these can be only native token - composable_traits::assets::XcmAssetLocation(MultiLocation::parent()) - )); - }); - KusamaRelay::execute_with(|| { - let transfered = kusama_runtime::XcmPallet::reserve_transfer_assets( - kusama_runtime::Origin::signed(ALICE.into()), - Box::new(Parachain(PICASSO_PARA_ID).into().into()), - Box::new( - Junction::AccountId32 { id: crate::kusama_test_net::BOB, network: NetworkId::Any } - .into() - .into(), - ), - Box::new((Here, 3 * PICA).into()), - 0, - ); - assert_ok!(transfered); - assert_eq!( - kusama_runtime::Balances::free_balance(&ParaId::from(PICASSO_PARA_ID).into_account()), - 13 * PICA - ); - }); - - Picasso::execute_with(|| { - let native_token = - picasso_runtime::Assets::free_balance(CurrencyId::KSM, &AccountId::from(BOB)); - assert_eq!(native_token, 3 * PICA); - }); -} - -#[test] -fn transfer_to_relay_chain() { - crate::kusama_test_net::KusamaNetwork::reset(); - env_logger_init(); - Picasso::execute_with(|| { - assert_ok!(::set_location( - CurrencyId::KSM, - XcmAssetLocation::RELAY_NATIVE, - )); - let transferred = picasso_runtime::XTokens::transfer( - picasso_runtime::Origin::signed(ALICE.into()), - CurrencyId::KSM, - 3 * PICA, - Box::new( - MultiLocation::new( - 1, - X1(Junction::AccountId32 { id: BOB, network: NetworkId::Any }), - ) - .into(), - ), - 4_600_000_000, - ); - - assert_ok!(transferred); - - let remaining = - picasso_runtime::Assets::free_balance(CurrencyId::KSM, &AccountId::from(ALICE)); - - assert_eq!(remaining, ALICE_PARACHAIN_KSM - 3 * PICA); - }); - - KusamaRelay::execute_with(|| { - assert_eq!( - kusama_runtime::Balances::free_balance(&AccountId::from(BOB)), - 2999893333340 // 3 * PICA - fee - ); - }); -} - -#[test] -fn transfer_from_dali() { - crate::kusama_test_net::KusamaNetwork::reset(); - env_logger_init(); - - Picasso::execute_with(|| { - assert_ok!(::set_location( - CurrencyId::PICA, - composable_traits::assets::XcmAssetLocation(MultiLocation::new( - 1, - X2(Parachain(DALI_PARA_ID), GeneralKey(CurrencyId::PICA.encode())) - )) - )); - }); - - let local_withdraw_amount = 3 * PICA; - Dali::execute_with(|| { - assert_ok!(dali_runtime::XTokens::transfer( - dali_runtime::Origin::signed(ALICE.into()), - CurrencyId::PICA, - local_withdraw_amount, - Box::new( - MultiLocation::new( - 1, - X2( - Junction::Parachain(PICASSO_PARA_ID), - Junction::AccountId32 { id: BOB, network: NetworkId::Any } - ) - ) - .into() - ), - 399_600_000_000 - )); - assert_eq!( - dali_runtime::Assets::free_balance(CurrencyId::PICA, &AccountId::from(ALICE)), - 200 * PICA - local_withdraw_amount - ); - }); - - Picasso::execute_with(|| { - let balance = - picasso_runtime::Assets::free_balance(CurrencyId::PICA, &AccountId::from(BOB)); - assert_eq!(balance, local_withdraw_amount); - }); -} - -#[test] -fn transfer_from_picasso_to_dali() { - crate::kusama_test_net::KusamaNetwork::reset(); - env_logger_init(); - - Dali::execute_with(|| { - assert_ok!(::set_location( - // local id - CurrencyId::PICA, - // remote id - // first part is remote network, - // second part is id of asset on remote - composable_traits::assets::XcmAssetLocation(MultiLocation::new( - 1, - X2(Parachain(PICASSO_PARA_ID), GeneralKey(CurrencyId::PICA.encode())) - )) - )); - }); - - Picasso::execute_with(|| { - assert_ok!(::set_location( - CurrencyId::PICA, - composable_traits::assets::XcmAssetLocation(MultiLocation::new( - 1, - X2(Parachain(DALI_PARA_ID), GeneralKey(CurrencyId::PICA.encode())) - )) - )); - - assert_ok!(picasso_runtime::XTokens::transfer( - picasso_runtime::Origin::signed(ALICE.into()), - CurrencyId::PICA, - 3 * PICA, - Box::new( - MultiLocation::new( - 1, - X2( - Junction::Parachain(DALI_PARA_ID), - Junction::AccountId32 { id: BOB, network: NetworkId::Any } - ) - ) - .into() - ), - 399_600_000_000 - )); - assert_eq!( - picasso_runtime::Balances::free_balance(&AccountId::from(ALICE)), - 200 * PICA - 3 * PICA - ); - }); - - Dali::execute_with(|| { - let balance = dali_runtime::Assets::free_balance(CurrencyId::PICA, &AccountId::from(BOB)); - assert_eq!(balance, 3 * PICA); - }); -} - -#[test] -fn transfer_insufficient_amount_should_fail() { - Dali::execute_with(|| { - assert_ok!(dali_runtime::XTokens::transfer( - dali_runtime::Origin::signed(ALICE.into()), - CurrencyId::PICA, - 1_000_000 - 1, - Box::new( - MultiLocation::new( - 1, - X2( - Junction::Parachain(PICASSO_PARA_ID), - Junction::AccountId32 { id: BOB, network: NetworkId::Any } - ) - ) - .into() - ), - 399_600_000_000 - )); - assert_eq!(dali_runtime::Balances::free_balance(&AccountId::from(ALICE)), 199999999000001); - }); - - Picasso::execute_with(|| { - // Xcm should fail therefore nothing should be deposit into beneficiary account - assert_eq!( - picasso_runtime::Tokens::free_balance(CurrencyId::PICA, &AccountId::from(BOB)), - 0 - ); - }); -} - -/// Acala's tests -#[test] -#[ignore] -fn transfer_from_relay_chain_deposit_to_treasury_if_below_ed() { - KusamaRelay::execute_with(|| { - assert_ok!(kusama_runtime::XcmPallet::reserve_transfer_assets( - kusama_runtime::Origin::signed(ALICE.into()), - Box::new(Parachain(PICASSO_PARA_ID).into().into()), - Box::new(Junction::AccountId32 { id: BOB, network: NetworkId::Any }.into().into()), - Box::new((Here, 128_000_111).into()), - 0 - )); - }); - - Picasso::execute_with(|| { - assert_eq!( - picasso_runtime::Tokens::free_balance(CurrencyId::KSM, &AccountId::from(BOB)), - 0 - ); - assert_eq!( - picasso_runtime::Tokens::free_balance( - CurrencyId::KSM, - &picasso_runtime::TreasuryAccount::get() - ), - 1_000_128_000_111 - ); - }); -} - -#[test] -#[ignore] -fn xcm_transfer_execution_barrier_trader_works() { - let expect_weight_limit = 600_000_000; - let weight_limit_too_low = 500_000_000; - let unit_instruction_weight = 200_000_000; - - // relay-chain use normal account to send xcm, destination para-chain can't pass Barrier check - let message = Xcm(vec![ - ReserveAssetDeposited((Parent, 100).into()), - BuyExecution { fees: (Parent, 100).into(), weight_limit: Unlimited }, - DepositAsset { assets: All.into(), max_assets: 1, beneficiary: Here.into() }, - ]); - KusamaRelay::execute_with(|| { - let r = pallet_xcm::Pallet::::send( - kusama_runtime::Origin::signed(ALICE.into()), - Box::new(Parachain(PICASSO_PARA_ID).into().into()), - Box::new(xcm::VersionedXcm::from(message)), - ); - assert_ok!(r); - }); - Picasso::execute_with(|| { - assert!(picasso_runtime::System::events().iter().any(|r| matches!( - r.event, - picasso_runtime::Event::DmpQueue(cumulus_pallet_dmp_queue::Event::ExecutedDownward( - _, - Outcome::Error(XcmError::Barrier) - )) - ))); - }); - - // AllowTopLevelPaidExecutionFrom barrier test case: - // para-chain use XcmExecutor `execute_xcm()` method to execute xcm. - // if `weight_limit` in BuyExecution is less than `xcm_weight(max_weight)`, then Barrier can't - // pass. other situation when `weight_limit` is `Unlimited` or large than `xcm_weight`, then - // it's ok. - let message = Xcm::(vec![ - ReserveAssetDeposited((Parent, 100).into()), - BuyExecution { fees: (Parent, 100).into(), weight_limit: Limited(weight_limit_too_low) }, - DepositAsset { assets: All.into(), max_assets: 1, beneficiary: Here.into() }, - ]); - Picasso::execute_with(|| { - let r = XcmExecutor::::execute_xcm( - Parent, - message, - expect_weight_limit, - ); - assert_eq!(r, Outcome::Error(XcmError::Barrier)); - }); - - // trader inside BuyExecution have TooExpensive error if payment less than calculated weight - // amount. the minimum of calculated weight amount(`FixedRateOfFungible`) is - // 96_000_000 - let message = Xcm::(vec![ - ReserveAssetDeposited((Parent, 95_999_999).into()), - BuyExecution { - fees: (Parent, 95_999_999).into(), - weight_limit: Limited(expect_weight_limit), - }, - DepositAsset { assets: All.into(), max_assets: 1, beneficiary: Here.into() }, - ]); - Picasso::execute_with(|| { - let r = XcmExecutor::::execute_xcm( - Parent, - message, - expect_weight_limit, - ); - assert_eq!( - r, - Outcome::Incomplete( - expect_weight_limit - unit_instruction_weight, - XcmError::TooExpensive - ) - ); - }); - - // all situation fulfilled, execute success - let message = Xcm::(vec![ - ReserveAssetDeposited((Parent, 96_000_000).into()), - BuyExecution { - fees: (Parent, 96_000_000).into(), - weight_limit: Limited(expect_weight_limit), - }, - DepositAsset { assets: All.into(), max_assets: 1, beneficiary: Here.into() }, - ]); - Picasso::execute_with(|| { - let r = XcmExecutor::::execute_xcm( - Parent, - message, - expect_weight_limit, - ); - assert_eq!(r, Outcome::Complete(expect_weight_limit)); - }); -} - -#[test] -#[ignore] -fn subscribe_version_notify_works() { - // relay chain subscribe version notify of para chain - KusamaRelay::execute_with(|| { - let r = pallet_xcm::Pallet::::force_subscribe_version_notify( - kusama_runtime::Origin::root(), - Box::new(Parachain(PICASSO_PARA_ID).into().into()), - ); - assert_ok!(r); - }); - KusamaRelay::execute_with(|| { - kusama_runtime::System::assert_has_event(kusama_runtime::Event::XcmPallet( - pallet_xcm::Event::SupportedVersionChanged( - MultiLocation { parents: 0, interior: X1(Parachain(PICASSO_PARA_ID)) }, - 2, - ), - )); - }); - - // para chain subscribe version notify of relay chain - Picasso::execute_with(|| { - let r = pallet_xcm::Pallet::::force_subscribe_version_notify( - picasso_runtime::Origin::root(), - Box::new(Parent.into()), - ); - assert_ok!(r); - }); - Picasso::execute_with(|| { - picasso_runtime::System::assert_has_event(picasso_runtime::Event::RelayerXcm( - pallet_xcm::Event::SupportedVersionChanged( - MultiLocation { parents: 1, interior: Here }, - 2, - ), - )); - }); - - // para chain subscribe version notify of sibling chain - Picasso::execute_with(|| { - let r = pallet_xcm::Pallet::::force_subscribe_version_notify( - picasso_runtime::Origin::root(), - Box::new((Parent, Parachain(PICASSO_PARA_ID)).into()), - ); - assert_ok!(r); - }); - Picasso::execute_with(|| { - assert!(picasso_runtime::System::events().iter().any(|r| matches!( - r.event, - picasso_runtime::Event::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent( - Some(_) - )) - ))); - }); - Dali::execute_with(|| { - assert!(dali_runtime::System::events().iter().any(|r| matches!( - r.event, - picasso_runtime::Event::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent( - Some(_) - )) | picasso_runtime::Event::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success( - Some(_) - )) - ))); - }); -} diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs deleted file mode 100644 index 81bc3c04696..00000000000 --- a/integration-tests/src/lib.rs +++ /dev/null @@ -1,17 +0,0 @@ -/// this must be singleton -#[cfg(test)] -pub fn env_logger_init() { - let _ = env_logger::builder().is_test(true).try_init(); -} - -#[cfg(test)] -mod kusama_test_net; - -#[cfg(test)] -mod xcm_tests; - -#[cfg(test)] -mod cross_chain_transfer; - -#[cfg(test)] -mod runtime_tests; diff --git a/nix/.gitignore b/nix/.gitignore index 2f1dabb2288..de542068d7a 100644 --- a/nix/.gitignore +++ b/nix/.gitignore @@ -1 +1,2 @@ +*.log ops.json \ No newline at end of file diff --git a/nix/README.md b/nix/README.md index 36c5ce25526..aecdafd1b33 100644 --- a/nix/README.md +++ b/nix/README.md @@ -1,17 +1,29 @@ -# Install Nix + Flakes +# /!\ Install Nix + Flakes 1. https://nixos.org/download.html 2. https://nixos.wiki/wiki/Flakes # Run locally -1. `nix develop` -2. `launch-devnet` +1. `./latest.sh SPEC` where `SPEC` is one of the runtime: + - `dali-dev` + - `picasso-dev` + - `composable-dev` 3. Reach alice at `https://polkadot.js.org/apps/?rpc=ws://localhost:9944#/explorer` -# Deploy to GCE +NOTE: The script will automatically run the latest devnet deployed from the latest origin/main commit. -1. Download your GCE service account key and save it as `ops.json` -2. `nix develop .#deploy` -3. `nixops create -d devnet-gce` -4. `nixops deploy -d devnet-gce` +# GCE + +/!\ Download your GCE service account key and save it as `ops.json`. + +## Deploy + +1. `nix develop .#deploy` +2. `nixops create -d devnet-gce` +3. `nixops deploy -d devnet-gce` + +## Connect to CI deployed machines + +1. Download nixops CI state: `gsutil cp gs://composable-state/deployment.nixops .` +2. Run `NIXOPS_STATE=deployment.nixops nixops ssh composable-devnet-dali-dev` diff --git a/nix/devnet-gce.nix b/nix/devnet-gce.nix index 52fb07a3426..cf736f8d8e0 100644 --- a/nix/devnet-gce.nix +++ b/nix/devnet-gce.nix @@ -4,10 +4,7 @@ localtunnel, }: let - gcefy-version = version: - builtins.replaceStrings [ "." ] [ "-" ] version; - domain = "${composable.name}-${composable.spec}-${gcefy-version composable.version}"; - domain-latest = "${composable.name}-${composable.spec}-latest"; + machine-name = "composable-devnet-${composable.spec}"; in { resources.gceNetworks.composable-devnet = credentials // { name = "composable-devnet-network"; @@ -22,7 +19,7 @@ in { }; }; }; - devnet-machine = { pkgs, resources, ... }: + "${machine-name}" = { pkgs, resources, ... }: let devnet = pkgs.callPackage ./devnet.nix { inherit composable; @@ -32,7 +29,7 @@ in { deployment = { targetEnv = "gce"; gce = credentials // { - machineName = "composable-devnet"; + machineName = machine-name; network = resources.gceNetworks.composable-devnet; region = "europe-central2-c"; instanceType = "n2-standard-4"; @@ -43,6 +40,10 @@ in { ]; }; }; + nix = { + gc.automatic = true; + autoOptimiseStore = true; + }; networking.firewall.allowedTCPPorts = [ 80 443 ]; systemd.services.composable-devnet = { wantedBy = [ "multi-user.target" ]; @@ -51,35 +52,20 @@ in { serviceConfig = { Type = "simple"; User = "root"; - ExecStart = "${devnet}/bin/launch-devnet"; + ExecStart = "${devnet.script}/bin/run-${composable.spec}"; Restart = "always"; RuntimeMaxSec = "86400"; # 1 day lease period for rococo, restart it }; }; - systemd.services.localtunnel-commit = { - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - description = "Local Tunnel Server"; - serviceConfig = { - Type = "simple"; - User = "root"; - Restart = "always"; - ExecStart = "${localtunnel}/bin/lt --port 80 --subdomain ${domain}"; - }; - }; - systemd.services.localtunnel-latest = { - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - description = "Local Tunnel Server"; - serviceConfig = { - Type = "simple"; - User = "root"; - Restart = "always"; - ExecStart = "${localtunnel}/bin/lt --port 80 --subdomain ${domain-latest}"; - }; + security.acme = { + acceptTerms = true; + email = "hussein@composable.finance"; }; services.nginx = - let virtualConfig = + let + runtimeName = pkgs.lib.removeSuffix "-dev" composable.spec; + domain = "${runtimeName}.devnets.composablefinance.ninja"; + virtualConfig = let routify-nodes = prefix: map (node: (node // { @@ -93,18 +79,36 @@ in { routified-composable-nodes ++ routified-polkadot-nodes; in { - locations = builtins.foldl' (x: y: x // y) {} (map (node: { + enableACME = true; + forceSSL = true; + locations = builtins.foldl' (x: y: x // y) { + "= /doc/" = { + return = "301 https://${domain}/doc/composable/index.html"; + }; + "= /doc" = { + return = "301 https://${domain}/doc/composable/index.html"; + }; + "/doc/" = { + root = devnet.documentation; + }; + } (map (node: { "/${node.name}" = { proxyPass = "http://127.0.0.1:${builtins.toString node.wsPort}"; proxyWebsockets = true; + extraConfig = '' + proxy_set_header Origin ""; + proxy_set_header Host 127.0.0.1:${builtins.toString node.wsPort}; + ''; }; }) routified-nodes); }; in { enable = true; + enableReload = true; + recommendedOptimisation = true; + recommendedGzipSettings = true; serverNamesHashBucketSize = 128; - virtualHosts."${domain}.loca.lt" = virtualConfig; - virtualHosts."${domain-latest}.loca.lt" = virtualConfig; + virtualHosts."${domain}" = virtualConfig; }; }; } diff --git a/nix/devnet.json b/nix/devnet.json index e2a3eaca629..ddc975eb622 100644 --- a/nix/devnet.json +++ b/nix/devnet.json @@ -1,13 +1 @@ -{ - "composable": { - "name": "picasso", - "version": "315f320b2a55e23c046217f9653ca379208910f0", - "spec": "picasso-dev", - "hash": "sha256:1lsza72bzql50m643s7g0l9kzy4myjhwjkrwk35hpc42nf22s4cs" - }, - "polkadot": { - "version": "0.9.13", - "spec": "rococo-local", - "hash": "sha256:1iwhb1sgi8yk1nmmix7jr8rzjdl9kh50jx8s8a2fllzpllbbwdkw" - } -} +{ "composable": { "name": "picasso", "version": "68d0c38b8c3e65021a99888f35cd5d58238cfa07", "hash": "0qj4hrsvxcblmf8xfq46bg345sq733ay9mywd11q3l8cb6w464vd" }, "polkadot": { "version": "0.9.17-rc4", "hash": "10q34jml0yab7inbkdd193gpxjl880kkdjf029qlnjzh7wdihg0f" } } diff --git a/nix/devnet.nix b/nix/devnet.nix index 9a3bd86be5f..422c5180c2a 100644 --- a/nix/devnet.nix +++ b/nix/devnet.nix @@ -55,6 +55,8 @@ let tar -xvf $src mkdir -p $out/bin mv release/composable $out/bin + + mv doc $out ''; }; @@ -71,18 +73,6 @@ let bin = relaychain-bin; chain = relaychain-spec; nodes = map (make-node tmp-directory "relaychain") polkadot.nodes; - genesis = { - runtime = { - runtime_genesis_config = { - configuration = { - config = { - validation_upgrade_frequency = 1; - validation_upgrade_delay = 1; - }; - }; - }; - }; - }; }; parachains = [ { @@ -103,9 +93,9 @@ let tmp-directory = "/tmp/polkadot-launch"; - devnet-config = + devnet-polkalaunch-config = pkgs.writeTextFile { - name = "devnet.json"; + name = "devnet-polkalaunch.json"; text = builtins.toJSON ( make-polkalaunch-config { inherit tmp-directory; @@ -116,9 +106,11 @@ let } ); }; -in -pkgs.writeScriptBin "launch-devnet" '' - #!${pkgs.bash}/bin/bash -e - rm -rf ${tmp-directory} - ${polkalaunch}/bin/polkadot-launch ${devnet-config} -'' +in { + script = + pkgs.writeShellScriptBin "run-${composable.spec}" '' + rm -rf ${tmp-directory} + ${polkalaunch}/bin/polkadot-launch ${devnet-polkalaunch-config} + ''; + documentation = "${composable-bin}/share"; +} diff --git a/nix/flake.lock b/nix/flake.lock index 0e3770f69d7..32771a7123e 100644 --- a/nix/flake.lock +++ b/nix/flake.lock @@ -2,17 +2,17 @@ "nodes": { "flake-utils": { "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", "owner": "numtide", "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { "owner": "numtide", "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" } }, @@ -35,17 +35,17 @@ }, "nixpkgs": { "locked": { - "lastModified": 1640139330, - "narHash": "sha256-Nkp3wUOGwtoQ7EH28RLVJ7EqB/e0TU7VcsM7GLy+SdY=", + "lastModified": 1644579682, + "narHash": "sha256-u4f5KQvK8vrhiYFcqHCVYxGGiCrKpRqxkn2S3QOprd8=", "owner": "nixos", "repo": "nixpkgs", - "rev": "81cef6b70fb5d5cdba5a0fef3f714c2dadaf0d6d", + "rev": "ec7d9d4c182c54acd649674cf1023d40a0539eb7", "type": "github" }, "original": { "owner": "nixos", "repo": "nixpkgs", - "rev": "81cef6b70fb5d5cdba5a0fef3f714c2dadaf0d6d", + "rev": "ec7d9d4c182c54acd649674cf1023d40a0539eb7", "type": "github" } }, diff --git a/nix/flake.nix b/nix/flake.nix index ee375d42c78..ba516d6fbf1 100644 --- a/nix/flake.nix +++ b/nix/flake.nix @@ -1,8 +1,8 @@ { description = "Composable Devnet Scripts"; inputs = { - nixpkgs.url = "github:nixos/nixpkgs/81cef6b70fb5d5cdba5a0fef3f714c2dadaf0d6d"; - flake-utils.url = "github:numtide/flake-utils/74f7e4319258e287b0f9cb95426c9853b282730b"; + nixpkgs.url = "github:nixos/nixpkgs/ec7d9d4c182c54acd649674cf1023d40a0539eb7"; + flake-utils.url = "github:numtide/flake-utils/3cecb5b042f7f209c56ffd8371b2711a290ec797"; localtunnel-src = { url = "github:localtunnel/localtunnel/c8e85f49624d606730779fc4295a38fd0e650af5"; flake = false; @@ -10,7 +10,11 @@ }; outputs = { nixpkgs, flake-utils, localtunnel-src, ... }: let - mk-composable = { name, version, spec, hash}: { + bins = + (if builtins.pathExists ./devnet.json + then builtins.fromJSON (builtins.readFile ./devnet.json) + else throw "Devnet `devnet.json` definition missing, please follow the README.md instructions."); + mk-composable = spec: { name, version, hash }: { inherit name; inherit version; inherit spec; @@ -33,7 +37,7 @@ port = 30777; }]; }; - mk-polkadot = { version, spec, hash }: { + mk-polkadot = spec: { version, hash }: { inherit version; inherit spec; inherit hash; @@ -51,10 +55,13 @@ port = 31300; }]; }; - latest = ({ composable, polkadot}: { - composable = mk-composable composable; - polkadot = mk-polkadot polkadot; - }) (builtins.fromJSON (builtins.readFile ./devnet.json)); + mk-latest = spec: + ({ composable, polkadot }: { + composable = mk-composable spec composable; + polkadot = mk-polkadot "rococo-local" polkadot; + }) bins; + latest-dali = mk-latest "dali-dev"; + latest-picasso = mk-latest "picasso-dev"; in { nixopsConfigurations.default = @@ -62,47 +69,48 @@ pkgs-nixos = import nixpkgs {}; conf = if builtins.pathExists ./ops.json then builtins.fromJSON (builtins.readFile ./ops.json) - else throw "GCE credentials `ops.json` not found, please download it."; + else throw "Operations credentials `ops.json` definition missng, please follow the README.md instructions."; credentials = { project = conf.project_id; serviceAccount = conf.client_email; accessKey = conf.private_key; }; - localtunnel = pkgs-nixos.mkYarnPackage rec{ + localtunnel = pkgs-nixos.mkYarnPackage rec { name = "localtunnel"; src = localtunnel-src; }; in - /* NOTE(hussein-aitlahcen) - I initially used this script to be able to generate N machines. - I'll leave the fold and logic as is and just use the latest to overwrite the previous devnet machine. - */ - builtins.foldl' (machines: next-machine: machines // import ./devnet-gce.nix { + builtins.foldl' (machines: { composable, polkadot }: machines // import ./devnet-gce.nix { inherit localtunnel; inherit credentials; - inherit (next-machine) composable; - inherit (next-machine) polkadot; + inherit composable; + inherit polkadot; }) { inherit nixpkgs; network.description = "Composable Devnet"; network.storage.legacy = {}; - } [ latest ]; + } [ latest-dali latest-picasso ]; } // flake-utils.lib.eachDefaultSystem (system: let pkgs = import nixpkgs { inherit system; }; in rec { - packages.devnet = pkgs.callPackage ./devnet.nix { - inherit (latest) composable; - inherit (latest) polkadot; - }; + packages.devnet-dali = (pkgs.callPackage ./devnet.nix { + inherit (latest-dali) composable; + inherit (latest-dali) polkadot; + }).script; + packages.devnet-picasso = (pkgs.callPackage ./devnet.nix { + inherit (latest-picasso) composable; + inherit (latest-picasso) polkadot; + }).script; packages.localtunnel = pkgs.mkYarnPackage rec { name = "localtunnel"; src = localtunnel-src; }; packages.deploy = pkgs.mkShell { buildInputs = [ - packages.devnet + packages.devnet-dali + packages.devnet-picasso packages.localtunnel (pkgs.nixopsUnstable.override { overrides = (self: super: { @@ -118,11 +126,14 @@ ); }); })]; + # NOTE: nixops depends on nixpkgs for the virtual machine initial conf... + NIX_PATH = "nixpkgs=${pkgs.path}"; }; - defaultPackage = packages.devnet; + defaultPackage = packages.devnet-dali; devShell = pkgs.mkShell { buildInputs = [ - defaultPackage + packages.devnet-dali + packages.devnet-picasso ]; }; } diff --git a/nix/latest.sh b/nix/latest.sh new file mode 100755 index 00000000000..4402ab80acc --- /dev/null +++ b/nix/latest.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env nix-shell +#! nix-shell -i bash -p nix-prefetch-scripts jq +REVISION=$(git rev-parse origin/main) +echo "Revision: ${REVISION}" +URL="https://storage.googleapis.com/composable-binaries/community-releases/picasso/composable-picasso-${REVISION}.tar.gz" +echo "Url: ${URL}" +HASH=$(nix-prefetch-url ${URL}) +echo "Hash: ${HASH}" +echo $(cat devnet.json | jq --arg version ${REVISION} '.composable.version = $version' | jq --arg hash ${HASH} '.composable.hash = $hash') > devnet.json +nix develop --command run-$1 diff --git a/node/Cargo.toml b/node/Cargo.toml index 8291abdb5fa..cb93a7a5283 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -1,102 +1,120 @@ [package] -name = "composable-node" -version = '1.0.9' authors = ["Composable Developers"] -homepage = "https://composable.finance" build = "build.rs" edition = "2018" +homepage = "https://composable.finance" +name = "composable-node" +version = "1.0.0" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [dependencies] +clap = "3.1.6" codec = { package = "parity-scale-codec", version = "2.0.0" } jsonrpc-core = "18" log = "0.4.14" serde = { version = "1.0.130", features = ["derive"] } -structopt = "0.3.8" # Local Dependencies -picasso-runtime = { path = "../runtime/picasso" } +common = { path = "../runtime/common" } composable-runtime = { path = "../runtime/composable", optional = true } dali-runtime = { path = "../runtime/dali", optional = true } -common = { path = "../runtime/common" } +picasso-runtime = { path = "../runtime/picasso" } +primitives = { path = "../runtime/primitives" } + +pallet-assets = { path = "../frame/assets" } +pallet-crowdloan-rewards = { path = "../frame/crowdloan-rewards" } + +assets-rpc = { path = "../frame/assets/rpc" } +assets-runtime-api = { path = "../frame/assets/runtime-api" } +crowdloan-rewards-rpc = { path = "../frame/crowdloan-rewards/rpc" } +crowdloan-rewards-runtime-api = { path = "../frame/crowdloan-rewards/runtime-api" } # FRAME Dependencies -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } ## Substrate Client Dependencies -sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-consensus-slots = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", features = ["wasmtime"] } -sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -grandpa = { package = "sc-finality-grandpa", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +grandpa = { package = "sc-finality-grandpa", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-consensus-slots = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", features = [ + "wasmtime", +] } +sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } ## Substrate Primitive Dependencies -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-storage = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-storage = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } # Cumulus dependencies -cumulus-client-consensus-aura = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16" } -cumulus-client-consensus-common = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16" } -cumulus-client-collator = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16" } -cumulus-client-cli = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16" } -cumulus-client-network = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16" } -cumulus-client-service = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16" } -cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16" } -cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16" } -cumulus-relay-chain-interface = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16" } -cumulus-relay-chain-local = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16" } +cumulus-client-cli = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17" } +cumulus-client-collator = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17" } +cumulus-client-consensus-aura = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17" } +cumulus-client-consensus-common = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17" } +cumulus-client-network = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17" } +cumulus-client-service = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17" } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17" } +cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17" } +cumulus-relay-chain-interface = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17" } +cumulus-relay-chain-local = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17" } # Polkadot dependencies -polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", features = ["rococo-native"] } -polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16" } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16" } -polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16" } +polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", features = [ + "rococo-native", +] } +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17" } +polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17" } [build-dependencies] -substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } [dev-dependencies] hex = "0.4.3" [features] +composable = ["composable-runtime"] +dali = ["dali-runtime"] default = [] -runtime-benchmarks = ["polkadot-service/runtime-benchmarks", "picasso-runtime/runtime-benchmarks", "composable-runtime/runtime-benchmarks", "dali-runtime/runtime-benchmarks"] ocw = [] -dali = ["dali-runtime"] -composable = ["composable-runtime"] +runtime-benchmarks = [ + "polkadot-service/runtime-benchmarks", + "picasso-runtime/runtime-benchmarks", + "composable-runtime/runtime-benchmarks", + "dali-runtime/runtime-benchmarks", +] std = ["picasso-runtime/std", "composable-runtime/std", "dali-runtime/std"] diff --git a/node/src/chain_spec.rs b/node/src/chain_spec.rs index eb90b5e5917..3694c9dd7eb 100644 --- a/node/src/chain_spec.rs +++ b/node/src/chain_spec.rs @@ -112,7 +112,8 @@ pub fn picasso_dev() -> picasso::ChainSpec { ], dev_accounts(), PARA_ID, - picasso_runtime::ExistentialDeposit::get(), + common::NativeExistentialDeposit::get(), + picasso_runtime::TreasuryAccount::get(), ) }, vec![], @@ -155,7 +156,8 @@ pub fn dali_dev() -> dali::ChainSpec { ], dev_accounts(), PARA_ID, - dali_runtime::ExistentialDeposit::get(), + common::NativeExistentialDeposit::get(), + dali_runtime::TreasuryAccount::get(), ) }, vec![], @@ -198,7 +200,8 @@ pub fn composable_dev() -> composable::ChainSpec { ], dev_accounts(), PARA_ID, - picasso_runtime::ExistentialDeposit::get(), + composable_runtime::ExistentialDeposit::get(), + composable_runtime::TreasuryAccount::get(), ) }, vec![], diff --git a/node/src/chain_spec/composable.rs b/node/src/chain_spec/composable.rs index 706f8a97ac2..2f66cdf3ff6 100644 --- a/node/src/chain_spec/composable.rs +++ b/node/src/chain_spec/composable.rs @@ -19,6 +19,7 @@ pub fn genesis_config( accounts: Vec, id: ParaId, existential_deposit: Balance, + treasury: AccountId, ) -> composable_runtime::GenesisConfig { composable_runtime::GenesisConfig { system: composable_runtime::SystemConfig { @@ -27,8 +28,12 @@ pub fn genesis_config( .to_vec(), }, balances: composable_runtime::BalancesConfig { - // Configure endowed accounts with initial balance of 1 << 60. - balances: accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), + // Configure endowed accounts with initial balance. + balances: vec![ + vec![(treasury, existential_deposit)], + accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), + ] + .concat(), }, aura: Default::default(), sudo: composable_runtime::SudoConfig { diff --git a/node/src/chain_spec/dali.rs b/node/src/chain_spec/dali.rs index 61cc2b263af..940b643da46 100644 --- a/node/src/chain_spec/dali.rs +++ b/node/src/chain_spec/dali.rs @@ -19,6 +19,7 @@ pub fn genesis_config( accounts: Vec, id: ParaId, existential_deposit: Balance, + treasury: AccountId, ) -> dali_runtime::GenesisConfig { dali_runtime::GenesisConfig { system: dali_runtime::SystemConfig { @@ -27,8 +28,12 @@ pub fn genesis_config( .to_vec(), }, balances: dali_runtime::BalancesConfig { - // Configure endowed accounts with initial balance of 1 << 60. - balances: accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), + // Configure endowed accounts with initial balance. + balances: vec![ + vec![(treasury, existential_deposit)], + accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), + ] + .concat(), }, aura: Default::default(), sudo: dali_runtime::SudoConfig { diff --git a/node/src/chain_spec/picasso.rs b/node/src/chain_spec/picasso.rs index 9ba53dafe71..bbd8dcaf742 100644 --- a/node/src/chain_spec/picasso.rs +++ b/node/src/chain_spec/picasso.rs @@ -19,6 +19,7 @@ pub fn genesis_config( accounts: Vec, id: ParaId, existential_deposit: Balance, + treasury: AccountId, ) -> picasso_runtime::GenesisConfig { picasso_runtime::GenesisConfig { system: picasso_runtime::SystemConfig { @@ -27,8 +28,12 @@ pub fn genesis_config( .to_vec(), }, balances: picasso_runtime::BalancesConfig { - // Configure endowed accounts with initial balance of 1 << 60. - balances: accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), + // Configure endowed accounts with initial balance. + balances: vec![ + vec![(treasury, existential_deposit)], + accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), + ] + .concat(), }, aura: Default::default(), sudo: picasso_runtime::SudoConfig { diff --git a/node/src/cli.rs b/node/src/cli.rs index d92b2daffe6..3a2adeaf303 100644 --- a/node/src/cli.rs +++ b/node/src/cli.rs @@ -1,16 +1,16 @@ use crate::chain_spec; +use clap::Parser; use std::path::PathBuf; -use structopt::StructOpt; /// Sub-commands supported by the collator. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub enum Subcommand { /// Export the genesis state of the parachain. - #[structopt(name = "export-genesis-state")] + #[clap(name = "export-genesis-state")] ExportGenesisState(ExportGenesisStateCommand), /// Export the genesis wasm of the parachain. - #[structopt(name = "export-genesis-wasm")] + #[clap(name = "export-genesis-wasm")] ExportGenesisWasm(ExportGenesisWasmCommand), /// Build a chain specification. @@ -35,66 +35,63 @@ pub enum Subcommand { Revert(sc_cli::RevertCmd), /// Key management cli utilities + #[clap(subcommand)] Key(sc_cli::KeySubcommand), /// The custom benchmark subcommmand benchmarking runtime pallets. - #[structopt(name = "benchmark", about = "Benchmark runtime pallets.")] + #[clap(name = "benchmark", about = "Benchmark runtime pallets.")] Benchmark(frame_benchmarking_cli::BenchmarkCmd), } /// Command for exporting the genesis state of the parachain -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct ExportGenesisStateCommand { /// Output file name or stdout if unspecified. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] pub output: Option, /// Id of the parachain this state is for. /// /// Default: 100 - #[structopt(long, conflicts_with = "chain")] + #[clap(long, conflicts_with = "chain")] pub parachain_id: Option, /// Write output in binary. Default is to write in hex. - #[structopt(short, long)] + #[clap(short, long)] pub raw: bool, /// The name of the chain for that the genesis state should be exported. - #[structopt(long, conflicts_with = "parachain-id")] + #[clap(long, conflicts_with = "parachain-id")] pub chain: Option, } /// Command for exporting the genesis wasm file. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct ExportGenesisWasmCommand { /// Output file name or stdout if unspecified. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] pub output: Option, /// Write output in binary. Default is to write in hex. - #[structopt(short, long)] + #[clap(short, long)] pub raw: bool, /// The name of the chain for that the genesis wasm file should be exported. - #[structopt(long)] + #[clap(long)] pub chain: Option, } -#[derive(Debug, StructOpt)] -#[structopt(settings = &[ - structopt::clap::AppSettings::GlobalVersion, - structopt::clap::AppSettings::ArgsNegateSubcommands, - structopt::clap::AppSettings::SubcommandsNegateReqs, -])] +#[derive(Debug, Parser)] +#[clap()] pub struct Cli { - #[structopt(subcommand)] + #[clap(subcommand)] pub subcommand: Option, - #[structopt(flatten)] + #[clap(flatten)] pub run: cumulus_client_cli::RunCmd, /// Relaychain arguments - #[structopt(raw = true)] + #[clap(raw = true)] pub relaychain_args: Vec, } @@ -119,6 +116,6 @@ impl RelayChainCli { let extension = chain_spec::Extensions::try_get(&*para_config.chain_spec); let chain_id = extension.map(|e| e.relay_chain.clone()); let base_path = para_config.base_path.as_ref().map(|x| x.path().join("polkadot")); - Self { base_path, chain_id, base: polkadot_cli::RunCmd::from_iter(relay_chain_args) } + Self { base_path, chain_id, base: polkadot_cli::RunCmd::parse_from(relay_chain_args) } } } diff --git a/node/src/rpc.rs b/node/src/rpc.rs index 8a307d6b4db..07893231b7d 100644 --- a/node/src/rpc.rs +++ b/node/src/rpc.rs @@ -5,9 +5,12 @@ #![warn(missing_docs)] +use primitives::currency::CurrencyId; use std::sync::Arc; +use assets_rpc::{Assets, AssetsApi}; use common::{AccountId, AccountIndex, Balance}; +use crowdloan_rewards_rpc::{CrowdloanRewards, CrowdloanRewardsApi}; pub use sc_rpc_api::DenyUnsafe; use sc_transaction_pool_api::TransactionPool; use sp_api::ProvideRuntimeApi; @@ -34,6 +37,8 @@ where C: Send + Sync + 'static, C::Api: substrate_frame_rpc_system::AccountNonceApi, C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, + C::Api: assets_runtime_api::AssetsRuntimeApi, + C::Api: crowdloan_rewards_runtime_api::CrowdloanRewardsRuntimeApi, C::Api: BlockBuilder, P: TransactionPool + 'static, { @@ -45,7 +50,11 @@ where io.extend_with(SystemApi::to_delegate(FullSystem::new(client.clone(), pool, deny_unsafe))); - io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new(client))); + io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new(client.clone()))); + + io.extend_with(AssetsApi::to_delegate(Assets::new(client.clone()))); + + io.extend_with(CrowdloanRewardsApi::to_delegate(CrowdloanRewards::new(client))); // Extend this RPC with a custom API by using the following syntax. // `YourRpcStruct` should have a reference to a client, which is needed diff --git a/node/src/runtime.rs b/node/src/runtime.rs index b8fff9e4afe..429bc3e4b7c 100644 --- a/node/src/runtime.rs +++ b/node/src/runtime.rs @@ -1,4 +1,5 @@ use common::{AccountId, Balance, Index, OpaqueBlock as Block}; +use primitives::currency::CurrencyId; use sp_runtime::traits::BlakeTwo256; /// Consider this a trait alias. @@ -8,6 +9,8 @@ pub trait HostRuntimeApis: + sp_block_builder::BlockBuilder + substrate_frame_rpc_system::AccountNonceApi + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi + + assets_runtime_api::AssetsRuntimeApi + + crowdloan_rewards_runtime_api::CrowdloanRewardsRuntimeApi + sp_api::Metadata + sp_consensus_aura::AuraApi + sp_offchain::OffchainWorkerApi @@ -26,6 +29,8 @@ where + sp_block_builder::BlockBuilder + substrate_frame_rpc_system::AccountNonceApi + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi + + assets_runtime_api::AssetsRuntimeApi + + crowdloan_rewards_runtime_api::CrowdloanRewardsRuntimeApi + sp_api::Metadata + sp_consensus_aura::AuraApi + sp_offchain::OffchainWorkerApi diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index 4c9abf9ffa1..bc18be126dd 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -1,61 +1,75 @@ [package] -name = "common" -version = "0.8.30" authors = ["Composable Developers "] edition = "2021" +name = "common" +version = "0.8.30" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [package.metadata.cargo-udeps.ignore] -normal = [ - "prrimitives" -] +normal = ["primitives"] [dependencies] -sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -frame-system = { package = "frame-system", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -frame-support = { package = "frame-support", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } - -collator-selection = { package = "pallet-collator-selection", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -balances = { package = "pallet-balances", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -collective = { package = "pallet-collective", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -treasury = { package = "pallet-treasury", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ + "derive", +] } +frame-support = { package = "frame-support", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +frame-system = { package = "frame-system", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } + +# xcm +xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } + +balances = { package = "pallet-balances", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +collator-selection = { package = "pallet-collator-selection", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +collective = { package = "pallet-collective", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +treasury = { package = "pallet-treasury", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } + +composable-traits = { path = "../../frame/composable-traits", default-features = false } +num-traits = { version = "0.2.14", default-features = false } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } primitives = { path = "../primitives", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } [dev-dependencies] +authorship = { package = "pallet-authorship", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } serde = { version = "1.0.130" } -authorship = { package = "pallet-authorship", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -sudo = { package = "pallet-sudo", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -num-traits = { version = "0.2.14", default-features = false } -composable-traits = { path = "../../frame/composable-traits" , default-features = false} +sudo = { package = "pallet-sudo", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } [features] default = ["std"] +runtime-benchmarks = [] std = [ - "codec/std", - "sp-consensus-aura/std", - "sp-runtime/std", - "primitives/std", - "sp-std/std", - "sp-io/std", - "frame-support/std", - "frame-system/std", - "collator-selection/std", - "balances/std", - "collective/std", - "treasury/std", - "polkadot-primitives/std", + "codec/std", + "orml-traits/std", + "sp-consensus-aura/std", + "sp-runtime/std", + "primitives/std", + "composable-traits/std", + "sp-std/std", + "sp-io/std", + "frame-support/std", + "frame-system/std", + "collator-selection/std", + "balances/std", + "collective/std", + "treasury/std", + "polkadot-primitives/std", "scale-info/std", + "xcm/std", + "xcm-builder/std", + "xcm-executor/std", ] diff --git a/runtime/common/src/impls.rs b/runtime/common/src/impls.rs index 0801562646d..9abda8db8d4 100644 --- a/runtime/common/src/impls.rs +++ b/runtime/common/src/impls.rs @@ -147,7 +147,7 @@ mod tests { where I: 'a, { - Some(Default::default()) + Some(AccountId::from([0u8; 32])) } } @@ -181,6 +181,7 @@ mod tests { } parameter_type_with_key! { + // TODO: make this non zero pub ExistentialDeposits: |_currency_id: CurrencyId| -> Balance { Zero::zero() }; @@ -219,8 +220,8 @@ mod tests { /// percentage of proposal that most be bonded by the proposer pub const ProposalBond: Permill = Permill::from_percent(5); // TODO: rationale? - pub ProposalBondMinimum: Balance = 5 * CurrencyId::PICA.unit::(); - pub ProposalBondMaximum: Balance = 1000 * CurrencyId::PICA.unit::(); + pub ProposalBondMinimum: Balance = 5 * CurrencyId::unit::(); + pub ProposalBondMaximum: Balance = 1000 * CurrencyId::unit::(); pub const SpendPeriod: BlockNumber = 7 * DAYS; pub const Burn: Permill = Permill::from_percent(0); @@ -259,8 +260,6 @@ mod tests { let fee = Balances::issue(10); let tip = Balances::issue(20); - assert_eq!(Balances::free_balance(AccountId::default()), 0); - DealWithFees::on_unbalanceds(vec![fee, tip].into_iter()); // Author gets 50% of tip and 50% of fee = 15 @@ -276,8 +275,6 @@ mod tests { let fee = Balances::issue(0); let tip = Balances::issue(0); - assert_eq!(Balances::free_balance(AccountId::default()), 0); - DealWithFees::on_unbalanceds(vec![fee, tip].into_iter()); // Author gets 50% of tip and 50% of fee = 15 @@ -292,8 +289,6 @@ mod tests { let fee = Balances::issue(1); let tip = Balances::issue(1); - assert_eq!(Balances::free_balance(AccountId::default()), 0); - DealWithFees::on_unbalanceds(vec![fee, tip].into_iter()); // Author gets 50% of tip and 50% of fee = 15 diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 7be3eb3005a..54f7c05ddeb 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -13,13 +13,30 @@ #![cfg_attr(not(feature = "std"), no_std)] pub mod impls; +pub mod xcmp; +use composable_traits::oracle::MinimalOracle; pub use constants::*; +use frame_support::parameter_types; +use orml_traits::parameter_type_with_key; +use primitives::currency::CurrencyId; +use sp_runtime::DispatchError; pub use types::*; -/// Common types of statemint and statemine. +/// Common types of statemint and statemine and dali and picasso and composable. mod types { + use codec::{Decode, Encode, MaxEncodedLen}; + use core::fmt::Debug; + use scale_info::TypeInfo; use sp_runtime::traits::{IdentifyAccount, Verify}; + // todo move it into more shared directory so it can be shared with + // tests, integration, benchmark, (simnode?) + + pub type BondOfferId = u128; + + /// Timestamp implementation. + pub type Moment = u64; + /// An index to a block. pub type BlockNumber = u32; @@ -63,6 +80,17 @@ mod types { /// Opaque block pub type OpaqueBlock = sp_runtime::generic::Block; + + #[derive(Copy, Clone, PartialEq, Eq, Debug, Encode, Decode, MaxEncodedLen, TypeInfo)] + pub enum MosaicRemoteAssetId { + EthereumTokenAddress([u8; 20]), + } + + impl From<[u8; 20]> for MosaicRemoteAssetId { + fn from(x: [u8; 20]) -> Self { + MosaicRemoteAssetId::EthereumTokenAddress(x) + } + } } /// Common constants of statemint and statemine @@ -107,3 +135,61 @@ mod constants { collective::EnsureProportionAtLeast<_1, _2, AccountId, CouncilInstance>, >; } + +pub struct PriceConverter; + +impl MinimalOracle for PriceConverter { + type AssetId = CurrencyId; + + type Balance = Balance; + + fn get_price_inverse( + asset_id: Self::AssetId, + amount: Self::Balance, + ) -> Result { + match asset_id { + CurrencyId::PICA => Ok(amount), + CurrencyId::KSM => Ok(amount / 10), + CurrencyId::kUSD => Ok(amount / 10), + _ => Err(DispatchError::Other("cannot pay with given weight")), + } + } +} + +// cannot be zero as in benches it fails Invalid input: InsufficientBalance +fn native_existential_desposit() -> Balance { + 100 * CurrencyId::milli::() +} + +parameter_types! { + /// Existential deposit (ED for short) is minimum amount an account has to hold to stay in state. + pub NativeExistentialDeposit: Balance = native_existential_desposit(); +} + +#[cfg(feature = "runtime-benchmarks")] +pub fn multi_existential_deposits(_currency_id: &CurrencyId) -> Balance { + // ISSUE: + // Running benchmarks with non zero multideopist leads to fail in 3rd party pallet. + // It is not cleary why it happens.pub const BaseXcmWeight: Weight = 100_000_000; + // 2022-03-14 20:50:19 Running Benchmark: collective.set_members 2/1 1/1 + // Error: + // 0: Invalid input: Account cannot exist with the funds that would be given + use num_traits::Zero; + Balance::zero() +} + +#[cfg(not(feature = "runtime-benchmarks"))] +pub fn multi_existential_deposits(currency_id: &CurrencyId) -> Balance { + match *currency_id { + CurrencyId::PICA => NativeExistentialDeposit::get(), + id => PriceConverter::get_price_inverse(id, NativeExistentialDeposit::get()) + .unwrap_or(Balance::MAX), // TODO: here DEX call to pemissioned markets should come + } +} + +parameter_type_with_key! { + // Minimum amount an account has to hold to stay in state + pub MultiExistentialDeposits: |currency_id: CurrencyId| -> Balance { + multi_existential_deposits(currency_id) + }; +} diff --git a/runtime/common/src/xcmp/mod.rs b/runtime/common/src/xcmp/mod.rs new file mode 100644 index 00000000000..ffd31866107 --- /dev/null +++ b/runtime/common/src/xcmp/mod.rs @@ -0,0 +1,350 @@ +//! proposed shared XCM setup parameters and impl +use crate::{AccountId, Balance}; +use codec::{Decode, Encode}; +use composable_traits::{ + assets::{RemoteAssetRegistry, XcmAssetLocation}, + oracle::MinimalOracle, +}; +use frame_support::{ + dispatch::Weight, + ensure, log, parameter_types, + traits::{Contains, Get}, + weights::WeightToFeePolynomial, +}; +use num_traits::Zero; +use orml_traits::location::Reserve; +use polkadot_primitives::v1::Id; +use primitives::currency::{CurrencyId, WellKnownCurrency}; +use sp_runtime::traits::Convert; +use sp_std::marker::PhantomData; +use xcm::{latest::MultiAsset, prelude::*}; +use xcm_builder::*; +use xcm_executor::{ + traits::{FilterAssetLocation, ShouldExecute, WeightTrader}, + *, +}; + +parameter_types! { + // similar to what Acala/Hydra has + pub const BaseXcmWeight: Weight = 100_000_000; +} + +/// this is debug struct implementing as many XCMP interfaces as possible +/// it just dumps content, no modification. +/// returns default expected +pub struct XcmpDebug; + +impl ShouldExecute for XcmpDebug { + fn should_execute( + origin: &MultiLocation, + message: &mut Xcm, + max_weight: Weight, + weight_credit: &mut Weight, + ) -> Result<(), ()> { + log::trace!(target: "xcmp::should_execute", "{:?} {:?} {:?} {:?}", origin, message, max_weight, weight_credit); + Err(()) + } +} + +/// NOTE: there could be payments taken on other side, so cannot rely on this to work end to end +pub struct DebugAllowUnpaidExecutionFrom(PhantomData); +impl> ShouldExecute for DebugAllowUnpaidExecutionFrom { + fn should_execute( + origin: &MultiLocation, + _message: &mut Xcm, + _max_weight: Weight, + _weight_credit: &mut Weight, + ) -> Result<(), ()> { + log::trace!( + target: "xcm::barriers", + "AllowUnpaidExecutionFrom origin: {:?}, message: {:?}, max_weight: {:?}, weight_credit: {:?}, contains: {:?}", + origin, _message, _max_weight, _weight_credit, T::contains(origin), + ); + ensure!(T::contains(origin), ()); + Ok(()) + } +} + +pub struct TransactionFeePoolTrader< + AssetConverter, + PriceConverter, + Treasury: TakeRevenue, + WeightToFee, +> { + _marker: PhantomData<(AssetConverter, PriceConverter, Treasury, WeightToFee)>, + fee: Balance, + price: Balance, + asset_location: Option, +} + +impl< + AssetConverter: Convert>, + PriceConverter: MinimalOracle, + Treasury: TakeRevenue, + WeightToFee: WeightToFeePolynomial, + > WeightTrader for TransactionFeePoolTrader +{ + fn new() -> Self { + Self { + _marker: + PhantomData::<(AssetConverter, PriceConverter, Treasury, WeightToFee)>::default(), + fee: 0, + price: 0, + asset_location: None, + } + } + + fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result { + // this is for trusted chains origin, see `f` if any + // TODO: dicuss if we need payments from Relay chain or common goods chains? + if weight.is_zero() { + return Ok(payment) + } + + // only support first fungible assets now. + let xcmp_asset_id = payment + .fungible + .iter() + .next() + .map_or(Err(XcmError::TooExpensive), |v| Ok(v.0))?; + + if let AssetId::Concrete(ref multi_location) = xcmp_asset_id.clone() { + if let Some(asset_id) = AssetConverter::convert(multi_location.clone()) { + let fee = WeightToFee::calc(&weight); + let price = PriceConverter::get_price_inverse(asset_id, fee) + .map_err(|_| XcmError::TooExpensive)?; + + let required = + MultiAsset { id: xcmp_asset_id.clone(), fun: Fungibility::Fungible(price) }; + + log::trace!(target : "xcmp::buy_weight", "{:?} {:?} ", required, payment ); + let unused = payment.checked_sub(required).map_err(|_| XcmError::TooExpensive)?; + + self.fee = self.fee.saturating_add(fee); + self.price = self.price.saturating_add(price); + self.asset_location = Some(multi_location.clone()); + return Ok(unused) + } + } + + log::info!(target : "xcmp::buy_weight", "required {:?}; provided {:?};", weight, payment ); + Err(XcmError::TooExpensive) + } + + fn refund_weight(&mut self, weight: Weight) -> Option { + if let Some(ref asset_location) = self.asset_location { + let fee = WeightToFee::calc(&weight); + let fee = self.fee.min(fee); + let price = fee.saturating_mul(self.price) / self.fee; + self.price = self.price.saturating_sub(price); + self.fee = self.fee.saturating_sub(fee); + if price > 0 { + return Some((asset_location.clone(), price).into()) + } + } + + None + } +} + +pub struct ToTreasury( + PhantomData<(AssetsConverter, Assets, TreasuryAccount)>, +); +impl< + AssetsConverter: Convert>, + Assets: orml_traits::currency::MultiCurrency, + Treasury: Get, + > TakeRevenue for ToTreasury +{ + fn take_revenue(revenue: MultiAsset) { + if let MultiAsset { id: Concrete(location), fun: Fungible(amount) } = revenue { + log::info!(target: "xcmp::take_revenue", "{:?} {:?}", &location, amount); + if let Some(currency_id) = AssetsConverter::convert(location) { + let account = &Treasury::get(); + match ::deposit(currency_id, account, amount) { + Ok(_) => {}, + Err(err) => log::error!(target: "xcmp", "{:?}", err), + }; + } + } + } +} + +/// is collaed to convert some account id to account id on other network +/// as of now it is same as in Acala/Hydra +pub struct AccountIdToMultiLocation; +impl Convert for AccountIdToMultiLocation { + fn convert(account: AccountId) -> MultiLocation { + // considers any other network using globally unique ids + X1(AccountId32 { network: NetworkId::Any, id: account.into() }).into() + } +} + +/// well know XCMP origin +pub trait XcmpAssets { + fn remote_to_local(location: MultiLocation) -> Option; +} + +/// Converts currency to and from local and remote +pub struct CurrencyIdConvert( + PhantomData<(AssetRegistry, WellKnownCurrency, ThisParaId, WellKnownXcmpAssets)>, +); + +/// converts local currency into remote, +/// native currency is built in +impl< + AssetRegistry: RemoteAssetRegistry, + WellKnown: WellKnownCurrency, + ThisParaId: Get, + WellKnownXcmpAssets, + > sp_runtime::traits::Convert> + for CurrencyIdConvert +{ + fn convert(id: CurrencyId) -> Option { + match id { + CurrencyId::NATIVE => Some(MultiLocation::new( + 1, + X2(Parachain(ThisParaId::get().into()), GeneralKey(id.encode())), + )), + CurrencyId::RELAY_NATIVE => Some(MultiLocation::parent()), + _ => + if let Some(location) = AssetRegistry::asset_to_location(id).map(Into::into) { + Some(location) + } else { + log::trace!( + target: "xcmp:convert", + "mapping for {:?} on {:?} parachain not found", + id, + ThisParaId::get() + ); + None + }, + } + } +} + +// must be non assositated consta to allow for pattern match +pub const RELAY_LOCATION: MultiLocation = MultiLocation { parents: 1, interior: Here }; + +/// covderts remote asset to local +/// 1. if remote is origin without key(some identifiers), than it is native token +/// 2. if origin is parent of this consensus, than this is relay +/// 2. if origin is this consensus, than it is this native token +/// 3. if origin is some well know chain and key(asset id) is exactly same as binary value on remote +/// chain, that we map to local currency 4. if origin is mapped by sender to include our mapped id +/// into our chain, than we also map that +/// +/// so: +/// 1. in some cases origin leads to asset id +/// 2. in some well know cases remote asset id is statically typed into here (so it is okey to send +/// their id to us) 3. and in other cases they must map on us, and than send our id to here +impl< + AssetsRegistry: RemoteAssetRegistry, + WellKnown: WellKnownCurrency, + ThisParaId: Get, + WellKnownXcmpAssets: XcmpAssets, + > Convert> + for CurrencyIdConvert +{ + fn convert(location: MultiLocation) -> Option { + log::trace!(target: "xcmp::convert", "converting {:?} on {:?}", &location, ThisParaId::get()); + match location { + MultiLocation { parents, interior: X2(Parachain(id), GeneralKey(key)) } + if parents == 1 && Id::from(id) == ThisParaId::get() => + { + if let Ok(currency_id) = CurrencyId::decode(&mut &key[..]) { + if let CurrencyId::NATIVE = currency_id { + Some(CurrencyId::NATIVE) + } else { + log::error!(target: "xcmp", "currency {:?} is not yet handled", currency_id); + None + } + } else { + log::error!(target: "xcmp", "currency {:?} is not yet handled", &key); + None + } + }, + RELAY_LOCATION => { + // TODO: support DOT via abstracting CurrencyId + Some(CurrencyId::RELAY_NATIVE) + }, + MultiLocation { parents: 0, interior: X1(GeneralKey(key)) } => { + // adapt for reanchor canonical location: https://github.com/paritytech/polkadot/pull/4470 + let currency_id = CurrencyId::decode(&mut &key[..]).ok()?; + match currency_id { + CurrencyId::NATIVE => Some(CurrencyId::NATIVE), + _ => None, + } + }, + // delegate to asset-registry + _ => + if let Some(currency_id) = WellKnownXcmpAssets::remote_to_local(location.clone()) { + Some(currency_id) + } else { + log::trace!(target: "xcmp", "using assets registry for {:?}", location); + let result = AssetsRegistry::location_to_asset(XcmAssetLocation(location)) + .map(Into::into); + if result.is_none() { + log::error!(target: "xcmp", "failed converting currency"); + } + result + }, + } + } +} + +/// covert remote to local, usually when receiving transfer +impl< + T: RemoteAssetRegistry, + WellKnown: WellKnownCurrency, + ThisParaId: Get, + WellKnownXcmpAssets: XcmpAssets, + > Convert> + for CurrencyIdConvert +{ + fn convert(asset: MultiAsset) -> Option { + log::trace!(target: "xcmp", "converting {:?}", &asset); + if let MultiAsset { id: Concrete(location), .. } = asset { + >>::convert(location) + } else { + log::error!(target: "xcmp", "failed to find remote asset"); + None + } + } +} + +pub struct DebugMultiNativeAsset; +impl FilterAssetLocation for DebugMultiNativeAsset { + fn filter_asset_location(asset: &MultiAsset, origin: &MultiLocation) -> bool { + log::trace!( + target: "xcmp::filter_asset_location", + "asset: {:?}; origin: {:?}; reserve: {:?};", + &asset, + &origin, + &asset.clone().reserve(), + ); + false + } +} + +impl Drop for TransactionFeePoolTrader { + fn drop(&mut self) { + log::info!(target : "xcmp::take_revenue", "{:?} {:?}", &self.asset_location, self.fee); + if let Some(asset) = self.asset_location.take() { + if self.price > Balance::zero() { + Treasury::take_revenue((asset, self.price).into()); + } + } + } +} + +// // here we should add any partner network for zero cost transactions +// // 1000 is statmeing - see kusama runtime setup +// // (1, Here) - jump 1 up, and say here - Relay +// // (1, 1000) - jump 1 up and go to child 1000 +// match_type! { +// pub type WellKnownsChains: impl Contains = { +// | +// MultiLocation { parents: 1, interior: X1(Parachain(1000)) } +// }; +// } diff --git a/runtime/composable/Cargo.toml b/runtime/composable/Cargo.toml index 9078ea3758b..9298807133f 100644 --- a/runtime/composable/Cargo.toml +++ b/runtime/composable/Cargo.toml @@ -1,209 +1,223 @@ [package] +edition = "2021" name = "composable-runtime" version = "0.1.0" -edition = "2021" -description = "Composable, Polkadot Parachain Runtime Implementation" authors = ["Seun Lanlege "] +description = "Composable, Polkadot Parachain Runtime Implementation" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [package.metadata.cargo-udeps.ignore] normal = [ - "pallet-vault", - "session-benchmarking", - "assets-registry", - "currency-factory", - "oracle", - "vault", - "assets", - "governance-registry", - "call-filter", - "orml-unknown-tokens", - "orml-xtokens", + "pallet-vault", + "session-benchmarking", + "assets-registry", + "currency-factory", + "oracle", + "vault", + "assets", + "governance-registry", + "call-filter", + "orml-unknown-tokens", + "orml-xtokens", ] [dependencies] -frame-system = { package = "frame-system", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -executive = { package = "frame-executive", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } +executive = { package = "frame-executive", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +frame-system = { package = "frame-system", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } # primitives -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } # modules -aura = { package = "pallet-aura", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -authorship = { package = "pallet-authorship", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -balances = { package = "pallet-balances", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -indices = { package = "pallet-indices", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -randomness-collective-flip = { package = "pallet-randomness-collective-flip", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -collective = { package = "pallet-collective", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -membership = { package = "pallet-membership", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -scheduler = { package = "pallet-scheduler", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -session = { package = "pallet-session", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sudo = { package = "pallet-sudo", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -timestamp = { package = "pallet-timestamp", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -treasury = { package = "pallet-treasury", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -democracy = { package = "pallet-democracy", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -transaction-payment = { package = "pallet-transaction-payment", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -utility = { package = "pallet-utility", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -preimage = { package = "pallet-preimage", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } +aura = { package = "pallet-aura", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +authorship = { package = "pallet-authorship", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +balances = { package = "pallet-balances", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +collective = { package = "pallet-collective", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +crowdloan-rewards = { package = "pallet-crowdloan-rewards", path = '../../frame/crowdloan-rewards', default-features = false } +democracy = { package = "pallet-democracy", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +indices = { package = "pallet-indices", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +membership = { package = "pallet-membership", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } +preimage = { package = "pallet-preimage", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +randomness-collective-flip = { package = "pallet-randomness-collective-flip", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +scheduler = { package = "pallet-scheduler", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +session = { package = "pallet-session", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } smallvec = "1.6.1" +sudo = { package = "pallet-sudo", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +timestamp = { package = "pallet-timestamp", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +transaction-payment = { package = "pallet-transaction-payment", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +treasury = { package = "pallet-treasury", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +utility = { package = "pallet-utility", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } # local modules +assets = { package = "pallet-assets", path = '../../frame/assets', default-features = false } assets-registry = { package = "pallet-assets-registry", path = '../../frame/assets-registry', default-features = false, optional = true } -assets = { package = "pallet-assets", path = '../../frame/assets', default-features = false, optional = true } +call-filter = { package = "pallet-call-filter", path = "../../frame/call-filter", default-features = false } common = { path = "../common", default-features = false } -primitives = { path = "../primitives", default-features = false } +composable-support = { path = "../../frame/composable-support", default-features = false } +composable-traits = { path = "../../frame/composable-traits", default-features = false } +currency-factory = { package = "pallet-currency-factory", path = "../../frame/currency-factory", default-features = false } +governance-registry = { package = "pallet-governance-registry", path = "../../frame/governance-registry", default-features = false } oracle = { package = "pallet-oracle", path = "../../frame/oracle", default-features = false, optional = true } +primitives = { path = "../primitives", default-features = false } vault = { package = "pallet-vault", path = "../../frame/vault", default-features = false, optional = true } -governance-registry = { package = "pallet-governance-registry", path = "../../frame/governance-registry", default-features = false, optional = true } -currency-factory = { package = "pallet-currency-factory", path = "../../frame/currency-factory", default-features = false, optional = true} -composable-traits = { path = "../../frame/composable-traits" , default-features = false} -call-filter = { package = "pallet-call-filter", path = "../../frame/call-filter", default-features = false } # Used for the node template's RPCs -system-rpc-runtime-api = { package = "frame-system-rpc-runtime-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -transaction-payment-rpc-runtime-api = { package = "pallet-transaction-payment-rpc-runtime-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } +system-rpc-runtime-api = { package = "frame-system-rpc-runtime-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +transaction-payment-rpc-runtime-api = { package = "pallet-transaction-payment-rpc-runtime-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } + +# local RPCs +assets-runtime-api = { path = '../../frame/assets/runtime-api', default-features = false } +crowdloan-rewards-runtime-api = { path = '../../frame/crowdloan-rewards/runtime-api', default-features = false } # Used for runtime benchmarking -frame-benchmarking = { package = "frame-benchmarking", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false, optional = true } -system-benchmarking = { package = "frame-system-benchmarking", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false, optional = true } -hex-literal = { version = "0.3.1", optional = true } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ + "derive", +] } +frame-benchmarking = { package = "frame-benchmarking", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false, optional = true } +hex-literal = { version = "0.3.3", optional = true } +system-benchmarking = { package = "frame-system-benchmarking", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false, optional = true } # Parachain Utilities -cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -collator-selection = { package = "pallet-collator-selection", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -session-benchmarking = { package = "cumulus-pallet-session-benchmarking", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +collator-selection = { package = "pallet-collator-selection", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } +session-benchmarking = { package = "cumulus-pallet-session-benchmarking", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } # orml XCM support -orml-xtokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -orml-xcm-support = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -orml-unknown-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } +orml-unknown-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } +orml-xcm-support = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } +orml-xtokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } + +# simnode support +simnode-apis = { package = "simnode-runtime-apis", git = "https://github.com/polytope-labs/substrate-simnode", default-features = false, branch = "master" } [build-dependencies] -substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } [features] default = ["std"] +runtime-benchmarks = [ + "assets/runtime-benchmarks", + "balances/runtime-benchmarks", + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "system-benchmarking", + "frame-system/runtime-benchmarks", + "hex-literal", + "balances/runtime-benchmarks", + "timestamp/runtime-benchmarks", + "assets-registry/runtime-benchmarks", + "oracle/runtime-benchmarks", + "collective/runtime-benchmarks", + "collator-selection/runtime-benchmarks", + "session-benchmarking/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", + "indices/runtime-benchmarks", + "membership/runtime-benchmarks", + "treasury/runtime-benchmarks", + "scheduler/runtime-benchmarks", + "collective/runtime-benchmarks", + "democracy/runtime-benchmarks", + "utility/runtime-benchmarks", + "vault/runtime-benchmarks", + "common/runtime-benchmarks", +] std = [ - "codec/std", - "sp-api/std", - "sp-std/std", - "sp-core/std", - "sp-runtime/std", - "sp-version/std", - "sp-offchain/std", - "sp-session/std", - "sp-block-builder/std", - "sp-transaction-pool/std", - "sp-inherents/std", - "frame-support/std", - "executive/std", - "frame-system/std", - "utility/std", - "authorship/std", - "balances/std", - "randomness-collective-flip/std", - "timestamp/std", - "session/std", - "sudo/std", - "indices/std", - "oracle/std", - "vault/std", - "assets/std", - "governance-registry/std", - "call-filter/std", - "currency-factory/std", - "orml-tokens/std", - "orml-traits/std", - "treasury/std", - "democracy/std", - "scheduler/std", - "common/std", - "primitives/std", - "collective/std", - "transaction-payment/std", - "parachain-info/std", - "cumulus-pallet-aura-ext/std", - "cumulus-pallet-parachain-system/std", - "cumulus-pallet-xcmp-queue/std", - "cumulus-pallet-xcm/std", - "cumulus-primitives-core/std", - "cumulus-primitives-timestamp/std", - "cumulus-primitives-utility/std", - "collator-selection/std", - "xcm/std", - "xcm-builder/std", - "xcm-executor/std", - "aura/std", - "sp-consensus-aura/std", - "scale-info/std", - "orml-xtokens/std", - "orml-xcm-support/std", - "orml-unknown-tokens/std", - "assets-registry/std", - "assets/std", - "governance-registry/std", - "preimage/std", - "membership/std", - "system-rpc-runtime-api/std", - "transaction-payment-rpc-runtime-api/std", + "codec/std", + "composable-support/std", + "sp-api/std", + "sp-std/std", + "sp-core/std", + "sp-runtime/std", + "sp-version/std", + "sp-offchain/std", + "sp-session/std", + "sp-block-builder/std", + "sp-transaction-pool/std", + "sp-inherents/std", + "frame-support/std", + "executive/std", + "frame-system/std", + "utility/std", + "authorship/std", + "balances/std", + "randomness-collective-flip/std", + "timestamp/std", + "session/std", + "sudo/std", + "indices/std", + "oracle/std", + "vault/std", + "assets/std", + "governance-registry/std", + "call-filter/std", + "currency-factory/std", + "orml-tokens/std", + "orml-traits/std", + "treasury/std", + "democracy/std", + "scheduler/std", + "common/std", + "primitives/std", + "collective/std", + "transaction-payment/std", + "parachain-info/std", + "cumulus-pallet-aura-ext/std", + "cumulus-pallet-parachain-system/std", + "cumulus-pallet-xcmp-queue/std", + "cumulus-pallet-xcm/std", + "cumulus-primitives-core/std", + "cumulus-primitives-timestamp/std", + "cumulus-primitives-utility/std", + "collator-selection/std", + "xcm/std", + "xcm-builder/std", + "xcm-executor/std", + "aura/std", + "sp-consensus-aura/std", + "scale-info/std", + "orml-xtokens/std", + "orml-xcm-support/std", + "orml-unknown-tokens/std", + "assets-registry/std", + "governance-registry/std", + "preimage/std", + "membership/std", + "system-rpc-runtime-api/std", + "transaction-payment-rpc-runtime-api/std", ] -runtime-benchmarks = [ - "assets/runtime-benchmarks", - "balances/runtime-benchmarks", - "frame-benchmarking", - "frame-support/runtime-benchmarks", - "system-benchmarking", - "frame-system/runtime-benchmarks", - "hex-literal", - "balances/runtime-benchmarks", - "timestamp/runtime-benchmarks", - "assets-registry/runtime-benchmarks", - "oracle/runtime-benchmarks", - "collective/runtime-benchmarks", - "collator-selection/runtime-benchmarks", - "session-benchmarking/runtime-benchmarks", - "pallet-xcm/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "xcm-builder/runtime-benchmarks", - "indices/runtime-benchmarks", - "membership/runtime-benchmarks", - "treasury/runtime-benchmarks", - "scheduler/runtime-benchmarks", - "collective/runtime-benchmarks", - "democracy/runtime-benchmarks", - "utility/runtime-benchmarks", - "vault/runtime-benchmarks", -] \ No newline at end of file diff --git a/runtime/composable/src/lib.rs b/runtime/composable/src/lib.rs index 7076e6997a0..32e8d292adf 100644 --- a/runtime/composable/src/lib.rs +++ b/runtime/composable/src/lib.rs @@ -23,8 +23,8 @@ mod weights; mod xcmp; use common::{ impls::DealWithFees, AccountId, AccountIndex, Address, Amount, AuraId, Balance, BlockNumber, - CouncilInstance, EnsureRootOrHalfCouncil, Hash, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, - HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION, + CouncilInstance, EnsureRootOrHalfCouncil, Hash, Moment, Signature, AVERAGE_ON_INITIALIZE_RATIO, + DAYS, HOURS, MAXIMUM_BLOCK_WEIGHT, MILLISECS_PER_BLOCK, NORMAL_DISPATCH_RATIO, SLOT_DURATION, }; use orml_traits::parameter_type_with_key; use primitives::currency::CurrencyId; @@ -37,6 +37,7 @@ use sp_runtime::{ ApplyExtrinsicResult, }; +use composable_support::rpc_helpers::SafeRpcWrapper; use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; @@ -100,7 +101,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`, // `spec_version`, and `authoring_version` are the same between Wasm and native. spec_version: 1000, - impl_version: 2, + impl_version: 4, apis: RUNTIME_API_VERSIONS, transaction_version: 2, state_version: 0, @@ -219,7 +220,7 @@ parameter_types! { impl timestamp::Config for Runtime { /// A timestamp: milliseconds since the Unix epoch. - type Moment = u64; + type Moment = Moment; /// What to do when SLOT_DURATION has passed? type OnTimestampSet = Aura; type MinimumPeriod = MinimumPeriod; @@ -228,8 +229,8 @@ impl timestamp::Config for Runtime { parameter_types! { /// Minimum amount an account has to hold to stay in state. - // minimum account balance is given as 0.1 PICA ~ 100 CurrencyId::PICA.milli() - pub ExistentialDeposit: Balance = 100 * CurrencyId::PICA.milli::(); + // minimum account balance is given as 0.1 PICA ~ 100 CurrencyId::milli() + pub ExistentialDeposit: Balance = 100 * CurrencyId::milli::(); /// Max locks that can be placed on an account. Capped for storage /// concerns. pub const MaxLocks: u32 = 50; @@ -251,7 +252,7 @@ impl balances::Config for Runtime { parameter_types! { /// 1 milli-pica/byte should be fine - pub TransactionByteFee: Balance = CurrencyId::PICA.milli(); + pub TransactionByteFee: Balance = CurrencyId::milli(); // The portion of the `NORMAL_DISPATCH_RATIO` that we adjust the fees with. Blocks filled less /// than this will decrease the weight and more will increase. @@ -272,7 +273,7 @@ pub struct WeightToFee; impl WeightToFeePolynomial for WeightToFee { type Balance = Balance; fn polynomial() -> WeightToFeeCoefficients { - let p = CurrencyId::PICA.milli::(); + let p = CurrencyId::milli::(); let q = 10 * Balance::from(ExtrinsicBaseWeight::get()); smallvec::smallvec![WeightToFeeCoefficient { degree: 1, @@ -300,7 +301,7 @@ impl sudo::Config for Runtime { parameter_types! { /// Deposit required to get an index. - pub IndexDeposit: Balance = 100 * CurrencyId::PICA.unit::(); + pub IndexDeposit: Balance = 100 * CurrencyId::unit::(); } impl indices::Config for Runtime { @@ -379,7 +380,7 @@ parameter_types! { pub const StalePrice: BlockNumber = 5; /// TODO: discuss with omar/cosmin - pub MinStake: Balance = 1000 * CurrencyId::PICA.unit::(); + pub MinStake: Balance = 1000 * CurrencyId::unit::(); pub const MaxAnswerBound: u32 = 25; pub const MaxAssetsCount: u32 = 100_000; pub const MaxHistory: u32 = 20; @@ -464,6 +465,18 @@ impl collator_selection::Config for Runtime { type WeightInfo = weights::collator_selection::WeightInfo; } +impl assets::Config for Runtime { + type NativeAssetId = NativeAssetId; + type GenerateCurrencyId = CurrencyFactory; + type AssetId = CurrencyId; + type Balance = Balance; + type NativeCurrency = Balances; + type MultiCurrency = Tokens; + type WeightInfo = (); + type AdminOrigin = EnsureRootOrHalfCouncil; + type GovernanceRegistry = GovernanceRegistry; +} + parameter_type_with_key! { // TODO: pub ExistentialDeposits: |_currency_id: CurrencyId| -> Balance { @@ -501,8 +514,8 @@ parameter_types! { /// percentage of proposal that most be bonded by the proposer pub const ProposalBond: Permill = Permill::from_percent(5); // TODO: rationale? - pub ProposalBondMinimum: Balance = 5 * CurrencyId::PICA.unit::(); - pub ProposalBondMaximum: Balance = 1000 * CurrencyId::PICA.unit::(); + pub ProposalBondMinimum: Balance = 5 * CurrencyId::unit::(); + pub ProposalBondMaximum: Balance = 1000 * CurrencyId::unit::(); pub const SpendPeriod: BlockNumber = 7 * DAYS; pub const Burn: Permill = Permill::from_percent(0); @@ -581,7 +594,7 @@ impl scheduler::Config for Runtime { parameter_types! { pub const PreimageMaxSize: u32 = 4096 * 1024; - pub PreimageBaseDeposit: Balance = 10 * CurrencyId::PICA.unit::(); + pub PreimageBaseDeposit: Balance = 10 * CurrencyId::unit::(); } impl preimage::Config for Runtime { @@ -606,16 +619,31 @@ parameter_types! { pub const VotingPeriod: BlockNumber = 5 * DAYS; pub const FastTrackVotingPeriod: BlockNumber = 3 * HOURS; - pub MinimumDeposit: Balance = 100 * CurrencyId::PICA.unit::(); + pub MinimumDeposit: Balance = 100 * CurrencyId::unit::(); pub const EnactmentPeriod: BlockNumber = 2 * DAYS; pub const CooloffPeriod: BlockNumber = 7 * DAYS; // TODO: prod value - pub PreimageByteDeposit: Balance = CurrencyId::PICA.milli(); + pub PreimageByteDeposit: Balance = CurrencyId::milli(); pub const InstantAllowed: bool = true; pub const MaxVotes: u32 = 100; pub const MaxProposals: u32 = 100; } +impl governance_registry::Config for Runtime { + type Event = Event; + type AssetId = CurrencyId; + type WeightInfo = (); +} + +impl currency_factory::Config for Runtime { + type Event = Event; + type AssetId = CurrencyId; + type AddOrigin = EnsureRootOrHalfCouncil; + type ReserveOrigin = EnsureRootOrHalfCouncil; + type WeightInfo = (); + // type WeightInfo = weights::currency_factory::WeightInfo; +} + impl democracy::Config for Runtime { type Proposal = Call; type Event = Event; @@ -653,15 +681,46 @@ impl democracy::Config for Runtime { type WeightInfo = weights::democracy::WeightInfo; } +parameter_types! { + pub const CrowdloanRewardsId: PalletId = PalletId(*b"pal_crow"); + pub const InitialPayment: Perbill = Perbill::from_percent(25); + pub const VestingStep: Moment = (7 * DAYS as Moment) * MILLISECS_PER_BLOCK; + pub const Prefix: &'static [u8] = b"composable-"; +} + +impl crowdloan_rewards::Config for Runtime { + type Event = Event; + type Balance = Balance; + type RewardAsset = Assets; + type AdminOrigin = EnsureRootOrHalfCouncil; + type Convert = sp_runtime::traits::ConvertInto; + type RelayChainAccountId = [u8; 32]; + type InitialPayment = InitialPayment; + type VestingStep = VestingStep; + type Prefix = Prefix; + type WeightInfo = (); + type PalletId = CrowdloanRewardsId; + type Moment = Moment; + type Time = Timestamp; +} + +parameter_types! { + pub const MaxStrategies: usize = 255; + pub NativeAssetId: CurrencyId = CurrencyId::PICA; + pub CreationDeposit: Balance = 10 * CurrencyId::unit::(); + pub VaultExistentialDeposit: Balance = 1000 * CurrencyId::unit::(); + pub RentPerBlock: Balance = CurrencyId::milli::(); + pub const VaultMinimumDeposit: Balance = 10_000; + pub const VaultMinimumWithdrawal: Balance = 10_000; + pub const VaultPalletId: PalletId = PalletId(*b"cubic___"); +} + /// The calls we permit to be executed by extrinsics pub struct BaseCallFilter; impl Contains for BaseCallFilter { fn contains(call: &Call) -> bool { - !matches!( - call, - Call::Balances(_) | Call::Indices(_) | Call::Democracy(_) | Call::Treasury(_) - ) + !matches!(call, Call::Tokens(_) | Call::Indices(_) | Call::Democracy(_) | Call::Treasury(_)) } } @@ -698,7 +757,7 @@ construct_runtime!( Democracy: democracy::{Pallet, Call, Storage, Config, Event} = 33, Scheduler: scheduler::{Pallet, Call, Storage, Event} = 34, Utility: utility::{Pallet, Call, Event} = 35, - Preimage: preimage::{Pallet, Call, Storage, Event} = 36, + Preimage: preimage::{Pallet, Call, Storage, Event} = 36, // XCM helpers. XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event} = 40, @@ -707,6 +766,11 @@ construct_runtime!( DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event} = 43, Tokens: orml_tokens::{Pallet, Call, Storage, Event} = 52, + + CurrencyFactory: currency_factory::{Pallet, Storage, Event} = 53, + CrowdloanRewards: crowdloan_rewards::{Pallet, Call, Storage, Event, ValidateUnsigned} = 56, + Assets: assets::{Pallet, Call, Storage} = 57, + GovernanceRegistry: governance_registry::{Pallet, Call, Storage, Event} = 58, } ); @@ -771,6 +835,21 @@ mod benches { } impl_runtime_apis! { + impl assets_runtime_api::AssetsRuntimeApi for Runtime { + fn balance_of(SafeRpcWrapper(asset_id): SafeRpcWrapper, account_id: AccountId) -> SafeRpcWrapper /* Balance */ { + SafeRpcWrapper(>::balance(asset_id, &account_id)) + } + } + + impl crowdloan_rewards_runtime_api::CrowdloanRewardsRuntimeApi for Runtime { + fn amount_available_to_claim_for(account_id: AccountId) -> SafeRpcWrapper { + SafeRpcWrapper( + crowdloan_rewards::amount_available_to_claim_for::(account_id) + .unwrap_or_else(|_| Balance::zero()) + ) + } + } + impl sp_api::Core for Runtime { fn version() -> RuntimeVersion { VERSION @@ -877,13 +956,42 @@ impl_runtime_apis! { } } + + impl simnode_apis::CreateTransactionApi for Runtime { + fn create_transaction(call: Call, signer: AccountId) -> Vec { + use sp_runtime::{ + generic::Era, MultiSignature, + traits::StaticLookup, + }; + use sp_core::sr25519; + + let nonce = frame_system::Pallet::::account_nonce(signer.clone()); + let extra = ( + system::CheckNonZeroSender::::new(), + system::CheckSpecVersion::::new(), + system::CheckTxVersion::::new(), + system::CheckGenesis::::new(), + system::CheckEra::::from(Era::Immortal), + system::CheckNonce::::from(nonce), + system::CheckWeight::::new(), + transaction_payment::ChargeTransactionPayment::::from(0), + ); + + let signature = MultiSignature::from(sr25519::Signature([0_u8;64])); + let address = AccountIdLookup::unlookup(signer); + let ext = UncheckedExtrinsic::new_signed(call, address, signature, extra); + + ext.encode() + } + } + #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { fn benchmark_metadata(extra: bool) -> ( Vec, Vec, ) { - use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList}; + use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use system_benchmarking::Pallet as SystemBench; use session_benchmarking::Pallet as SessionBench; @@ -900,7 +1008,7 @@ impl_runtime_apis! { fn dispatch_benchmark( config: frame_benchmarking::BenchmarkConfig ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey}; + use frame_benchmarking::{Benchmarking, BenchmarkBatch, TrackedStorageKey}; use system_benchmarking::Pallet as SystemBench; impl system_benchmarking::Config for Runtime {} diff --git a/runtime/composable/src/weights/balances.rs b/runtime/composable/src/weights/balances.rs index effdccc6e5a..8b6a45e1d3b 100644 --- a/runtime/composable/src/weights/balances.rs +++ b/runtime/composable/src/weights/balances.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `balances` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=composable-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=balances +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/composable/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -30,43 +31,43 @@ pub struct WeightInfo(PhantomData); impl balances::WeightInfo for WeightInfo { // Storage: System Account (r:2 w:2) fn transfer() -> Weight { - (84_077_000 as Weight) + (95_037_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: System Account (r:1 w:1) fn transfer_keep_alive() -> Weight { - (49_893_000 as Weight) + (58_879_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn set_balance_creating() -> Weight { - (28_200_000 as Weight) + (34_804_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn set_balance_killing() -> Weight { - (34_293_000 as Weight) + (41_604_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:3 w:3) fn force_transfer() -> Weight { - (84_155_000 as Weight) + (95_676_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: System Account (r:1 w:1) fn transfer_all() -> Weight { - (61_279_000 as Weight) + (70_772_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn force_unreserve() -> Weight { - (26_083_000 as Weight) + (32_437_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } diff --git a/runtime/composable/src/weights/collator_selection.rs b/runtime/composable/src/weights/collator_selection.rs index 734a112334b..d6e9b92e5d1 100644 --- a/runtime/composable/src/weights/collator_selection.rs +++ b/runtime/composable/src/weights/collator_selection.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `collator_selection` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=composable-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=collator_selection +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/composable/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -28,21 +29,23 @@ use sp_std::marker::PhantomData; /// Weight functions for `collator_selection`. pub struct WeightInfo(PhantomData); impl collator_selection::WeightInfo for WeightInfo { + // Storage: Session NextKeys (r:1 w:0) // Storage: CollatorSelection Invulnerables (r:0 w:1) fn set_invulnerables(b: u32, ) -> Weight { - (15_646_000 as Weight) - // Standard Error: 0 - .saturating_add((40_000 as Weight).saturating_mul(b as Weight)) + (16_673_000 as Weight) + // Standard Error: 7_000 + .saturating_add((6_970_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: CollatorSelection DesiredCandidates (r:0 w:1) fn set_desired_candidates() -> Weight { - (13_953_000 as Weight) + (16_896_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: CollatorSelection CandidacyBond (r:0 w:1) fn set_candidacy_bond() -> Weight { - (14_437_000 as Weight) + (16_956_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: CollatorSelection Candidates (r:1 w:1) @@ -52,18 +55,18 @@ impl collator_selection::WeightInfo for WeightInfo { // Storage: CollatorSelection CandidacyBond (r:1 w:0) // Storage: CollatorSelection LastAuthoredBlock (r:0 w:1) fn register_as_candidate(c: u32, ) -> Weight { - (89_736_000 as Weight) - // Standard Error: 1_000 - .saturating_add((173_000 as Weight).saturating_mul(c as Weight)) + (117_333_000 as Weight) + // Standard Error: 2_000 + .saturating_add((307_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: CollatorSelection Candidates (r:1 w:1) // Storage: CollatorSelection LastAuthoredBlock (r:0 w:1) fn leave_intent(c: u32, ) -> Weight { - (81_766_000 as Weight) - // Standard Error: 1_000 - .saturating_add((240_000 as Weight).saturating_mul(c as Weight)) + (138_310_000 as Weight) + // Standard Error: 4_000 + .saturating_add((351_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -71,7 +74,7 @@ impl collator_selection::WeightInfo for WeightInfo { // Storage: System BlockWeight (r:1 w:1) // Storage: CollatorSelection LastAuthoredBlock (r:0 w:1) fn note_author() -> Weight { - (61_512_000 as Weight) + (70_700_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -82,10 +85,10 @@ impl collator_selection::WeightInfo for WeightInfo { // Storage: System BlockWeight (r:1 w:1) fn new_session(r: u32, c: u32, ) -> Weight { (0 as Weight) - // Standard Error: 4_493_000 - .saturating_add((22_945_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 4_493_000 - .saturating_add((118_123_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 5_632_000 + .saturating_add((28_678_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 5_632_000 + .saturating_add((148_534_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(c as Weight))) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(c as Weight))) diff --git a/runtime/composable/src/weights/collective.rs b/runtime/composable/src/weights/collective.rs index 9558ace3227..9c60d878a1a 100644 --- a/runtime/composable/src/weights/collective.rs +++ b/runtime/composable/src/weights/collective.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `collective` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=composable-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=collective +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/composable/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -34,12 +35,12 @@ impl collective::WeightInfo for WeightInfo { // Storage: Council Prime (r:0 w:1) fn set_members(m: u32, n: u32, p: u32, ) -> Weight { (0 as Weight) - // Standard Error: 209_000 - .saturating_add((11_995_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 209_000 - .saturating_add((179_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 209_000 - .saturating_add((23_116_000 as Weight).saturating_mul(p as Weight)) + // Standard Error: 16_000 + .saturating_add((28_694_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 16_000 + .saturating_add((277_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 16_000 + .saturating_add((34_676_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(p as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -47,21 +48,21 @@ impl collective::WeightInfo for WeightInfo { } // Storage: Council Members (r:1 w:0) fn execute(b: u32, m: u32, ) -> Weight { - (20_657_000 as Weight) + (25_784_000 as Weight) // Standard Error: 0 .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 0 - .saturating_add((93_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((121_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Council Members (r:1 w:0) // Storage: Council ProposalOf (r:1 w:0) fn propose_execute(b: u32, m: u32, ) -> Weight { - (25_129_000 as Weight) + (29_738_000 as Weight) // Standard Error: 0 .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 0 - .saturating_add((176_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((232_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) } // Storage: Council Members (r:1 w:0) @@ -70,22 +71,22 @@ impl collective::WeightInfo for WeightInfo { // Storage: Council ProposalCount (r:1 w:1) // Storage: Council Voting (r:0 w:1) fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight { - (34_266_000 as Weight) + (31_957_000 as Weight) // Standard Error: 0 - .saturating_add((10_000 as Weight).saturating_mul(b as Weight)) - // Standard Error: 2_000 - .saturating_add((105_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 2_000 - .saturating_add((425_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((17_000 as Weight).saturating_mul(b as Weight)) + // Standard Error: 3_000 + .saturating_add((167_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 3_000 + .saturating_add((558_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Council Members (r:1 w:0) // Storage: Council Voting (r:1 w:1) fn vote(m: u32, ) -> Weight { - (42_847_000 as Weight) - // Standard Error: 3_000 - .saturating_add((198_000 as Weight).saturating_mul(m as Weight)) + (60_623_000 as Weight) + // Standard Error: 4_000 + .saturating_add((291_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -94,11 +95,11 @@ impl collective::WeightInfo for WeightInfo { // Storage: Council Proposals (r:1 w:1) // Storage: Council ProposalOf (r:0 w:1) fn close_early_disapproved(m: u32, p: u32, ) -> Weight { - (42_813_000 as Weight) - // Standard Error: 2_000 - .saturating_add((189_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 2_000 - .saturating_add((356_000 as Weight).saturating_mul(p as Weight)) + (50_374_000 as Weight) + // Standard Error: 3_000 + .saturating_add((257_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 3_000 + .saturating_add((457_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -107,13 +108,13 @@ impl collective::WeightInfo for WeightInfo { // Storage: Council ProposalOf (r:1 w:1) // Storage: Council Proposals (r:1 w:1) fn close_early_approved(b: u32, m: u32, p: u32, ) -> Weight { - (51_855_000 as Weight) + (50_092_000 as Weight) // Standard Error: 0 - .saturating_add((8_000 as Weight).saturating_mul(b as Weight)) - // Standard Error: 2_000 - .saturating_add((195_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 2_000 - .saturating_add((424_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((14_000 as Weight).saturating_mul(b as Weight)) + // Standard Error: 3_000 + .saturating_add((321_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 3_000 + .saturating_add((593_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -123,11 +124,11 @@ impl collective::WeightInfo for WeightInfo { // Storage: Council Proposals (r:1 w:1) // Storage: Council ProposalOf (r:0 w:1) fn close_disapproved(m: u32, p: u32, ) -> Weight { - (48_871_000 as Weight) - // Standard Error: 2_000 - .saturating_add((181_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 2_000 - .saturating_add((349_000 as Weight).saturating_mul(p as Weight)) + (52_096_000 as Weight) + // Standard Error: 3_000 + .saturating_add((310_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 3_000 + .saturating_add((478_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -137,13 +138,13 @@ impl collective::WeightInfo for WeightInfo { // Storage: Council ProposalOf (r:1 w:1) // Storage: Council Proposals (r:1 w:1) fn close_approved(b: u32, m: u32, p: u32, ) -> Weight { - (54_571_000 as Weight) + (59_760_000 as Weight) // Standard Error: 0 - .saturating_add((9_000 as Weight).saturating_mul(b as Weight)) - // Standard Error: 2_000 - .saturating_add((207_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 2_000 - .saturating_add((418_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((11_000 as Weight).saturating_mul(b as Weight)) + // Standard Error: 4_000 + .saturating_add((308_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 3_000 + .saturating_add((596_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -151,9 +152,9 @@ impl collective::WeightInfo for WeightInfo { // Storage: Council Voting (r:0 w:1) // Storage: Council ProposalOf (r:0 w:1) fn disapprove_proposal(p: u32, ) -> Weight { - (25_921_000 as Weight) - // Standard Error: 1_000 - .saturating_add((412_000 as Weight).saturating_mul(p as Weight)) + (30_583_000 as Weight) + // Standard Error: 2_000 + .saturating_add((505_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } diff --git a/runtime/composable/src/weights/democracy.rs b/runtime/composable/src/weights/democracy.rs index afc2f6a013f..bc1338c40a9 100644 --- a/runtime/composable/src/weights/democracy.rs +++ b/runtime/composable/src/weights/democracy.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `democracy` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=composable-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=democracy +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/composable/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -33,15 +34,15 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy Blacklist (r:1 w:0) // Storage: Democracy DepositOf (r:0 w:1) fn propose() -> Weight { - (74_909_000 as Weight) + (92_800_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy DepositOf (r:1 w:1) fn second(s: u32, ) -> Weight { - (38_710_000 as Weight) - // Standard Error: 1_000 - .saturating_add((240_000 as Weight).saturating_mul(s as Weight)) + (54_533_000 as Weight) + // Standard Error: 4_000 + .saturating_add((301_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -49,9 +50,9 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_new(r: u32, ) -> Weight { - (43_131_000 as Weight) - // Standard Error: 1_000 - .saturating_add((246_000 as Weight).saturating_mul(r as Weight)) + (69_231_000 as Weight) + // Standard Error: 3_000 + .saturating_add((296_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -59,16 +60,16 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_existing(r: u32, ) -> Weight { - (43_407_000 as Weight) - // Standard Error: 1_000 - .saturating_add((225_000 as Weight).saturating_mul(r as Weight)) + (69_142_000 as Weight) + // Standard Error: 3_000 + .saturating_add((311_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy Cancellations (r:1 w:1) fn emergency_cancel() -> Weight { - (25_856_000 as Weight) + (31_287_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -79,45 +80,45 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:2 w:2) fn blacklist(p: u32, ) -> Weight { - (89_295_000 as Weight) - // Standard Error: 6_000 - .saturating_add((566_000 as Weight).saturating_mul(p as Weight)) + (107_807_000 as Weight) + // Standard Error: 8_000 + .saturating_add((706_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:0) fn external_propose(v: u32, ) -> Weight { - (13_453_000 as Weight) + (16_461_000 as Weight) // Standard Error: 0 - .saturating_add((91_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((116_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_majority() -> Weight { - (2_844_000 as Weight) + (3_182_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_default() -> Weight { - (2_886_000 as Weight) + (3_328_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:1) // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn fast_track() -> Weight { - (26_634_000 as Weight) + (32_647_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:1) fn veto_external(v: u32, ) -> Weight { - (29_471_000 as Weight) - // Standard Error: 2_000 - .saturating_add((113_000 as Weight).saturating_mul(v as Weight)) + (34_636_000 as Weight) + // Standard Error: 1_000 + .saturating_add((148_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -125,23 +126,23 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:2 w:2) fn cancel_proposal(p: u32, ) -> Weight { - (65_565_000 as Weight) - // Standard Error: 2_000 - .saturating_add((518_000 as Weight).saturating_mul(p as Weight)) + (79_179_000 as Weight) + // Standard Error: 4_000 + .saturating_add((669_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn cancel_referendum() -> Weight { - (16_176_000 as Weight) + (19_412_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn cancel_queued(r: u32, ) -> Weight { - (30_608_000 as Weight) - // Standard Error: 2_000 - .saturating_add((1_570_000 as Weight).saturating_mul(r as Weight)) + (38_847_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_798_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -149,9 +150,9 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy ReferendumCount (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:1 w:0) fn on_initialize_base(r: u32, ) -> Weight { - (5_773_000 as Weight) - // Standard Error: 5_000 - .saturating_add((5_338_000 as Weight).saturating_mul(r as Weight)) + (5_667_000 as Weight) + // Standard Error: 6_000 + .saturating_add((6_812_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -163,9 +164,9 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy PublicProps (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:1 w:0) fn on_initialize_base_with_launch_period(r: u32, ) -> Weight { - (14_026_000 as Weight) - // Standard Error: 4_000 - .saturating_add((5_334_000 as Weight).saturating_mul(r as Weight)) + (15_630_000 as Weight) + // Standard Error: 6_000 + .saturating_add((6_820_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -174,9 +175,9 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn delegate(r: u32, ) -> Weight { - (57_660_000 as Weight) - // Standard Error: 4_000 - .saturating_add((7_064_000 as Weight).saturating_mul(r as Weight)) + (110_148_000 as Weight) + // Standard Error: 236_000 + .saturating_add((9_475_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(4 as Weight)) @@ -185,9 +186,9 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy VotingOf (r:2 w:2) // Storage: Democracy ReferendumInfoOf (r:1 w:1) fn undelegate(r: u32, ) -> Weight { - (26_308_000 as Weight) - // Standard Error: 6_000 - .saturating_add((7_096_000 as Weight).saturating_mul(r as Weight)) + (30_427_000 as Weight) + // Standard Error: 8_000 + .saturating_add((8_830_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -195,12 +196,12 @@ impl democracy::WeightInfo for WeightInfo { } // Storage: Democracy PublicProps (r:0 w:1) fn clear_public_proposals() -> Weight { - (3_131_000 as Weight) + (3_685_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy Preimages (r:1 w:1) fn note_preimage(b: u32, ) -> Weight { - (42_010_000 as Weight) + (48_277_000 as Weight) // Standard Error: 0 .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) @@ -208,16 +209,16 @@ impl democracy::WeightInfo for WeightInfo { } // Storage: Democracy Preimages (r:1 w:1) fn note_imminent_preimage(b: u32, ) -> Weight { - (27_462_000 as Weight) + (31_367_000 as Weight) // Standard Error: 0 - .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy Preimages (r:1 w:1) // Storage: System Account (r:1 w:0) fn reap_preimage(b: u32, ) -> Weight { - (39_771_000 as Weight) + (48_565_000 as Weight) // Standard Error: 0 .saturating_add((1_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) @@ -227,9 +228,9 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlock_remove(r: u32, ) -> Weight { - (37_208_000 as Weight) - // Standard Error: 1_000 - .saturating_add((114_000 as Weight).saturating_mul(r as Weight)) + (48_471_000 as Weight) + // Standard Error: 10_000 + .saturating_add((186_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -237,27 +238,27 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlock_set(r: u32, ) -> Weight { - (36_216_000 as Weight) + (43_240_000 as Weight) // Standard Error: 2_000 - .saturating_add((191_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((250_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) fn remove_vote(r: u32, ) -> Weight { - (20_278_000 as Weight) - // Standard Error: 1_000 - .saturating_add((193_000 as Weight).saturating_mul(r as Weight)) + (25_009_000 as Weight) + // Standard Error: 2_000 + .saturating_add((250_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) fn remove_other_vote(r: u32, ) -> Weight { - (20_174_000 as Weight) + (25_531_000 as Weight) // Standard Error: 2_000 - .saturating_add((193_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((244_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } diff --git a/runtime/composable/src/weights/frame_system.rs b/runtime/composable/src/weights/frame_system.rs index 6fbe3abd35d..cb672fbfe57 100644 --- a/runtime/composable/src/weights/frame_system.rs +++ b/runtime/composable/src/weights/frame_system.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `frame_system` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=composable-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=frame_system +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/composable/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -34,36 +35,36 @@ impl frame_system::WeightInfo for WeightInfo { .saturating_add((1_000 as Weight).saturating_mul(b as Weight)) } fn remark_with_event(b: u32, ) -> Weight { - (17_383_000 as Weight) + (0 as Weight) // Standard Error: 0 - .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) } // Storage: System Digest (r:1 w:1) // Storage: unknown [0x3a686561707061676573] (r:0 w:1) fn set_heap_pages() -> Weight { - (5_140_000 as Weight) + (5_772_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn set_storage(i: u32, ) -> Weight { (0 as Weight) - // Standard Error: 0 - .saturating_add((845_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 1_000 + .saturating_add((978_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn kill_storage(i: u32, ) -> Weight { - (508_000 as Weight) - // Standard Error: 1_000 - .saturating_add((556_000 as Weight).saturating_mul(i as Weight)) + (0 as Weight) + // Standard Error: 2_000 + .saturating_add((663_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn kill_prefix(p: u32, ) -> Weight { (0 as Weight) - // Standard Error: 1_000 - .saturating_add((898_000 as Weight).saturating_mul(p as Weight)) + // Standard Error: 2_000 + .saturating_add((1_367_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(p as Weight))) } } diff --git a/runtime/composable/src/weights/indices.rs b/runtime/composable/src/weights/indices.rs index 64fe48b69c4..b4cf13252fe 100644 --- a/runtime/composable/src/weights/indices.rs +++ b/runtime/composable/src/weights/indices.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `indices` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=composable-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=indices +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/composable/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -30,33 +31,33 @@ pub struct WeightInfo(PhantomData); impl indices::WeightInfo for WeightInfo { // Storage: Indices Accounts (r:1 w:1) fn claim() -> Weight { - (37_831_000 as Weight) + (45_009_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - (45_343_000 as Weight) + (56_046_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Indices Accounts (r:1 w:1) fn free() -> Weight { - (38_017_000 as Weight) + (45_955_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn force_transfer() -> Weight { - (39_059_000 as Weight) + (47_021_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Indices Accounts (r:1 w:1) fn freeze() -> Weight { - (43_452_000 as Weight) + (52_666_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } diff --git a/runtime/composable/src/weights/membership.rs b/runtime/composable/src/weights/membership.rs index cacb84958c4..58172054ba0 100644 --- a/runtime/composable/src/weights/membership.rs +++ b/runtime/composable/src/weights/membership.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `membership` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=composable-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=membership +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/composable/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -33,9 +34,9 @@ impl membership::WeightInfo for WeightInfo { // Storage: Council Members (r:0 w:1) // Storage: Council Prime (r:0 w:1) fn add_member(m: u32, ) -> Weight { - (22_951_000 as Weight) - // Standard Error: 1_000 - .saturating_add((123_000 as Weight).saturating_mul(m as Weight)) + (26_982_000 as Weight) + // Standard Error: 11_000 + .saturating_add((205_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -45,9 +46,9 @@ impl membership::WeightInfo for WeightInfo { // Storage: Council Members (r:0 w:1) // Storage: Council Prime (r:0 w:1) fn remove_member(m: u32, ) -> Weight { - (29_232_000 as Weight) - // Standard Error: 10_000 - .saturating_add((412_000 as Weight).saturating_mul(m as Weight)) + (34_085_000 as Weight) + // Standard Error: 0 + .saturating_add((150_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -57,9 +58,9 @@ impl membership::WeightInfo for WeightInfo { // Storage: Council Members (r:0 w:1) // Storage: Council Prime (r:0 w:1) fn swap_member(m: u32, ) -> Weight { - (43_962_000 as Weight) - // Standard Error: 7_000 - .saturating_add((261_000 as Weight).saturating_mul(m as Weight)) + (34_582_000 as Weight) + // Standard Error: 1_000 + .saturating_add((168_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -69,9 +70,9 @@ impl membership::WeightInfo for WeightInfo { // Storage: Council Members (r:0 w:1) // Storage: Council Prime (r:0 w:1) fn reset_member(m: u32, ) -> Weight { - (50_808_000 as Weight) - // Standard Error: 7_000 - .saturating_add((436_000 as Weight).saturating_mul(m as Weight)) + (35_020_000 as Weight) + // Standard Error: 1_000 + .saturating_add((358_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -81,9 +82,9 @@ impl membership::WeightInfo for WeightInfo { // Storage: Council Members (r:0 w:1) // Storage: Council Prime (r:0 w:1) fn change_key(m: u32, ) -> Weight { - (49_406_000 as Weight) - // Standard Error: 6_000 - .saturating_add((231_000 as Weight).saturating_mul(m as Weight)) + (36_301_000 as Weight) + // Standard Error: 1_000 + .saturating_add((163_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -91,18 +92,18 @@ impl membership::WeightInfo for WeightInfo { // Storage: CouncilMembership Prime (r:0 w:1) // Storage: Council Prime (r:0 w:1) fn set_prime(m: u32, ) -> Weight { - (11_766_000 as Weight) - // Standard Error: 4_000 - .saturating_add((148_000 as Weight).saturating_mul(m as Weight)) + (9_647_000 as Weight) + // Standard Error: 0 + .saturating_add((112_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: CouncilMembership Prime (r:0 w:1) // Storage: Council Prime (r:0 w:1) fn clear_prime(m: u32, ) -> Weight { - (5_433_000 as Weight) + (3_507_000 as Weight) // Standard Error: 0 - .saturating_add((7_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } } diff --git a/runtime/composable/src/weights/scheduler.rs b/runtime/composable/src/weights/scheduler.rs index 192fd7a90ab..2444b615831 100644 --- a/runtime/composable/src/weights/scheduler.rs +++ b/runtime/composable/src/weights/scheduler.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `scheduler` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=composable-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=scheduler +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/composable/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -28,38 +29,149 @@ use sp_std::marker::PhantomData; /// Weight functions for `scheduler`. pub struct WeightInfo(PhantomData); impl scheduler::WeightInfo for WeightInfo { + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Scheduler Lookup (r:0 w:1) + fn on_initialize_periodic_named_resolved(s: u32, ) -> Weight { + (14_905_000 as Weight) + // Standard Error: 56_000 + .saturating_add((45_343_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((4 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:1 w:1) + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Scheduler Lookup (r:0 w:1) + fn on_initialize_named_resolved(s: u32, ) -> Weight { + (11_917_000 as Weight) + // Standard Error: 35_000 + .saturating_add((35_404_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + fn on_initialize_periodic_resolved(s: u32, ) -> Weight { + (14_519_000 as Weight) + // Standard Error: 53_000 + .saturating_add((38_989_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:1 w:1) + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + fn on_initialize_resolved(s: u32, ) -> Weight { + (10_860_000 as Weight) + // Standard Error: 26_000 + .saturating_add((32_568_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Preimage PreimageFor (r:1 w:0) + // Storage: Scheduler Lookup (r:0 w:1) + fn on_initialize_named_aborted(s: u32, ) -> Weight { + (13_436_000 as Weight) + // Standard Error: 16_000 + .saturating_add((14_536_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Preimage PreimageFor (r:1 w:0) + fn on_initialize_aborted(s: u32, ) -> Weight { + (15_220_000 as Weight) + // Standard Error: 12_000 + .saturating_add((8_540_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Scheduler Lookup (r:0 w:1) + fn on_initialize_periodic_named(s: u32, ) -> Weight { + (23_540_000 as Weight) + // Standard Error: 20_000 + .saturating_add((22_615_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:2 w:2) + fn on_initialize_periodic(s: u32, ) -> Weight { + (20_291_000 as Weight) + // Standard Error: 20_000 + .saturating_add((16_426_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:1 w:1) + // Storage: Scheduler Lookup (r:0 w:1) + fn on_initialize_named(s: u32, ) -> Weight { + (23_854_000 as Weight) + // Standard Error: 17_000 + .saturating_add((12_873_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:1 w:1) + fn on_initialize(s: u32, ) -> Weight { + (19_709_000 as Weight) + // Standard Error: 15_000 + .saturating_add((10_448_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } // Storage: Scheduler Agenda (r:1 w:1) fn schedule(s: u32, ) -> Weight { - (49_690_000 as Weight) - // Standard Error: 19_000 - .saturating_add((252_000 as Weight).saturating_mul(s as Weight)) + (30_588_000 as Weight) + // Standard Error: 5_000 + .saturating_add((155_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Agenda (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn cancel(s: u32, ) -> Weight { - (45_839_000 as Weight) - // Standard Error: 34_000 - .saturating_add((2_023_000 as Weight).saturating_mul(s as Weight)) + (29_694_000 as Weight) + // Standard Error: 4_000 + .saturating_add((1_681_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn schedule_named(s: u32, ) -> Weight { - (52_119_000 as Weight) - // Standard Error: 26_000 - .saturating_add((249_000 as Weight).saturating_mul(s as Weight)) + (36_960_000 as Weight) + // Standard Error: 3_000 + .saturating_add((167_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn cancel_named(s: u32, ) -> Weight { - (44_031_000 as Weight) - // Standard Error: 32_000 - .saturating_add((2_483_000 as Weight).saturating_mul(s as Weight)) + (33_002_000 as Weight) + // Standard Error: 6_000 + .saturating_add((1_747_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } diff --git a/runtime/composable/src/weights/session.rs b/runtime/composable/src/weights/session.rs index 82593ab0aac..61955d65b5b 100644 --- a/runtime/composable/src/weights/session.rs +++ b/runtime/composable/src/weights/session.rs @@ -1,38 +1,45 @@ -//! Autogenerated weights for session + +//! Autogenerated weights for `session` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-08-22, STEPS: `[5, ]`, REPEAT: 2, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 128 +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable // benchmark -// --chain=picasso-dev +// --chain=composable-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=session +// --pallet=* // --extrinsic=* -// --steps=5 -// --repeat=2 -// --raw -// --output=./runtime/picasso/src/weights +// --steps=50 +// --repeat=20 +// --output=runtime/composable/src/weights +// --log +// error +#![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] use frame_support::{traits::Get, weights::Weight}; use sp_std::marker::PhantomData; -/// Weight functions for session. +/// Weight functions for `session`. pub struct WeightInfo(PhantomData); impl session::WeightInfo for WeightInfo { + // Storage: Session NextKeys (r:1 w:1) + // Storage: Session KeyOwner (r:1 w:1) fn set_keys() -> Weight { - (47_000_000 as Weight) + (30_112_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: Session NextKeys (r:1 w:1) + // Storage: Session KeyOwner (r:0 w:1) fn purge_keys() -> Weight { - (30_000_000 as Weight) + (21_336_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } diff --git a/runtime/composable/src/weights/timestamp.rs b/runtime/composable/src/weights/timestamp.rs index bea80e21db2..ebb9cbe9d30 100644 --- a/runtime/composable/src/weights/timestamp.rs +++ b/runtime/composable/src/weights/timestamp.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `timestamp` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=composable-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=timestamp +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/composable/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -31,11 +32,11 @@ impl timestamp::WeightInfo for WeightInfo { // Storage: Timestamp Now (r:1 w:1) // Storage: Aura CurrentSlot (r:1 w:0) fn set() -> Weight { - (10_133_000 as Weight) + (14_092_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn on_finalize() -> Weight { - (4_673_000 as Weight) + (6_718_000 as Weight) } } diff --git a/runtime/composable/src/weights/treasury.rs b/runtime/composable/src/weights/treasury.rs index 142187c0af6..362c61c275b 100644 --- a/runtime/composable/src/weights/treasury.rs +++ b/runtime/composable/src/weights/treasury.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `treasury` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=composable-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=treasury +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/composable/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -31,23 +32,23 @@ impl treasury::WeightInfo for WeightInfo { // Storage: Treasury ProposalCount (r:1 w:1) // Storage: Treasury Proposals (r:0 w:1) fn propose_spend() -> Weight { - (71_832_000 as Weight) + (46_724_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Treasury Proposals (r:1 w:1) // Storage: System Account (r:2 w:2) fn reject_proposal() -> Weight { - (99_792_000 as Weight) + (71_520_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Treasury Proposals (r:1 w:0) // Storage: Treasury Approvals (r:1 w:1) fn approve_proposal(p: u32, ) -> Weight { - (20_117_000 as Weight) - // Standard Error: 21_000 - .saturating_add((851_000 as Weight).saturating_mul(p as Weight)) + (14_992_000 as Weight) + // Standard Error: 5_000 + .saturating_add((268_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -55,9 +56,9 @@ impl treasury::WeightInfo for WeightInfo { // Storage: Treasury Approvals (r:1 w:1) // Storage: Treasury Proposals (r:1 w:1) fn on_initialize_proposals(p: u32, ) -> Weight { - (181_391_000 as Weight) - // Standard Error: 2_226_000 - .saturating_add((65_079_000 as Weight).saturating_mul(p as Weight)) + (64_464_000 as Weight) + // Standard Error: 139_000 + .saturating_add((66_581_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(p as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) diff --git a/runtime/composable/src/weights/utility.rs b/runtime/composable/src/weights/utility.rs index e3a1b4c7a6b..5dc7455a93a 100644 --- a/runtime/composable/src/weights/utility.rs +++ b/runtime/composable/src/weights/utility.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `utility` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("composable-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=composable-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=utility +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/composable/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -29,19 +30,19 @@ use sp_std::marker::PhantomData; pub struct WeightInfo(PhantomData); impl utility::WeightInfo for WeightInfo { fn batch(c: u32, ) -> Weight { - (28_696_000 as Weight) - // Standard Error: 2_000 - .saturating_add((6_008_000 as Weight).saturating_mul(c as Weight)) + (49_130_000 as Weight) + // Standard Error: 5_000 + .saturating_add((6_190_000 as Weight).saturating_mul(c as Weight)) } fn as_derivative() -> Weight { - (3_987_000 as Weight) + (4_805_000 as Weight) } fn batch_all(c: u32, ) -> Weight { - (17_207_000 as Weight) - // Standard Error: 5_000 - .saturating_add((6_603_000 as Weight).saturating_mul(c as Weight)) + (28_897_000 as Weight) + // Standard Error: 10_000 + .saturating_add((6_833_000 as Weight).saturating_mul(c as Weight)) } fn dispatch_as() -> Weight { - (14_969_000 as Weight) + (17_456_000 as Weight) } } diff --git a/runtime/composable/src/xcmp.rs b/runtime/composable/src/xcmp.rs index 266b85515ec..75091fb3495 100644 --- a/runtime/composable/src/xcmp.rs +++ b/runtime/composable/src/xcmp.rs @@ -5,10 +5,13 @@ use super::*; // recursive dependency onto runtime use codec::{Decode, Encode}; use composable_traits::assets::{RemoteAssetRegistry, XcmAssetLocation}; -use cumulus_primitives_core::ParaId; +use core::marker::PhantomData; +use cumulus_primitives_core::{IsSystem, ParaId}; use frame_support::{ construct_runtime, log, match_type, parameter_types, - traits::{Contains, Everything, KeyOwnerProofSystem, Nothing, Randomness, StorageInfo}, + traits::{ + Contains, Everything, KeyOwnerProofSystem, Nothing, OriginTrait, Randomness, StorageInfo, + }, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, DispatchClass, IdentityFee, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, @@ -16,31 +19,27 @@ use frame_support::{ }, PalletId, }; - +use orml_traits::parameter_type_with_key; use orml_xcm_support::{IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset}; - +use pallet_xcm::XcmPassthrough; +use polkadot_parachain::primitives::Sibling; +use sp_api::impl_runtime_apis; +use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ traits::{AccountIdLookup, BlakeTwo256, Convert, ConvertInto, Zero}, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, }; - -use orml_traits::parameter_type_with_key; -use sp_api::impl_runtime_apis; -use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; - -use pallet_xcm::XcmPassthrough; -use polkadot_parachain::primitives::Sibling; use sp_std::prelude::*; use xcm::latest::{prelude::*, Error}; use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, LocationInverter, - ParentIsDefault, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, }; use xcm_executor::{ - traits::{TransactAsset, WeightTrader}, + traits::{ConvertOrigin, TransactAsset, WeightTrader}, Assets, Config, XcmExecutor, }; @@ -86,8 +85,8 @@ pub type XcmRouter = ( /// when determining ownership of accounts for asset transacting and when attempting to use XCM /// `Transact` in order to determine the dispatch Origin. pub type LocationToAccountId = ( - // The parent (Relay-chain) origin converts to the default `AccountId`. - ParentIsDefault, + // The parent (Relay-chain) origin converts to the parent `AccountId`. + ParentIsPreset, // Sibling parachain origins convert to AccountId via the `ParaId::into`. SiblingParachainConvertsVia, // Straight up local `AccountId32` origins just alias directly to `AccountId`. @@ -201,11 +200,13 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type XcmExecutor = XcmExecutor; type VersionWrapper = (); type ChannelInfo = ParachainSystem; - type ExecuteOverweightOrigin = EnsureRoot; + type ExecuteOverweightOrigin = EnsureRootOrHalfCouncil; + type ControllerOrigin = EnsureRootOrHalfCouncil; + type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; } impl cumulus_pallet_dmp_queue::Config for Runtime { type Event = Event; type XcmExecutor = XcmExecutor; - type ExecuteOverweightOrigin = system::EnsureRoot; + type ExecuteOverweightOrigin = EnsureRootOrHalfCouncil; } diff --git a/runtime/dali/Cargo.toml b/runtime/dali/Cargo.toml index 0884c6bbcfd..e1302c64980 100644 --- a/runtime/dali/Cargo.toml +++ b/runtime/dali/Cargo.toml @@ -1,229 +1,262 @@ [package] +edition = "2021" name = "dali-runtime" version = "0.1.0" -edition = "2021" -description = "Dali, Testnet Parachain Runtime Implementation" authors = ["Seun Lanlege "] +description = "Dali, Testnet Parachain Runtime Implementation" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [package.metadata.cargo-udeps.ignore] -normal = ["pallet-vault", "session-benchmarking", "assets-registry", "currency-factory", "oracle", "vault", "assets", "governance-registry", "call-filter", "orml-unknown-tokens", "orml-xtokens"] +normal = [ + "pallet-vault", + "session-benchmarking", + "assets-registry", + "currency-factory", + "oracle", + "vault", + "assets", + "governance-registry", + "call-filter", + "orml-unknown-tokens", + "orml-xtokens", +] [dependencies] -frame-system = { package = "frame-system", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -executive = { package = "frame-executive", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } +executive = { package = "frame-executive", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +frame-system = { package = "frame-system", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } # primitives -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } # modules -aura = { package = "pallet-aura", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -authorship = { package = "pallet-authorship", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -balances = { package = "pallet-balances", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -indices = { package = "pallet-indices", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -randomness-collective-flip = { package = "pallet-randomness-collective-flip", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -collective = { package = "pallet-collective", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -identity = { package = "pallet-identity", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -multisig = { package = "pallet-multisig", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -membership = { package = "pallet-membership", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -scheduler = { package = "pallet-scheduler", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -session = { package = "pallet-session", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sudo = { package = "pallet-sudo", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -timestamp = { package = "pallet-timestamp", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -treasury = { package = "pallet-treasury", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -democracy = { package = "pallet-democracy", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -transaction-payment = { package = "pallet-transaction-payment", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -utility = { package = "pallet-utility", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -preimage = { package = "pallet-preimage", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } +aura = { package = "pallet-aura", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +authorship = { package = "pallet-authorship", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +balances = { package = "pallet-balances", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +collective = { package = "pallet-collective", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +democracy = { package = "pallet-democracy", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +identity = { package = "pallet-identity", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +indices = { package = "pallet-indices", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +membership = { package = "pallet-membership", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +multisig = { package = "pallet-multisig", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } +preimage = { package = "pallet-preimage", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +randomness-collective-flip = { package = "pallet-randomness-collective-flip", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +scheduler = { package = "pallet-scheduler", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +session = { package = "pallet-session", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } smallvec = "1.6.1" +sudo = { package = "pallet-sudo", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +timestamp = { package = "pallet-timestamp", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +transaction-payment = { package = "pallet-transaction-payment", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +treasury = { package = "pallet-treasury", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +utility = { package = "pallet-utility", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } # local modules -assets-registry = { package = "pallet-assets-registry", path = '../../frame/assets-registry', default-features = false } assets = { package = "pallet-assets", path = '../../frame/assets', default-features = false } -crowdloan-rewards = { package = "pallet-crowdloan-rewards", path = '../../frame/crowdloan-rewards', default-features = false } +assets-registry = { package = "pallet-assets-registry", path = '../../frame/assets-registry', default-features = false } bonded-finance = { package = "pallet-bonded-finance", path = "../../frame/bonded-finance", default-features = false } -vesting = { package = "pallet-vesting", path = "../../frame/vesting", default-features = false } +call-filter = { package = "pallet-call-filter", path = "../../frame/call-filter", default-features = false } +common = { path = "../common", default-features = false } +composable-support = { path = '../../frame/composable-support', default-features = false } +composable-traits = { path = "../../frame/composable-traits", default-features = false } +crowdloan-rewards = { package = "pallet-crowdloan-rewards", path = '../../frame/crowdloan-rewards', default-features = false } +currency-factory = { package = "pallet-currency-factory", path = "../../frame/currency-factory", default-features = false } +curve-amm = { package = "pallet-curve-amm", path = "../../frame/curve-amm", default-features = false } dutch-auction = { package = "pallet-dutch-auction", path = "../../frame/dutch-auction", default-features = false } +governance-registry = { package = "pallet-governance-registry", path = "../../frame/governance-registry", default-features = false } +lending = { package = "pallet-lending", path = "../../frame/lending", default-features = false } liquidations = { package = "pallet-liquidations", path = "../../frame/liquidations", default-features = false } -common = { path = "../common", default-features = false } -primitives = { path = "../primitives", default-features = false } +liquidity-bootstrapping = { package = "pallet-liquidity-bootstrapping", path = "../../frame/liquidity-bootstrapping", default-features = false } +mosaic = { package = "pallet-mosaic", path = "../../frame/mosaic", default-features = false } oracle = { package = "pallet-oracle", path = "../../frame/oracle", default-features = false } +primitives = { path = "../primitives", default-features = false } +uniswap-v2 = { package = "pallet-uniswap-v2", path = "../../frame/uniswap-v2", default-features = false } vault = { package = "pallet-vault", path = "../../frame/vault", default-features = false } -governance-registry = { package = "pallet-governance-registry", path = "../../frame/governance-registry", default-features = false } -currency-factory = { package = "pallet-currency-factory", path = "../../frame/currency-factory", default-features = false } -composable-traits = { path = "../../frame/composable-traits" , default-features = false} -call-filter = { package = "pallet-call-filter", path = "../../frame/call-filter", default-features = false } -mosaic = { package = "pallet-mosaic", path = "../../frame/mosaic", default-features = false } +vesting = { package = "pallet-vesting", path = "../../frame/vesting", default-features = false } # Used for the node template's RPCs -system-rpc-runtime-api = { package = "frame-system-rpc-runtime-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -transaction-payment-rpc-runtime-api = { package = "pallet-transaction-payment-rpc-runtime-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } +system-rpc-runtime-api = { package = "frame-system-rpc-runtime-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +transaction-payment-rpc-runtime-api = { package = "pallet-transaction-payment-rpc-runtime-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } + +# local RPCs +assets-runtime-api = { path = '../../frame/assets/runtime-api', default-features = false } +crowdloan-rewards-runtime-api = { path = '../../frame/crowdloan-rewards/runtime-api', default-features = false } # Used for runtime benchmarking -frame-benchmarking = { package = "frame-benchmarking", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false, optional = true } -system-benchmarking = { package = "frame-system-benchmarking", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false, optional = true } -hex-literal = { version = "0.3.1", optional = true } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ + "derive", +] } +frame-benchmarking = { package = "frame-benchmarking", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false, optional = true } +hex-literal = { version = "0.3.3", optional = true } +system-benchmarking = { package = "frame-system-benchmarking", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false, optional = true } # Parachain Utilities -cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -collator-selection = { package = "pallet-collator-selection", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -session-benchmarking = { package = "cumulus-pallet-session-benchmarking", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +collator-selection = { package = "pallet-collator-selection", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } +session-benchmarking = { package = "cumulus-pallet-session-benchmarking", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } # orml XCM support -orml-xtokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -orml-xcm-support = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -orml-unknown-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } +orml-unknown-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } +orml-xcm-support = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } +orml-xtokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } # simnode support simnode-apis = { package = "simnode-runtime-apis", git = "https://github.com/polytope-labs/substrate-simnode", default-features = false, branch = "master" } [build-dependencies] -substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } [features] -default = ["std"] -std = [ - "codec/std", - "sp-api/std", - "sp-std/std", - "sp-core/std", - "sp-runtime/std", - "sp-version/std", - "sp-offchain/std", - "sp-session/std", - "sp-block-builder/std", - "sp-transaction-pool/std", - "sp-inherents/std", - "frame-support/std", - "executive/std", - "frame-system/std", - "utility/std", - "authorship/std", - "balances/std", - "randomness-collective-flip/std", - "timestamp/std", - "session/std", - "sudo/std", - "indices/std", - "oracle/std", - "identity/std", - "multisig/std", - "vault/std", - "assets/std", - "governance-registry/std", - "call-filter/std", - "currency-factory/std", - "orml-tokens/std", - "orml-traits/std", - "treasury/std", - "democracy/std", - "scheduler/std", - "common/std", - "primitives/std", - "collective/std", - "transaction-payment/std", - "parachain-info/std", - "cumulus-pallet-aura-ext/std", - "cumulus-pallet-parachain-system/std", - "cumulus-pallet-xcmp-queue/std", - "cumulus-pallet-xcm/std", - "cumulus-primitives-core/std", - "cumulus-primitives-timestamp/std", - "cumulus-primitives-utility/std", - "collator-selection/std", - "xcm/std", - "xcm-builder/std", - "xcm-executor/std", - "aura/std", - "sp-consensus-aura/std", - "scale-info/std", - "orml-xtokens/std", - "orml-xcm-support/std", - "orml-unknown-tokens/std", - "assets-registry/std", - "assets/std", - "governance-registry/std", - "composable-traits/std", - "crowdloan-rewards/std", - "bonded-finance/std", - "dutch-auction/std", - "liquidations/std", - "vesting/std", - "mosaic/std", - "preimage/std", - "membership/std", - "system-rpc-runtime-api/std", - "transaction-payment-rpc-runtime-api/std", - "liquidations/std", - "simnode-apis/std" -] +default = ["std", "wasm-builder"] +local-integration-tests = [] runtime-benchmarks = [ - "assets/runtime-benchmarks", - "balances/runtime-benchmarks", - "frame-benchmarking", - "frame-support/runtime-benchmarks", - "system-benchmarking", - "frame-system/runtime-benchmarks", - "hex-literal", - "balances/runtime-benchmarks", - "timestamp/runtime-benchmarks", - "assets-registry/runtime-benchmarks", - "oracle/runtime-benchmarks", - "collective/runtime-benchmarks", - "collator-selection/runtime-benchmarks", - "session-benchmarking/runtime-benchmarks", - "pallet-xcm/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "xcm-builder/runtime-benchmarks", - "indices/runtime-benchmarks", - "crowdloan-rewards/runtime-benchmarks", - "identity/runtime-benchmarks", - "multisig/runtime-benchmarks", - "membership/runtime-benchmarks", - "treasury/runtime-benchmarks", - "scheduler/runtime-benchmarks", - "collective/runtime-benchmarks", - "democracy/runtime-benchmarks", - "utility/runtime-benchmarks", - "vault/runtime-benchmarks", - "vesting/runtime-benchmarks", - "assets/runtime-benchmarks", - "bonded-finance/runtime-benchmarks", - "dutch-auction/runtime-benchmarks", - "mosaic/runtime-benchmarks", - "currency-factory/runtime-benchmarks", - "liquidations/runtime-benchmarks", + "assets/runtime-benchmarks", + "balances/runtime-benchmarks", + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "system-benchmarking", + "frame-system/runtime-benchmarks", + "hex-literal", + "balances/runtime-benchmarks", + "timestamp/runtime-benchmarks", + "assets-registry/runtime-benchmarks", + "oracle/runtime-benchmarks", + "collective/runtime-benchmarks", + "collator-selection/runtime-benchmarks", + "session-benchmarking/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", + "indices/runtime-benchmarks", + "crowdloan-rewards/runtime-benchmarks", + "identity/runtime-benchmarks", + "multisig/runtime-benchmarks", + "membership/runtime-benchmarks", + "treasury/runtime-benchmarks", + "scheduler/runtime-benchmarks", + "collective/runtime-benchmarks", + "democracy/runtime-benchmarks", + "utility/runtime-benchmarks", + "vault/runtime-benchmarks", + "vesting/runtime-benchmarks", + "assets/runtime-benchmarks", + "bonded-finance/runtime-benchmarks", + "dutch-auction/runtime-benchmarks", + "mosaic/runtime-benchmarks", + "currency-factory/runtime-benchmarks", + "liquidations/runtime-benchmarks", + "lending/runtime-benchmarks", + "uniswap-v2/runtime-benchmarks", + "curve-amm/runtime-benchmarks", + "liquidity-bootstrapping/runtime-benchmarks", + "common/runtime-benchmarks", +] +std = [ + "codec/std", + "sp-api/std", + "sp-std/std", + "sp-core/std", + "sp-runtime/std", + "sp-version/std", + "sp-offchain/std", + "sp-session/std", + "sp-block-builder/std", + "sp-transaction-pool/std", + "sp-inherents/std", + "frame-support/std", + "executive/std", + "frame-system/std", + "utility/std", + "authorship/std", + "balances/std", + "randomness-collective-flip/std", + "timestamp/std", + "session/std", + "sudo/std", + "indices/std", + "oracle/std", + "identity/std", + "multisig/std", + "vault/std", + "assets/std", + "governance-registry/std", + "call-filter/std", + "currency-factory/std", + "orml-tokens/std", + "orml-traits/std", + "treasury/std", + "democracy/std", + "scheduler/std", + "common/std", + "primitives/std", + "collective/std", + "transaction-payment/std", + "parachain-info/std", + "cumulus-pallet-aura-ext/std", + "cumulus-pallet-parachain-system/std", + "cumulus-pallet-xcmp-queue/std", + "cumulus-pallet-xcm/std", + "cumulus-primitives-core/std", + "cumulus-primitives-timestamp/std", + "cumulus-primitives-utility/std", + "collator-selection/std", + "xcm/std", + "xcm-builder/std", + "xcm-executor/std", + "aura/std", + "sp-consensus-aura/std", + "scale-info/std", + "orml-xtokens/std", + "orml-xcm-support/std", + "orml-unknown-tokens/std", + "assets-registry/std", + "assets/std", + "composable-traits/std", + "crowdloan-rewards/std", + "bonded-finance/std", + "dutch-auction/std", + "lending/std", + "vesting/std", + "mosaic/std", + "preimage/std", + "membership/std", + "system-rpc-runtime-api/std", + "transaction-payment-rpc-runtime-api/std", + "liquidations/std", + "simnode-apis/std", + "uniswap-v2/std", + "curve-amm/std", + "liquidity-bootstrapping/std", ] -sim-node = [] +wasm-builder = [] diff --git a/runtime/dali/build.rs b/runtime/dali/build.rs index 9b53d2457df..73544cbb687 100644 --- a/runtime/dali/build.rs +++ b/runtime/dali/build.rs @@ -1,9 +1,18 @@ -use substrate_wasm_builder::WasmBuilder; - fn main() { - WasmBuilder::new() - .with_current_project() - .export_heap_base() - .import_memory() - .build() + // NOTE: could make reproducible clean builds like next: + // - remove this file + // - put relevant rust code behind cfg target wasm into this package + // - create separate native package which will include bytes of WASM_BINARY (make it read from + // target depending on cfg of build debug/release) + // - make cargo make to build this package for wasm target with all proper env vars + // - make sure that CI/CD gets wasm only via make file to make builds more reproducible + // - document that maximal reproducability is possible if to build in layered docker + #[cfg(feature = "wasm-builder")] + { + substrate_wasm_builder::WasmBuilder::new() + .with_current_project() + .export_heap_base() + .import_memory() + .build() + } } diff --git a/runtime/dali/src/README.md b/runtime/dali/src/README.md new file mode 100644 index 00000000000..9ef8758770a --- /dev/null +++ b/runtime/dali/src/README.md @@ -0,0 +1,27 @@ + + +## XCMP + + +### Payments + +We allow for payments with native assets or with some configured rated foreign assets. + + +#### Acala + + +Acala follow next steps: + +- use DEX to trade + - DEX has has currency and there is enough to pay? + - Yes. Pay + - No. Go to next. + - If there is hardcoded ratio? + - Yes. Pay + - No. Go to next. + - If there is asset metadata with ability to have existential deposit payment in it? + - Yes. Use ED as ratio for swap and pay if enough + - No. Do not execute. + +And has issues https://github.com/AcalaNetwork/Acala/issues/1921 \ No newline at end of file diff --git a/runtime/dali/src/lib.rs b/runtime/dali/src/lib.rs index 95372c7f7ae..fc122787aac 100644 --- a/runtime/dali/src/lib.rs +++ b/runtime/dali/src/lib.rs @@ -15,24 +15,31 @@ #![recursion_limit = "256"] // Make the WASM binary available. -#[cfg(feature = "std")] +#[cfg(all(feature = "std", feature = "wasm-builder"))] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); mod weights; mod xcmp; + +// TODO: consider moving this to shared runtime +pub use xcmp::{MaxInstructions, UnitWeightCost}; + use common::{ impls::DealWithFees, AccountId, AccountIndex, Address, Amount, AuraId, Balance, BlockNumber, - CouncilInstance, EnsureRootOrHalfCouncil, Hash, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, - HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION, + BondOfferId, CouncilInstance, EnsureRootOrHalfCouncil, Hash, Moment, MosaicRemoteAssetId, + MultiExistentialDeposits, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, + MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION, }; +use composable_support::rpc_helpers::SafeRpcWrapper; use cumulus_primitives_core::ParaId; -use orml_traits::parameter_type_with_key; use primitives::currency::CurrencyId; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, Zero}, + traits::{ + AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, Zero, + }, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, }; @@ -55,7 +62,7 @@ pub use frame_support::{ }; use codec::Encode; -use frame_support::traits::{EqualPrivilegeOnly, OnRuntimeUpgrade}; +use frame_support::traits::{fungibles, EqualPrivilegeOnly, OnRuntimeUpgrade}; use frame_system as system; use scale_info::TypeInfo; #[cfg(any(feature = "std", test))] @@ -104,7 +111,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. spec_version: 1000, - impl_version: 4, + impl_version: 8, apis: RUNTIME_API_VERSIONS, transaction_version: 3, state_version: 0, @@ -216,12 +223,12 @@ impl aura::Config for Runtime { impl cumulus_pallet_aura_ext::Config for Runtime {} parameter_types! { - pub BasicDeposit: Balance = 8 * CurrencyId::PICA.unit::(); - pub FieldDeposit: Balance = 256 * CurrencyId::PICA.milli::(); + pub BasicDeposit: Balance = 8 * CurrencyId::unit::(); + pub FieldDeposit: Balance = 256 * CurrencyId::milli::(); pub const MaxAdditionalFields: u32 = 32; pub const MaxRegistrars: u32 = 8; pub const MaxSubAccounts: u32 = 32; - pub SubAccountDeposit: Balance = 2 * CurrencyId::PICA.unit::(); + pub SubAccountDeposit: Balance = 2 * CurrencyId::unit::(); } impl identity::Config for Runtime { @@ -240,8 +247,8 @@ impl identity::Config for Runtime { } parameter_types! { - pub DepositBase: u64 = CurrencyId::PICA.unit(); - pub DepositFactor: u64 = 32 * CurrencyId::PICA.milli::(); + pub DepositBase: u64 = CurrencyId::unit(); + pub DepositFactor: u64 = 32 * CurrencyId::milli::(); pub const MaxSignatories: u16 = 5; } @@ -263,7 +270,7 @@ parameter_types! { impl timestamp::Config for Runtime { /// A timestamp: milliseconds since the Unix epoch. - type Moment = u64; + type Moment = Moment; /// What to do when SLOT_DURATION has passed? type OnTimestampSet = Aura; type MinimumPeriod = MinimumPeriod; @@ -271,8 +278,6 @@ impl timestamp::Config for Runtime { } parameter_types! { - /// Minimum amount an account has to hold to stay in state. - pub ExistentialDeposit: Balance = 100 * CurrencyId::PICA.milli::(); /// Max locks that can be placed on an account. Capped for storage /// concerns. pub const MaxLocks: u32 = 50; @@ -287,14 +292,14 @@ impl balances::Config for Runtime { /// The ubiquitous event type. type Event = Event; type DustRemoval = Treasury; - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = common::NativeExistentialDeposit; type AccountStore = System; type WeightInfo = weights::balances::WeightInfo; } parameter_types! { /// 1 milli-pica/byte should be fine - pub TransactionByteFee: Balance = CurrencyId::PICA.milli::(); + pub TransactionByteFee: Balance = CurrencyId::milli::(); // The portion of the `NORMAL_DISPATCH_RATIO` that we adjust the fees with. Blocks filled less /// than this will decrease the weight and more will increase. @@ -315,7 +320,7 @@ pub struct WeightToFee; impl WeightToFeePolynomial for WeightToFee { type Balance = Balance; fn polynomial() -> WeightToFeeCoefficients { - let p = CurrencyId::PICA.milli::(); + let p = CurrencyId::milli::(); let q = 10 * Balance::from(ExtrinsicBaseWeight::get()); smallvec::smallvec![WeightToFeeCoefficient { degree: 1, @@ -343,7 +348,7 @@ impl sudo::Config for Runtime { parameter_types! { /// Deposit required to get an index. - pub IndexDeposit: Balance = 100 * CurrencyId::PICA.unit::(); + pub IndexDeposit: Balance = 100 * CurrencyId::unit::(); } impl indices::Config for Runtime { @@ -422,7 +427,7 @@ parameter_types! { pub const StalePrice: BlockNumber = 5; /// TODO: discuss with omar/cosmin - pub MinStake: Balance = 1000 * CurrencyId::PICA.unit::(); + pub MinStake: Balance = 1000 * CurrencyId::unit::(); pub const MaxAnswerBound: u32 = 25; pub const MaxAssetsCount: u32 = 100_000; pub const MaxHistory: u32 = 20; @@ -434,7 +439,7 @@ impl oracle::Config for Runtime { type Event = Event; type AuthorityId = oracle::crypto::BathurstStId; type AssetId = CurrencyId; - type PriceValue = u128; + type PriceValue = Balance; type StakeLock = StakeLock; type MinStake = MinStake; type StalePrice = StalePrice; @@ -527,13 +532,6 @@ impl collator_selection::Config for Runtime { type WeightInfo = weights::collator_selection::WeightInfo; } -parameter_type_with_key! { - // TODO: - pub ExistentialDeposits: |_currency_id: CurrencyId| -> Balance { - Zero::zero() - }; -} - pub struct DustRemovalWhitelist; impl Contains for DustRemovalWhitelist { fn contains(a: &AccountId) -> bool { @@ -553,7 +551,7 @@ impl orml_tokens::Config for Runtime { type Amount = Amount; type CurrencyId = CurrencyId; type WeightInfo = weights::tokens::WeightInfo; - type ExistentialDeposits = ExistentialDeposits; + type ExistentialDeposits = MultiExistentialDeposits; type OnDust = orml_tokens::TransferDust; type MaxLocks = MaxLocks; type DustRemovalWhitelist = DustRemovalWhitelist; @@ -571,8 +569,8 @@ parameter_types! { /// percentage of proposal that most be bonded by the proposer pub const ProposalBond: Permill = Permill::from_percent(5); // TODO: rationale? - pub ProposalBondMinimum: Balance = 5 * CurrencyId::PICA.unit::(); - pub ProposalBondMaximum: Balance = 1000 * CurrencyId::PICA.unit::(); + pub ProposalBondMinimum: Balance = 5 * CurrencyId::unit::(); + pub ProposalBondMaximum: Balance = 1000 * CurrencyId::unit::(); pub const SpendPeriod: BlockNumber = 7 * DAYS; pub const Burn: Permill = Permill::from_percent(0); @@ -661,11 +659,11 @@ parameter_types! { pub const VotingPeriod: BlockNumber = 5 * DAYS; pub const FastTrackVotingPeriod: BlockNumber = 3 * HOURS; - pub MinimumDeposit: Balance = 100 * CurrencyId::PICA.unit::(); + pub MinimumDeposit: Balance = 100 * CurrencyId::unit::(); pub const EnactmentPeriod: BlockNumber = 2 * DAYS; pub const CooloffPeriod: BlockNumber = 7 * DAYS; // TODO: prod value - pub PreimageByteDeposit: Balance = CurrencyId::PICA.milli::(); + pub PreimageByteDeposit: Balance = CurrencyId::milli::(); pub const InstantAllowed: bool = true; pub const MaxVotes: u32 = 100; pub const MaxProposals: u32 = 100; @@ -710,7 +708,7 @@ impl democracy::Config for Runtime { parameter_types! { pub const PreimageMaxSize: u32 = 4096 * 1024; - pub PreimageBaseDeposit: Balance = 10 * CurrencyId::PICA.unit::(); + pub PreimageBaseDeposit: Balance = 10 * CurrencyId::unit::(); } impl preimage::Config for Runtime { @@ -726,9 +724,9 @@ impl preimage::Config for Runtime { parameter_types! { pub const MaxStrategies: usize = 255; pub NativeAssetId: CurrencyId = CurrencyId::PICA; - pub CreationDeposit: Balance = 10 * CurrencyId::PICA.unit::(); - pub VaultExistentialDeposit: Balance = 1000 * CurrencyId::PICA.unit::(); - pub RentPerBlock: Balance = CurrencyId::PICA.milli(); + pub CreationDeposit: Balance = 10 * CurrencyId::unit::(); + pub VaultExistentialDeposit: Balance = 1000 * CurrencyId::unit::(); + pub RentPerBlock: Balance = CurrencyId::milli(); pub const VaultMinimumDeposit: Balance = 10_000; pub const VaultMinimumWithdrawal: Balance = 10_000; pub const VaultPalletId: PalletId = PalletId(*b"cubic___"); @@ -766,7 +764,8 @@ impl currency_factory::Config for Runtime { impl assets_registry::Config for Runtime { type Event = Event; type LocalAssetId = CurrencyId; - type ForeignAssetId = composable_traits::assets::XcmAssetLocation; + type ForeignAssetId = CurrencyId; + type Location = composable_traits::assets::XcmAssetLocation; type UpdateAdminOrigin = EnsureRootOrHalfCouncil; type LocalAdminOrigin = assets_registry::EnsureLocalAdmin; type ForeignAdminOrigin = assets_registry::EnsureForeignAdmin; @@ -791,22 +790,26 @@ impl assets::Config for Runtime { } parameter_types! { - pub const InitialPayment: Perbill = Perbill::from_percent(50); - pub const VestingStep: BlockNumber = 7 * DAYS; + pub const CrowdloanRewardsId: PalletId = PalletId(*b"pal_crow"); + pub const InitialPayment: Perbill = Perbill::from_percent(25); + pub const VestingStep: Moment = 1; pub const Prefix: &'static [u8] = b"picasso-"; } impl crowdloan_rewards::Config for Runtime { type Event = Event; type Balance = Balance; - type Currency = Assets; + type RewardAsset = Assets; type AdminOrigin = EnsureRootOrHalfCouncil; type Convert = sp_runtime::traits::ConvertInto; - type RelayChainAccountId = [u8; 32]; + type RelayChainAccountId = sp_runtime::AccountId32; type InitialPayment = InitialPayment; type VestingStep = VestingStep; type Prefix = Prefix; type WeightInfo = weights::crowdloan_rewards::WeightInfo; + type PalletId = CrowdloanRewardsId; + type Moment = Moment; + type Time = Timestamp; } /// The calls we permit to be executed by extrinsics @@ -817,10 +820,7 @@ impl Contains for BaseCallFilter { if call_filter::Pallet::::contains(call) { return false } - !matches!( - call, - Call::Balances(_) | Call::Indices(_) | Call::Democracy(_) | Call::Treasury(_) - ) + !matches!(call, Call::Tokens(_) | Call::Indices(_) | Call::Democracy(_) | Call::Treasury(_)) } } @@ -839,7 +839,7 @@ impl call_filter::Config for Runtime { parameter_types! { pub const MaxVestingSchedule: u32 = 2; - pub MinVestedTransfer: u64 = 10 * CurrencyId::PICA.unit::(); + pub MinVestedTransfer: u64 = 10 * CurrencyId::unit::(); } impl vesting::Config for Runtime { @@ -847,19 +847,21 @@ impl vesting::Config for Runtime { type Event = Event; type MaxVestingSchedules = MaxVestingSchedule; type MinVestedTransfer = MinVestedTransfer; - type VestedTransferOrigin = system::EnsureSigned; - type WeightInfo = (); + type VestedTransferOrigin = EnsureRootOrHalfCouncil; + type WeightInfo = weights::vesting::WeightInfo; + type Moment = Moment; + type Time = Timestamp; } parameter_types! { pub const BondedFinanceId: PalletId = PalletId(*b"bondedfi"); - pub MinReward: Balance = 100 * CurrencyId::PICA.unit::(); - pub Stake: Balance = 10 * CurrencyId::PICA.unit::(); + pub MinReward: Balance = 100 * CurrencyId::unit::(); + pub Stake: Balance = 10 * CurrencyId::unit::(); } impl bonded_finance::Config for Runtime { - type AdminOrigin = EnsureRoot; - type BondOfferId = u64; + type AdminOrigin = EnsureRootOrHalfCouncil; + type BondOfferId = BondOfferId; type Convert = sp_runtime::traits::ConvertInto; type Currency = Assets; type Event = Event; @@ -868,6 +870,7 @@ impl bonded_finance::Config for Runtime { type PalletId = BondedFinanceId; type Stake = Stake; type Vesting = Vesting; + type WeightInfo = weights::bonded_finance::WeightInfo; } parameter_types! { @@ -904,6 +907,7 @@ impl mosaic::Config for Runtime { type MinimumTimeLockPeriod = MinimumTimeLockPeriod; type BudgetPenaltyDecayer = mosaic::BudgetPenaltyDecayer; type NetworkId = u32; + type RemoteAssetId = MosaicRemoteAssetId; type ControlOrigin = EnsureRootOrHalfCouncil; type WeightInfo = weights::mosaic::WeightInfo; } @@ -914,17 +918,102 @@ pub type OrderId = u128; parameter_types! { pub const LiquidationsPalletId: PalletId = PalletId(*b"liqdatns"); } + impl liquidations::Config for Runtime { type Event = Event; type UnixTime = Timestamp; type DutchAuction = DutchAuction; type LiquidationStrategyId = LiquidationStrategyId; type OrderId = OrderId; - type WeightInfo = (); + type WeightInfo = weights::liquidations::WeightInfo; type ParachainId = ParaId; type PalletId = LiquidationsPalletId; } +parameter_types! { + pub const MaxLendingCount: u32 = 10; + pub LendingPalletId: PalletId = PalletId(*b"liqiudat"); + pub OracleMarketCreationStake : Balance = 300; +} + +impl lending::Config for Runtime { + type Event = Event; + type Oracle = Oracle; + type VaultId = u64; + type Vault = Vault; + type CurrencyFactory = CurrencyFactory; + type MultiCurrency = Assets; + type Liquidation = Liquidations; + type UnixTime = Timestamp; + type MaxLendingCount = MaxLendingCount; + type AuthorityId = oracle::crypto::BathurstStId; + type WeightInfo = weights::lending::WeightInfo; + type LiquidationStrategyId = u32; + type OracleMarketCreationStake = OracleMarketCreationStake; + type PalletId = LendingPalletId; + type NativeCurrency = Balances; + type WeightToFee = WeightToFee; +} + +pub type PoolId = u128; + +parameter_types! { + pub const ConstantProductPalletId: PalletId = PalletId(*b"pal_cnst"); +} + +impl uniswap_v2::Config for Runtime { + type Event = Event; + type AssetId = CurrencyId; + type Balance = Balance; + type CurrencyFactory = CurrencyFactory; + type Assets = Assets; + type Convert = ConvertInto; + type PoolId = PoolId; + type PalletId = ConstantProductPalletId; + type WeightInfo = weights::uniswap_v2::WeightInfo; +} + +parameter_types! { + pub const StableSwapPalletId: PalletId = PalletId(*b"pal_stab"); +} + +impl curve_amm::Config for Runtime { + type Event = Event; + type AssetId = CurrencyId; + type Balance = Balance; + type CurrencyFactory = CurrencyFactory; + type Assets = Assets; + type Convert = ConvertInto; + type PoolId = PoolId; + type PalletId = StableSwapPalletId; + type WeightInfo = weights::curve_amm::WeightInfo; +} + +parameter_types! { + pub LBPId: PalletId = PalletId(*b"pall_lbp"); + pub MinSaleDuration: BlockNumber = DAYS; + pub MaxSaleDuration: BlockNumber = 30 * DAYS; + pub MaxInitialWeight: Permill = Permill::from_percent(95); + pub MinFinalWeight: Permill = Permill::from_percent(5); +} + +impl liquidity_bootstrapping::Config for Runtime { + type Event = Event; + type AssetId = CurrencyId; + type Balance = Balance; + type Convert = ConvertInto; + type Assets = Tokens; + type PoolId = PoolId; + type LocalAssets = CurrencyFactory; + type PalletId = LBPId; + type MinSaleDuration = MinSaleDuration; + type MaxSaleDuration = MaxSaleDuration; + type MaxInitialWeight = MaxInitialWeight; + type MinFinalWeight = MinFinalWeight; + type WeightInfo = weights::liquidity_bootstrapping::WeightInfo; + type AdminOrigin = EnsureRootOrHalfCouncil; +} + construct_runtime!( pub enum Runtime where Block = Block, @@ -959,7 +1048,7 @@ construct_runtime!( Democracy: democracy::{Pallet, Call, Storage, Config, Event} = 33, Scheduler: scheduler::{Pallet, Call, Storage, Event} = 34, Utility: utility::{Pallet, Call, Event} = 35, - Preimage: preimage::{Pallet, Call, Storage, Event} = 36, + Preimage: preimage::{Pallet, Call, Storage, Event} = 36, // XCM helpers. XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event} = 40, @@ -982,7 +1071,10 @@ construct_runtime!( DutchAuction: dutch_auction::{Pallet, Call, Storage, Event} = 61, Mosaic: mosaic::{Pallet, Call, Storage, Event} = 62, Liquidations: liquidations::{Pallet, Call, Storage, Event} = 63, - + Lending: lending::{Pallet, Call, Storage, Event} = 64, + ConstantProductDex: uniswap_v2::{Pallet, Call, Storage, Event} = 65, + StableSwapDex: curve_amm::{Pallet, Call, Storage, Event} = 66, + LiquidityBootstrapping: liquidity_bootstrapping::{Pallet, Call, Storage, Event} = 67, CallFilter: call_filter::{Pallet, Call, Storage, Event} = 100, } ); @@ -1045,14 +1137,36 @@ mod benches { [identity, Identity] [multisig, Multisig] [vault, Vault] + [vesting, Vesting] [oracle, Oracle] [dutch_auction, DutchAuction] + [currency_factory, CurrencyFactory] [mosaic, Mosaic] [liquidations, Liquidations] + [bonded_finance, BondedFinance] + //FIXME: broken with dali [lending, Lending] + [uniswap_v2, ConstantProductDex] + [curve_amm, StableSwapDex] + [liquidity_bootstrapping, LiquidityBootstrapping] ); } impl_runtime_apis! { + impl assets_runtime_api::AssetsRuntimeApi for Runtime { + fn balance_of(asset_id: SafeRpcWrapper, account_id: AccountId) -> SafeRpcWrapper /* Balance */ { + SafeRpcWrapper(>::balance(asset_id.0, &account_id)) + } + } + + impl crowdloan_rewards_runtime_api::CrowdloanRewardsRuntimeApi for Runtime { + fn amount_available_to_claim_for(account_id: AccountId) -> SafeRpcWrapper { + SafeRpcWrapper ( + crowdloan_rewards::amount_available_to_claim_for::(account_id) + .unwrap_or_else(|_| Balance::zero()) + ) + } + } + impl sp_api::Core for Runtime { fn version() -> RuntimeVersion { VERSION @@ -1158,7 +1272,7 @@ impl_runtime_apis! { TransactionPayment::query_fee_details(uxt, len) } } - #[cfg(feature = "sim-node")] + impl simnode_apis::CreateTransactionApi for Runtime { fn create_transaction(call: Call, signer: AccountId) -> Vec { use sp_runtime::{ @@ -1179,7 +1293,7 @@ impl_runtime_apis! { transaction_payment::ChargeTransactionPayment::::from(0), ); - let signature = MultiSignature::from(sr25519::Signature([0u8;64])); + let signature = MultiSignature::from(sr25519::Signature([0_u8;64])); let address = AccountIdLookup::unlookup(signer); let ext = UncheckedExtrinsic::new_signed(call, address, signature, extra); @@ -1198,37 +1312,16 @@ impl_runtime_apis! { use system_benchmarking::Pallet as SystemBench; use session_benchmarking::Pallet as SessionBench; - let mut list = Vec::::new(); - - list_benchmark!(list, extra, frame_system, SystemBench::); - list_benchmark!(list, extra, balances, Balances); - list_benchmark!(list, extra, timestamp, Timestamp); - list_benchmark!(list, extra, collator_selection, CollatorSelection); - list_benchmark!(list, extra, indices, Indices); - list_benchmark!(list, extra, membership, CouncilMembership); - list_benchmark!(list, extra, treasury, Treasury); - list_benchmark!(list, extra, scheduler, Scheduler); - list_benchmark!(list, extra, democracy, Democracy); - list_benchmark!(list, extra, collective, Council); - list_benchmark!(list, extra, utility, Utility); - list_benchmark!(list, extra, identity, Identity); - list_benchmark!(list, extra, multisig, Multisig); - list_benchmark!(list, extra, vault, Vault); - list_benchmark!(list, extra, oracle, Oracle); - list_benchmark!(list, extra, dutch_auction, DutchAuction); - list_benchmark!(list, extra, currency_factory, CurrencyFactory); - list_benchmark!(list, extra, liquidations, Liquidations); - + list_benchmarks!(list, extra); let storage_info = AllPalletsWithSystem::storage_info(); - return (list, storage_info) } fn dispatch_benchmark( config: frame_benchmarking::BenchmarkConfig ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey}; + use frame_benchmarking::{Benchmarking, BenchmarkBatch, TrackedStorageKey}; use system_benchmarking::Pallet as SystemBench; impl system_benchmarking::Config for Runtime {} @@ -1251,26 +1344,7 @@ impl_runtime_apis! { let mut batches = Vec::::new(); let params = (&config, &whitelist); - - add_benchmark!(params, batches, frame_system, SystemBench::); - add_benchmark!(params, batches, balances, Balances); - add_benchmark!(params, batches, timestamp, Timestamp); - add_benchmark!(params, batches, session, SessionBench::); - add_benchmark!(params, batches, collator_selection, CollatorSelection); - add_benchmark!(params, batches, indices, Indices); - add_benchmark!(params, batches, membership, CouncilMembership); - add_benchmark!(params, batches, treasury, Treasury); - add_benchmark!(params, batches, scheduler, Scheduler); - add_benchmark!(params, batches, democracy, Democracy); - add_benchmark!(params, batches, collective, Council); - add_benchmark!(params, batches, utility, Utility); - add_benchmark!(params, batches, identity, Identity); - add_benchmark!(params, batches, multisig, Multisig); - add_benchmark!(params, batches, vault, Vault); - add_benchmark!(params, batches, oracle, Oracle); - add_benchmark!(params, batches, dutch_auction, DutchAuction); - add_benchmark!(params, batches, currency_factory, CurrencyFactory); - add_benchmark!(params, batches, liquidations, Liquidations); + add_benchmarks!(params, batches); if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) diff --git a/runtime/dali/src/weights/balances.rs b/runtime/dali/src/weights/balances.rs index 300e77dac17..fa6645ac6e0 100644 --- a/runtime/dali/src/weights/balances.rs +++ b/runtime/dali/src/weights/balances.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `balances` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=dali-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=balances +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/dali/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -30,43 +31,43 @@ pub struct WeightInfo(PhantomData); impl balances::WeightInfo for WeightInfo { // Storage: System Account (r:2 w:2) fn transfer() -> Weight { - (160_436_000 as Weight) + (100_653_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: System Account (r:1 w:1) fn transfer_keep_alive() -> Weight { - (95_923_000 as Weight) + (61_112_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn set_balance_creating() -> Weight { - (55_369_000 as Weight) + (37_122_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn set_balance_killing() -> Weight { - (68_956_000 as Weight) + (43_600_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:3 w:3) fn force_transfer() -> Weight { - (163_390_000 as Weight) + (101_452_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: System Account (r:1 w:1) fn transfer_all() -> Weight { - (115_415_000 as Weight) + (73_835_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn force_unreserve() -> Weight { - (51_043_000 as Weight) + (34_366_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } diff --git a/runtime/dali/src/weights/bonded_finance.rs b/runtime/dali/src/weights/bonded_finance.rs new file mode 100644 index 00000000000..849e1349521 --- /dev/null +++ b/runtime/dali/src/weights/bonded_finance.rs @@ -0,0 +1,58 @@ + +//! Autogenerated weights for `bonded_finance` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/composable +// benchmark +// --chain=dali-dev +// --execution=wasm +// --wasm-execution=compiled +// --pallet=* +// --extrinsic=* +// --steps=50 +// --repeat=20 +// --output=runtime/dali/src/weights +// --log +// error + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for `bonded_finance`. +pub struct WeightInfo(PhantomData); +impl bonded_finance::WeightInfo for WeightInfo { + // Storage: BondedFinance BondOfferCount (r:1 w:1) + // Storage: System Account (r:2 w:2) + // Storage: Tokens Accounts (r:2 w:2) + // Storage: BondedFinance BondOffers (r:0 w:1) + fn offer() -> Weight { + (123_761_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } + // Storage: BondedFinance BondOffers (r:1 w:1) + // Storage: Tokens Accounts (r:4 w:4) + // Storage: System Account (r:2 w:2) + // Storage: Vesting VestingSchedules (r:2 w:2) + // Storage: Tokens Locks (r:2 w:2) + fn bond() -> Weight { + (246_647_000 as Weight) + .saturating_add(T::DbWeight::get().reads(11 as Weight)) + .saturating_add(T::DbWeight::get().writes(11 as Weight)) + } + // Storage: BondedFinance BondOffers (r:1 w:1) + // Storage: System Account (r:2 w:2) + fn cancel() -> Weight { + (75_640_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } +} diff --git a/runtime/dali/src/weights/collator_selection.rs b/runtime/dali/src/weights/collator_selection.rs index 46459b6f76c..340e2938b74 100644 --- a/runtime/dali/src/weights/collator_selection.rs +++ b/runtime/dali/src/weights/collator_selection.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `collator_selection` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=dali-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=collator_selection +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/dali/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -28,21 +29,23 @@ use sp_std::marker::PhantomData; /// Weight functions for `collator_selection`. pub struct WeightInfo(PhantomData); impl collator_selection::WeightInfo for WeightInfo { + // Storage: Session NextKeys (r:1 w:0) // Storage: CollatorSelection Invulnerables (r:0 w:1) fn set_invulnerables(b: u32, ) -> Weight { - (17_720_000 as Weight) - // Standard Error: 0 - .saturating_add((41_000 as Weight).saturating_mul(b as Weight)) + (18_935_000 as Weight) + // Standard Error: 7_000 + .saturating_add((7_104_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: CollatorSelection DesiredCandidates (r:0 w:1) fn set_desired_candidates() -> Weight { - (15_958_000 as Weight) + (18_630_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: CollatorSelection CandidacyBond (r:0 w:1) fn set_candidacy_bond() -> Weight { - (16_528_000 as Weight) + (18_800_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: CollatorSelection Candidates (r:1 w:1) @@ -52,18 +55,18 @@ impl collator_selection::WeightInfo for WeightInfo { // Storage: CollatorSelection CandidacyBond (r:1 w:0) // Storage: CollatorSelection LastAuthoredBlock (r:0 w:1) fn register_as_candidate(c: u32, ) -> Weight { - (87_409_000 as Weight) - // Standard Error: 1_000 - .saturating_add((176_000 as Weight).saturating_mul(c as Weight)) + (116_433_000 as Weight) + // Standard Error: 4_000 + .saturating_add((320_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: CollatorSelection Candidates (r:1 w:1) // Storage: CollatorSelection LastAuthoredBlock (r:0 w:1) fn leave_intent(c: u32, ) -> Weight { - (5_665_000 as Weight) - // Standard Error: 12_000 - .saturating_add((499_000 as Weight).saturating_mul(c as Weight)) + (138_119_000 as Weight) + // Standard Error: 4_000 + .saturating_add((346_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -71,7 +74,7 @@ impl collator_selection::WeightInfo for WeightInfo { // Storage: System BlockWeight (r:1 w:1) // Storage: CollatorSelection LastAuthoredBlock (r:0 w:1) fn note_author() -> Weight { - (109_858_000 as Weight) + (75_997_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -82,10 +85,10 @@ impl collator_selection::WeightInfo for WeightInfo { // Storage: System BlockWeight (r:1 w:1) fn new_session(r: u32, c: u32, ) -> Weight { (0 as Weight) - // Standard Error: 4_362_000 - .saturating_add((10_263_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 4_362_000 - .saturating_add((114_349_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 5_591_000 + .saturating_add((28_281_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 5_591_000 + .saturating_add((147_447_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(c as Weight))) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(c as Weight))) diff --git a/runtime/dali/src/weights/collective.rs b/runtime/dali/src/weights/collective.rs index ade46bf478f..7ff28712d72 100644 --- a/runtime/dali/src/weights/collective.rs +++ b/runtime/dali/src/weights/collective.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `collective` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=dali-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=collective +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/dali/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -32,12 +33,14 @@ impl collective::WeightInfo for WeightInfo { // Storage: Council Proposals (r:1 w:0) // Storage: Council Voting (r:100 w:100) // Storage: Council Prime (r:0 w:1) - fn set_members(m: u32, _n: u32, p: u32, ) -> Weight { + fn set_members(m: u32, n: u32, p: u32, ) -> Weight { (0 as Weight) - // Standard Error: 147_000 - .saturating_add((15_753_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 147_000 - .saturating_add((21_061_000 as Weight).saturating_mul(p as Weight)) + // Standard Error: 120_000 + .saturating_add((28_692_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 120_000 + .saturating_add((361_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 120_000 + .saturating_add((34_658_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(p as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -46,22 +49,22 @@ impl collective::WeightInfo for WeightInfo { // Storage: Council Members (r:1 w:0) // Storage: CallFilter DisabledCalls (r:1 w:0) fn execute(b: u32, m: u32, ) -> Weight { - (26_304_000 as Weight) + (31_974_000 as Weight) // Standard Error: 0 .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) - // Standard Error: 0 - .saturating_add((95_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 1_000 + .saturating_add((148_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) } // Storage: Council Members (r:1 w:0) // Storage: Council ProposalOf (r:1 w:0) // Storage: CallFilter DisabledCalls (r:1 w:0) fn propose_execute(b: u32, m: u32, ) -> Weight { - (30_572_000 as Weight) + (35_661_000 as Weight) // Standard Error: 0 - .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) - // Standard Error: 0 - .saturating_add((174_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((5_000 as Weight).saturating_mul(b as Weight)) + // Standard Error: 1_000 + .saturating_add((251_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) } // Storage: Council Members (r:1 w:0) @@ -70,22 +73,22 @@ impl collective::WeightInfo for WeightInfo { // Storage: Council ProposalCount (r:1 w:1) // Storage: Council Voting (r:0 w:1) fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight { - (34_775_000 as Weight) + (32_868_000 as Weight) // Standard Error: 0 - .saturating_add((11_000 as Weight).saturating_mul(b as Weight)) - // Standard Error: 2_000 - .saturating_add((106_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 2_000 - .saturating_add((423_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((17_000 as Weight).saturating_mul(b as Weight)) + // Standard Error: 3_000 + .saturating_add((174_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 3_000 + .saturating_add((568_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Council Members (r:1 w:0) // Storage: Council Voting (r:1 w:1) fn vote(m: u32, ) -> Weight { - (43_971_000 as Weight) - // Standard Error: 2_000 - .saturating_add((189_000 as Weight).saturating_mul(m as Weight)) + (61_045_000 as Weight) + // Standard Error: 3_000 + .saturating_add((318_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -94,11 +97,11 @@ impl collective::WeightInfo for WeightInfo { // Storage: Council Proposals (r:1 w:1) // Storage: Council ProposalOf (r:0 w:1) fn close_early_disapproved(m: u32, p: u32, ) -> Weight { - (45_223_000 as Weight) - // Standard Error: 2_000 - .saturating_add((183_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 2_000 - .saturating_add((347_000 as Weight).saturating_mul(p as Weight)) + (52_799_000 as Weight) + // Standard Error: 3_000 + .saturating_add((274_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 3_000 + .saturating_add((441_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -108,13 +111,13 @@ impl collective::WeightInfo for WeightInfo { // Storage: CallFilter DisabledCalls (r:1 w:0) // Storage: Council Proposals (r:1 w:1) fn close_early_approved(b: u32, m: u32, p: u32, ) -> Weight { - (58_316_000 as Weight) - // Standard Error: 0 - .saturating_add((9_000 as Weight).saturating_mul(b as Weight)) + (26_015_000 as Weight) // Standard Error: 2_000 - .saturating_add((197_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 2_000 - .saturating_add((426_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((30_000 as Weight).saturating_mul(b as Weight)) + // Standard Error: 19_000 + .saturating_add((460_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 18_000 + .saturating_add((782_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -124,11 +127,11 @@ impl collective::WeightInfo for WeightInfo { // Storage: Council Proposals (r:1 w:1) // Storage: Council ProposalOf (r:0 w:1) fn close_disapproved(m: u32, p: u32, ) -> Weight { - (50_752_000 as Weight) - // Standard Error: 2_000 - .saturating_add((178_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 2_000 - .saturating_add((339_000 as Weight).saturating_mul(p as Weight)) + (59_904_000 as Weight) + // Standard Error: 3_000 + .saturating_add((271_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 3_000 + .saturating_add((440_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -139,13 +142,13 @@ impl collective::WeightInfo for WeightInfo { // Storage: CallFilter DisabledCalls (r:1 w:0) // Storage: Council Proposals (r:1 w:1) fn close_approved(b: u32, m: u32, p: u32, ) -> Weight { - (63_225_000 as Weight) + (58_101_000 as Weight) // Standard Error: 0 - .saturating_add((8_000 as Weight).saturating_mul(b as Weight)) - // Standard Error: 2_000 - .saturating_add((201_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 2_000 - .saturating_add((427_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((15_000 as Weight).saturating_mul(b as Weight)) + // Standard Error: 4_000 + .saturating_add((390_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 4_000 + .saturating_add((651_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -153,9 +156,9 @@ impl collective::WeightInfo for WeightInfo { // Storage: Council Voting (r:0 w:1) // Storage: Council ProposalOf (r:0 w:1) fn disapprove_proposal(p: u32, ) -> Weight { - (27_181_000 as Weight) - // Standard Error: 1_000 - .saturating_add((408_000 as Weight).saturating_mul(p as Weight)) + (32_494_000 as Weight) + // Standard Error: 2_000 + .saturating_add((521_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } diff --git a/runtime/dali/src/weights/currency_factory.rs b/runtime/dali/src/weights/currency_factory.rs index 88b41b41c3f..5da82d6b2cd 100644 --- a/runtime/dali/src/weights/currency_factory.rs +++ b/runtime/dali/src/weights/currency_factory.rs @@ -1 +1,38 @@ -pub use currency_factory::SubstrateWeight as WeightInfo; + +//! Autogenerated weights for `currency_factory` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/composable +// benchmark +// --chain=dali-dev +// --execution=wasm +// --wasm-execution=compiled +// --pallet=* +// --extrinsic=* +// --steps=50 +// --repeat=20 +// --output=runtime/dali/src/weights +// --log +// error + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for `currency_factory`. +pub struct WeightInfo(PhantomData); +impl currency_factory::WeightInfo for WeightInfo { + // Storage: CurrencyFactory AssetIdRanges (r:1 w:1) + fn add_range() -> Weight { + (26_671_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } +} diff --git a/runtime/dali/src/weights/curve_amm.rs b/runtime/dali/src/weights/curve_amm.rs new file mode 100644 index 00000000000..8ccfb0423b7 --- /dev/null +++ b/runtime/dali/src/weights/curve_amm.rs @@ -0,0 +1,82 @@ + +//! Autogenerated weights for `curve_amm` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/composable +// benchmark +// --chain=dali-dev +// --execution=wasm +// --wasm-execution=compiled +// --pallet=* +// --extrinsic=* +// --steps=50 +// --repeat=20 +// --output=runtime/dali/src/weights +// --log +// error + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for `curve_amm`. +pub struct WeightInfo(PhantomData); +impl curve_amm::WeightInfo for WeightInfo { + // Storage: CurrencyFactory AssetIdRanges (r:1 w:1) + // Storage: StableSwapDex PoolCount (r:1 w:1) + // Storage: StableSwapDex Pools (r:0 w:1) + fn create() -> Weight { + (34_099_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + // Storage: StableSwapDex Pools (r:1 w:0) + // Storage: Tokens Accounts (r:5 w:5) + // Storage: Tokens TotalIssuance (r:1 w:1) + // Storage: System Account (r:1 w:1) + fn add_liquidity() -> Weight { + (182_669_000 as Weight) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) + .saturating_add(T::DbWeight::get().writes(7 as Weight)) + } + // Storage: StableSwapDex Pools (r:1 w:0) + // Storage: Tokens Accounts (r:5 w:5) + // Storage: Tokens TotalIssuance (r:1 w:1) + // Storage: System Account (r:1 w:0) + fn remove_liquidity() -> Weight { + (127_551_000 as Weight) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } + // Storage: StableSwapDex Pools (r:1 w:0) + // Storage: Tokens Accounts (r:5 w:5) + // Storage: System Account (r:2 w:1) + fn buy() -> Weight { + (332_631_000 as Weight) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } + // Storage: StableSwapDex Pools (r:1 w:0) + // Storage: Tokens Accounts (r:5 w:5) + // Storage: System Account (r:2 w:1) + fn sell() -> Weight { + (233_109_000 as Weight) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } + // Storage: StableSwapDex Pools (r:1 w:0) + // Storage: Tokens Accounts (r:5 w:5) + // Storage: System Account (r:2 w:1) + fn swap() -> Weight { + (227_400_000 as Weight) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } +} diff --git a/runtime/dali/src/weights/democracy.rs b/runtime/dali/src/weights/democracy.rs index 79253495cfb..943843a7698 100644 --- a/runtime/dali/src/weights/democracy.rs +++ b/runtime/dali/src/weights/democracy.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `democracy` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=dali-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=democracy +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/dali/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -33,15 +34,13 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy Blacklist (r:1 w:0) // Storage: Democracy DepositOf (r:0 w:1) fn propose() -> Weight { - (78_147_000 as Weight) + (190_934_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy DepositOf (r:1 w:1) - fn second(s: u32, ) -> Weight { - (40_901_000 as Weight) - // Standard Error: 1_000 - .saturating_add((247_000 as Weight).saturating_mul(s as Weight)) + fn second(_s: u32, ) -> Weight { + (135_075_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -49,9 +48,9 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_new(r: u32, ) -> Weight { - (44_497_000 as Weight) - // Standard Error: 1_000 - .saturating_add((237_000 as Weight).saturating_mul(r as Weight)) + (72_527_000 as Weight) + // Standard Error: 3_000 + .saturating_add((319_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -59,16 +58,16 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_existing(r: u32, ) -> Weight { - (44_328_000 as Weight) - // Standard Error: 1_000 - .saturating_add((224_000 as Weight).saturating_mul(r as Weight)) + (73_286_000 as Weight) + // Standard Error: 3_000 + .saturating_add((299_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy Cancellations (r:1 w:1) fn emergency_cancel() -> Weight { - (27_961_000 as Weight) + (36_040_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -79,45 +78,45 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:2 w:2) fn blacklist(p: u32, ) -> Weight { - (95_296_000 as Weight) - // Standard Error: 6_000 - .saturating_add((566_000 as Weight).saturating_mul(p as Weight)) + (110_992_000 as Weight) + // Standard Error: 8_000 + .saturating_add((718_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:0) fn external_propose(v: u32, ) -> Weight { - (13_838_000 as Weight) + (17_040_000 as Weight) // Standard Error: 0 - .saturating_add((88_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((126_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_majority() -> Weight { - (2_993_000 as Weight) + (3_354_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_default() -> Weight { - (2_876_000 as Weight) + (3_452_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:1) // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn fast_track() -> Weight { - (29_139_000 as Weight) + (34_476_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:1) fn veto_external(v: u32, ) -> Weight { - (30_300_000 as Weight) - // Standard Error: 0 - .saturating_add((115_000 as Weight).saturating_mul(v as Weight)) + (36_531_000 as Weight) + // Standard Error: 1_000 + .saturating_add((150_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -125,23 +124,23 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:2 w:2) fn cancel_proposal(p: u32, ) -> Weight { - (70_582_000 as Weight) - // Standard Error: 2_000 - .saturating_add((499_000 as Weight).saturating_mul(p as Weight)) + (82_581_000 as Weight) + // Standard Error: 4_000 + .saturating_add((697_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn cancel_referendum() -> Weight { - (18_194_000 as Weight) + (21_148_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn cancel_queued(r: u32, ) -> Weight { - (31_439_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_990_000 as Weight).saturating_mul(r as Weight)) + (41_219_000 as Weight) + // Standard Error: 5_000 + .saturating_add((2_427_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -149,9 +148,9 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy ReferendumCount (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:1 w:0) fn on_initialize_base(r: u32, ) -> Weight { - (6_091_000 as Weight) - // Standard Error: 4_000 - .saturating_add((5_373_000 as Weight).saturating_mul(r as Weight)) + (5_387_000 as Weight) + // Standard Error: 6_000 + .saturating_add((6_789_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -163,9 +162,9 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy PublicProps (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:1 w:0) fn on_initialize_base_with_launch_period(r: u32, ) -> Weight { - (14_522_000 as Weight) - // Standard Error: 4_000 - .saturating_add((5_383_000 as Weight).saturating_mul(r as Weight)) + (14_382_000 as Weight) + // Standard Error: 7_000 + .saturating_add((6_815_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -174,9 +173,9 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn delegate(r: u32, ) -> Weight { - (60_787_000 as Weight) - // Standard Error: 5_000 - .saturating_add((7_105_000 as Weight).saturating_mul(r as Weight)) + (68_734_000 as Weight) + // Standard Error: 9_000 + .saturating_add((9_062_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(4 as Weight)) @@ -185,9 +184,9 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy VotingOf (r:2 w:2) // Storage: Democracy ReferendumInfoOf (r:1 w:1) fn undelegate(r: u32, ) -> Weight { - (28_718_000 as Weight) - // Standard Error: 5_000 - .saturating_add((7_101_000 as Weight).saturating_mul(r as Weight)) + (29_425_000 as Weight) + // Standard Error: 9_000 + .saturating_add((9_118_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -195,12 +194,12 @@ impl democracy::WeightInfo for WeightInfo { } // Storage: Democracy PublicProps (r:0 w:1) fn clear_public_proposals() -> Weight { - (3_294_000 as Weight) + (3_782_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy Preimages (r:1 w:1) fn note_preimage(b: u32, ) -> Weight { - (44_503_000 as Weight) + (52_760_000 as Weight) // Standard Error: 0 .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) @@ -208,16 +207,16 @@ impl democracy::WeightInfo for WeightInfo { } // Storage: Democracy Preimages (r:1 w:1) fn note_imminent_preimage(b: u32, ) -> Weight { - (30_171_000 as Weight) + (35_806_000 as Weight) // Standard Error: 0 - .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy Preimages (r:1 w:1) // Storage: System Account (r:1 w:0) fn reap_preimage(b: u32, ) -> Weight { - (41_252_000 as Weight) + (51_123_000 as Weight) // Standard Error: 0 .saturating_add((1_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) @@ -227,9 +226,9 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlock_remove(r: u32, ) -> Weight { - (38_156_000 as Weight) - // Standard Error: 1_000 - .saturating_add((119_000 as Weight).saturating_mul(r as Weight)) + (47_498_000 as Weight) + // Standard Error: 2_000 + .saturating_add((138_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -237,27 +236,27 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlock_set(r: u32, ) -> Weight { - (36_213_000 as Weight) - // Standard Error: 1_000 - .saturating_add((209_000 as Weight).saturating_mul(r as Weight)) + (44_503_000 as Weight) + // Standard Error: 2_000 + .saturating_add((303_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) fn remove_vote(r: u32, ) -> Weight { - (20_612_000 as Weight) - // Standard Error: 1_000 - .saturating_add((201_000 as Weight).saturating_mul(r as Weight)) + (25_797_000 as Weight) + // Standard Error: 2_000 + .saturating_add((249_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) fn remove_other_vote(r: u32, ) -> Weight { - (20_752_000 as Weight) - // Standard Error: 1_000 - .saturating_add((203_000 as Weight).saturating_mul(r as Weight)) + (26_548_000 as Weight) + // Standard Error: 2_000 + .saturating_add((257_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } diff --git a/runtime/dali/src/weights/dutch_auction.rs b/runtime/dali/src/weights/dutch_auction.rs index 54a377306ca..e6a7a7d4258 100644 --- a/runtime/dali/src/weights/dutch_auction.rs +++ b/runtime/dali/src/weights/dutch_auction.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `dutch_auction` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,19 +11,20 @@ // --chain=dali-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=dutch_auction +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw -// --output=./runtime/dali/src/weights +// --output=runtime/dali/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] -use sp_std::marker::PhantomData; use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; /// Weight functions for `dutch_auction`. pub struct WeightInfo(PhantomData); @@ -34,7 +35,7 @@ impl dutch_auction::WeightInfo for WeightInfo { // Storage: Tokens Accounts (r:1 w:1) // Storage: DutchAuction SellOrders (r:0 w:1) fn ask() -> Weight { - (185_212_000 as Weight) + (97_376_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -43,7 +44,7 @@ impl dutch_auction::WeightInfo for WeightInfo { // Storage: Tokens Accounts (r:1 w:1) // Storage: DutchAuction Takes (r:1 w:1) fn take() -> Weight { - (140_074_000 as Weight) + (58_100_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -51,7 +52,7 @@ impl dutch_auction::WeightInfo for WeightInfo { // Storage: Tokens Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn liquidate() -> Weight { - (150_867_000 as Weight) + (85_779_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -59,7 +60,7 @@ impl dutch_auction::WeightInfo for WeightInfo { // Storage: DutchAuction SellOrders (r:1 w:1) // Storage: Tokens Accounts (r:2 w:2) fn known_overhead_for_on_finalize() -> Weight { - (195_022_000 as Weight) + (94_732_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } diff --git a/runtime/dali/src/weights/frame_system.rs b/runtime/dali/src/weights/frame_system.rs index 5ef4c87e683..6ac4ea3ccee 100644 --- a/runtime/dali/src/weights/frame_system.rs +++ b/runtime/dali/src/weights/frame_system.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `frame_system` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=dali-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=frame_system +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/dali/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -41,29 +42,29 @@ impl frame_system::WeightInfo for WeightInfo { // Storage: System Digest (r:1 w:1) // Storage: unknown [0x3a686561707061676573] (r:0 w:1) fn set_heap_pages() -> Weight { - (5_224_000 as Weight) + (6_583_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn set_storage(i: u32, ) -> Weight { - (94_631_000 as Weight) - // Standard Error: 27_000 - .saturating_add((1_016_000 as Weight).saturating_mul(i as Weight)) + (0 as Weight) + // Standard Error: 1_000 + .saturating_add((1_030_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn kill_storage(i: u32, ) -> Weight { (0 as Weight) - // Standard Error: 16_000 - .saturating_add((1_112_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 1_000 + .saturating_add((660_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn kill_prefix(p: u32, ) -> Weight { (0 as Weight) - // Standard Error: 16_000 - .saturating_add((1_829_000 as Weight).saturating_mul(p as Weight)) + // Standard Error: 2_000 + .saturating_add((1_366_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(p as Weight))) } } diff --git a/runtime/dali/src/weights/identity.rs b/runtime/dali/src/weights/identity.rs index e338838aae5..3884a9a8973 100644 --- a/runtime/dali/src/weights/identity.rs +++ b/runtime/dali/src/weights/identity.rs @@ -1,22 +1,23 @@ + //! Autogenerated weights for `identity` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-12-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 // Executed Command: -// target/release/composable +// ./target/release/composable // benchmark -// --chain=picasso-dev +// --chain=dali-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=identity +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw -// --output=./runtime/picasso/src/weights - +// --output=runtime/dali/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -30,19 +31,19 @@ pub struct WeightInfo(PhantomData); impl identity::WeightInfo for WeightInfo { // Storage: Identity Registrars (r:1 w:1) fn add_registrar(r: u32, ) -> Weight { - (15_250_000 as Weight) - // Standard Error: 15_000 - .saturating_add((314_000 as Weight).saturating_mul(r as Weight)) + (26_683_000 as Weight) + // Standard Error: 25_000 + .saturating_add((650_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity IdentityOf (r:1 w:1) fn set_identity(r: u32, x: u32, ) -> Weight { - (38_324_000 as Weight) - // Standard Error: 138_000 - .saturating_add((371_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 23_000 - .saturating_add((721_000 as Weight).saturating_mul(x as Weight)) + (60_131_000 as Weight) + // Standard Error: 121_000 + .saturating_add((620_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 20_000 + .saturating_add((981_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -50,9 +51,9 @@ impl identity::WeightInfo for WeightInfo { // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:1 w:1) fn set_subs_new(s: u32, ) -> Weight { - (30_857_000 as Weight) - // Standard Error: 4_000 - .saturating_add((5_258_000 as Weight).saturating_mul(s as Weight)) + (53_443_000 as Weight) + // Standard Error: 15_000 + .saturating_add((7_014_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -62,9 +63,9 @@ impl identity::WeightInfo for WeightInfo { // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:1) fn set_subs_old(p: u32, ) -> Weight { - (30_284_000 as Weight) - // Standard Error: 3_000 - .saturating_add((1_744_000 as Weight).saturating_mul(p as Weight)) + (51_506_000 as Weight) + // Standard Error: 9_000 + .saturating_add((2_232_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(p as Weight))) @@ -73,13 +74,13 @@ impl identity::WeightInfo for WeightInfo { // Storage: Identity IdentityOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:32) fn clear_identity(r: u32, s: u32, x: u32, ) -> Weight { - (39_087_000 as Weight) - // Standard Error: 19_000 - .saturating_add((186_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 2_000 - .saturating_add((1_730_000 as Weight).saturating_mul(s as Weight)) - // Standard Error: 2_000 - .saturating_add((392_000 as Weight).saturating_mul(x as Weight)) + (58_358_000 as Weight) + // Standard Error: 71_000 + .saturating_add((803_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 10_000 + .saturating_add((2_314_000 as Weight).saturating_mul(s as Weight)) + // Standard Error: 10_000 + .saturating_add((543_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -87,56 +88,56 @@ impl identity::WeightInfo for WeightInfo { // Storage: Identity Registrars (r:1 w:0) // Storage: Identity IdentityOf (r:1 w:1) fn request_judgement(r: u32, x: u32, ) -> Weight { - (40_102_000 as Weight) - // Standard Error: 13_000 - .saturating_add((298_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 2_000 - .saturating_add((759_000 as Weight).saturating_mul(x as Weight)) + (64_620_000 as Weight) + // Standard Error: 51_000 + .saturating_add((766_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 8_000 + .saturating_add((951_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity IdentityOf (r:1 w:1) fn cancel_request(r: u32, x: u32, ) -> Weight { - (37_638_000 as Weight) - // Standard Error: 11_000 - .saturating_add((188_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 1_000 - .saturating_add((755_000 as Weight).saturating_mul(x as Weight)) + (59_617_000 as Weight) + // Standard Error: 46_000 + .saturating_add((456_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 7_000 + .saturating_add((989_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_fee(r: u32, ) -> Weight { - (6_144_000 as Weight) - // Standard Error: 6_000 - .saturating_add((218_000 as Weight).saturating_mul(r as Weight)) + (10_660_000 as Weight) + // Standard Error: 16_000 + .saturating_add((466_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_account_id(r: u32, ) -> Weight { - (6_049_000 as Weight) - // Standard Error: 6_000 - .saturating_add((241_000 as Weight).saturating_mul(r as Weight)) + (10_839_000 as Weight) + // Standard Error: 15_000 + .saturating_add((465_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_fields(r: u32, ) -> Weight { - (6_054_000 as Weight) - // Standard Error: 7_000 - .saturating_add((246_000 as Weight).saturating_mul(r as Weight)) + (10_748_000 as Weight) + // Standard Error: 18_000 + .saturating_add((463_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:0) // Storage: Identity IdentityOf (r:1 w:1) fn provide_judgement(r: u32, x: u32, ) -> Weight { - (26_391_000 as Weight) - // Standard Error: 13_000 - .saturating_add((194_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 1_000 - .saturating_add((737_000 as Weight).saturating_mul(x as Weight)) + (42_920_000 as Weight) + // Standard Error: 48_000 + .saturating_add((645_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 6_000 + .saturating_add((992_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -145,13 +146,13 @@ impl identity::WeightInfo for WeightInfo { // Storage: System Account (r:2 w:2) // Storage: Identity SuperOf (r:0 w:32) fn kill_identity(r: u32, s: u32, x: u32, ) -> Weight { - (56_977_000 as Weight) - // Standard Error: 25_000 - .saturating_add((266_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 3_000 - .saturating_add((1_758_000 as Weight).saturating_mul(s as Weight)) - // Standard Error: 3_000 - .saturating_add((13_000 as Weight).saturating_mul(x as Weight)) + (88_412_000 as Weight) + // Standard Error: 91_000 + .saturating_add((619_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 13_000 + .saturating_add((2_302_000 as Weight).saturating_mul(s as Weight)) + // Standard Error: 13_000 + .saturating_add((51_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -160,18 +161,18 @@ impl identity::WeightInfo for WeightInfo { // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn add_sub(s: u32, ) -> Weight { - (41_795_000 as Weight) - // Standard Error: 2_000 - .saturating_add((167_000 as Weight).saturating_mul(s as Weight)) + (67_179_000 as Weight) + // Standard Error: 7_000 + .saturating_add((389_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Identity IdentityOf (r:1 w:0) // Storage: Identity SuperOf (r:1 w:1) fn rename_sub(s: u32, ) -> Weight { - (11_996_000 as Weight) - // Standard Error: 0 - .saturating_add((63_000 as Weight).saturating_mul(s as Weight)) + (20_792_000 as Weight) + // Standard Error: 4_000 + .saturating_add((145_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -179,18 +180,18 @@ impl identity::WeightInfo for WeightInfo { // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn remove_sub(s: u32, ) -> Weight { - (42_170_000 as Weight) - // Standard Error: 2_000 - .saturating_add((185_000 as Weight).saturating_mul(s as Weight)) + (68_740_000 as Weight) + // Standard Error: 9_000 + .saturating_add((392_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn quit_sub(s: u32, ) -> Weight { - (25_569_000 as Weight) - // Standard Error: 1_000 - .saturating_add((181_000 as Weight).saturating_mul(s as Weight)) + (44_997_000 as Weight) + // Standard Error: 9_000 + .saturating_add((370_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } diff --git a/runtime/dali/src/weights/indices.rs b/runtime/dali/src/weights/indices.rs index d91878670a3..a50b3ec6465 100644 --- a/runtime/dali/src/weights/indices.rs +++ b/runtime/dali/src/weights/indices.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `indices` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=dali-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=indices +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/dali/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -30,33 +31,33 @@ pub struct WeightInfo(PhantomData); impl indices::WeightInfo for WeightInfo { // Storage: Indices Accounts (r:1 w:1) fn claim() -> Weight { - (67_998_000 as Weight) + (50_968_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - (82_134_000 as Weight) + (60_052_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Indices Accounts (r:1 w:1) fn free() -> Weight { - (72_248_000 as Weight) + (49_427_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn force_transfer() -> Weight { - (45_055_000 as Weight) + (50_398_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Indices Accounts (r:1 w:1) fn freeze() -> Weight { - (82_402_000 as Weight) + (55_410_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } diff --git a/runtime/dali/src/weights/lending.rs b/runtime/dali/src/weights/lending.rs new file mode 100644 index 00000000000..46861d4e97f --- /dev/null +++ b/runtime/dali/src/weights/lending.rs @@ -0,0 +1,69 @@ +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +pub struct WeightInfo(PhantomData); + +impl lending::weights::WeightInfo for WeightInfo { + fn create_new_market() -> Weight { + (96_881_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(11 as Weight)) + } + fn deposit_collateral() -> Weight { + 123_789_000_u64 + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + fn withdraw_collateral() -> Weight { + 138_802_000_u64 + .saturating_add(T::DbWeight::get().reads(10_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + fn borrow() -> Weight { + (332_730_000 as Weight) + .saturating_add(T::DbWeight::get().reads(19 as Weight)) + .saturating_add(T::DbWeight::get().writes(9 as Weight)) + } + fn repay_borrow() -> Weight { + (209_694_000 as Weight) + .saturating_add(T::DbWeight::get().reads(13 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } + fn now() -> Weight { + (4_744_000 as Weight).saturating_add(T::DbWeight::get().reads(1 as Weight)) + } + fn accrue_interest() -> Weight { + (76_626_000 as Weight) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn account_id() -> Weight { + (3_126_000 as Weight) + } + fn available_funds() -> Weight { + (16_450_000 as Weight).saturating_add(T::DbWeight::get().reads(2 as Weight)) + } + fn handle_withdrawable() -> Weight { + (20_716_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn handle_depositable() -> Weight { + (40_066_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn handle_must_liquidate() -> Weight { + (38_744_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + + fn liquidate(positions_count: Weight) -> Weight { + 10000 * positions_count + } +} \ No newline at end of file diff --git a/runtime/dali/src/weights/liqudations.rs b/runtime/dali/src/weights/liqudations.rs deleted file mode 100644 index c2b31b6815e..00000000000 --- a/runtime/dali/src/weights/liqudations.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] - -use frame_support::{traits::Get, weights::Weight}; -use sp_std::marker::PhantomData; - -/// Weight functions for `mosaic`. -pub struct WeightInfo(PhantomData); - -impl liquidation::weights::WeightInfo for WeightInfo { - fn add_liquidation_strategy() -> Weight { - 10000 - } -} \ No newline at end of file diff --git a/runtime/dali/src/weights/liquidations.rs b/runtime/dali/src/weights/liquidations.rs new file mode 100644 index 00000000000..d1547d758e3 --- /dev/null +++ b/runtime/dali/src/weights/liquidations.rs @@ -0,0 +1,38 @@ + +//! Autogenerated weights for `liquidations` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/composable +// benchmark +// --chain=dali-dev +// --execution=wasm +// --wasm-execution=compiled +// --pallet=* +// --extrinsic=* +// --steps=50 +// --repeat=20 +// --output=runtime/dali/src/weights +// --log +// error + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for `liquidations`. +pub struct WeightInfo(PhantomData); +impl liquidations::WeightInfo for WeightInfo { + // Storage: Liquidations DefaultStrategyIndex (r:1 w:0) + // Storage: Liquidations Strategies (r:1 w:0) + fn add_liquidation_strategy() -> Weight { + (7_295_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + } +} diff --git a/runtime/dali/src/weights/liquidity_bootstrapping.rs b/runtime/dali/src/weights/liquidity_bootstrapping.rs new file mode 100644 index 00000000000..962e071b41c --- /dev/null +++ b/runtime/dali/src/weights/liquidity_bootstrapping.rs @@ -0,0 +1,79 @@ + +//! Autogenerated weights for `liquidity_bootstrapping` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/composable +// benchmark +// --chain=dali-dev +// --execution=wasm +// --wasm-execution=compiled +// --pallet=* +// --extrinsic=* +// --steps=50 +// --repeat=20 +// --output=runtime/dali/src/weights +// --log +// error + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for `liquidity_bootstrapping`. +pub struct WeightInfo(PhantomData); +impl liquidity_bootstrapping::WeightInfo for WeightInfo { + // Storage: LiquidityBootstrapping PoolCount (r:1 w:1) + // Storage: LiquidityBootstrapping Pools (r:0 w:1) + fn create() -> Weight { + (25_847_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: LiquidityBootstrapping Pools (r:1 w:0) + // Storage: Tokens Accounts (r:4 w:4) + // Storage: System Account (r:2 w:1) + fn buy() -> Weight { + (141_307_000 as Weight) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) + } + // Storage: LiquidityBootstrapping Pools (r:1 w:0) + // Storage: Tokens Accounts (r:4 w:4) + // Storage: System Account (r:2 w:1) + fn sell() -> Weight { + (125_192_000 as Weight) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) + } + // Storage: LiquidityBootstrapping Pools (r:1 w:0) + // Storage: Tokens Accounts (r:4 w:4) + // Storage: System Account (r:2 w:1) + fn swap() -> Weight { + (119_364_000 as Weight) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) + } + // Storage: LiquidityBootstrapping Pools (r:1 w:0) + // Storage: Tokens Accounts (r:4 w:4) + // Storage: System Account (r:1 w:1) + fn add_liquidity() -> Weight { + (116_946_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) + } + // Storage: LiquidityBootstrapping Pools (r:1 w:1) + // Storage: Tokens Accounts (r:4 w:4) + // Storage: System Account (r:1 w:0) + fn remove_liquidity() -> Weight { + (100_444_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) + } +} diff --git a/runtime/dali/src/weights/membership.rs b/runtime/dali/src/weights/membership.rs index c89cce501e4..a5d3d51d57d 100644 --- a/runtime/dali/src/weights/membership.rs +++ b/runtime/dali/src/weights/membership.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `membership` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=dali-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=membership +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/dali/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -33,9 +34,9 @@ impl membership::WeightInfo for WeightInfo { // Storage: Council Members (r:0 w:1) // Storage: Council Prime (r:0 w:1) fn add_member(m: u32, ) -> Weight { - (41_977_000 as Weight) - // Standard Error: 10_000 - .saturating_add((257_000 as Weight).saturating_mul(m as Weight)) + (30_348_000 as Weight) + // Standard Error: 11_000 + .saturating_add((195_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -45,9 +46,9 @@ impl membership::WeightInfo for WeightInfo { // Storage: Council Members (r:0 w:1) // Storage: Council Prime (r:0 w:1) fn remove_member(m: u32, ) -> Weight { - (57_502_000 as Weight) - // Standard Error: 9_000 - .saturating_add((113_000 as Weight).saturating_mul(m as Weight)) + (37_304_000 as Weight) + // Standard Error: 0 + .saturating_add((145_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -57,9 +58,9 @@ impl membership::WeightInfo for WeightInfo { // Storage: Council Members (r:0 w:1) // Storage: Council Prime (r:0 w:1) fn swap_member(m: u32, ) -> Weight { - (53_945_000 as Weight) - // Standard Error: 6_000 - .saturating_add((212_000 as Weight).saturating_mul(m as Weight)) + (37_471_000 as Weight) + // Standard Error: 1_000 + .saturating_add((169_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -69,9 +70,9 @@ impl membership::WeightInfo for WeightInfo { // Storage: Council Members (r:0 w:1) // Storage: Council Prime (r:0 w:1) fn reset_member(m: u32, ) -> Weight { - (57_806_000 as Weight) - // Standard Error: 16_000 - .saturating_add((132_000 as Weight).saturating_mul(m as Weight)) + (37_886_000 as Weight) + // Standard Error: 1_000 + .saturating_add((359_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -81,9 +82,9 @@ impl membership::WeightInfo for WeightInfo { // Storage: Council Members (r:0 w:1) // Storage: Council Prime (r:0 w:1) fn change_key(m: u32, ) -> Weight { - (40_024_000 as Weight) - // Standard Error: 12_000 - .saturating_add((444_000 as Weight).saturating_mul(m as Weight)) + (38_943_000 as Weight) + // Standard Error: 1_000 + .saturating_add((171_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -91,18 +92,16 @@ impl membership::WeightInfo for WeightInfo { // Storage: CouncilMembership Prime (r:0 w:1) // Storage: Council Prime (r:0 w:1) fn set_prime(m: u32, ) -> Weight { - (12_745_000 as Weight) - // Standard Error: 5_000 - .saturating_add((73_000 as Weight).saturating_mul(m as Weight)) + (10_315_000 as Weight) + // Standard Error: 0 + .saturating_add((121_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: CouncilMembership Prime (r:0 w:1) // Storage: Council Prime (r:0 w:1) - fn clear_prime(m: u32, ) -> Weight { - (3_127_000 as Weight) - // Standard Error: 1_000 - .saturating_add((44_000 as Weight).saturating_mul(m as Weight)) + fn clear_prime(_m: u32, ) -> Weight { + (3_967_000 as Weight) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } } diff --git a/runtime/dali/src/weights/mod.rs b/runtime/dali/src/weights/mod.rs index aa34b18ff3d..71de74024e0 100644 --- a/runtime/dali/src/weights/mod.rs +++ b/runtime/dali/src/weights/mod.rs @@ -1,5 +1,6 @@ #![allow(clippy::unnecessary_cast)] pub mod balances; +pub mod bonded_finance; pub mod collator_selection; pub mod collective; pub mod crowdloan_rewards; @@ -14,9 +15,15 @@ pub mod mosaic; pub mod multisig; pub mod oracle; // pub mod scheduler; +pub mod curve_amm; +pub mod lending; +pub mod liquidations; +pub mod liquidity_bootstrapping; pub mod session; pub mod timestamp; pub mod tokens; pub mod treasury; +pub mod uniswap_v2; pub mod utility; pub mod vault; +pub mod vesting; diff --git a/runtime/dali/src/weights/mosaic.rs b/runtime/dali/src/weights/mosaic.rs index 27197f67e3b..a446d6fc0d0 100644 --- a/runtime/dali/src/weights/mosaic.rs +++ b/runtime/dali/src/weights/mosaic.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `mosaic` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-01, STEPS: `10`, REPEAT: 5, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=dali-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=mosaic +// --pallet=* // --extrinsic=* -// --steps=10 -// --repeat=5 -// --raw -// --output=./runtime/dali/src/weights +// --steps=50 +// --repeat=20 +// --output=runtime/dali/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -27,84 +28,96 @@ use sp_std::marker::PhantomData; /// Weight functions for `mosaic`. pub struct WeightInfo(PhantomData); -impl mosaic::weights::WeightInfo for WeightInfo { +impl mosaic::WeightInfo for WeightInfo { // Storage: Mosaic Relayer (r:0 w:1) fn set_relayer() -> Weight { - (11_000_000 as Weight) + (22_905_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Mosaic Relayer (r:1 w:1) fn rotate_relayer() -> Weight { - (14_000_000 as Weight) + (29_379_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Mosaic Relayer (r:1 w:0) // Storage: Mosaic NetworkInfos (r:0 w:1) fn set_network() -> Weight { - (14_000_000 as Weight) + (30_703_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Mosaic AssetsInfo (r:1 w:1) fn set_budget() -> Weight { - (14_000_000 as Weight) + (30_390_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Mosaic AssetsInfo (r:1 w:0) + // Storage: Mosaic LocalToRemoteAsset (r:1 w:0) // Storage: Mosaic NetworkInfos (r:1 w:0) // Storage: System Account (r:2 w:2) // Storage: Mosaic TimeLockPeriod (r:1 w:0) // Storage: Mosaic OutgoingTransactions (r:1 w:1) // Storage: Mosaic Nonce (r:1 w:1) fn transfer_to() -> Weight { - (58_000_000 as Weight) - .saturating_add(T::DbWeight::get().reads(7 as Weight)) + (127_241_000 as Weight) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Mosaic Relayer (r:1 w:0) + // Storage: Mosaic RemoteToLocalAsset (r:1 w:0) // Storage: Mosaic OutgoingTransactions (r:1 w:1) // Storage: System Account (r:1 w:1) fn accept_transfer() -> Weight { - (38_000_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) + (83_948_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Mosaic OutgoingTransactions (r:1 w:1) // Storage: System Account (r:2 w:2) fn claim_stale_to() -> Weight { - (46_000_000 as Weight) + (92_516_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Mosaic Relayer (r:1 w:0) + // Storage: Mosaic RemoteToLocalAsset (r:1 w:0) // Storage: Mosaic AssetsInfo (r:1 w:1) // Storage: System Account (r:1 w:1) // Storage: Mosaic IncomingTransactions (r:1 w:1) fn timelocked_mint() -> Weight { - (43_000_000 as Weight) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) + (92_941_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Mosaic TimeLockPeriod (r:0 w:1) fn set_timelock_duration() -> Weight { - (2_000_000 as Weight) + (2_878_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Mosaic Relayer (r:1 w:0) + // Storage: Mosaic RemoteToLocalAsset (r:1 w:0) // Storage: Mosaic IncomingTransactions (r:1 w:1) // Storage: System Account (r:1 w:1) fn rescind_timelocked_mint() -> Weight { - (36_000_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) + (82_207_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Mosaic IncomingTransactions (r:1 w:1) // Storage: System Account (r:2 w:2) fn claim_to() -> Weight { - (44_000_000 as Weight) + (89_270_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } + // Storage: Mosaic NetworkInfos (r:1 w:0) + // Storage: Mosaic LocalToRemoteAsset (r:1 w:1) + // Storage: Mosaic RemoteToLocalAsset (r:0 w:1) + fn update_asset_mapping() -> Weight { + (37_079_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } } diff --git a/runtime/dali/src/weights/multisig.rs b/runtime/dali/src/weights/multisig.rs index 0bee6ac7f84..8cfa36db7be 100644 --- a/runtime/dali/src/weights/multisig.rs +++ b/runtime/dali/src/weights/multisig.rs @@ -1,22 +1,23 @@ + //! Autogenerated weights for `multisig` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-12-09, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 // Executed Command: -// target/release/composable +// ./target/release/composable // benchmark -// --chain=picasso-dev +// --chain=dali-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=multisig +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw -// --output=./runtime/picasso/src/weights - +// --output=runtime/dali/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -28,19 +29,21 @@ use sp_std::marker::PhantomData; /// Weight functions for `multisig`. pub struct WeightInfo(PhantomData); impl multisig::WeightInfo for WeightInfo { - // Storage: CallFilter PausedTransactions (r:1 w:0) - fn as_multi_threshold_1(_z: u32, ) -> Weight { - (7_559_000 as Weight) + // Storage: CallFilter DisabledCalls (r:1 w:0) + fn as_multi_threshold_1(z: u32, ) -> Weight { + (13_950_000 as Weight) + // Standard Error: 0 + .saturating_add((1_000 as Weight).saturating_mul(z as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) fn as_multi_create(s: u32, z: u32, ) -> Weight { - (38_469_000 as Weight) - // Standard Error: 35_000 - .saturating_add((552_000 as Weight).saturating_mul(s as Weight)) + (60_617_000 as Weight) + // Standard Error: 148_000 + .saturating_add((1_006_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 - .saturating_add((1_000 as Weight).saturating_mul(z as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(z as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -48,81 +51,77 @@ impl multisig::WeightInfo for WeightInfo { // Storage: Multisig Calls (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) fn as_multi_create_store(s: u32, z: u32, ) -> Weight { - (43_628_000 as Weight) - // Standard Error: 53_000 - .saturating_add((492_000 as Weight).saturating_mul(s as Weight)) + (68_359_000 as Weight) + // Standard Error: 190_000 + .saturating_add((965_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 - .saturating_add((1_000 as Weight).saturating_mul(z as Weight)) + .saturating_add((3_000 as Weight).saturating_mul(z as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) fn as_multi_approve(s: u32, z: u32, ) -> Weight { - (22_585_000 as Weight) - // Standard Error: 33_000 - .saturating_add((298_000 as Weight).saturating_mul(s as Weight)) + (38_118_000 as Weight) + // Standard Error: 133_000 + .saturating_add((551_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 - .saturating_add((1_000 as Weight).saturating_mul(z as Weight)) + .saturating_add((2_000 as Weight).saturating_mul(z as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: Multisig Calls (r:1 w:1) fn as_multi_approve_store(s: u32, z: u32, ) -> Weight { - (41_470_000 as Weight) - // Standard Error: 674_000 - .saturating_add((653_000 as Weight).saturating_mul(s as Weight)) + (63_680_000 as Weight) + // Standard Error: 192_000 + .saturating_add((1_185_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 - .saturating_add((1_000 as Weight).saturating_mul(z as Weight)) + .saturating_add((3_000 as Weight).saturating_mul(z as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: Multisig Calls (r:1 w:1) // Storage: System Account (r:1 w:1) - // Storage: CallFilter PausedTransactions (r:1 w:0) - fn as_multi_complete(s: u32, z: u32, ) -> Weight { - (59_247_000 as Weight) - // Standard Error: 61_000 - .saturating_add((199_000 as Weight).saturating_mul(s as Weight)) + // Storage: CallFilter DisabledCalls (r:1 w:0) + fn as_multi_complete(_s: u32, z: u32, ) -> Weight { + (102_150_000 as Weight) // Standard Error: 0 - .saturating_add((2_000 as Weight).saturating_mul(z as Weight)) + .saturating_add((3_000 as Weight).saturating_mul(z as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) fn approve_as_multi_create(s: u32, ) -> Weight { - (39_002_000 as Weight) - // Standard Error: 43_000 - .saturating_add((255_000 as Weight).saturating_mul(s as Weight)) + (61_010_000 as Weight) + // Standard Error: 96_000 + .saturating_add((569_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: Multisig Calls (r:1 w:0) fn approve_as_multi_approve(_s: u32, ) -> Weight { - (25_053_000 as Weight) + (42_018_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: Multisig Calls (r:1 w:1) // Storage: System Account (r:1 w:1) - // Storage: CallFilter PausedTransactions (r:1 w:0) - fn approve_as_multi_complete(s: u32, ) -> Weight { - (75_973_000 as Weight) - // Standard Error: 39_000 - .saturating_add((209_000 as Weight).saturating_mul(s as Weight)) + // Storage: CallFilter DisabledCalls (r:1 w:0) + fn approve_as_multi_complete(_s: u32, ) -> Weight { + (131_323_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: Multisig Calls (r:1 w:1) fn cancel_as_multi(s: u32, ) -> Weight { - (59_455_000 as Weight) - // Standard Error: 38_000 - .saturating_add((432_000 as Weight).saturating_mul(s as Weight)) + (95_147_000 as Weight) + // Standard Error: 160_000 + .saturating_add((385_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } diff --git a/runtime/dali/src/weights/oracle.rs b/runtime/dali/src/weights/oracle.rs index 095ac7dc6ce..526f821bb8c 100644 --- a/runtime/dali/src/weights/oracle.rs +++ b/runtime/dali/src/weights/oracle.rs @@ -1,75 +1,105 @@ -//! Autogenerated weights for oracle + +//! Autogenerated weights for `oracle` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-08-30, STEPS: `[5, ]`, REPEAT: 2, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 128 +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable // benchmark -// --chain=picasso-dev +// --chain=dali-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=oracle +// --pallet=* // --extrinsic=* -// --steps=5 -// --repeat=2 -// --raw -// --output=./runtime/picasso/src/weights +// --steps=50 +// --repeat=20 +// --output=runtime/dali/src/weights +// --log +// error +#![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] use frame_support::{traits::Get, weights::Weight}; use sp_std::marker::PhantomData; -/// Weight functions for oracle. +/// Weight functions for `oracle`. pub struct WeightInfo(PhantomData); impl oracle::WeightInfo for WeightInfo { + // Storage: Oracle AssetsCount (r:1 w:1) + // Storage: Oracle AssetsInfo (r:1 w:1) fn add_asset_and_info() -> Weight { - (28_998_000 as Weight) - .saturating_add(T::DbWeight::get().reads(1 as Weight)) + (30_758_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: Oracle ControllerToSigner (r:1 w:1) + // Storage: Oracle SignerToController (r:1 w:1) + // Storage: Oracle OracleStake (r:1 w:1) fn set_signer() -> Weight { - (122_818_000 as Weight) + (110_998_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } + // Storage: Oracle ControllerToSigner (r:1 w:0) + // Storage: Oracle OracleStake (r:1 w:1) + // Storage: System Account (r:1 w:1) fn add_stake() -> Weight { - (114_274_000 as Weight) + (96_941_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: Oracle ControllerToSigner (r:1 w:0) + // Storage: Oracle OracleStake (r:1 w:1) + // Storage: Oracle DeclaredWithdraws (r:0 w:1) fn remove_stake() -> Weight { - (38_201_000 as Weight) + (37_136_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: Oracle ControllerToSigner (r:1 w:1) + // Storage: Oracle DeclaredWithdraws (r:1 w:1) + // Storage: System Account (r:1 w:0) + // Storage: Oracle SignerToController (r:0 w:1) fn reclaim_stake() -> Weight { - (54_632_000 as Weight) + (45_287_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } - fn submit_price(p: u32) -> Weight { - (76_538_000 as Weight) - // Standard Error: 154_000 - .saturating_add((798_000 as Weight).saturating_mul(p as Weight)) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) - } - fn update_pre_prices(p: u32) -> Weight { - (11_478_000 as Weight) - // Standard Error: 27_000 - .saturating_add((206_000 as Weight).saturating_mul(p as Weight)) - .saturating_add(T::DbWeight::get().reads(1 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + // Storage: Oracle OracleStake (r:1 w:0) + // Storage: Oracle Prices (r:1 w:0) + // Storage: Oracle AssetsInfo (r:1 w:0) + // Storage: Oracle AnswerInTransit (r:1 w:1) + // Storage: Oracle PrePrices (r:1 w:1) + fn submit_price(p: u32, ) -> Weight { + (55_780_000 as Weight) + // Standard Error: 7_000 + .saturating_add((296_000 as Weight).saturating_mul(p as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } - fn update_price(p: u32) -> Weight { - (0 as Weight) - // Standard Error: 2_426_000 - .saturating_add((22_017_000 as Weight).saturating_mul(p as Weight)) + // Storage: Oracle PrePrices (r:1 w:1) + // Storage: Oracle AnswerInTransit (r:1 w:1) + fn update_pre_prices(p: u32, ) -> Weight { + (15_551_000 as Weight) + // Standard Error: 3_000 + .saturating_add((215_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: Oracle PriceHistory (r:1 w:1) + // Storage: Oracle SignerToController (r:1 w:0) + // Storage: Oracle AnswerInTransit (r:1 w:1) + // Storage: Oracle Prices (r:0 w:1) + // Storage: Oracle PrePrices (r:0 w:1) + fn update_price(p: u32, ) -> Weight { + (31_154_000 as Weight) + // Standard Error: 84_000 + .saturating_add((15_332_000 as Weight).saturating_mul(p as Weight)) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) } } diff --git a/runtime/dali/src/weights/scheduler.rs b/runtime/dali/src/weights/scheduler.rs index ec7eadb3c6c..a455e00739d 100644 --- a/runtime/dali/src/weights/scheduler.rs +++ b/runtime/dali/src/weights/scheduler.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `scheduler` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=dali-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=scheduler +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/dali/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -28,38 +29,149 @@ use sp_std::marker::PhantomData; /// Weight functions for `scheduler`. pub struct WeightInfo(PhantomData); impl scheduler::WeightInfo for WeightInfo { + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Scheduler Lookup (r:0 w:1) + fn on_initialize_periodic_named_resolved(s: u32, ) -> Weight { + (17_858_000 as Weight) + // Standard Error: 50_000 + .saturating_add((48_635_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((4 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:1 w:1) + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + // Storage: Scheduler Lookup (r:0 w:1) + fn on_initialize_named_resolved(s: u32, ) -> Weight { + (12_696_000 as Weight) + // Standard Error: 53_000 + .saturating_add((38_308_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + fn on_initialize_periodic_resolved(s: u32, ) -> Weight { + (22_499_000 as Weight) + // Standard Error: 95_000 + .saturating_add((42_012_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:1 w:1) + // Storage: Preimage PreimageFor (r:1 w:1) + // Storage: Preimage StatusFor (r:1 w:1) + fn on_initialize_resolved(s: u32, ) -> Weight { + (12_523_000 as Weight) + // Standard Error: 69_000 + .saturating_add((35_402_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Preimage PreimageFor (r:1 w:0) + // Storage: Scheduler Lookup (r:0 w:1) + fn on_initialize_named_aborted(s: u32, ) -> Weight { + (13_139_000 as Weight) + // Standard Error: 18_000 + .saturating_add((16_652_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Preimage PreimageFor (r:1 w:0) + fn on_initialize_aborted(s: u32, ) -> Weight { + (15_583_000 as Weight) + // Standard Error: 14_000 + .saturating_add((10_382_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + // Storage: Scheduler Agenda (r:2 w:2) + // Storage: Scheduler Lookup (r:0 w:1) + fn on_initialize_periodic_named(s: u32, ) -> Weight { + (17_163_000 as Weight) + // Standard Error: 91_000 + .saturating_add((26_041_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:2 w:2) + fn on_initialize_periodic(s: u32, ) -> Weight { + (28_578_000 as Weight) + // Standard Error: 18_000 + .saturating_add((18_680_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:1 w:1) + // Storage: Scheduler Lookup (r:0 w:1) + fn on_initialize_named(s: u32, ) -> Weight { + (27_906_000 as Weight) + // Standard Error: 24_000 + .saturating_add((15_079_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) + } + // Storage: Scheduler Agenda (r:1 w:1) + fn on_initialize(s: u32, ) -> Weight { + (23_554_000 as Weight) + // Standard Error: 13_000 + .saturating_add((12_566_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } // Storage: Scheduler Agenda (r:1 w:1) fn schedule(s: u32, ) -> Weight { - (26_133_000 as Weight) + (32_955_000 as Weight) // Standard Error: 3_000 - .saturating_add((121_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((162_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Agenda (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn cancel(s: u32, ) -> Weight { - (25_861_000 as Weight) - // Standard Error: 26_000 - .saturating_add((1_700_000 as Weight).saturating_mul(s as Weight)) + (31_986_000 as Weight) + // Standard Error: 5_000 + .saturating_add((2_355_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn schedule_named(s: u32, ) -> Weight { - (31_526_000 as Weight) - // Standard Error: 1_000 - .saturating_add((147_000 as Weight).saturating_mul(s as Weight)) + (43_247_000 as Weight) + // Standard Error: 4_000 + .saturating_add((99_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn cancel_named(s: u32, ) -> Weight { - (26_934_000 as Weight) - // Standard Error: 6_000 - .saturating_add((1_733_000 as Weight).saturating_mul(s as Weight)) + (10_543_000 as Weight) + // Standard Error: 85_000 + .saturating_add((3_962_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } diff --git a/runtime/dali/src/weights/session.rs b/runtime/dali/src/weights/session.rs index 82593ab0aac..08fc53f58d1 100644 --- a/runtime/dali/src/weights/session.rs +++ b/runtime/dali/src/weights/session.rs @@ -1,38 +1,45 @@ -//! Autogenerated weights for session + +//! Autogenerated weights for `session` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-08-22, STEPS: `[5, ]`, REPEAT: 2, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 128 +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable // benchmark -// --chain=picasso-dev +// --chain=dali-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=session +// --pallet=* // --extrinsic=* -// --steps=5 -// --repeat=2 -// --raw -// --output=./runtime/picasso/src/weights +// --steps=50 +// --repeat=20 +// --output=runtime/dali/src/weights +// --log +// error +#![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] use frame_support::{traits::Get, weights::Weight}; use sp_std::marker::PhantomData; -/// Weight functions for session. +/// Weight functions for `session`. pub struct WeightInfo(PhantomData); impl session::WeightInfo for WeightInfo { + // Storage: Session NextKeys (r:1 w:1) + // Storage: Session KeyOwner (r:1 w:1) fn set_keys() -> Weight { - (47_000_000 as Weight) + (29_712_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } + // Storage: Session NextKeys (r:1 w:1) + // Storage: Session KeyOwner (r:0 w:1) fn purge_keys() -> Weight { - (30_000_000 as Weight) + (22_617_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } diff --git a/runtime/dali/src/weights/timestamp.rs b/runtime/dali/src/weights/timestamp.rs index f8ba18938d6..549bbaae50f 100644 --- a/runtime/dali/src/weights/timestamp.rs +++ b/runtime/dali/src/weights/timestamp.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `timestamp` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=dali-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=timestamp +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/dali/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -31,11 +32,11 @@ impl timestamp::WeightInfo for WeightInfo { // Storage: Timestamp Now (r:1 w:1) // Storage: Aura CurrentSlot (r:1 w:0) fn set() -> Weight { - (18_977_000 as Weight) + (12_371_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn on_finalize() -> Weight { - (8_350_000 as Weight) + (5_846_000 as Weight) } } diff --git a/runtime/dali/src/weights/treasury.rs b/runtime/dali/src/weights/treasury.rs index f893b42bcba..fe814f34172 100644 --- a/runtime/dali/src/weights/treasury.rs +++ b/runtime/dali/src/weights/treasury.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `treasury` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=dali-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=treasury +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/dali/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -31,23 +32,23 @@ impl treasury::WeightInfo for WeightInfo { // Storage: Treasury ProposalCount (r:1 w:1) // Storage: Treasury Proposals (r:0 w:1) fn propose_spend() -> Weight { - (67_339_000 as Weight) + (50_237_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Treasury Proposals (r:1 w:1) // Storage: System Account (r:2 w:2) fn reject_proposal() -> Weight { - (89_248_000 as Weight) + (76_230_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Treasury Proposals (r:1 w:0) // Storage: Treasury Approvals (r:1 w:1) fn approve_proposal(p: u32, ) -> Weight { - (15_617_000 as Weight) - // Standard Error: 50_000 - .saturating_add((297_000 as Weight).saturating_mul(p as Weight)) + (16_221_000 as Weight) + // Standard Error: 4_000 + .saturating_add((288_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -55,9 +56,9 @@ impl treasury::WeightInfo for WeightInfo { // Storage: Treasury Approvals (r:1 w:1) // Storage: Treasury Proposals (r:1 w:1) fn on_initialize_proposals(p: u32, ) -> Weight { - (50_253_000 as Weight) - // Standard Error: 1_061_000 - .saturating_add((65_655_000 as Weight).saturating_mul(p as Weight)) + (69_078_000 as Weight) + // Standard Error: 78_000 + .saturating_add((69_161_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(p as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) diff --git a/runtime/dali/src/weights/uniswap_v2.rs b/runtime/dali/src/weights/uniswap_v2.rs new file mode 100644 index 00000000000..56f689826ca --- /dev/null +++ b/runtime/dali/src/weights/uniswap_v2.rs @@ -0,0 +1,82 @@ + +//! Autogenerated weights for `uniswap_v2` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/composable +// benchmark +// --chain=dali-dev +// --execution=wasm +// --wasm-execution=compiled +// --pallet=* +// --extrinsic=* +// --steps=50 +// --repeat=20 +// --output=runtime/dali/src/weights +// --log +// error + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for `uniswap_v2`. +pub struct WeightInfo(PhantomData); +impl uniswap_v2::WeightInfo for WeightInfo { + // Storage: CurrencyFactory AssetIdRanges (r:1 w:1) + // Storage: ConstantProductDex PoolCount (r:1 w:1) + // Storage: ConstantProductDex Pools (r:0 w:1) + fn create() -> Weight { + (33_986_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + // Storage: ConstantProductDex Pools (r:1 w:0) + // Storage: Tokens Accounts (r:5 w:5) + // Storage: Tokens TotalIssuance (r:1 w:1) + // Storage: System Account (r:1 w:1) + fn add_liquidity() -> Weight { + (154_956_000 as Weight) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) + .saturating_add(T::DbWeight::get().writes(7 as Weight)) + } + // Storage: ConstantProductDex Pools (r:1 w:0) + // Storage: Tokens Accounts (r:5 w:5) + // Storage: Tokens TotalIssuance (r:1 w:1) + // Storage: System Account (r:1 w:0) + fn remove_liquidity() -> Weight { + (123_643_000 as Weight) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } + // Storage: ConstantProductDex Pools (r:1 w:0) + // Storage: Tokens Accounts (r:5 w:5) + // Storage: System Account (r:2 w:1) + fn buy() -> Weight { + (153_717_000 as Weight) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } + // Storage: ConstantProductDex Pools (r:1 w:0) + // Storage: Tokens Accounts (r:5 w:5) + // Storage: System Account (r:2 w:1) + fn sell() -> Weight { + (144_463_000 as Weight) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } + // Storage: ConstantProductDex Pools (r:1 w:0) + // Storage: Tokens Accounts (r:5 w:5) + // Storage: System Account (r:2 w:1) + fn swap() -> Weight { + (137_512_000 as Weight) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } +} diff --git a/runtime/dali/src/weights/utility.rs b/runtime/dali/src/weights/utility.rs index ec86559933e..1a1485a5298 100644 --- a/runtime/dali/src/weights/utility.rs +++ b/runtime/dali/src/weights/utility.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `utility` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-01-18, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -11,12 +11,13 @@ // --chain=dali-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=utility +// --pallet=* // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/dali/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -30,24 +31,24 @@ pub struct WeightInfo(PhantomData); impl utility::WeightInfo for WeightInfo { // Storage: CallFilter DisabledCalls (r:1 w:0) fn batch(c: u32, ) -> Weight { - (31_182_000 as Weight) - // Standard Error: 2_000 - .saturating_add((9_073_000 as Weight).saturating_mul(c as Weight)) + (69_440_000 as Weight) + // Standard Error: 17_000 + .saturating_add((9_276_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: CallFilter DisabledCalls (r:1 w:0) fn as_derivative() -> Weight { - (8_550_000 as Weight) + (10_279_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: CallFilter DisabledCalls (r:1 w:0) fn batch_all(c: u32, ) -> Weight { - (15_732_000 as Weight) - // Standard Error: 5_000 - .saturating_add((9_666_000 as Weight).saturating_mul(c as Weight)) + (33_922_000 as Weight) + // Standard Error: 10_000 + .saturating_add((9_880_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } fn dispatch_as() -> Weight { - (17_050_000 as Weight) + (20_214_000 as Weight) } } diff --git a/runtime/dali/src/weights/vault.rs b/runtime/dali/src/weights/vault.rs index 179cd304bdb..4be256d64e9 100644 --- a/runtime/dali/src/weights/vault.rs +++ b/runtime/dali/src/weights/vault.rs @@ -1,23 +1,23 @@ + //! Autogenerated weights for `vault` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-11-10, STEPS: `40`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable // benchmark -// --chain=picasso-dev +// --chain=dali-dev // --execution=wasm // --wasm-execution=compiled -// --pallet=vault +// --pallet=* // --extrinsic=* -// --steps=40 +// --steps=50 // --repeat=20 -// --raw -// --output -// ./runtime/picasso/src/weights/ - +// --output=runtime/dali/src/weights +// --log +// error #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -30,15 +30,14 @@ use sp_std::marker::PhantomData; pub struct WeightInfo(PhantomData); impl vault::WeightInfo for WeightInfo { // Storage: Vault VaultCount (r:1 w:1) - // Storage: Factory CurrencyCounter (r:1 w:1) + // Storage: CurrencyFactory AssetIdRanges (r:1 w:1) // Storage: System Account (r:2 w:2) // Storage: Vault LpTokensToVaults (r:0 w:1) - // Storage: Vault Allocations (r:0 w:1) // Storage: Vault Vaults (r:0 w:1) fn create() -> Weight { - (144_989_000 as Weight) + (137_658_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(7 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) } // Storage: Vault Vaults (r:1 w:0) // Storage: Tokens Accounts (r:3 w:3) @@ -46,7 +45,7 @@ impl vault::WeightInfo for WeightInfo { // Storage: Vault CapitalStructure (r:2 w:0) // Storage: System Account (r:1 w:1) fn deposit() -> Weight { - (140_947_000 as Weight) + (147_945_000 as Weight) .saturating_add(T::DbWeight::get().reads(9 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } @@ -55,33 +54,33 @@ impl vault::WeightInfo for WeightInfo { // Storage: Vault CapitalStructure (r:2 w:0) // Storage: Tokens TotalIssuance (r:2 w:1) fn withdraw() -> Weight { - (112_296_000 as Weight) + (124_839_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Vault Vaults (r:1 w:1) fn emergency_shutdown() -> Weight { - (25_497_000 as Weight) + (28_073_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Vault Vaults (r:1 w:1) fn start_() -> Weight { - (25_388_000 as Weight) + (27_397_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Vault Vaults (r:1 w:1) // Storage: System Account (r:1 w:1) fn add_surcharge() -> Weight { - (77_802_000 as Weight) + (77_780_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Vault Vaults (r:1 w:1) // Storage: System Account (r:1 w:1) fn claim_surcharge() -> Weight { - (70_839_000 as Weight) + (73_897_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -89,7 +88,7 @@ impl vault::WeightInfo for WeightInfo { // Storage: System Account (r:1 w:0) // Storage: Vault LpTokensToVaults (r:0 w:1) fn delete_tombstoned() -> Weight { - (25_030_000 as Weight) + (25_856_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } diff --git a/runtime/dali/src/weights/vesting.rs b/runtime/dali/src/weights/vesting.rs new file mode 100644 index 00000000000..041ea71c8c9 --- /dev/null +++ b/runtime/dali/src/weights/vesting.rs @@ -0,0 +1,70 @@ + +//! Autogenerated weights for `vesting` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dali-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/composable +// benchmark +// --chain=dali-dev +// --execution=wasm +// --wasm-execution=compiled +// --pallet=* +// --extrinsic=* +// --steps=50 +// --repeat=20 +// --output=runtime/dali/src/weights +// --log +// error + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for `vesting`. +pub struct WeightInfo(PhantomData); +impl vesting::WeightInfo for WeightInfo { + // Storage: Vesting VestingSchedules (r:1 w:1) + // Storage: Tokens Locks (r:1 w:1) + // Storage: Tokens Accounts (r:1 w:1) + // Storage: Timestamp Now (r:1 w:0) + fn claim(s: u32, ) -> Weight { + (63_980_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + // Storage: Vesting VestingSchedules (r:1 w:1) + // Storage: Tokens Accounts (r:2 w:2) + // Storage: System Account (r:2 w:1) + // Storage: Tokens Locks (r:1 w:1) + fn vested_transfer() -> Weight { + (106_897_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) + } + // Storage: Tokens Locks (r:1 w:1) + // Storage: Tokens Accounts (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Vesting VestingSchedules (r:0 w:1) + fn update_vesting_schedules(_s: u32, ) -> Weight { + (60_852_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) + } + // Storage: Vesting VestingSchedules (r:1 w:1) + // Storage: Tokens Locks (r:1 w:1) + // Storage: Tokens Accounts (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Timestamp Now (r:1 w:0) + fn claim_for(_s: u32, ) -> Weight { + (65_037_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) + } +} diff --git a/runtime/dali/src/xcmp.rs b/runtime/dali/src/xcmp.rs index 70a494543cb..f7fd7e7daed 100644 --- a/runtime/dali/src/xcmp.rs +++ b/runtime/dali/src/xcmp.rs @@ -1,47 +1,54 @@ //! Setup of XCMP for parachain to allow cross chain transfers and other operations. //! Very similar to https://github.com/galacticcouncil/Basilisk-node/blob/master/runtime/basilisk/src/xcm.rs #![allow(unused_imports)] // allow until v2 xcm released (instead creating 2 runtimes) - use super::*; // recursive dependency onto runtime - use codec::{Decode, Encode}; -use composable_traits::assets::{RemoteAssetRegistry, XcmAssetLocation}; -use cumulus_primitives_core::ParaId; +use common::xcmp::*; +use composable_traits::{ + assets::{RemoteAssetRegistry, XcmAssetLocation}, + defi::Ratio, + oracle::MinimalOracle, +}; +use cumulus_primitives_core::{IsSystem, ParaId}; use frame_support::{ - construct_runtime, log, match_type, parameter_types, - traits::{Contains, Everything, KeyOwnerProofSystem, Nothing, Randomness, StorageInfo}, + construct_runtime, ensure, log, match_type, parameter_types, + traits::{ + Contains, Everything, KeyOwnerProofSystem, Nothing, OriginTrait, Randomness, StorageInfo, + }, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, DispatchClass, IdentityFee, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }, - PalletId, + PalletId, RuntimeDebug, }; - -use orml_xcm_support::{IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset}; - +use orml_traits::{location::Reserve, parameter_type_with_key, MultiCurrency}; +use orml_xcm_support::{ + DepositToAlternative, IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset, OnDepositFail, +}; +use pallet_xcm::XcmPassthrough; +use polkadot_parachain::primitives::Sibling; +use primitives::currency::WellKnownCurrency; +use sp_api::impl_runtime_apis; +use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ traits::{AccountIdLookup, BlakeTwo256, Convert, ConvertInto, Zero}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, + ApplyExtrinsicResult, DispatchError, }; - -use orml_traits::parameter_type_with_key; -use sp_api::impl_runtime_apis; -use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; - -use pallet_xcm::XcmPassthrough; -use polkadot_parachain::primitives::Sibling; -use sp_std::prelude::*; +use sp_std::{marker::PhantomData, prelude::*}; use xcm::latest::{prelude::*, Error}; use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, - AllowTopLevelPaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, LocationInverter, - ParentIsDefault, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, + LocationInverter, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, + SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeRevenue, TakeWeightCredit, }; use xcm_executor::{ - traits::{TransactAsset, WeightTrader}, + traits::{ + ConvertOrigin, DropAssets, FilterAssetLocation, ShouldExecute, TransactAsset, WeightTrader, + }, Assets, Config, XcmExecutor, }; @@ -52,40 +59,15 @@ parameter_types! { pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into(); } -// here we should add any partner network for zero cost transactions -match_type! { - pub type SpecParachain: impl Contains = { - MultiLocation { parents: 1, interior: X1(Parachain(2000)) } | - MultiLocation { parents: 1, interior: X1(Parachain(3000)) } - }; -} - -/// this is debug struct implementing as many XCMP interfaces as possible -/// it just dumps content, no modification. -/// returns default expected -pub struct XcmpDebug; - -impl xcm_executor::traits::ShouldExecute for XcmpDebug { - fn should_execute( - origin: &MultiLocation, - message: &mut Xcm, - max_weight: Weight, - weight_credit: &mut Weight, - ) -> Result<(), ()> { - log::trace!("{:?} {:?} {:?} {:?}", origin, message, max_weight, weight_credit); - Err(()) - } -} - pub type Barrier = ( XcmpDebug, - TakeWeightCredit, - AllowTopLevelPaidExecutionFrom, - xcm_builder::AllowUnpaidExecutionFrom, + //DebugAllowUnpaidExecutionFrom, // Expected responses are OK. AllowKnownQueryResponses, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, + TakeWeightCredit, ); pub type LocalOriginToLocation = SignedToAccountId32; @@ -103,8 +85,8 @@ pub type XcmRouter = ( /// when determining ownership of accounts for asset transacting and when attempting to use XCM /// `Transact` in order to determine the dispatch Origin. pub type LocationToAccountId = ( - // The parent (Relay-chain) origin converts to the default `AccountId`. - ParentIsDefault, + // The parent (Relay-chain) origin converts to the parent `AccountId`. + ParentIsPreset, // Sibling parachain origins convert to AccountId via the `ParaId::into`. SiblingParachainConvertsVia, // Straight up local `AccountId32` origins just alias directly to `AccountId`. @@ -135,74 +117,175 @@ pub type XcmOriginToTransactDispatchOrigin = ( XcmPassthrough, ); +pub struct StaticAssetsMap; + +pub mod parachains { + pub mod karura { + pub const ID: u32 = 3000; + pub const KUSD_KEY: &[u8] = &[0, 129]; + } +} + +impl XcmpAssets for StaticAssetsMap { + fn remote_to_local(location: MultiLocation) -> Option { + match location { + MultiLocation { parents: 1, interior: X2(Parachain(para_id), GeneralKey(key)) } => + match (para_id, &key[..]) { + (parachains::karura::ID, parachains::karura::KUSD_KEY) => + Some(CurrencyId::kUSD), + _ => None, + }, + _ => None, + } + } +} + pub type LocalAssetTransactor = MultiCurrencyAdapter< crate::Assets, UnknownTokens, - IsNativeConcrete, + IsNativeConcrete, AccountId, LocationToAccountId, CurrencyId, - CurrencyIdConvert, - // TODO(hussein-aitlahcen): DepositFailureHandler - (), + AssetsIdConverter, + DepositToAlternative, >; -parameter_types! { - pub const BaseXcmWeight: Weight = 0; - pub const MaxInstructions: u32 = 10_000; -} +pub struct PriceConverter; + +impl MinimalOracle for PriceConverter { + type AssetId = CurrencyId; -// TODO: as of now we allow any, but need to decide on payments as in Acala -pub struct TradePassthrough(); + type Balance = Balance; -/// any payment to pass -impl WeightTrader for TradePassthrough { - fn new() -> Self { - Self() + fn get_price_inverse( + asset_id: Self::AssetId, + amount: Self::Balance, + ) -> Result { + match asset_id { + CurrencyId::PICA => Ok(amount), + CurrencyId::KSM => Ok(amount / 10), + CurrencyId::kUSD => Ok(amount / 10), + _ => Err(DispatchError::Other("cannot pay with given weight")), + } } +} +pub struct RelayReserveFromParachain; +impl FilterAssetLocation for RelayReserveFromParachain { + fn filter_asset_location(asset: &MultiAsset, origin: &MultiLocation) -> bool { + // NOTE: In Acala there is not such thing + // if asset is KSM and send from some parachain then allow for that + asset.reserve() == Some(MultiLocation::parent()) && + matches!(origin, MultiLocation { parents: 1, interior: X1(Parachain(_)) }) + } +} - fn buy_weight(&mut self, _weight: Weight, payment: Assets) -> Result { - // Just let it through for now - Ok(payment) +type IsReserveAssetLocationFilter = + (DebugMultiNativeAsset, MultiNativeAsset, RelayReserveFromParachain); + +type AssetsIdConverter = + CurrencyIdConvert; + +pub type Trader = TransactionFeePoolTrader< + AssetsIdConverter, + PriceConverter, + ToTreasury, + WeightToFee, +>; + +pub struct CaptureDropAssets< + Treasury: TakeRevenue, + PriceConverter: MinimalOracle, + AssetConverter: Convert>, +>(PhantomData<(Treasury, PriceConverter, AssetConverter)>); + +/// if asset put into Holding Registry of XCM VM, but did nothing to this +/// or if too small to pay weight, +/// it will get here +/// if asset location and origin is known, put into treasury, +/// else if asset location and origin not know, hash it until it will be added +impl< + Treasury: TakeRevenue, + PriceConverter: MinimalOracle, + AssetConverter: Convert>, + > DropAssets for CaptureDropAssets +{ + fn drop_assets(origin: &MultiLocation, assets: Assets) -> Weight { + let multi_assets: Vec = assets.into(); + let mut can_return_on_request = vec![]; + log::info!(target : "xcmp", "drop_assets"); + let mut weight = Weight::zero(); + for asset in multi_assets { + if let MultiAsset { id: Concrete(location), fun: Fungible(_amount) } = asset.clone() { + if let Some(_converted) = AssetConverter::convert(location) { + Treasury::take_revenue(asset); + } else { + can_return_on_request.push(asset); + } + } else { + can_return_on_request.push(asset); + } + } + if !can_return_on_request.is_empty() { + weight += RelayerXcm::drop_assets(origin, can_return_on_request.into()); + } + weight } } +pub type CaptureAssetTrap = CaptureDropAssets< + ToTreasury, + PriceConverter, + AssetsIdConverter, +>; + pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { type Call = Call; type XcmSender = XcmRouter; type AssetTransactor = LocalAssetTransactor; - type OriginConverter = XcmOriginToTransactDispatchOrigin; - type IsReserve = MultiNativeAsset; + type IsReserve = IsReserveAssetLocationFilter; type IsTeleporter = (); // <- should be enough to allow teleportation of PICA type LocationInverter = LocationInverter; type Barrier = Barrier; - type Weigher = FixedWeightBounds; + type Weigher = FixedWeightBounds; - type Trader = TradePassthrough; + type Trader = Trader; type ResponseHandler = RelayerXcm; type SubscriptionService = RelayerXcm; type AssetClaims = RelayerXcm; - type AssetTrap = RelayerXcm; + type AssetTrap = CaptureAssetTrap; } parameter_types! { pub SelfLocation: MultiLocation = MultiLocation::new(1, X1(Parachain(ParachainInfo::parachain_id().into()))); - pub const MaxAssetsForTransfer: usize = 10; + // safe value to start to transfer 1 asset only in one message (as in Acala) + pub const MaxAssetsForTransfer: usize = 1; +} + +parameter_type_with_key! { + pub ParachainMinFee: |location: MultiLocation| -> u128 { + #[allow(clippy::match_ref_pats)] // false positive + match (location.parents, location.first_interior()) { + // (1, Some(Parachain(2))) => 40, + _ => 0, + } + }; } impl orml_xtokens::Config for Runtime { type Event = Event; type Balance = Balance; type CurrencyId = CurrencyId; - type CurrencyIdConvert = CurrencyIdConvert; + type CurrencyIdConvert = AssetsIdConverter; type AccountIdToMultiLocation = AccountIdToMultiLocation; type SelfLocation = SelfLocation; type XcmExecutor = XcmExecutor; - type Weigher = FixedWeightBounds; + type Weigher = FixedWeightBounds; type BaseXcmWeight = BaseXcmWeight; + type MinXcmFee = ParachainMinFee; type LocationInverter = LocationInverter; type MaxAssetsForTransfer = MaxAssetsForTransfer; } @@ -211,104 +294,12 @@ impl orml_unknown_tokens::Config for Runtime { type Event = Event; } -/// is collaed to convert some account id to account id on other network -/// as of now it is same as in Acala/Hydra -pub struct AccountIdToMultiLocation; -impl Convert for AccountIdToMultiLocation { - fn convert(account: AccountId) -> MultiLocation { - // considers any other network using globally unique ids - X1(AccountId32 { network: NetworkId::Any, id: account.into() }).into() - } -} - -/// Converts currency to and from local and remote -pub struct CurrencyIdConvert; - -/// converts local currency into remote, -/// native currency is built in -impl sp_runtime::traits::Convert> for CurrencyIdConvert { - fn convert(id: CurrencyId) -> Option { - match id { - CurrencyId::INVALID => { - log::warn!( - "mapping for {:?} on {:?} parachain not found", - id, - ParachainInfo::parachain_id() - ); - None - }, - CurrencyId::PICA => Some(MultiLocation::new( - 1, - X2(Parachain(ParachainInfo::parachain_id().into()), GeneralKey(id.encode())), - )), - _ => { - if let Some(location) = - ::asset_to_location(id).map(Into::into) - { - Some(location) - } else { - log::warn!( - "mapping for {:?} on {:?} parachain not found", - id, - ParachainInfo::parachain_id() - ); - None - } - }, - } - } -} - -/// converts from Relay parent chain to child chain currency -/// expected that currency in location is in format well known for local chain -impl Convert> for CurrencyIdConvert { - fn convert(location: MultiLocation) -> Option { - log::trace!("converting {:?} on {:?}", &location, ParachainInfo::parachain_id()); - match location { - MultiLocation { parents, interior: X2(Parachain(id), GeneralKey(key)) } - if parents == 1 && ParaId::from(id) == ParachainInfo::parachain_id() => - { - // Handling native asset for this parachain - if let Ok(currency_id) = CurrencyId::decode(&mut &key[..]) { - // we currently have only one native asset - match currency_id { - CurrencyId::PICA => Some(CurrencyId::PICA), - _ => { - log::error!("failed converting currency"); - None - }, - } - } else { - log::error!("failed converting currency"); - None - } - }, - // delegate to asset-registry - _ => { - let result = ::location_to_asset( - XcmAssetLocation(location), - ) - .map(Into::into); - if result.is_none() { - log::error!("failed converting currency"); - } - result - }, - } - } -} - -/// covert remote to local, usually when receiving transfer -impl Convert> for CurrencyIdConvert { - fn convert(asset: MultiAsset) -> Option { - log::trace!("converting {:?}", &asset); - if let MultiAsset { id: Concrete(location), .. } = asset { - Self::convert(location) - } else { - log::error!("failed to find remote asset"); - None - } - } +// make setup as in Acala, max instructions seems resoanble, for weigth may consider to settle with +// our PICA +parameter_types! { + // One XCM operation is 200_000_000 weight, cross-chain transfer ~= 2x of transfer. + pub const UnitWeightCost: Weight = 200_000_000; + pub const MaxInstructions: u32 = 100; } impl pallet_xcm::Config for Runtime { @@ -317,12 +308,12 @@ impl pallet_xcm::Config for Runtime { type XcmRouter = XcmRouter; type ExecuteXcmOrigin = EnsureXcmOrigin; /// https://medium.com/kusama-network/kusamas-governance-thwarts-would-be-attacker-9023180f6fb - type XcmExecuteFilter = Everything; + type XcmExecuteFilter = Nothing; type XcmExecutor = XcmExecutor; type XcmTeleportFilter = Everything; type XcmReserveTransferFilter = Everything; type LocationInverter = LocationInverter; - type Weigher = FixedWeightBounds; + type Weigher = FixedWeightBounds; type Origin = Origin; type Call = Call; @@ -330,6 +321,7 @@ impl pallet_xcm::Config for Runtime { type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; } +/// cumulus is defaultt implementation of queue integrated with polkadot and kusama runtimes impl cumulus_pallet_xcm::Config for Runtime { type Event = Event; type XcmExecutor = XcmExecutor; @@ -340,11 +332,13 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type XcmExecutor = XcmExecutor; type VersionWrapper = (); type ChannelInfo = ParachainSystem; - type ExecuteOverweightOrigin = EnsureRoot; + type ExecuteOverweightOrigin = EnsureRootOrHalfCouncil; + type ControllerOrigin = EnsureRootOrHalfCouncil; + type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; } impl cumulus_pallet_dmp_queue::Config for Runtime { type Event = Event; type XcmExecutor = XcmExecutor; - type ExecuteOverweightOrigin = system::EnsureRoot; + type ExecuteOverweightOrigin = EnsureRootOrHalfCouncil; } diff --git a/runtime/picasso/Cargo.toml b/runtime/picasso/Cargo.toml index 3872c0bb704..77abee8b0a3 100644 --- a/runtime/picasso/Cargo.toml +++ b/runtime/picasso/Cargo.toml @@ -1,221 +1,235 @@ [package] +edition = "2021" name = "picasso-runtime" version = "0.1.0" -edition = "2021" -description = "Picasso, Kusama Parachain Runtime Implementation" authors = ["Seun Lanlege "] +description = "Picasso, Kusama Parachain Runtime Implementation" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [package.metadata.cargo-udeps.ignore] normal = [ - "assets", - "assets-registry", - "call-filter", - "currency-factory", - "governance-registry", - "oracle", - "orml-unknown-tokens", - "orml-xtokens", - "pallet-bonded-finance", - "pallet-vault", - "session-benchmarking", - "vault", + "assets", + "assets-registry", + "call-filter", + "currency-factory", + "governance-registry", + "oracle", + "orml-unknown-tokens", + "orml-xtokens", + "pallet-bonded-finance", + "pallet-vault", + "session-benchmarking", + "vault", ] [dependencies] -frame-system = { package = "frame-system", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -executive = { package = "frame-executive", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } +executive = { package = "frame-executive", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +frame-system = { package = "frame-system", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } # primitives -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } # modules -aura = { package = "pallet-aura", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -authorship = { package = "pallet-authorship", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -balances = { package = "pallet-balances", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -indices = { package = "pallet-indices", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -randomness-collective-flip = { package = "pallet-randomness-collective-flip", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -collective = { package = "pallet-collective", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -identity = { package = "pallet-identity", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -multisig = { package = "pallet-multisig", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -membership = { package = "pallet-membership", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -scheduler = { package = "pallet-scheduler", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -session = { package = "pallet-session", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -sudo = { package = "pallet-sudo", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -timestamp = { package = "pallet-timestamp", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -treasury = { package = "pallet-treasury", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -democracy = { package = "pallet-democracy", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -transaction-payment = { package = "pallet-transaction-payment", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -utility = { package = "pallet-utility", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -preimage = { package = "pallet-preimage", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } +aura = { package = "pallet-aura", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +authorship = { package = "pallet-authorship", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +balances = { package = "pallet-balances", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +collective = { package = "pallet-collective", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +democracy = { package = "pallet-democracy", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +identity = { package = "pallet-identity", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +indices = { package = "pallet-indices", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +membership = { package = "pallet-membership", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +multisig = { package = "pallet-multisig", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } +preimage = { package = "pallet-preimage", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +randomness-collective-flip = { package = "pallet-randomness-collective-flip", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +scheduler = { package = "pallet-scheduler", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +session = { package = "pallet-session", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } smallvec = "1.6.1" +sudo = { package = "pallet-sudo", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +timestamp = { package = "pallet-timestamp", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +transaction-payment = { package = "pallet-transaction-payment", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +treasury = { package = "pallet-treasury", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +utility = { package = "pallet-utility", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } # local modules - +assets = { package = "pallet-assets", path = '../../frame/assets', default-features = false } +assets-registry = { package = "pallet-assets-registry", path = '../../frame/assets-registry', default-features = false } +bonded-finance = { package = "pallet-bonded-finance", path = "../../frame/bonded-finance", default-features = false } +call-filter = { package = "pallet-call-filter", path = "../../frame/call-filter", default-features = false } common = { path = "../common", default-features = false } -primitives = { path = "../primitives", default-features = false } +composable-support = { path = "../../frame/composable-support", default-features = false } composable-traits = { path = "../../frame/composable-traits", default-features = false } -call-filter = { package = "pallet-call-filter", path = "../../frame/call-filter", default-features = false } +crowdloan-rewards = { package = "pallet-crowdloan-rewards", path = '../../frame/crowdloan-rewards', default-features = false } currency-factory = { package = "pallet-currency-factory", path = "../../frame/currency-factory", default-features = false } governance-registry = { package = "pallet-governance-registry", path = "../../frame/governance-registry", default-features = false } -assets = { package = "pallet-assets", path = '../../frame/assets', default-features = false } -crowdloan-rewards = { package = "pallet-crowdloan-rewards", path = '../../frame/crowdloan-rewards', default-features = false } +primitives = { path = "../primitives", default-features = false } vesting = { package = "pallet-vesting", path = "../../frame/vesting", default-features = false } -bonded-finance = { package = "pallet-bonded-finance", path = "../../frame/bonded-finance", default-features = false } # Used for the node template's RPCs -system-rpc-runtime-api = { package = "frame-system-rpc-runtime-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -transaction-payment-rpc-runtime-api = { package = "pallet-transaction-payment-rpc-runtime-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } +system-rpc-runtime-api = { package = "frame-system-rpc-runtime-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +transaction-payment-rpc-runtime-api = { package = "pallet-transaction-payment-rpc-runtime-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } + +# local RPCs +assets-runtime-api = { path = '../../frame/assets/runtime-api', default-features = false } +crowdloan-rewards-runtime-api = { path = '../../frame/crowdloan-rewards/runtime-api', default-features = false } # Used for runtime benchmarking -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false, optional = true } -system-benchmarking = { package = "frame-system-benchmarking", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false, optional = true } -hex-literal = { version = "0.3.1", optional = true } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ + "derive", +] } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false, optional = true } +hex-literal = { version = "0.3.3", optional = true } +system-benchmarking = { package = "frame-system-benchmarking", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false, optional = true } # Parachain Utilities -cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -collator-selection = { package = "pallet-collator-selection", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -session-benchmarking = { package = "cumulus-pallet-session-benchmarking", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } -polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +collator-selection = { package = "pallet-collator-selection", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } +session-benchmarking = { package = "cumulus-pallet-session-benchmarking", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false } # orml XCM support -orml-xtokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -orml-xcm-support = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } -orml-unknown-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "2b1c9fb367ccb8e13601b2da43d1c5d9737b93c6", default-features = false } +orml-unknown-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } +orml-xcm-support = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } +orml-xtokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "9e041dc9d213f843b18b3008f32f3acabb287dcb", default-features = false } # simnode support -simnode-apis = { package = "simnode-runtime-apis", git = "https://github.com/polytope-labs/substrate-simnode", default-features = false, branch = "master" } +simnode-apis = { package = "simnode-runtime-apis", git = "https://github.com/polytope-labs/substrate-simnode", default-features = false, branch = "master" } [build-dependencies] -substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } [features] -default = ["std"] +default = ["std", "wasm-builder"] +local-integration-tests = [] std = [ - "codec/std", - "sp-api/std", - "sp-std/std", - "sp-core/std", - "sp-runtime/std", - "sp-version/std", - "sp-offchain/std", - "sp-session/std", - "sp-block-builder/std", - "sp-transaction-pool/std", - "sp-inherents/std", - "frame-support/std", - "executive/std", - "frame-system/std", - "utility/std", - "authorship/std", - "balances/std", - "randomness-collective-flip/std", - "timestamp/std", - "session/std", - "sudo/std", - "indices/std", - "identity/std", - "multisig/std", - "call-filter/std", - "orml-tokens/std", - "orml-traits/std", - "treasury/std", - "democracy/std", - "scheduler/std", - "common/std", - "primitives/std", - "collective/std", - "transaction-payment/std", - "parachain-info/std", - "cumulus-pallet-aura-ext/std", - "cumulus-pallet-parachain-system/std", - "cumulus-pallet-xcmp-queue/std", - "cumulus-pallet-xcm/std", - "cumulus-primitives-core/std", - "cumulus-primitives-timestamp/std", - "cumulus-primitives-utility/std", - "collator-selection/std", - "xcm/std", - "xcm-builder/std", - "xcm-executor/std", - "aura/std", - "sp-consensus-aura/std", - "scale-info/std", - "orml-xtokens/std", - "orml-xcm-support/std", - "orml-unknown-tokens/std", - "composable-traits/std", - "governance-registry/std", - "currency-factory/std", - "assets/std", - "vesting/std", - "bonded-finance/std", - "crowdloan-rewards/std", - "preimage/std", - "membership/std", - "system-rpc-runtime-api/std", - "transaction-payment-rpc-runtime-api/std", - "simnode-apis/std" + "codec/std", + "sp-api/std", + "sp-std/std", + "sp-core/std", + "sp-runtime/std", + "sp-version/std", + "sp-offchain/std", + "sp-session/std", + "sp-block-builder/std", + "sp-transaction-pool/std", + "sp-inherents/std", + "frame-support/std", + "executive/std", + "frame-system/std", + "utility/std", + "authorship/std", + "balances/std", + "randomness-collective-flip/std", + "timestamp/std", + "session/std", + "sudo/std", + "indices/std", + "identity/std", + "multisig/std", + "call-filter/std", + "orml-tokens/std", + "orml-traits/std", + "treasury/std", + "democracy/std", + "scheduler/std", + "common/std", + "primitives/std", + "collective/std", + "transaction-payment/std", + "parachain-info/std", + "cumulus-pallet-aura-ext/std", + "cumulus-pallet-parachain-system/std", + "cumulus-pallet-xcmp-queue/std", + "cumulus-pallet-xcm/std", + "cumulus-primitives-core/std", + "cumulus-primitives-timestamp/std", + "cumulus-primitives-utility/std", + "collator-selection/std", + "xcm/std", + "xcm-builder/std", + "xcm-executor/std", + "aura/std", + "sp-consensus-aura/std", + "scale-info/std", + "orml-xtokens/std", + "orml-xcm-support/std", + "orml-unknown-tokens/std", + "composable-traits/std", + "composable-support/std", + "governance-registry/std", + "currency-factory/std", + "assets/std", + "assets-registry/std", + "vesting/std", + "bonded-finance/std", + "crowdloan-rewards/std", + "preimage/std", + "membership/std", + "system-rpc-runtime-api/std", + "transaction-payment-rpc-runtime-api/std", + "simnode-apis/std", ] +wasm-builder = [] runtime-benchmarks = [ - "balances/runtime-benchmarks", - "frame-benchmarking", - "frame-support/runtime-benchmarks", - "system-benchmarking", - "frame-system/runtime-benchmarks", - "hex-literal", - "balances/runtime-benchmarks", - "timestamp/runtime-benchmarks", - "collective/runtime-benchmarks", - "collator-selection/runtime-benchmarks", - "session-benchmarking/runtime-benchmarks", - "pallet-xcm/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "xcm-builder/runtime-benchmarks", - "indices/runtime-benchmarks", - "identity/runtime-benchmarks", - "multisig/runtime-benchmarks", - "membership/runtime-benchmarks", - "treasury/runtime-benchmarks", - "scheduler/runtime-benchmarks", - "collective/runtime-benchmarks", - "democracy/runtime-benchmarks", - "utility/runtime-benchmarks", - "crowdloan-rewards/runtime-benchmarks", - "currency-factory/runtime-benchmarks", - "assets/runtime-benchmarks", - "vesting/runtime-benchmarks", - "bonded-finance/runtime-benchmarks", + "balances/runtime-benchmarks", + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "system-benchmarking", + "frame-system/runtime-benchmarks", + "hex-literal", + "balances/runtime-benchmarks", + "timestamp/runtime-benchmarks", + "collective/runtime-benchmarks", + "collator-selection/runtime-benchmarks", + "session-benchmarking/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", + "indices/runtime-benchmarks", + "identity/runtime-benchmarks", + "multisig/runtime-benchmarks", + "membership/runtime-benchmarks", + "treasury/runtime-benchmarks", + "scheduler/runtime-benchmarks", + "collective/runtime-benchmarks", + "democracy/runtime-benchmarks", + "utility/runtime-benchmarks", + "crowdloan-rewards/runtime-benchmarks", + "currency-factory/runtime-benchmarks", + "assets/runtime-benchmarks", + "assets-registry/runtime-benchmarks", + "vesting/runtime-benchmarks", + "bonded-finance/runtime-benchmarks", + "common/runtime-benchmarks", ] -sim-node = [] diff --git a/runtime/picasso/build.rs b/runtime/picasso/build.rs index 9b53d2457df..110287eb065 100644 --- a/runtime/picasso/build.rs +++ b/runtime/picasso/build.rs @@ -1,9 +1,10 @@ -use substrate_wasm_builder::WasmBuilder; - fn main() { - WasmBuilder::new() - .with_current_project() - .export_heap_base() - .import_memory() - .build() + #[cfg(feature = "wasm-builder")] + { + substrate_wasm_builder::WasmBuilder::new() + .with_current_project() + .export_heap_base() + .import_memory() + .build() + } } diff --git a/runtime/picasso/src/lib.rs b/runtime/picasso/src/lib.rs index 557bcfac69e..298b8fb90cd 100644 --- a/runtime/picasso/src/lib.rs +++ b/runtime/picasso/src/lib.rs @@ -16,17 +16,20 @@ #![recursion_limit = "256"] // Make the WASM binary available. -#[cfg(feature = "std")] +#[cfg(all(feature = "std", feature = "wasm-builder"))] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); mod weights; mod xcmp; +pub use xcmp::{MaxInstructions, UnitWeightCost, XcmConfig}; + use common::{ impls::DealWithFees, AccountId, AccountIndex, Address, Amount, AuraId, Balance, BlockNumber, - CouncilInstance, EnsureRootOrHalfCouncil, Hash, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, - HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION, + BondOfferId, CouncilInstance, EnsureRootOrHalfCouncil, Hash, Moment, MultiExistentialDeposits, + NativeExistentialDeposit, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, + MAXIMUM_BLOCK_WEIGHT, MILLISECS_PER_BLOCK, NORMAL_DISPATCH_RATIO, SLOT_DURATION, }; -use orml_traits::parameter_type_with_key; + use primitives::currency::CurrencyId; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; @@ -37,6 +40,7 @@ use sp_runtime::{ ApplyExtrinsicResult, }; +use composable_support::rpc_helpers::SafeRpcWrapper; use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; @@ -55,7 +59,7 @@ pub use frame_support::{ }; use codec::Encode; -use frame_support::traits::{EqualPrivilegeOnly, OnRuntimeUpgrade}; +use frame_support::traits::{fungibles, EqualPrivilegeOnly, OnRuntimeUpgrade}; use frame_system as system; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; @@ -100,7 +104,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`, // `spec_version`, and `authoring_version` are the same between Wasm and native. spec_version: 1000, - impl_version: 4, + impl_version: 8, apis: RUNTIME_API_VERSIONS, transaction_version: 3, state_version: 0, @@ -198,6 +202,38 @@ impl system::Config for Runtime { impl randomness_collective_flip::Config for Runtime {} +parameter_types! { + pub NativeAssetId: CurrencyId = CurrencyId::PICA; +} + +impl assets_registry::Config for Runtime { + type Event = Event; + type LocalAssetId = CurrencyId; + type ForeignAssetId = CurrencyId; + type Location = composable_traits::assets::XcmAssetLocation; + type UpdateAdminOrigin = EnsureRootOrHalfCouncil; + type LocalAdminOrigin = assets_registry::EnsureLocalAdmin; + type ForeignAdminOrigin = assets_registry::EnsureForeignAdmin; +} + +impl assets::Config for Runtime { + type NativeAssetId = NativeAssetId; + type GenerateCurrencyId = CurrencyFactory; + type AssetId = CurrencyId; + type Balance = Balance; + type NativeCurrency = Balances; + type MultiCurrency = Tokens; + type WeightInfo = (); + type AdminOrigin = EnsureRootOrHalfCouncil; + type GovernanceRegistry = GovernanceRegistry; +} + +impl governance_registry::Config for Runtime { + type Event = Event; + type AssetId = CurrencyId; + type WeightInfo = (); +} + parameter_types! { // Maximum authorities/collators for aura pub const MaxAuthorities: u32 = 100; @@ -212,12 +248,12 @@ impl aura::Config for Runtime { impl cumulus_pallet_aura_ext::Config for Runtime {} parameter_types! { - pub BasicDeposit: Balance = 8 * CurrencyId::PICA.unit::(); - pub FieldDeposit: Balance = 256 * CurrencyId::PICA.milli::(); + pub BasicDeposit: Balance = 8 * CurrencyId::unit::(); + pub FieldDeposit: Balance = 256 * CurrencyId::milli::(); pub const MaxAdditionalFields: u32 = 32; pub const MaxRegistrars: u32 = 8; pub const MaxSubAccounts: u32 = 32; - pub SubAccountDeposit: Balance = 2 * CurrencyId::PICA.unit::(); + pub SubAccountDeposit: Balance = 2 * CurrencyId::unit::(); } impl identity::Config for Runtime { @@ -236,8 +272,8 @@ impl identity::Config for Runtime { } parameter_types! { - pub DepositBase: u64 = CurrencyId::PICA.unit(); - pub DepositFactor: u64 = 32 * CurrencyId::PICA.milli::(); + pub DepositBase: u64 = CurrencyId::unit(); + pub DepositFactor: u64 = 32 * CurrencyId::milli::(); pub const MaxSignatories: u16 = 5; } @@ -259,7 +295,7 @@ parameter_types! { impl timestamp::Config for Runtime { /// A timestamp: milliseconds since the Unix epoch. - type Moment = u64; + type Moment = Moment; /// What to do when SLOT_DURATION has passed? type OnTimestampSet = Aura; type MinimumPeriod = MinimumPeriod; @@ -267,9 +303,6 @@ impl timestamp::Config for Runtime { } parameter_types! { - /// Minimum amount an account has to hold to stay in state. - // minimum account balance is given as 0.1 PICA ~ 100 CurrencyId::PICA.milli() - pub ExistentialDeposit: Balance = 100 * CurrencyId::PICA.milli::(); /// Max locks that can be placed on an account. Capped for storage /// concerns. pub const MaxLocks: u32 = 50; @@ -284,14 +317,14 @@ impl balances::Config for Runtime { /// The ubiquitous event type. type Event = Event; type DustRemoval = Treasury; - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = NativeExistentialDeposit; type AccountStore = System; type WeightInfo = weights::balances::WeightInfo; } parameter_types! { /// 1 milli-pica/byte should be fine - pub TransactionByteFee: Balance = CurrencyId::PICA.milli(); + pub TransactionByteFee: Balance = CurrencyId::milli(); // The portion of the `NORMAL_DISPATCH_RATIO` that we adjust the fees with. Blocks filled less /// than this will decrease the weight and more will increase. @@ -312,7 +345,7 @@ pub struct WeightToFee; impl WeightToFeePolynomial for WeightToFee { type Balance = Balance; fn polynomial() -> WeightToFeeCoefficients { - let p = CurrencyId::PICA.milli::(); + let p = CurrencyId::milli::(); let q = 10 * Balance::from(ExtrinsicBaseWeight::get()); smallvec::smallvec![WeightToFeeCoefficient { degree: 1, @@ -340,7 +373,7 @@ impl sudo::Config for Runtime { parameter_types! { /// Deposit required to get an index. - pub IndexDeposit: Balance = 100 * CurrencyId::PICA.unit::(); + pub IndexDeposit: Balance = 100 * CurrencyId::unit::(); } impl indices::Config for Runtime { @@ -413,18 +446,6 @@ where type Extrinsic = UncheckedExtrinsic; } -//TODO set -parameter_types! { - pub const StakeLock: BlockNumber = 50; - pub const StalePrice: BlockNumber = 5; - - /// TODO: discuss with omar/cosmin - pub MinStake: Balance = 1000 * CurrencyId::PICA.unit::(); - pub const MaxAnswerBound: u32 = 25; - pub const MaxAssetsCount: u32 = 100_000; - pub const MaxHistory: u32 = 20; -} - // Parachain stuff. // See https://github.com/paritytech/cumulus/blob/polkadot-v0.9.8/polkadot-parachains/rococo/src/lib.rs for details. parameter_types! { @@ -504,13 +525,6 @@ impl collator_selection::Config for Runtime { type WeightInfo = weights::collator_selection::WeightInfo; } -parameter_type_with_key! { - // TODO: - pub ExistentialDeposits: |_currency_id: CurrencyId| -> Balance { - Zero::zero() - }; -} - pub struct DustRemovalWhitelist; impl Contains for DustRemovalWhitelist { fn contains(a: &AccountId) -> bool { @@ -530,7 +544,7 @@ impl orml_tokens::Config for Runtime { type Amount = Amount; type CurrencyId = CurrencyId; type WeightInfo = weights::tokens::WeightInfo; - type ExistentialDeposits = ExistentialDeposits; + type ExistentialDeposits = MultiExistentialDeposits; type OnDust = orml_tokens::TransferDust; type MaxLocks = MaxLocks; type DustRemovalWhitelist = DustRemovalWhitelist; @@ -538,11 +552,10 @@ impl orml_tokens::Config for Runtime { parameter_types! { pub const TreasuryPalletId: PalletId = PalletId(*b"picatrsy"); - /// percentage of proposal that most be bonded by the proposer + /// Percentage of proposal that most be bonded by the proposer. pub const ProposalBond: Permill = Permill::from_percent(5); - // TODO: rationale? - pub ProposalBondMinimum: Balance = 5 * CurrencyId::PICA.unit::(); - pub ProposalBondMaximum: Balance = 1000 * CurrencyId::PICA.unit::(); + pub ProposalBondMinimum: Balance = 5000 * CurrencyId::unit::(); + pub ProposalBondMaximum: Balance = 10000 * CurrencyId::unit::(); pub const SpendPeriod: BlockNumber = 7 * DAYS; pub const Burn: Permill = Permill::from_percent(0); @@ -564,7 +577,6 @@ impl treasury::Config for Runtime { type MaxApprovals = MaxApprovals; type BurnDestination = (); type WeightInfo = weights::treasury::WeightInfo; - // TODO: add bounties? type SpendFunds = (); } @@ -621,7 +633,7 @@ impl scheduler::Config for Runtime { parameter_types! { pub const PreimageMaxSize: u32 = 4096 * 1024; - pub PreimageBaseDeposit: Balance = 10 * CurrencyId::PICA.unit::(); + pub PreimageBaseDeposit: Balance = 10 * CurrencyId::unit::(); } impl preimage::Config for Runtime { @@ -646,11 +658,14 @@ parameter_types! { pub const VotingPeriod: BlockNumber = 5 * DAYS; pub const FastTrackVotingPeriod: BlockNumber = 3 * HOURS; - pub MinimumDeposit: Balance = 100 * CurrencyId::PICA.unit::(); + pub MinimumDeposit: Balance = 100 * CurrencyId::unit::(); pub const EnactmentPeriod: BlockNumber = 2 * DAYS; pub const CooloffPeriod: BlockNumber = 7 * DAYS; - // TODO: prod value - pub PreimageByteDeposit: Balance = CurrencyId::PICA.milli(); + + // Note that Kusama uses 10 millis, however KSM is significantly more expensive + // https://github.com/paritytech/polkadot/blob/dc784f9b47e4681897cfd477b4f0760330875a87/runtime/kusama/src/lib.rs#L237 + // so we increase it by a factor 10. This might still be on the low side. + pub PreimageByteDeposit: Balance = CurrencyId::milli::() * 100_u128; pub const InstantAllowed: bool = true; pub const MaxVotes: u32 = 100; pub const MaxProposals: u32 = 100; @@ -666,7 +681,6 @@ impl democracy::Config for Runtime { type VoteLockingPeriod = EnactmentPeriod; type MinimumDeposit = MinimumDeposit; - // TODO: prod values type ExternalOrigin = EnsureRootOrHalfCouncil; type ExternalMajorityOrigin = EnsureRootOrHalfCouncil; type ExternalDefaultOrigin = EnsureRootOrHalfCouncil; @@ -701,50 +715,32 @@ impl currency_factory::Config for Runtime { type WeightInfo = weights::currency_factory::WeightInfo; } -impl governance_registry::Config for Runtime { - type Event = Event; - type AssetId = CurrencyId; - type WeightInfo = (); -} - -parameter_types! { - pub NativeAssetId: CurrencyId = CurrencyId::PICA; -} - -impl assets::Config for Runtime { - type NativeAssetId = NativeAssetId; - type GenerateCurrencyId = CurrencyFactory; - type AssetId = CurrencyId; - type Balance = Balance; - type NativeCurrency = Balances; - type MultiCurrency = Tokens; - type WeightInfo = (); - type AdminOrigin = EnsureRootOrHalfCouncil; - type GovernanceRegistry = GovernanceRegistry; -} - parameter_types! { - pub const InitialPayment: Perbill = Perbill::from_percent(25); - pub const VestingStep: BlockNumber = 7 * DAYS; - pub const Prefix: &'static [u8] = b"picasso-"; + pub const CrowdloanRewardsId: PalletId = PalletId(*b"pal_crow"); + pub const InitialPayment: Perbill = Perbill::from_percent(25); + pub const VestingStep: Moment = (7 * DAYS as Moment) * MILLISECS_PER_BLOCK; + pub const Prefix: &'static [u8] = b"picasso-"; } impl crowdloan_rewards::Config for Runtime { type Event = Event; type Balance = Balance; - type Currency = Assets; + type RewardAsset = Assets; type AdminOrigin = EnsureRootOrHalfCouncil; type Convert = sp_runtime::traits::ConvertInto; - type RelayChainAccountId = [u8; 32]; + type RelayChainAccountId = sp_runtime::AccountId32; type InitialPayment = InitialPayment; type VestingStep = VestingStep; type Prefix = Prefix; type WeightInfo = weights::crowdloan_rewards::WeightInfo; + type PalletId = CrowdloanRewardsId; + type Moment = Moment; + type Time = Timestamp; } parameter_types! { pub const MaxVestingSchedule: u32 = 128; - pub MinVestedTransfer: u64 = CurrencyId::PICA.milli::(); + pub MinVestedTransfer: u64 = CurrencyId::milli::(); } impl vesting::Config for Runtime { @@ -752,19 +748,21 @@ impl vesting::Config for Runtime { type Event = Event; type MaxVestingSchedules = MaxVestingSchedule; type MinVestedTransfer = MinVestedTransfer; - type VestedTransferOrigin = system::EnsureSigned; - type WeightInfo = (); + type VestedTransferOrigin = EnsureRootOrHalfCouncil; + type WeightInfo = weights::vesting::WeightInfo; + type Moment = Moment; + type Time = Timestamp; } parameter_types! { pub const BondedFinanceId: PalletId = PalletId(*b"bondedfi"); - pub MinReward: Balance = 10 * CurrencyId::PICA.unit::(); - pub Stake: Balance = 10 * CurrencyId::PICA.unit::(); + pub MinReward: Balance = 10 * CurrencyId::unit::(); + pub Stake: Balance = 10 * CurrencyId::unit::(); } impl bonded_finance::Config for Runtime { - type AdminOrigin = EnsureRoot; - type BondOfferId = u64; + type AdminOrigin = EnsureRootOrHalfCouncil; + type BondOfferId = BondOfferId; type Convert = sp_runtime::traits::ConvertInto; type Currency = Assets; type Event = Event; @@ -773,6 +771,7 @@ impl bonded_finance::Config for Runtime { type PalletId = BondedFinanceId; type Stake = Stake; type Vesting = Vesting; + type WeightInfo = weights::bonded_finance::WeightInfo; } /// The calls we permit to be executed by extrinsics @@ -780,10 +779,7 @@ pub struct BaseCallFilter; impl Contains for BaseCallFilter { fn contains(call: &Call) -> bool { - !matches!( - call, - Call::Balances(_) | Call::Indices(_) | Call::Democracy(_) | Call::Treasury(_) - ) + !matches!(call, Call::Tokens(_) | Call::Indices(_) | Call::Democracy(_) | Call::Treasury(_)) } } @@ -829,6 +825,8 @@ construct_runtime!( RelayerXcm: pallet_xcm::{Pallet, Call, Event, Origin} = 41, CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event, Origin} = 42, DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event} = 43, + XTokens: orml_xtokens::{Pallet, Storage, Call, Event} = 44, + UnknownTokens: orml_unknown_tokens::{Pallet, Storage, Event} = 45, Tokens: orml_tokens::{Pallet, Call, Storage, Event} = 52, CurrencyFactory: currency_factory::{Pallet, Storage, Event} = 53, @@ -837,6 +835,7 @@ construct_runtime!( CrowdloanRewards: crowdloan_rewards::{Pallet, Call, Storage, Event, ValidateUnsigned} = 56, Vesting: vesting::{Call, Event, Pallet, Storage} = 57, BondedFinance: bonded_finance::{Call, Event, Pallet, Storage} = 58, + AssetsRegistry: assets_registry::{Pallet, Call, Storage, Event} = 59, } ); @@ -900,10 +899,28 @@ mod benches { [utility, Utility] [identity, Identity] [multisig, Multisig] + [currency_factory, CurrencyFactory] + [bonded_finance, BondedFinance] + [vesting, Vesting] ); } impl_runtime_apis! { + impl assets_runtime_api::AssetsRuntimeApi for Runtime { + fn balance_of(asset_id: SafeRpcWrapper, account_id: AccountId) -> SafeRpcWrapper /* Balance */ { + SafeRpcWrapper(>::balance(asset_id.0, &account_id)) + } + } + + impl crowdloan_rewards_runtime_api::CrowdloanRewardsRuntimeApi for Runtime { + fn amount_available_to_claim_for(account_id: AccountId) -> SafeRpcWrapper { + SafeRpcWrapper ( + crowdloan_rewards::amount_available_to_claim_for::(account_id) + .unwrap_or_else(|_| Balance::zero()) + ) + } + } + impl sp_api::Core for Runtime { fn version() -> RuntimeVersion { VERSION @@ -1010,7 +1027,7 @@ impl_runtime_apis! { } } - #[cfg(feature = "sim-node")] + impl simnode_apis::CreateTransactionApi for Runtime { fn create_transaction(call: Call, signer: AccountId) -> Vec { use sp_runtime::{ @@ -1029,7 +1046,7 @@ impl_runtime_apis! { system::CheckWeight::::new(), transaction_payment::ChargeTransactionPayment::::from(0), ); - let signature = MultiSignature::from(sr25519::Signature([0u8;64])); + let signature = MultiSignature::from(sr25519::Signature([0_u8;64])); let address = AccountIdLookup::unlookup(signer); let ext = UncheckedExtrinsic::new_signed(call, address, signature, extra); ext.encode() @@ -1048,21 +1065,7 @@ impl_runtime_apis! { use session_benchmarking::Pallet as SessionBench; let mut list = Vec::::new(); - - list_benchmark!(list, extra, frame_system, SystemBench::); - list_benchmark!(list, extra, balances, Balances); - list_benchmark!(list, extra, timestamp, Timestamp); - list_benchmark!(list, extra, collator_selection, CollatorSelection); - list_benchmark!(list, extra, indices, Indices); - list_benchmark!(list, extra, membership, CouncilMembership); - list_benchmark!(list, extra, treasury, Treasury); - list_benchmark!(list, extra, scheduler, Scheduler); - list_benchmark!(list, extra, democracy, Democracy); - list_benchmark!(list, extra, collective, Council); - list_benchmark!(list, extra, utility, Utility); - list_benchmark!(list, extra, identity, Identity); - list_benchmark!(list, extra, multisig, Multisig); - list_benchmark!(list, extra, currency_factory, CurrencyFactory); + list_benchmarks!(list, extra); let storage_info = AllPalletsWithSystem::storage_info(); @@ -1095,22 +1098,7 @@ impl_runtime_apis! { let mut batches = Vec::::new(); let params = (&config, &whitelist); - - add_benchmark!(params, batches, frame_system, SystemBench::); - add_benchmark!(params, batches, balances, Balances); - add_benchmark!(params, batches, timestamp, Timestamp); - add_benchmark!(params, batches, session, SessionBench::); - add_benchmark!(params, batches, collator_selection, CollatorSelection); - add_benchmark!(params, batches, indices, Indices); - add_benchmark!(params, batches, membership, CouncilMembership); - add_benchmark!(params, batches, treasury, Treasury); - add_benchmark!(params, batches, scheduler, Scheduler); - add_benchmark!(params, batches, democracy, Democracy); - add_benchmark!(params, batches, collective, Council); - add_benchmark!(params, batches, utility, Utility); - add_benchmark!(params, batches, identity, Identity); - add_benchmark!(params, batches, multisig, Multisig); - add_benchmark!(params, batches, currency_factory, CurrencyFactory); + add_benchmarks!(params, batches); if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) diff --git a/runtime/picasso/src/weights/balances.rs b/runtime/picasso/src/weights/balances.rs index 3a15529f9fb..7fe982a6e23 100644 --- a/runtime/picasso/src/weights/balances.rs +++ b/runtime/picasso/src/weights/balances.rs @@ -2,7 +2,7 @@ //! Autogenerated weights for `balances` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 1024 // Executed Command: @@ -15,7 +15,6 @@ // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/picasso/src/weights // --log // error @@ -32,43 +31,43 @@ pub struct WeightInfo(PhantomData); impl balances::WeightInfo for WeightInfo { // Storage: System Account (r:2 w:2) fn transfer() -> Weight { - (94_813_000 as Weight) + (99_919_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: System Account (r:1 w:1) fn transfer_keep_alive() -> Weight { - (59_109_000 as Weight) + (61_205_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn set_balance_creating() -> Weight { - (36_621_000 as Weight) + (37_506_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn set_balance_killing() -> Weight { - (42_567_000 as Weight) + (43_353_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:3 w:3) fn force_transfer() -> Weight { - (95_023_000 as Weight) + (99_659_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: System Account (r:1 w:1) fn transfer_all() -> Weight { - (70_629_000 as Weight) + (73_600_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: System Account (r:1 w:1) fn force_unreserve() -> Weight { - (32_951_000 as Weight) + (34_086_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } diff --git a/runtime/picasso/src/weights/bonded_finance.rs b/runtime/picasso/src/weights/bonded_finance.rs new file mode 100644 index 00000000000..f8909e7f0fb --- /dev/null +++ b/runtime/picasso/src/weights/bonded_finance.rs @@ -0,0 +1,58 @@ + +//! Autogenerated weights for `bonded_finance` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/composable +// benchmark +// --chain=picasso-dev +// --execution=wasm +// --wasm-execution=compiled +// --pallet=* +// --extrinsic=* +// --steps=50 +// --repeat=20 +// --output=runtime/picasso/src/weights +// --log +// error + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for `bonded_finance`. +pub struct WeightInfo(PhantomData); +impl bonded_finance::WeightInfo for WeightInfo { + // Storage: BondedFinance BondOfferCount (r:1 w:1) + // Storage: System Account (r:2 w:2) + // Storage: Tokens Accounts (r:2 w:2) + // Storage: BondedFinance BondOffers (r:0 w:1) + fn offer() -> Weight { + (125_980_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } + // Storage: BondedFinance BondOffers (r:1 w:1) + // Storage: Tokens Accounts (r:4 w:4) + // Storage: System Account (r:2 w:2) + // Storage: Vesting VestingSchedules (r:2 w:2) + // Storage: Tokens Locks (r:2 w:2) + fn bond() -> Weight { + (243_476_000 as Weight) + .saturating_add(T::DbWeight::get().reads(11 as Weight)) + .saturating_add(T::DbWeight::get().writes(11 as Weight)) + } + // Storage: BondedFinance BondOffers (r:1 w:1) + // Storage: System Account (r:2 w:2) + fn cancel() -> Weight { + (75_458_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } +} diff --git a/runtime/picasso/src/weights/collator_selection.rs b/runtime/picasso/src/weights/collator_selection.rs index ab5329ba51d..15222454f47 100644 --- a/runtime/picasso/src/weights/collator_selection.rs +++ b/runtime/picasso/src/weights/collator_selection.rs @@ -2,7 +2,7 @@ //! Autogenerated weights for `collator_selection` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 1024 // Executed Command: @@ -15,7 +15,6 @@ // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/picasso/src/weights // --log // error @@ -30,21 +29,23 @@ use sp_std::marker::PhantomData; /// Weight functions for `collator_selection`. pub struct WeightInfo(PhantomData); impl collator_selection::WeightInfo for WeightInfo { + // Storage: Session NextKeys (r:1 w:0) // Storage: CollatorSelection Invulnerables (r:0 w:1) fn set_invulnerables(b: u32, ) -> Weight { - (20_436_000 as Weight) - // Standard Error: 0 - .saturating_add((47_000 as Weight).saturating_mul(b as Weight)) + (18_819_000 as Weight) + // Standard Error: 7_000 + .saturating_add((7_030_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: CollatorSelection DesiredCandidates (r:0 w:1) fn set_desired_candidates() -> Weight { - (17_831_000 as Weight) + (19_006_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: CollatorSelection CandidacyBond (r:0 w:1) fn set_candidacy_bond() -> Weight { - (18_316_000 as Weight) + (19_482_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: CollatorSelection Candidates (r:1 w:1) @@ -54,18 +55,18 @@ impl collator_selection::WeightInfo for WeightInfo { // Storage: CollatorSelection CandidacyBond (r:1 w:0) // Storage: CollatorSelection LastAuthoredBlock (r:0 w:1) fn register_as_candidate(c: u32, ) -> Weight { - (110_744_000 as Weight) + (119_743_000 as Weight) // Standard Error: 2_000 - .saturating_add((314_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((308_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: CollatorSelection Candidates (r:1 w:1) // Storage: CollatorSelection LastAuthoredBlock (r:0 w:1) fn leave_intent(c: u32, ) -> Weight { - (127_036_000 as Weight) - // Standard Error: 3_000 - .saturating_add((364_000 as Weight).saturating_mul(c as Weight)) + (116_947_000 as Weight) + // Standard Error: 4_000 + .saturating_add((377_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -73,7 +74,7 @@ impl collator_selection::WeightInfo for WeightInfo { // Storage: System BlockWeight (r:1 w:1) // Storage: CollatorSelection LastAuthoredBlock (r:0 w:1) fn note_author() -> Weight { - (74_542_000 as Weight) + (74_201_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -84,10 +85,10 @@ impl collator_selection::WeightInfo for WeightInfo { // Storage: System BlockWeight (r:1 w:1) fn new_session(r: u32, c: u32, ) -> Weight { (0 as Weight) - // Standard Error: 5_821_000 - .saturating_add((29_576_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 5_821_000 - .saturating_add((153_392_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 5_555_000 + .saturating_add((28_383_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 5_555_000 + .saturating_add((146_699_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(c as Weight))) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(c as Weight))) diff --git a/runtime/picasso/src/weights/collective.rs b/runtime/picasso/src/weights/collective.rs index a81f06563c0..3fc1f0351db 100644 --- a/runtime/picasso/src/weights/collective.rs +++ b/runtime/picasso/src/weights/collective.rs @@ -2,7 +2,7 @@ //! Autogenerated weights for `collective` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 1024 // Executed Command: @@ -15,7 +15,6 @@ // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/picasso/src/weights // --log // error @@ -36,12 +35,12 @@ impl collective::WeightInfo for WeightInfo { // Storage: Council Prime (r:0 w:1) fn set_members(m: u32, n: u32, p: u32, ) -> Weight { (0 as Weight) - // Standard Error: 29_000 - .saturating_add((22_592_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 29_000 - .saturating_add((325_000 as Weight).saturating_mul(n as Weight)) - // Standard Error: 29_000 - .saturating_add((28_938_000 as Weight).saturating_mul(p as Weight)) + // Standard Error: 61_000 + .saturating_add((28_226_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 61_000 + .saturating_add((90_000 as Weight).saturating_mul(n as Weight)) + // Standard Error: 61_000 + .saturating_add((34_204_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(p as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -49,21 +48,21 @@ impl collective::WeightInfo for WeightInfo { } // Storage: Council Members (r:1 w:0) fn execute(b: u32, m: u32, ) -> Weight { - (27_052_000 as Weight) + (27_786_000 as Weight) // Standard Error: 0 - .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 0 - .saturating_add((123_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((128_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } // Storage: Council Members (r:1 w:0) // Storage: Council ProposalOf (r:1 w:0) fn propose_execute(b: u32, m: u32, ) -> Weight { - (31_493_000 as Weight) + (33_166_000 as Weight) // Standard Error: 0 .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 0 - .saturating_add((231_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((226_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) } // Storage: Council Members (r:1 w:0) @@ -72,22 +71,22 @@ impl collective::WeightInfo for WeightInfo { // Storage: Council ProposalCount (r:1 w:1) // Storage: Council Voting (r:0 w:1) fn propose_proposed(b: u32, m: u32, p: u32, ) -> Weight { - (38_032_000 as Weight) + (35_871_000 as Weight) // Standard Error: 0 - .saturating_add((14_000 as Weight).saturating_mul(b as Weight)) + .saturating_add((16_000 as Weight).saturating_mul(b as Weight)) // Standard Error: 3_000 - .saturating_add((142_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((156_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 3_000 - .saturating_add((549_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((558_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Council Members (r:1 w:0) // Storage: Council Voting (r:1 w:1) fn vote(m: u32, ) -> Weight { - (57_522_000 as Weight) - // Standard Error: 16_000 - .saturating_add((411_000 as Weight).saturating_mul(m as Weight)) + (61_881_000 as Weight) + // Standard Error: 4_000 + .saturating_add((307_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -96,11 +95,11 @@ impl collective::WeightInfo for WeightInfo { // Storage: Council Proposals (r:1 w:1) // Storage: Council ProposalOf (r:0 w:1) fn close_early_disapproved(m: u32, p: u32, ) -> Weight { - (52_599_000 as Weight) + (52_055_000 as Weight) // Standard Error: 3_000 - .saturating_add((256_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((271_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 3_000 - .saturating_add((438_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((430_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -109,13 +108,13 @@ impl collective::WeightInfo for WeightInfo { // Storage: Council ProposalOf (r:1 w:1) // Storage: Council Proposals (r:1 w:1) fn close_early_approved(b: u32, m: u32, p: u32, ) -> Weight { - (50_565_000 as Weight) - // Standard Error: 0 - .saturating_add((13_000 as Weight).saturating_mul(b as Weight)) - // Standard Error: 4_000 - .saturating_add((335_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 4_000 - .saturating_add((604_000 as Weight).saturating_mul(p as Weight)) + (43_965_000 as Weight) + // Standard Error: 2_000 + .saturating_add((21_000 as Weight).saturating_mul(b as Weight)) + // Standard Error: 18_000 + .saturating_add((307_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 17_000 + .saturating_add((689_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -125,11 +124,11 @@ impl collective::WeightInfo for WeightInfo { // Storage: Council Proposals (r:1 w:1) // Storage: Council ProposalOf (r:0 w:1) fn close_disapproved(m: u32, p: u32, ) -> Weight { - (54_270_000 as Weight) + (59_013_000 as Weight) // Standard Error: 3_000 - .saturating_add((297_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((260_000 as Weight).saturating_mul(m as Weight)) // Standard Error: 3_000 - .saturating_add((470_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((437_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -139,13 +138,13 @@ impl collective::WeightInfo for WeightInfo { // Storage: Council ProposalOf (r:1 w:1) // Storage: Council Proposals (r:1 w:1) fn close_approved(b: u32, m: u32, p: u32, ) -> Weight { - (43_694_000 as Weight) - // Standard Error: 1_000 - .saturating_add((17_000 as Weight).saturating_mul(b as Weight)) - // Standard Error: 15_000 - .saturating_add((430_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 15_000 - .saturating_add((639_000 as Weight).saturating_mul(p as Weight)) + (59_639_000 as Weight) + // Standard Error: 0 + .saturating_add((13_000 as Weight).saturating_mul(b as Weight)) + // Standard Error: 4_000 + .saturating_add((334_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 4_000 + .saturating_add((567_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -153,9 +152,9 @@ impl collective::WeightInfo for WeightInfo { // Storage: Council Voting (r:0 w:1) // Storage: Council ProposalOf (r:0 w:1) fn disapprove_proposal(p: u32, ) -> Weight { - (31_021_000 as Weight) + (33_523_000 as Weight) // Standard Error: 2_000 - .saturating_add((524_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((485_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } diff --git a/runtime/picasso/src/weights/currency_factory.rs b/runtime/picasso/src/weights/currency_factory.rs index 0b42664db7b..1990c7a1e27 100644 --- a/runtime/picasso/src/weights/currency_factory.rs +++ b/runtime/picasso/src/weights/currency_factory.rs @@ -2,8 +2,8 @@ //! Autogenerated weights for `currency_factory` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-04, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 128 +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 1024 // Executed Command: // ./target/release/composable @@ -15,7 +15,6 @@ // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/picasso/src/weights // --log // error @@ -32,7 +31,7 @@ pub struct WeightInfo(PhantomData); impl currency_factory::WeightInfo for WeightInfo { // Storage: CurrencyFactory AssetIdRanges (r:1 w:1) fn add_range() -> Weight { - (26_615_000 as Weight) + (24_209_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } diff --git a/runtime/picasso/src/weights/democracy.rs b/runtime/picasso/src/weights/democracy.rs index e322ae8c14d..22058ddb9f7 100644 --- a/runtime/picasso/src/weights/democracy.rs +++ b/runtime/picasso/src/weights/democracy.rs @@ -2,7 +2,7 @@ //! Autogenerated weights for `democracy` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 1024 // Executed Command: @@ -15,7 +15,6 @@ // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/picasso/src/weights // --log // error @@ -35,15 +34,15 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy Blacklist (r:1 w:0) // Storage: Democracy DepositOf (r:0 w:1) fn propose() -> Weight { - (92_756_000 as Weight) + (94_445_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy DepositOf (r:1 w:1) fn second(s: u32, ) -> Weight { - (54_466_000 as Weight) - // Standard Error: 4_000 - .saturating_add((335_000 as Weight).saturating_mul(s as Weight)) + (56_944_000 as Weight) + // Standard Error: 5_000 + .saturating_add((323_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -51,9 +50,9 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_new(r: u32, ) -> Weight { - (68_886_000 as Weight) + (73_158_000 as Weight) // Standard Error: 3_000 - .saturating_add((318_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((274_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -61,16 +60,16 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_existing(r: u32, ) -> Weight { - (69_280_000 as Weight) - // Standard Error: 4_000 - .saturating_add((317_000 as Weight).saturating_mul(r as Weight)) + (71_861_000 as Weight) + // Standard Error: 3_000 + .saturating_add((294_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy Cancellations (r:1 w:1) fn emergency_cancel() -> Weight { - (31_926_000 as Weight) + (33_738_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -81,45 +80,45 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:2 w:2) fn blacklist(p: u32, ) -> Weight { - (104_642_000 as Weight) - // Standard Error: 7_000 - .saturating_add((699_000 as Weight).saturating_mul(p as Weight)) + (109_180_000 as Weight) + // Standard Error: 8_000 + .saturating_add((720_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(7 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:0) fn external_propose(v: u32, ) -> Weight { - (16_407_000 as Weight) + (16_933_000 as Weight) // Standard Error: 0 - .saturating_add((123_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((121_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_majority() -> Weight { - (3_175_000 as Weight) + (3_441_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_default() -> Weight { - (3_267_000 as Weight) + (3_350_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:1) // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn fast_track() -> Weight { - (33_089_000 as Weight) + (34_665_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:1) fn veto_external(v: u32, ) -> Weight { - (34_791_000 as Weight) + (36_508_000 as Weight) // Standard Error: 1_000 - .saturating_add((156_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((152_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -127,23 +126,23 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:2 w:2) fn cancel_proposal(p: u32, ) -> Weight { - (78_252_000 as Weight) - // Standard Error: 4_000 - .saturating_add((668_000 as Weight).saturating_mul(p as Weight)) + (82_276_000 as Weight) + // Standard Error: 5_000 + .saturating_add((683_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn cancel_referendum() -> Weight { - (20_726_000 as Weight) + (21_514_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn cancel_queued(r: u32, ) -> Weight { - (40_892_000 as Weight) + (40_750_000 as Weight) // Standard Error: 5_000 - .saturating_add((1_921_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((2_482_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -151,9 +150,9 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy ReferendumCount (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:1 w:0) fn on_initialize_base(r: u32, ) -> Weight { - (4_031_000 as Weight) + (6_016_000 as Weight) // Standard Error: 7_000 - .saturating_add((7_096_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((6_816_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -165,9 +164,9 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy PublicProps (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:1 w:0) fn on_initialize_base_with_launch_period(r: u32, ) -> Weight { - (13_469_000 as Weight) + (15_091_000 as Weight) // Standard Error: 6_000 - .saturating_add((7_098_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((6_871_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -176,9 +175,9 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn delegate(r: u32, ) -> Weight { - (62_334_000 as Weight) - // Standard Error: 9_000 - .saturating_add((8_919_000 as Weight).saturating_mul(r as Weight)) + (66_498_000 as Weight) + // Standard Error: 11_000 + .saturating_add((9_061_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(4 as Weight)) @@ -187,9 +186,9 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy VotingOf (r:2 w:2) // Storage: Democracy ReferendumInfoOf (r:1 w:1) fn undelegate(r: u32, ) -> Weight { - (29_131_000 as Weight) - // Standard Error: 8_000 - .saturating_add((8_844_000 as Weight).saturating_mul(r as Weight)) + (33_060_000 as Weight) + // Standard Error: 11_000 + .saturating_add((9_000_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(r as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -197,12 +196,12 @@ impl democracy::WeightInfo for WeightInfo { } // Storage: Democracy PublicProps (r:0 w:1) fn clear_public_proposals() -> Weight { - (3_679_000 as Weight) + (3_740_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Democracy Preimages (r:1 w:1) fn note_preimage(b: u32, ) -> Weight { - (49_088_000 as Weight) + (51_403_000 as Weight) // Standard Error: 0 .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) @@ -210,7 +209,7 @@ impl democracy::WeightInfo for WeightInfo { } // Storage: Democracy Preimages (r:1 w:1) fn note_imminent_preimage(b: u32, ) -> Weight { - (34_519_000 as Weight) + (34_527_000 as Weight) // Standard Error: 0 .saturating_add((3_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) @@ -219,7 +218,7 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Democracy Preimages (r:1 w:1) // Storage: System Account (r:1 w:0) fn reap_preimage(b: u32, ) -> Weight { - (49_988_000 as Weight) + (51_480_000 as Weight) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) @@ -229,9 +228,9 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlock_remove(r: u32, ) -> Weight { - (44_735_000 as Weight) + (46_269_000 as Weight) // Standard Error: 2_000 - .saturating_add((130_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((161_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -239,27 +238,27 @@ impl democracy::WeightInfo for WeightInfo { // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) fn unlock_set(r: u32, ) -> Weight { - (42_581_000 as Weight) - // Standard Error: 3_000 - .saturating_add((262_000 as Weight).saturating_mul(r as Weight)) + (43_599_000 as Weight) + // Standard Error: 2_000 + .saturating_add((310_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) fn remove_vote(r: u32, ) -> Weight { - (24_407_000 as Weight) - // Standard Error: 2_000 - .saturating_add((234_000 as Weight).saturating_mul(r as Weight)) + (26_185_000 as Weight) + // Standard Error: 11_000 + .saturating_add((277_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) fn remove_other_vote(r: u32, ) -> Weight { - (24_891_000 as Weight) + (26_454_000 as Weight) // Standard Error: 2_000 - .saturating_add((230_000 as Weight).saturating_mul(r as Weight)) + .saturating_add((247_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } diff --git a/runtime/picasso/src/weights/frame_system.rs b/runtime/picasso/src/weights/frame_system.rs index 440cc284f62..e3266560850 100644 --- a/runtime/picasso/src/weights/frame_system.rs +++ b/runtime/picasso/src/weights/frame_system.rs @@ -2,7 +2,7 @@ //! Autogenerated weights for `frame_system` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 1024 // Executed Command: @@ -15,7 +15,6 @@ // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/picasso/src/weights // --log // error @@ -43,29 +42,29 @@ impl frame_system::WeightInfo for WeightInfo { // Storage: System Digest (r:1 w:1) // Storage: unknown [0x3a686561707061676573] (r:0 w:1) fn set_heap_pages() -> Weight { - (6_244_000 as Weight) + (6_526_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Skipped Metadata (r:0 w:0) fn set_storage(i: u32, ) -> Weight { (0 as Weight) - // Standard Error: 1_000 - .saturating_add((940_000 as Weight).saturating_mul(i as Weight)) + // Standard Error: 2_000 + .saturating_add((968_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn kill_storage(i: u32, ) -> Weight { (0 as Weight) // Standard Error: 1_000 - .saturating_add((669_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((649_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } // Storage: Skipped Metadata (r:0 w:0) fn kill_prefix(p: u32, ) -> Weight { (0 as Weight) - // Standard Error: 3_000 - .saturating_add((1_445_000 as Weight).saturating_mul(p as Weight)) + // Standard Error: 2_000 + .saturating_add((1_414_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(p as Weight))) } } diff --git a/runtime/picasso/src/weights/identity.rs b/runtime/picasso/src/weights/identity.rs index d460dcdbc67..9bf2a37c277 100644 --- a/runtime/picasso/src/weights/identity.rs +++ b/runtime/picasso/src/weights/identity.rs @@ -2,7 +2,7 @@ //! Autogenerated weights for `identity` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 1024 // Executed Command: @@ -15,7 +15,6 @@ // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/picasso/src/weights // --log // error @@ -32,19 +31,19 @@ pub struct WeightInfo(PhantomData); impl identity::WeightInfo for WeightInfo { // Storage: Identity Registrars (r:1 w:1) fn add_registrar(r: u32, ) -> Weight { - (25_684_000 as Weight) - // Standard Error: 26_000 - .saturating_add((642_000 as Weight).saturating_mul(r as Weight)) + (26_236_000 as Weight) + // Standard Error: 31_000 + .saturating_add((718_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity IdentityOf (r:1 w:1) fn set_identity(r: u32, x: u32, ) -> Weight { - (53_955_000 as Weight) - // Standard Error: 122_000 - .saturating_add((932_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 20_000 - .saturating_add((924_000 as Weight).saturating_mul(x as Weight)) + (56_091_000 as Weight) + // Standard Error: 125_000 + .saturating_add((1_004_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 21_000 + .saturating_add((1_017_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -52,9 +51,9 @@ impl identity::WeightInfo for WeightInfo { // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:1 w:1) fn set_subs_new(s: u32, ) -> Weight { - (48_507_000 as Weight) - // Standard Error: 21_000 - .saturating_add((6_969_000 as Weight).saturating_mul(s as Weight)) + (49_582_000 as Weight) + // Standard Error: 11_000 + .saturating_add((6_983_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -64,9 +63,9 @@ impl identity::WeightInfo for WeightInfo { // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:1) fn set_subs_old(p: u32, ) -> Weight { - (48_711_000 as Weight) + (50_800_000 as Weight) // Standard Error: 11_000 - .saturating_add((2_161_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((2_179_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(p as Weight))) @@ -75,13 +74,13 @@ impl identity::WeightInfo for WeightInfo { // Storage: Identity IdentityOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:32) fn clear_identity(r: u32, s: u32, x: u32, ) -> Weight { - (62_530_000 as Weight) - // Standard Error: 57_000 - .saturating_add((238_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 8_000 - .saturating_add((2_119_000 as Weight).saturating_mul(s as Weight)) - // Standard Error: 8_000 - .saturating_add((476_000 as Weight).saturating_mul(x as Weight)) + (63_094_000 as Weight) + // Standard Error: 74_000 + .saturating_add((489_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 11_000 + .saturating_add((2_165_000 as Weight).saturating_mul(s as Weight)) + // Standard Error: 11_000 + .saturating_add((450_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -89,56 +88,56 @@ impl identity::WeightInfo for WeightInfo { // Storage: Identity Registrars (r:1 w:0) // Storage: Identity IdentityOf (r:1 w:1) fn request_judgement(r: u32, x: u32, ) -> Weight { - (61_620_000 as Weight) - // Standard Error: 50_000 - .saturating_add((665_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 8_000 - .saturating_add((917_000 as Weight).saturating_mul(x as Weight)) + (61_926_000 as Weight) + // Standard Error: 69_000 + .saturating_add((978_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 11_000 + .saturating_add((969_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity IdentityOf (r:1 w:1) fn cancel_request(r: u32, x: u32, ) -> Weight { - (56_410_000 as Weight) - // Standard Error: 57_000 - .saturating_add((465_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 9_000 - .saturating_add((964_000 as Weight).saturating_mul(x as Weight)) + (59_531_000 as Weight) + // Standard Error: 37_000 + .saturating_add((343_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 6_000 + .saturating_add((955_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_fee(r: u32, ) -> Weight { - (10_342_000 as Weight) - // Standard Error: 32_000 - .saturating_add((436_000 as Weight).saturating_mul(r as Weight)) + (10_400_000 as Weight) + // Standard Error: 12_000 + .saturating_add((478_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_account_id(r: u32, ) -> Weight { - (10_287_000 as Weight) - // Standard Error: 23_000 - .saturating_add((443_000 as Weight).saturating_mul(r as Weight)) + (10_472_000 as Weight) + // Standard Error: 35_000 + .saturating_add((562_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:1) fn set_fields(r: u32, ) -> Weight { - (10_135_000 as Weight) - // Standard Error: 15_000 - .saturating_add((449_000 as Weight).saturating_mul(r as Weight)) + (11_058_000 as Weight) + // Standard Error: 29_000 + .saturating_add((364_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Identity Registrars (r:1 w:0) // Storage: Identity IdentityOf (r:1 w:1) fn provide_judgement(r: u32, x: u32, ) -> Weight { - (42_795_000 as Weight) - // Standard Error: 58_000 - .saturating_add((447_000 as Weight).saturating_mul(r as Weight)) + (42_008_000 as Weight) + // Standard Error: 62_000 + .saturating_add((786_000 as Weight).saturating_mul(r as Weight)) // Standard Error: 8_000 - .saturating_add((891_000 as Weight).saturating_mul(x as Weight)) + .saturating_add((925_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -147,13 +146,13 @@ impl identity::WeightInfo for WeightInfo { // Storage: System Account (r:2 w:2) // Storage: Identity SuperOf (r:0 w:32) fn kill_identity(r: u32, s: u32, x: u32, ) -> Weight { - (80_991_000 as Weight) - // Standard Error: 79_000 - .saturating_add((818_000 as Weight).saturating_mul(r as Weight)) - // Standard Error: 12_000 - .saturating_add((2_201_000 as Weight).saturating_mul(s as Weight)) - // Standard Error: 12_000 - .saturating_add((38_000 as Weight).saturating_mul(x as Weight)) + (85_049_000 as Weight) + // Standard Error: 110_000 + .saturating_add((679_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 16_000 + .saturating_add((2_243_000 as Weight).saturating_mul(s as Weight)) + // Standard Error: 16_000 + .saturating_add((91_000 as Weight).saturating_mul(x as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) @@ -162,18 +161,18 @@ impl identity::WeightInfo for WeightInfo { // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn add_sub(s: u32, ) -> Weight { - (65_477_000 as Weight) - // Standard Error: 13_000 - .saturating_add((330_000 as Weight).saturating_mul(s as Weight)) + (66_547_000 as Weight) + // Standard Error: 14_000 + .saturating_add((400_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Identity IdentityOf (r:1 w:0) // Storage: Identity SuperOf (r:1 w:1) fn rename_sub(s: u32, ) -> Weight { - (20_327_000 as Weight) - // Standard Error: 3_000 - .saturating_add((155_000 as Weight).saturating_mul(s as Weight)) + (20_920_000 as Weight) + // Standard Error: 4_000 + .saturating_add((134_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -181,18 +180,18 @@ impl identity::WeightInfo for WeightInfo { // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn remove_sub(s: u32, ) -> Weight { - (65_474_000 as Weight) + (67_930_000 as Weight) // Standard Error: 9_000 - .saturating_add((412_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((391_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) fn quit_sub(s: u32, ) -> Weight { - (42_609_000 as Weight) - // Standard Error: 8_000 - .saturating_add((388_000 as Weight).saturating_mul(s as Weight)) + (43_712_000 as Weight) + // Standard Error: 6_000 + .saturating_add((389_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } diff --git a/runtime/picasso/src/weights/indices.rs b/runtime/picasso/src/weights/indices.rs index 83f02c77d13..5c6b491874a 100644 --- a/runtime/picasso/src/weights/indices.rs +++ b/runtime/picasso/src/weights/indices.rs @@ -2,7 +2,7 @@ //! Autogenerated weights for `indices` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 1024 // Executed Command: @@ -15,7 +15,6 @@ // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/picasso/src/weights // --log // error @@ -32,33 +31,33 @@ pub struct WeightInfo(PhantomData); impl indices::WeightInfo for WeightInfo { // Storage: Indices Accounts (r:1 w:1) fn claim() -> Weight { - (45_502_000 as Weight) + (47_012_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - (56_220_000 as Weight) + (56_684_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Indices Accounts (r:1 w:1) fn free() -> Weight { - (46_938_000 as Weight) + (47_820_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn force_transfer() -> Weight { - (48_321_000 as Weight) + (49_226_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Indices Accounts (r:1 w:1) fn freeze() -> Weight { - (52_947_000 as Weight) + (55_388_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } diff --git a/runtime/picasso/src/weights/membership.rs b/runtime/picasso/src/weights/membership.rs index ac6273c343f..f156d1d0d62 100644 --- a/runtime/picasso/src/weights/membership.rs +++ b/runtime/picasso/src/weights/membership.rs @@ -2,7 +2,7 @@ //! Autogenerated weights for `membership` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 1024 // Executed Command: @@ -15,7 +15,6 @@ // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/picasso/src/weights // --log // error @@ -35,8 +34,8 @@ impl membership::WeightInfo for WeightInfo { // Storage: Council Members (r:0 w:1) // Storage: Council Prime (r:0 w:1) fn add_member(m: u32, ) -> Weight { - (27_522_000 as Weight) - // Standard Error: 10_000 + (29_396_000 as Weight) + // Standard Error: 12_000 .saturating_add((211_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -47,9 +46,9 @@ impl membership::WeightInfo for WeightInfo { // Storage: Council Members (r:0 w:1) // Storage: Council Prime (r:0 w:1) fn remove_member(m: u32, ) -> Weight { - (35_193_000 as Weight) - // Standard Error: 0 - .saturating_add((147_000 as Weight).saturating_mul(m as Weight)) + (23_036_000 as Weight) + // Standard Error: 15_000 + .saturating_add((599_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -58,10 +57,8 @@ impl membership::WeightInfo for WeightInfo { // Storage: CouncilMembership Prime (r:1 w:0) // Storage: Council Members (r:0 w:1) // Storage: Council Prime (r:0 w:1) - fn swap_member(m: u32, ) -> Weight { - (35_695_000 as Weight) - // Standard Error: 1_000 - .saturating_add((167_000 as Weight).saturating_mul(m as Weight)) + fn swap_member(_m: u32, ) -> Weight { + (96_285_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -71,9 +68,9 @@ impl membership::WeightInfo for WeightInfo { // Storage: Council Members (r:0 w:1) // Storage: Council Prime (r:0 w:1) fn reset_member(m: u32, ) -> Weight { - (35_796_000 as Weight) + (37_448_000 as Weight) // Standard Error: 1_000 - .saturating_add((338_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((358_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -83,9 +80,9 @@ impl membership::WeightInfo for WeightInfo { // Storage: Council Members (r:0 w:1) // Storage: Council Prime (r:0 w:1) fn change_key(m: u32, ) -> Weight { - (37_050_000 as Weight) - // Standard Error: 1_000 - .saturating_add((166_000 as Weight).saturating_mul(m as Weight)) + (38_958_000 as Weight) + // Standard Error: 0 + .saturating_add((164_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -93,16 +90,16 @@ impl membership::WeightInfo for WeightInfo { // Storage: CouncilMembership Prime (r:0 w:1) // Storage: Council Prime (r:0 w:1) fn set_prime(m: u32, ) -> Weight { - (9_442_000 as Weight) + (10_546_000 as Weight) // Standard Error: 0 - .saturating_add((120_000 as Weight).saturating_mul(m as Weight)) + .saturating_add((113_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: CouncilMembership Prime (r:0 w:1) // Storage: Council Prime (r:0 w:1) fn clear_prime(m: u32, ) -> Weight { - (3_475_000 as Weight) + (3_788_000 as Weight) // Standard Error: 0 .saturating_add((3_000 as Weight).saturating_mul(m as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) diff --git a/runtime/picasso/src/weights/mod.rs b/runtime/picasso/src/weights/mod.rs index 5c107a73168..f07ab4e00a0 100644 --- a/runtime/picasso/src/weights/mod.rs +++ b/runtime/picasso/src/weights/mod.rs @@ -1,5 +1,6 @@ #![allow(clippy::unnecessary_cast)] pub mod balances; +pub mod bonded_finance; pub mod collator_selection; pub mod collective; pub mod crowdloan_rewards; @@ -16,3 +17,4 @@ pub mod timestamp; pub mod tokens; pub mod treasury; pub mod utility; +pub mod vesting; diff --git a/runtime/picasso/src/weights/multisig.rs b/runtime/picasso/src/weights/multisig.rs index 3b2590f4b3e..05943258f05 100644 --- a/runtime/picasso/src/weights/multisig.rs +++ b/runtime/picasso/src/weights/multisig.rs @@ -2,7 +2,7 @@ //! Autogenerated weights for `multisig` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 1024 // Executed Command: @@ -15,7 +15,6 @@ // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/picasso/src/weights // --log // error @@ -31,16 +30,16 @@ use sp_std::marker::PhantomData; pub struct WeightInfo(PhantomData); impl multisig::WeightInfo for WeightInfo { fn as_multi_threshold_1(z: u32, ) -> Weight { - (6_361_000 as Weight) + (7_277_000 as Weight) // Standard Error: 0 .saturating_add((1_000 as Weight).saturating_mul(z as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) fn as_multi_create(s: u32, z: u32, ) -> Weight { - (60_843_000 as Weight) - // Standard Error: 153_000 - .saturating_add((43_000 as Weight).saturating_mul(s as Weight)) + (64_171_000 as Weight) + // Standard Error: 172_000 + .saturating_add((294_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(z as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) @@ -50,9 +49,9 @@ impl multisig::WeightInfo for WeightInfo { // Storage: Multisig Calls (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) fn as_multi_create_store(s: u32, z: u32, ) -> Weight { - (57_024_000 as Weight) - // Standard Error: 290_000 - .saturating_add((2_298_000 as Weight).saturating_mul(s as Weight)) + (67_099_000 as Weight) + // Standard Error: 189_000 + .saturating_add((969_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 .saturating_add((3_000 as Weight).saturating_mul(z as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) @@ -60,9 +59,9 @@ impl multisig::WeightInfo for WeightInfo { } // Storage: Multisig Multisigs (r:1 w:1) fn as_multi_approve(s: u32, z: u32, ) -> Weight { - (34_048_000 as Weight) - // Standard Error: 139_000 - .saturating_add((817_000 as Weight).saturating_mul(s as Weight)) + (40_275_000 as Weight) + // Standard Error: 153_000 + .saturating_add((101_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 .saturating_add((2_000 as Weight).saturating_mul(z as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) @@ -71,9 +70,9 @@ impl multisig::WeightInfo for WeightInfo { // Storage: Multisig Multisigs (r:1 w:1) // Storage: Multisig Calls (r:1 w:1) fn as_multi_approve_store(s: u32, z: u32, ) -> Weight { - (62_731_000 as Weight) - // Standard Error: 256_000 - .saturating_add((471_000 as Weight).saturating_mul(s as Weight)) + (60_977_000 as Weight) + // Standard Error: 192_000 + .saturating_add((1_391_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 .saturating_add((3_000 as Weight).saturating_mul(z as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) @@ -83,9 +82,9 @@ impl multisig::WeightInfo for WeightInfo { // Storage: Multisig Calls (r:1 w:1) // Storage: System Account (r:1 w:1) fn as_multi_complete(s: u32, z: u32, ) -> Weight { - (77_775_000 as Weight) - // Standard Error: 177_000 - .saturating_add((733_000 as Weight).saturating_mul(s as Weight)) + (80_154_000 as Weight) + // Standard Error: 164_000 + .saturating_add((1_033_000 as Weight).saturating_mul(s as Weight)) // Standard Error: 0 .saturating_add((4_000 as Weight).saturating_mul(z as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) @@ -94,16 +93,16 @@ impl multisig::WeightInfo for WeightInfo { // Storage: Multisig Multisigs (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) fn approve_as_multi_create(s: u32, ) -> Weight { - (56_877_000 as Weight) - // Standard Error: 287_000 - .saturating_add((1_125_000 as Weight).saturating_mul(s as Weight)) + (58_975_000 as Weight) + // Standard Error: 267_000 + .saturating_add((1_186_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: Multisig Calls (r:1 w:0) fn approve_as_multi_approve(_s: u32, ) -> Weight { - (42_458_000 as Weight) + (41_034_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -111,16 +110,18 @@ impl multisig::WeightInfo for WeightInfo { // Storage: Multisig Calls (r:1 w:1) // Storage: System Account (r:1 w:1) fn approve_as_multi_complete(s: u32, ) -> Weight { - (113_465_000 as Weight) - // Standard Error: 219_000 - .saturating_add((107_000 as Weight).saturating_mul(s as Weight)) + (110_970_000 as Weight) + // Standard Error: 183_000 + .saturating_add((1_159_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: Multisig Calls (r:1 w:1) - fn cancel_as_multi(_s: u32, ) -> Weight { - (95_997_000 as Weight) + fn cancel_as_multi(s: u32, ) -> Weight { + (95_207_000 as Weight) + // Standard Error: 321_000 + .saturating_add((45_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } diff --git a/runtime/picasso/src/weights/scheduler.rs b/runtime/picasso/src/weights/scheduler.rs index 499fb5aff49..ae22d762e05 100644 --- a/runtime/picasso/src/weights/scheduler.rs +++ b/runtime/picasso/src/weights/scheduler.rs @@ -2,7 +2,7 @@ //! Autogenerated weights for `scheduler` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 1024 // Executed Command: @@ -15,7 +15,6 @@ // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/picasso/src/weights // --log // error @@ -35,9 +34,9 @@ impl scheduler::WeightInfo for WeightInfo { // Storage: Preimage StatusFor (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_periodic_named_resolved(s: u32, ) -> Weight { - (12_447_000 as Weight) - // Standard Error: 37_000 - .saturating_add((45_215_000 as Weight).saturating_mul(s as Weight)) + (27_002_000 as Weight) + // Standard Error: 132_000 + .saturating_add((49_444_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -48,9 +47,9 @@ impl scheduler::WeightInfo for WeightInfo { // Storage: Preimage StatusFor (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_named_resolved(s: u32, ) -> Weight { - (8_652_000 as Weight) - // Standard Error: 33_000 - .saturating_add((35_256_000 as Weight).saturating_mul(s as Weight)) + (14_406_000 as Weight) + // Standard Error: 64_000 + .saturating_add((38_476_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -60,9 +59,9 @@ impl scheduler::WeightInfo for WeightInfo { // Storage: Preimage PreimageFor (r:1 w:1) // Storage: Preimage StatusFor (r:1 w:1) fn on_initialize_periodic_resolved(s: u32, ) -> Weight { - (14_999_000 as Weight) - // Standard Error: 31_000 - .saturating_add((38_613_000 as Weight).saturating_mul(s as Weight)) + (13_020_000 as Weight) + // Standard Error: 44_000 + .saturating_add((42_106_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -72,9 +71,9 @@ impl scheduler::WeightInfo for WeightInfo { // Storage: Preimage PreimageFor (r:1 w:1) // Storage: Preimage StatusFor (r:1 w:1) fn on_initialize_resolved(s: u32, ) -> Weight { - (9_598_000 as Weight) - // Standard Error: 30_000 - .saturating_add((32_457_000 as Weight).saturating_mul(s as Weight)) + (18_774_000 as Weight) + // Standard Error: 62_000 + .saturating_add((35_547_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -84,9 +83,9 @@ impl scheduler::WeightInfo for WeightInfo { // Storage: Preimage PreimageFor (r:1 w:0) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_named_aborted(s: u32, ) -> Weight { - (10_638_000 as Weight) - // Standard Error: 15_000 - .saturating_add((14_786_000 as Weight).saturating_mul(s as Weight)) + (15_446_000 as Weight) + // Standard Error: 27_000 + .saturating_add((16_581_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -95,9 +94,9 @@ impl scheduler::WeightInfo for WeightInfo { // Storage: Scheduler Agenda (r:2 w:2) // Storage: Preimage PreimageFor (r:1 w:0) fn on_initialize_aborted(s: u32, ) -> Weight { - (13_481_000 as Weight) - // Standard Error: 11_000 - .saturating_add((8_839_000 as Weight).saturating_mul(s as Weight)) + (14_890_000 as Weight) + // Standard Error: 18_000 + .saturating_add((10_489_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -105,9 +104,9 @@ impl scheduler::WeightInfo for WeightInfo { // Storage: Scheduler Agenda (r:2 w:2) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_periodic_named(s: u32, ) -> Weight { - (26_494_000 as Weight) - // Standard Error: 24_000 - .saturating_add((22_605_000 as Weight).saturating_mul(s as Weight)) + (25_650_000 as Weight) + // Standard Error: 22_000 + .saturating_add((25_012_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -115,9 +114,9 @@ impl scheduler::WeightInfo for WeightInfo { } // Storage: Scheduler Agenda (r:2 w:2) fn on_initialize_periodic(s: u32, ) -> Weight { - (22_001_000 as Weight) - // Standard Error: 19_000 - .saturating_add((16_562_000 as Weight).saturating_mul(s as Weight)) + (22_091_000 as Weight) + // Standard Error: 17_000 + .saturating_add((18_920_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(s as Weight))) .saturating_add(T::DbWeight::get().writes(1 as Weight)) @@ -126,53 +125,53 @@ impl scheduler::WeightInfo for WeightInfo { // Storage: Scheduler Agenda (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn on_initialize_named(s: u32, ) -> Weight { - (22_592_000 as Weight) - // Standard Error: 13_000 - .saturating_add((13_041_000 as Weight).saturating_mul(s as Weight)) + (24_294_000 as Weight) + // Standard Error: 18_000 + .saturating_add((15_139_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(s as Weight))) } // Storage: Scheduler Agenda (r:1 w:1) fn on_initialize(s: u32, ) -> Weight { - (22_344_000 as Weight) - // Standard Error: 11_000 - .saturating_add((10_551_000 as Weight).saturating_mul(s as Weight)) + (23_910_000 as Weight) + // Standard Error: 14_000 + .saturating_add((12_583_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Agenda (r:1 w:1) fn schedule(s: u32, ) -> Weight { - (30_303_000 as Weight) - // Standard Error: 2_000 - .saturating_add((165_000 as Weight).saturating_mul(s as Weight)) + (32_787_000 as Weight) + // Standard Error: 3_000 + .saturating_add((160_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Scheduler Agenda (r:1 w:1) // Storage: Scheduler Lookup (r:0 w:1) fn cancel(s: u32, ) -> Weight { - (29_502_000 as Weight) - // Standard Error: 5_000 - .saturating_add((1_800_000 as Weight).saturating_mul(s as Weight)) + (32_617_000 as Weight) + // Standard Error: 6_000 + .saturating_add((2_357_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn schedule_named(s: u32, ) -> Weight { - (37_595_000 as Weight) - // Standard Error: 3_000 - .saturating_add((163_000 as Weight).saturating_mul(s as Weight)) + (40_606_000 as Weight) + // Standard Error: 5_000 + .saturating_add((194_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn cancel_named(s: u32, ) -> Weight { - (33_665_000 as Weight) + (36_077_000 as Weight) // Standard Error: 6_000 - .saturating_add((1_849_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((2_341_000 as Weight).saturating_mul(s as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } diff --git a/runtime/picasso/src/weights/session.rs b/runtime/picasso/src/weights/session.rs index 16aae9c6328..b320014717a 100644 --- a/runtime/picasso/src/weights/session.rs +++ b/runtime/picasso/src/weights/session.rs @@ -2,7 +2,7 @@ //! Autogenerated weights for `session` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 1024 // Executed Command: @@ -15,7 +15,6 @@ // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/picasso/src/weights // --log // error @@ -33,14 +32,14 @@ impl session::WeightInfo for WeightInfo { // Storage: Session NextKeys (r:1 w:1) // Storage: Session KeyOwner (r:1 w:1) fn set_keys() -> Weight { - (28_811_000 as Weight) + (29_757_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Session NextKeys (r:1 w:1) // Storage: Session KeyOwner (r:0 w:1) fn purge_keys() -> Weight { - (22_372_000 as Weight) + (22_186_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } diff --git a/runtime/picasso/src/weights/timestamp.rs b/runtime/picasso/src/weights/timestamp.rs index c6a8faf1e49..e050f30adbc 100644 --- a/runtime/picasso/src/weights/timestamp.rs +++ b/runtime/picasso/src/weights/timestamp.rs @@ -2,7 +2,7 @@ //! Autogenerated weights for `timestamp` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 1024 // Executed Command: @@ -15,7 +15,6 @@ // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/picasso/src/weights // --log // error @@ -33,11 +32,11 @@ impl timestamp::WeightInfo for WeightInfo { // Storage: Timestamp Now (r:1 w:1) // Storage: Aura CurrentSlot (r:1 w:0) fn set() -> Weight { - (12_076_000 as Weight) + (12_406_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn on_finalize() -> Weight { - (5_615_000 as Weight) + (5_704_000 as Weight) } } diff --git a/runtime/picasso/src/weights/treasury.rs b/runtime/picasso/src/weights/treasury.rs index d8dac7a731b..bc20602ce0a 100644 --- a/runtime/picasso/src/weights/treasury.rs +++ b/runtime/picasso/src/weights/treasury.rs @@ -2,7 +2,7 @@ //! Autogenerated weights for `treasury` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 1024 // Executed Command: @@ -15,7 +15,6 @@ // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/picasso/src/weights // --log // error @@ -33,23 +32,23 @@ impl treasury::WeightInfo for WeightInfo { // Storage: Treasury ProposalCount (r:1 w:1) // Storage: Treasury Proposals (r:0 w:1) fn propose_spend() -> Weight { - (47_387_000 as Weight) + (48_863_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Treasury Proposals (r:1 w:1) // Storage: System Account (r:2 w:2) fn reject_proposal() -> Weight { - (71_185_000 as Weight) + (74_877_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } // Storage: Treasury Proposals (r:1 w:0) // Storage: Treasury Approvals (r:1 w:1) fn approve_proposal(p: u32, ) -> Weight { - (14_625_000 as Weight) - // Standard Error: 5_000 - .saturating_add((287_000 as Weight).saturating_mul(p as Weight)) + (15_893_000 as Weight) + // Standard Error: 4_000 + .saturating_add((293_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -57,9 +56,9 @@ impl treasury::WeightInfo for WeightInfo { // Storage: Treasury Approvals (r:1 w:1) // Storage: Treasury Proposals (r:1 w:1) fn on_initialize_proposals(p: u32, ) -> Weight { - (70_168_000 as Weight) - // Standard Error: 77_000 - .saturating_add((64_197_000 as Weight).saturating_mul(p as Weight)) + (70_313_000 as Weight) + // Standard Error: 74_000 + .saturating_add((67_592_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((3 as Weight).saturating_mul(p as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) diff --git a/runtime/picasso/src/weights/utility.rs b/runtime/picasso/src/weights/utility.rs index 3bca0b5275b..02efcb53b74 100644 --- a/runtime/picasso/src/weights/utility.rs +++ b/runtime/picasso/src/weights/utility.rs @@ -2,7 +2,7 @@ //! Autogenerated weights for `utility` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-02-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 1024 // Executed Command: @@ -15,7 +15,6 @@ // --extrinsic=* // --steps=50 // --repeat=20 -// --raw // --output=runtime/picasso/src/weights // --log // error @@ -31,19 +30,19 @@ use sp_std::marker::PhantomData; pub struct WeightInfo(PhantomData); impl utility::WeightInfo for WeightInfo { fn batch(c: u32, ) -> Weight { - (24_854_000 as Weight) - // Standard Error: 2_000 - .saturating_add((6_041_000 as Weight).saturating_mul(c as Weight)) + (2_950_000 as Weight) + // Standard Error: 10_000 + .saturating_add((7_284_000 as Weight).saturating_mul(c as Weight)) } fn as_derivative() -> Weight { - (4_388_000 as Weight) + (5_337_000 as Weight) } fn batch_all(c: u32, ) -> Weight { - (28_234_000 as Weight) + (24_251_000 as Weight) // Standard Error: 3_000 - .saturating_add((6_627_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((7_615_000 as Weight).saturating_mul(c as Weight)) } fn dispatch_as() -> Weight { - (19_225_000 as Weight) + (20_356_000 as Weight) } } diff --git a/runtime/picasso/src/weights/vesting.rs b/runtime/picasso/src/weights/vesting.rs new file mode 100644 index 00000000000..09834f9a2b6 --- /dev/null +++ b/runtime/picasso/src/weights/vesting.rs @@ -0,0 +1,75 @@ + +//! Autogenerated weights for `vesting` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-03-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("picasso-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/composable +// benchmark +// --chain=picasso-dev +// --execution=wasm +// --wasm-execution=compiled +// --pallet=* +// --extrinsic=* +// --steps=50 +// --repeat=20 +// --output=runtime/picasso/src/weights +// --log +// error + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for `vesting`. +pub struct WeightInfo(PhantomData); +impl vesting::WeightInfo for WeightInfo { + // Storage: Vesting VestingSchedules (r:1 w:1) + // Storage: Tokens Locks (r:1 w:1) + // Storage: Tokens Accounts (r:1 w:1) + // Storage: Timestamp Now (r:1 w:0) + fn claim(s: u32, ) -> Weight { + (56_327_000 as Weight) + // Standard Error: 44_000 + .saturating_add((2_653_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + // Storage: Vesting VestingSchedules (r:1 w:1) + // Storage: Tokens Accounts (r:2 w:2) + // Storage: System Account (r:2 w:1) + // Storage: Tokens Locks (r:1 w:1) + fn vested_transfer() -> Weight { + (106_114_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) + } + // Storage: Tokens Locks (r:1 w:1) + // Storage: Tokens Accounts (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Vesting VestingSchedules (r:0 w:1) + fn update_vesting_schedules(s: u32, ) -> Weight { + (58_329_000 as Weight) + // Standard Error: 2_000 + .saturating_add((145_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) + } + // Storage: Vesting VestingSchedules (r:1 w:1) + // Storage: Tokens Locks (r:1 w:1) + // Storage: Tokens Accounts (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Timestamp Now (r:1 w:0) + fn claim_for(s: u32, ) -> Weight { + (58_590_000 as Weight) + // Standard Error: 4_000 + .saturating_add((2_226_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } +} diff --git a/runtime/picasso/src/xcmp.rs b/runtime/picasso/src/xcmp.rs index 4c33b24b41c..0a35c833bad 100644 --- a/runtime/picasso/src/xcmp.rs +++ b/runtime/picasso/src/xcmp.rs @@ -1,80 +1,74 @@ //! Setup of XCMP for parachain to allow cross chain transfers and other operations. //! Very similar to https://github.com/galacticcouncil/Basilisk-node/blob/master/runtime/basilisk/src/xcm.rs #![allow(unused_imports)] // allow until v2 xcm released (instead creating 2 runtimes) - use super::*; // recursive dependency onto runtime - use codec::{Decode, Encode}; -use composable_traits::assets::{RemoteAssetRegistry, XcmAssetLocation}; -use cumulus_primitives_core::ParaId; +use common::xcmp::*; +use composable_traits::{ + assets::{RemoteAssetRegistry, XcmAssetLocation}, + defi::Ratio, + oracle::MinimalOracle, +}; +use cumulus_primitives_core::{IsSystem, ParaId}; use frame_support::{ - construct_runtime, log, match_type, parameter_types, - traits::{Contains, Everything, KeyOwnerProofSystem, Nothing, Randomness, StorageInfo}, + construct_runtime, ensure, log, match_type, parameter_types, + traits::{ + Contains, Everything, KeyOwnerProofSystem, Nothing, OriginTrait, Randomness, StorageInfo, + }, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, DispatchClass, IdentityFee, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }, - PalletId, + PalletId, RuntimeDebug, }; - -use orml_xcm_support::{IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset}; - +use orml_traits::{location::Reserve, parameter_type_with_key, MultiCurrency}; +use orml_xcm_support::{ + DepositToAlternative, IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset, OnDepositFail, +}; +use pallet_xcm::XcmPassthrough; +use polkadot_parachain::primitives::Sibling; +use primitives::currency::WellKnownCurrency; +use sp_api::impl_runtime_apis; +use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ traits::{AccountIdLookup, BlakeTwo256, Convert, ConvertInto, Zero}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, + ApplyExtrinsicResult, DispatchError, }; - -use orml_traits::parameter_type_with_key; -use sp_api::impl_runtime_apis; -use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; - -use pallet_xcm::XcmPassthrough; -use polkadot_parachain::primitives::Sibling; -use sp_std::prelude::*; +use sp_std::{marker::PhantomData, prelude::*}; use xcm::latest::{prelude::*, Error}; use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, - AllowTopLevelPaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, LocationInverter, - ParentIsDefault, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, + LocationInverter, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, + SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeRevenue, TakeWeightCredit, }; use xcm_executor::{ - traits::{TransactAsset, WeightTrader}, + traits::{ + ConvertOrigin, DropAssets, FilterAssetLocation, ShouldExecute, TransactAsset, WeightTrader, + }, Assets, Config, XcmExecutor, }; - parameter_types! { - // pub const RelayLocation: MultiLocation = MultiLocation::X1(Junction::Parent); + pub KsmLocation: MultiLocation = MultiLocation::parent(); pub const RelayNetwork: NetworkId = NetworkId::Kusama; pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into(); pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into(); } -// here we should add any partner network for zero cost transactions -match_type! { - pub type SpecParachain: impl Contains = { - MultiLocation { parents: 1, interior: X1(Parachain(2000)) } | - MultiLocation { parents: 1, interior: X1(Parachain(3000)) } - }; -} - pub type Barrier = ( - TakeWeightCredit, - AllowTopLevelPaidExecutionFrom, - xcm_builder::AllowUnpaidExecutionFrom, + XcmpDebug, + //DebugAllowUnpaidExecutionFrom, // Expected responses are OK. AllowKnownQueryResponses, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, + TakeWeightCredit, ); -/// No local origins on this chain are allowed to dispatch XCM sends/executions. -/// https://medium.com/kusama-network/kusamas-governance-thwarts-would-be-attacker-9023180f6fb -#[cfg(not(feature = "develop"))] -pub type LocalOriginToLocation = (); -#[cfg(feature = "develop")] pub type LocalOriginToLocation = SignedToAccountId32; /// The means for routing XCM messages which are not for local execution into the right message @@ -90,8 +84,8 @@ pub type XcmRouter = ( /// when determining ownership of accounts for asset transacting and when attempting to use XCM /// `Transact` in order to determine the dispatch Origin. pub type LocationToAccountId = ( - // The parent (Relay-chain) origin converts to the default `AccountId`. - ParentIsDefault, + // The parent (Relay-chain) origin converts to the parent `AccountId`. + ParentIsPreset, // Sibling parachain origins convert to AccountId via the `ParaId::into`. SiblingParachainConvertsVia, // Straight up local `AccountId32` origins just alias directly to `AccountId`. @@ -122,193 +116,189 @@ pub type XcmOriginToTransactDispatchOrigin = ( XcmPassthrough, ); -#[cfg(feature = "develop")] +pub struct StaticAssetsMap; + +pub mod parachains { + pub mod karura { + pub const ID: u32 = 3000; + pub const KUSD_KEY: &[u8] = &[0, 129]; + } +} + +impl XcmpAssets for StaticAssetsMap { + fn remote_to_local(location: MultiLocation) -> Option { + match location { + MultiLocation { parents: 1, interior: X2(Parachain(para_id), GeneralKey(key)) } => + match (para_id, &key[..]) { + (parachains::karura::ID, parachains::karura::KUSD_KEY) => + Some(CurrencyId::kUSD), + _ => None, + }, + _ => None, + } + } +} + pub type LocalAssetTransactor = MultiCurrencyAdapter< crate::Assets, UnknownTokens, - IsNativeConcrete, + IsNativeConcrete, AccountId, LocationToAccountId, CurrencyId, - CurrencyIdConvert, + AssetsIdConverter, + DepositToAlternative, >; -parameter_types! { - pub const BaseXcmWeight: Weight = 0; - pub const MaxInstructions: u32 = 10_000; -} +pub struct PriceConverter; + +impl MinimalOracle for PriceConverter { + type AssetId = CurrencyId; -#[cfg(feature = "develop")] -pub struct TradePassthrough(); + type Balance = Balance; -/// any payment to pass -#[cfg(feature = "develop")] -impl WeightTrader for TradePassthrough { - fn new() -> Self { - Self() + fn get_price_inverse( + asset_id: Self::AssetId, + amount: Self::Balance, + ) -> Result { + match asset_id { + CurrencyId::PICA => Ok(amount), + CurrencyId::KSM => Ok(amount / 10), + CurrencyId::kUSD => Ok(amount / 10), + _ => Err(DispatchError::Other("cannot pay with given weight")), + } } +} +pub struct RelayReserveFromParachain; +impl FilterAssetLocation for RelayReserveFromParachain { + fn filter_asset_location(asset: &MultiAsset, origin: &MultiLocation) -> bool { + // NOTE: In Acala there is not such thing + // if asset is KSM and send from some parachain then allow for that + asset.reserve() == Some(MultiLocation::parent()) && + matches!(origin, MultiLocation { parents: 1, interior: X1(Parachain(_)) }) + } +} - fn buy_weight(&mut self, _weight: Weight, payment: Assets) -> Result { - // Just let it through for now - Ok(payment) +type IsReserveAssetLocationFilter = + (DebugMultiNativeAsset, MultiNativeAsset, RelayReserveFromParachain); + +type AssetsIdConverter = + CurrencyIdConvert; + +pub type Trader = TransactionFeePoolTrader< + AssetsIdConverter, + PriceConverter, + ToTreasury, + WeightToFee, +>; + +pub struct CaptureDropAssets< + Treasury: TakeRevenue, + PriceConverter: MinimalOracle, + AssetConverter: Convert>, +>(PhantomData<(Treasury, PriceConverter, AssetConverter)>); + +/// if asset put into Holding Registry of XCM VM, but did nothing to this +/// or if too small to pay weight, +/// it will get here +/// if asset location and origin is known, put into treasury, +/// else if asset location and origin not know, hash it until it will be added +impl< + Treasury: TakeRevenue, + PriceConverter: MinimalOracle, + AssetConverter: Convert>, + > DropAssets for CaptureDropAssets +{ + fn drop_assets(origin: &MultiLocation, assets: Assets) -> Weight { + let multi_assets: Vec = assets.into(); + let mut can_return_on_request = vec![]; + log::info!(target : "xcmp", "drop_assets"); + let mut weight = Weight::zero(); + for asset in multi_assets { + if let MultiAsset { id: Concrete(location), fun: Fungible(_amount) } = asset.clone() { + if let Some(_converted) = AssetConverter::convert(location) { + Treasury::take_revenue(asset); + } else { + can_return_on_request.push(asset); + } + } else { + can_return_on_request.push(asset); + } + } + if !can_return_on_request.is_empty() { + weight += RelayerXcm::drop_assets(origin, can_return_on_request.into()); + } + weight } } +pub type CaptureAssetTrap = CaptureDropAssets< + ToTreasury, + PriceConverter, + AssetsIdConverter, +>; + pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { type Call = Call; type XcmSender = XcmRouter; - - #[cfg(not(feature = "develop"))] - type AssetTransactor = (); - // How to withdraw and deposit an asset. - #[cfg(feature = "develop")] type AssetTransactor = LocalAssetTransactor; - type OriginConverter = XcmOriginToTransactDispatchOrigin; - type IsReserve = MultiNativeAsset; + type IsReserve = IsReserveAssetLocationFilter; type IsTeleporter = (); // <- should be enough to allow teleportation of PICA type LocationInverter = LocationInverter; type Barrier = Barrier; - type Weigher = FixedWeightBounds; - - #[cfg(not(feature = "develop"))] - type Trader = (); - #[cfg(feature = "develop")] - type Trader = TradePassthrough; + type Weigher = FixedWeightBounds; - #[cfg(not(feature = "develop"))] - type ResponseHandler = (); - #[cfg(feature = "develop")] + type Trader = Trader; type ResponseHandler = RelayerXcm; type SubscriptionService = RelayerXcm; type AssetClaims = RelayerXcm; - type AssetTrap = RelayerXcm; + type AssetTrap = CaptureAssetTrap; } parameter_types! { pub SelfLocation: MultiLocation = MultiLocation::new(1, X1(Parachain(ParachainInfo::parachain_id().into()))); + // safe value to start to transfer 1 asset only in one message (as in Acala) + pub const MaxAssetsForTransfer: usize = 1; +} + +parameter_type_with_key! { + pub ParachainMinFee: |location: MultiLocation| -> u128 { + #[allow(clippy::match_ref_pats)] // false positive + match (location.parents, location.first_interior()) { + // (1, Some(Parachain(2))) => 40, + _ => 0, + } + }; } -#[cfg(feature = "develop")] impl orml_xtokens::Config for Runtime { type Event = Event; type Balance = Balance; type CurrencyId = CurrencyId; - type CurrencyIdConvert = CurrencyIdConvert; + type CurrencyIdConvert = AssetsIdConverter; type AccountIdToMultiLocation = AccountIdToMultiLocation; type SelfLocation = SelfLocation; type XcmExecutor = XcmExecutor; - type Weigher = FixedWeightBounds; + type Weigher = FixedWeightBounds; type BaseXcmWeight = BaseXcmWeight; type LocationInverter = LocationInverter; + type MaxAssetsForTransfer = MaxAssetsForTransfer; + type MinXcmFee = ParachainMinFee; } -#[cfg(feature = "develop")] impl orml_unknown_tokens::Config for Runtime { type Event = Event; } -pub struct AccountIdToMultiLocation; -impl Convert for AccountIdToMultiLocation { - fn convert(account: AccountId) -> MultiLocation { - X1(AccountId32 { network: NetworkId::Any, id: account.into() }).into() - } -} - -/// Converts currency to and from local and remote -#[cfg(feature = "develop")] -pub struct CurrencyIdConvert; - -/// converts local currency into remote, -/// native currency is built in -#[cfg(feature = "develop")] -impl sp_runtime::traits::Convert> for CurrencyIdConvert { - fn convert(id: CurrencyId) -> Option { - match id { - CurrencyId::INVALID => { - log::trace!( - "mapping for {:?} on {:?} parachain not found", - id, - ParachainInfo::parachain_id() - ); - None - }, - CurrencyId::PICA => Some(MultiLocation::new( - 1, - X2(Parachain(ParachainInfo::parachain_id().into()), GeneralKey(id.encode())), - )), - _ => { - if let Some(location) = - ::asset_to_location(id).map(Into::into) - { - Some(location) - } else { - log::trace!( - "mapping for {:?} on {:?} parachain not found", - id, - ParachainInfo::parachain_id() - ); - None - } - }, - } - } -} - -/// converts from Relay parent chain to child chain currency -/// expected that currency in location is in format well known for local chain -#[cfg(feature = "develop")] -impl Convert> for CurrencyIdConvert { - fn convert(location: MultiLocation) -> Option { - log::trace!("converting {:?} on {:?}", &location, ParachainInfo::parachain_id()); - match location { - MultiLocation { parents, interior: X2(Parachain(id), GeneralKey(key)) } - if parents == 1 && ParaId::from(id) == ParachainInfo::parachain_id() => - { - // Handling native asset for this parachain - if let Ok(currency_id) = CurrencyId::decode(&mut &key[..]) { - // we currently have only one native asset - match currency_id { - CurrencyId::PICA => Some(CurrencyId::PICA), - _ => { - log::error!("failed converting currency"); - None - }, - } - } else { - log::error!("failed converting currency"); - None - } - }, - // delegate to asset-registry - _ => { - let result = ::location_to_asset( - XcmAssetLocation(location), - ) - .map(Into::into); - if result.is_none() { - log::error!("failed converting currency"); - } - result - }, - } - } -} - -/// covert remote to local, usually when receiving transfer -#[cfg(feature = "develop")] -impl Convert> for CurrencyIdConvert { - fn convert(asset: MultiAsset) -> Option { - log::trace!("converting {:?}", &asset); - if let MultiAsset { id: Concrete(location), .. } = asset { - Self::convert(location) - } else { - log::error!("failed to find remote asset"); - None - } - } +// make setup as in Acala, max instructions seems resoanble, for weigth may consider to settle with +// our PICA +parameter_types! { + // One XCM operation is 200_000_000 weight, cross-chain transfer ~= 2x of transfer. + pub const UnitWeightCost: Weight = 200_000_000; + pub const MaxInstructions: u32 = 100; } impl pallet_xcm::Config for Runtime { @@ -317,15 +307,12 @@ impl pallet_xcm::Config for Runtime { type XcmRouter = XcmRouter; type ExecuteXcmOrigin = EnsureXcmOrigin; /// https://medium.com/kusama-network/kusamas-governance-thwarts-would-be-attacker-9023180f6fb - #[cfg(not(feature = "develop"))] type XcmExecuteFilter = Nothing; - #[cfg(feature = "develop")] - type XcmExecuteFilter = Everything; type XcmExecutor = XcmExecutor; type XcmTeleportFilter = Everything; type XcmReserveTransferFilter = Everything; type LocationInverter = LocationInverter; - type Weigher = FixedWeightBounds; + type Weigher = FixedWeightBounds; type Origin = Origin; type Call = Call; @@ -333,21 +320,47 @@ impl pallet_xcm::Config for Runtime { type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; } +/// cumulus is defaultt implementation of queue integrated with polkadot and kusama runtimes impl cumulus_pallet_xcm::Config for Runtime { type Event = Event; type XcmExecutor = XcmExecutor; } +pub struct SystemParachainAsSuperuser(PhantomData); +impl ConvertOrigin for SystemParachainAsSuperuser { + fn convert_origin( + origin: impl Into, + kind: OriginKind, + ) -> Result { + let origin = origin.into(); + if kind == OriginKind::Superuser && + matches!( + origin, + MultiLocation { + parents: 1, + interior: X1(Parachain(id)), + } if ParaId::from(id).is_system(), + ) { + Ok(Origin::root()) + } else { + Err(origin) + } + } +} + impl cumulus_pallet_xcmp_queue::Config for Runtime { type Event = Event; type XcmExecutor = XcmExecutor; type VersionWrapper = (); type ChannelInfo = ParachainSystem; - type ExecuteOverweightOrigin = EnsureRoot; + type ControllerOrigin = EnsureRootOrHalfCouncil; + type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; + // NOTE: we could consider allowance for some chains (see Acala tests ports PRs) + type ExecuteOverweightOrigin = EnsureRootOrHalfCouncil; } impl cumulus_pallet_dmp_queue::Config for Runtime { type Event = Event; type XcmExecutor = XcmExecutor; - type ExecuteOverweightOrigin = system::EnsureRoot; + type ExecuteOverweightOrigin = EnsureRootOrHalfCouncil; } diff --git a/runtime/primitives/Cargo.toml b/runtime/primitives/Cargo.toml index aeecb175f42..1a45fd83238 100644 --- a/runtime/primitives/Cargo.toml +++ b/runtime/primitives/Cargo.toml @@ -1,31 +1,35 @@ [package] -name = "primitives" -version = "0.1.0" authors = ["Composable Developers "] edition = "2021" +name = "primitives" +version = "0.1.0" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ + "derive", +] } +composable-support = { path = "../../frame/composable-support", default-features = false } +composable-traits = { path = "../../frame/composable-traits", default-features = false } +scale-info = { version = "1.0", default-features = false, features = [ + "derive", +] } serde = { version = '1.0.130', features = ['derive'], optional = true } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16", default-features = false } -composable-traits = { path = "../../frame/composable-traits", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16", default-features = false, optional = true} +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17", default-features = false } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17", default-features = false, optional = true } [features] default = ["std"] +develop = ["xcm"] std = [ - "serde", - "codec/std", - "sp-runtime/std", - "composable-traits/std", - "scale-info/std", -] -develop = [ - "xcm" + "serde", + "codec/std", + "sp-runtime/std", + "composable-traits/std", + "composable-support/std", + "scale-info/std", ] diff --git a/runtime/primitives/src/currency.rs b/runtime/primitives/src/currency.rs index 6d2e0f5115c..f88ea71d346 100644 --- a/runtime/primitives/src/currency.rs +++ b/runtime/primitives/src/currency.rs @@ -5,10 +5,24 @@ use core::ops::Div; use scale_info::TypeInfo; use sp_runtime::RuntimeDebug; +use composable_support::rpc_helpers::FromHexStr; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_runtime::sp_std::ops::Deref; +/// Trait used to write generalized code over well know currencies +/// We use const to allow for match on these +/// Allows to have reuse of code amids runtime and cross relay transfers in future. +// TODO: split CurrenyId for runtimes - one for DOT and one for KSM +pub trait WellKnownCurrency { + // works well with pattnrs unlike impl trait `associated consts cannot be referenced in + // patterns` + const NATIVE: Self; + /// usually we expect running with relay, + /// but if not, than degenrative case would be this equal to `NATIVE` + const RELAY_NATIVE: Self; +} + #[derive( Encode, Decode, @@ -27,22 +41,47 @@ use sp_runtime::sp_std::ops::Deref; #[repr(transparent)] pub struct CurrencyId(pub u128); +impl WellKnownCurrency for CurrencyId { + const NATIVE: CurrencyId = CurrencyId::PICA; + const RELAY_NATIVE: CurrencyId = CurrencyId::KSM; +} + impl CurrencyId { pub const INVALID: CurrencyId = CurrencyId(0); pub const PICA: CurrencyId = CurrencyId(1); pub const LAYR: CurrencyId = CurrencyId(2); pub const CROWD_LOAN: CurrencyId = CurrencyId(3); + + /// Kusama native token pub const KSM: CurrencyId = CurrencyId(4); + /// Karura stable coin(Karura Dollar), not native. + #[allow(non_upper_case_globals)] + pub const kUSD: CurrencyId = CurrencyId(129); + #[inline(always)] - pub fn decimals(&self) -> Exponent { + pub const fn decimals() -> Exponent { 12 } - pub fn unit>(&self) -> T { - T::from(10_u64.pow(self.decimals())) + pub fn unit>() -> T { + T::from(10_u64.pow(Self::decimals())) + } + pub fn milli + Div>() -> T { + Self::unit::() / T::from(1000_u64) } - pub fn milli + Div>(&self) -> T { - self.unit::() / T::from(1000_u64) +} + +impl FromHexStr for CurrencyId { + type Err = ::Err; + + fn from_hex_str(src: &str) -> core::result::Result { + u128::from_hex_str(src).map(CurrencyId) + } +} + +impl core::fmt::LowerHex for CurrencyId { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + core::fmt::LowerHex::fmt(&self.0, f) } } diff --git a/rustfmt.toml b/rustfmt.toml index 441913f619c..8b3be5e7d98 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -11,13 +11,13 @@ newline_style = "Unix" comment_width = 100 wrap_comments = true # Misc -chain_width = 80 -spaces_around_ranges = false binop_separator = "Back" -reorder_impl_items = false -match_arm_leading_pipes = "Preserve" +chain_width = 80 match_arm_blocks = false +match_arm_leading_pipes = "Preserve" match_block_trailing_comma = true +reorder_impl_items = false +spaces_around_ranges = false trailing_comma = "Vertical" trailing_semicolon = false use_field_init_shorthand = true diff --git a/scripts/polkadot-launch/README.md b/scripts/polkadot-launch/README.md index 582559f5112..29af90645f9 100644 --- a/scripts/polkadot-launch/README.md +++ b/scripts/polkadot-launch/README.md @@ -12,16 +12,12 @@ Need to do to run 4 relay chain nodes and 1 Composable's collator: cd "$old_pwd" ``` -2. build a Polkadot Relay Chain +2. download a Polkadot Relay Chain ```bash - old_pwd=$(pwd) - cd ../../.. - git clone -b v0.9.16 https://github.com/paritytech/polkadot - cd polkadot - cargo build --release - target/release/polkadot --version - cd "$old_pwd" + mkdir -p ../../../polkadot/target/release + curl https://github.com/paritytech/polkadot/releases/download/v0.9.17/polkadot -Lo ../../../polkadot/target/release/polkadot + ../../../polkadot/target/release/polkadot -- version ``` 3. build this project @@ -47,35 +43,28 @@ Need to do to run 4 relay chain nodes, 2 Composable's collators and 2 Basilisk's 1. build a Composable's collator ```bash - old_pwd=$(pwd) - cd ../.. - cargo build --release - target/release/composable --version - cd "$old_pwd" - ``` + ( + cd ../.. + cargo build --release + target/release/composable --version + ) + ``` -2. build a Polkadot Relay Chain +2. download a Polkadot Relay Chain ```bash - old_pwd=$(pwd) - cd ../../.. - git clone -b v0.9.16 https://github.com/paritytech/polkadot - cd polkadot - cargo build --release - target/release/polkadot --version - cd "$old_pwd" + mkdir -p ../../../polkadot/target/release + curl https://github.com/paritytech/polkadot/releases/download/v0.9.17/polkadot -Lo ../../../polkadot/target/release/polkadot + ../../../polkadot/target/release/polkadot -- version ``` -3. build a Basilisk's collator +3. download a Basilisk's collator ```bash - old_pwd=$(pwd) - cd ../../.. - git clone -b v5.0.3 https://github.com/galacticcouncil/Basilisk-node.git - cd Basilisk-node - cargo build --release - target/release/basilisk --version - cd "$old_pwd" + mkdir -p ../../../Basilisk-node/target/release + curl https://github.com/galacticcouncil/Basilisk-node/releases/download/v7.0.0/basilisk -Lo ../../../Basilisk-node/target/release/basilisk + chmod +x ../../../Basilisk-node/target/release/basilisk + ../../../Basilisk-node/target/release/basilisk --version ``` 4. build this project @@ -90,7 +79,15 @@ Need to do to run 4 relay chain nodes, 2 Composable's collators and 2 Basilisk's yarn composable_and_basilisk ``` + +## Run Kusama relay + Dali parachain + Hydra paracahin in Docker via Polka launcher + +Build via `sandbox docker` job in Actions into latest and git hash. + +``` +cargo make start-devnet-docker +``` URLs: -* `https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A9945#/explorer` is the 1st Relay Chain node -* `https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A9988#/explorer` is the 1st Composable's collator -* `https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A9998#/explorer` is the 1st Basilisk's collator +* [Relay]https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A9944#/explorer) is the 1st Relay Chain node +* [Composable Dali](https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A9988#/explorer) is the 1st Composable's collator +* [Basilisk](https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A9998#/explorer) is the 1st Basilisk's collator diff --git a/scripts/polkadot-launch/composable.json b/scripts/polkadot-launch/composable.json index 2d2212c599a..650ddc6fdac 100644 --- a/scripts/polkadot-launch/composable.json +++ b/scripts/polkadot-launch/composable.json @@ -8,7 +8,7 @@ "wsPort": 9944, "basePath": "/tmp/polkadot-launch/relaychains/alice", "port": 30444, - "flags": ["--beefy"] + "flags": ["--rpc-cors=all", "--beefy", "--enable-offchain-indexing=true"] }, { "name": "bob", @@ -38,19 +38,7 @@ "port": 30778, "flags": ["--beefy"] } - ], - "genesis": { - "runtime": { - "runtime_genesis_config": { - "configuration": { - "config": { - "validation_upgrade_frequency": 1, - "validation_upgrade_delay": 1 - } - } - } - } - } + ] }, "parachains": [ { diff --git a/scripts/polkadot-launch/composable_and_basilisk.json b/scripts/polkadot-launch/composable_and_basilisk.json index 7446ee7fccd..ee50152209c 100644 --- a/scripts/polkadot-launch/composable_and_basilisk.json +++ b/scripts/polkadot-launch/composable_and_basilisk.json @@ -7,32 +7,40 @@ "name": "alice", "wsPort": 9944, "port": 30444, - "flags": ["--rpc-cors=all"] + "flags": ["--rpc-cors=all", "--beefy", "--enable-offchain-indexing=true"] }, { "name": "bob", "wsPort": 9955, "port": 30555, - "flags": ["--rpc-cors=all"] + "flags": ["--rpc-cors=all", "--beefy"] }, { "name": "charlie", "wsPort": 9966, "port": 30666, - "flags": ["--rpc-cors=all"] + "flags": ["--rpc-cors=all", "--beefy"] }, { "name": "dave", "wsPort": 9977, "port": 30777, - "flags": ["--rpc-cors=all"] + "flags": ["--rpc-cors=all", "--beefy"] + }, + { + "name": "ferdie", + "wsPort": 9978, + "basePath": "/tmp/polkadot-launch/relaychains/ferdie", + "port": 30778, + "flags": ["--rpc-cors=all", "--beefy"] } + ], "runtime_genesis_config": { "parachainsConfiguration": { "config": { "validation_upgrade_frequency": 1, - "validation_upgrade_delay": 1 + "validation_upgrade_delay": 10 } } } @@ -58,7 +66,6 @@ }, { "bin": "../../../Basilisk-node/target/release/basilisk", - "id": "200", "chain":"local", "balance": "1000000000000000000000", "nodes": [ @@ -77,14 +84,14 @@ ], "hrmpChannels": [ { - "sender": 200, - "recipient": 2000, + "sender": 2000, + "recipient": 2090, "maxCapacity": 8, "maxMessageSize": 512 }, { - "sender": 2000, - "recipient": 200, + "sender": 2090, + "recipient": 2000, "maxCapacity": 8, "maxMessageSize": 512 } diff --git a/scripts/polkadot-launch/initialization/config/config.json b/scripts/polkadot-launch/initialization/config/config.json index f9100645d22..0ac63866572 100644 --- a/scripts/polkadot-launch/initialization/config/config.json +++ b/scripts/polkadot-launch/initialization/config/config.json @@ -1,11 +1,11 @@ { "assets": [ - {"name": "USDT", "composable_id": 1, "basilisk_id": 1}, - {"name": "BTC", "composable_id": 2, "basilisk_id": 2} + {"name": "USDT", "composable_id": 1, "basilisk_id": 1, "decimals": 12}, + {"name": "BTC", "composable_id": 2, "basilisk_id": 2, "descimals": 12} ], "basilisk_collator_url": "ws://127.0.0.1:9998", "composable_collator_url": "ws://127.0.0.1:9988", - "basilisk_para_id": 200, + "basilisk_para_id": 2090, "composable_para_id": 2000 } diff --git a/scripts/polkadot-launch/initialization/src/index.ts b/scripts/polkadot-launch/initialization/src/index.ts index 37a0b61003f..b420f6d2600 100644 --- a/scripts/polkadot-launch/initialization/src/index.ts +++ b/scripts/polkadot-launch/initialization/src/index.ts @@ -16,6 +16,7 @@ interface IAsset { name: string; composable_id: number; basilisk_id: number; + decimals: number; } async function main() { @@ -105,7 +106,7 @@ async function doComposableAssetsMapping( await sleep(1000); } - for (const { name, composable_id } of assets) { + for (const { name, composable_id, basilisk_id, decimals } of assets) { const basiliskAssetIdOpt = await basiliskApi.query.assetRegistry .assetIds(name); const basiliskAssetId: AssetId | null = basiliskAssetIdOpt.unwrapOr(null); @@ -124,17 +125,19 @@ async function doComposableAssetsMapping( { parents: 0, interior: junctionsV2 }, ); await composableApi.tx.assetsRegistry - .approveAssetsMappingCandidate(composable_id, location) + .approveAssetsMappingCandidate(composable_id, basilisk_id, location, decimals) .signAndSend(localAdmin, { nonce: -1 }, ({ status }: ISubmittableResult) => { if (status.isInBlock) { - console.log(`Current status of approveAssetsMappingCandidate(${composable_id}, ${location}) is ${status}`); + let function_call = `approveAssetsMappingCandidate(${composable_id}, ${basilisk_id}, ${location}, ${decimals})`; + console.log(`Current status of ${function_call} is ${status}`); } }); await composableApi.tx.assetsRegistry - .approveAssetsMappingCandidate(composable_id, location) + .approveAssetsMappingCandidate(composable_id, basilisk_id, location, decimals) .signAndSend(foreignAdmin, { nonce: -1 }, ({ status }: ISubmittableResult) => { if (status.isInBlock) { - console.log(`Current status of approveAssetsMappingCandidate(${composable_id}, ${location}) is ${status}`); + let function_call = `approveAssetsMappingCandidate(${composable_id}, ${basilisk_id}, ${location}, ${decimals})`; + console.log(`Current status of ${function_call} is ${status}`); } }); } diff --git a/scripts/polkadot-launch/initialization/yarn.lock b/scripts/polkadot-launch/initialization/yarn.lock index 9ca11930c37..e9ba763f066 100644 --- a/scripts/polkadot-launch/initialization/yarn.lock +++ b/scripts/polkadot-launch/initialization/yarn.lock @@ -1042,9 +1042,9 @@ next-tick@~1.0.0: integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= node-fetch@^2.6.6: - version "2.6.6" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.6.tgz#1751a7c01834e8e1697758732e9efb6eeadfaf89" - integrity sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA== + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" diff --git a/scripts/polkadot-launch/package.json b/scripts/polkadot-launch/package.json index ced6f2e3f90..3d39935a2bb 100644 --- a/scripts/polkadot-launch/package.json +++ b/scripts/polkadot-launch/package.json @@ -12,6 +12,8 @@ "author": "", "license": "ISC", "dependencies": { - "polkadot-launch": "^1.8.0" + "@types/node": "^17.0.18", + "polkadot-launch": "^1.9.0", + "typescript": "^4.5.5" } } diff --git a/scripts/polkadot-launch/yarn.lock b/scripts/polkadot-launch/yarn.lock index 9260b10ec5b..be772d63377 100644 --- a/scripts/polkadot-launch/yarn.lock +++ b/scripts/polkadot-launch/yarn.lock @@ -740,6 +740,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.42.tgz#2f021733232c2130c26f9eabbdd3bfd881774733" integrity sha512-aI3/oo5DzyiI5R/xAhxxRzfZlWlsbbqdgxfTPkqu/Zt+23GXiJvMCyPJT4+xKSXOnLqoL8jJYMLTwvK2M3a5hw== +"@types/node@^17.0.18": + version "17.0.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.18.tgz#3b4fed5cfb58010e3a2be4b6e74615e4847f1074" + integrity sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA== + "@types/pbkdf2@^3.0.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1" @@ -3097,7 +3102,7 @@ picomatch@^2.0.4, picomatch@^2.2.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -polkadot-launch@^1.8.0: +polkadot-launch@^1.9.0: version "1.10.0" resolved "https://registry.yarnpkg.com/polkadot-launch/-/polkadot-launch-1.10.0.tgz#896a4bd2dbc7d55b273abf3fed3c1f8af0c7fc0f" integrity sha512-Z+rprrJNXhap5Q3rK7IOAWMwSYgxRBxchvMb298Ns7/yZ1lO4pYAMUOTXRVtI3p1i36XRmHE4tr728fi2r6Krw== @@ -3453,9 +3458,9 @@ simple-concat@^1.0.0: integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== simple-get@^2.7.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" - integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw== + version "2.8.2" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.2.tgz#5708fb0919d440657326cd5fe7d2599d07705019" + integrity sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw== dependencies: decompress-response "^3.3.0" once "^1.3.1" @@ -3694,6 +3699,11 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" +typescript@^4.5.5: + version "4.5.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" + integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== + uint8arrays@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.0.0.tgz#260869efb8422418b6f04e3fac73a3908175c63b" diff --git a/scripts/benchmarks.sh b/scripts/run_benchmarks.sh similarity index 100% rename from scripts/benchmarks.sh rename to scripts/run_benchmarks.sh index 95fa5240b42..13791e5b751 100755 --- a/scripts/benchmarks.sh +++ b/scripts/run_benchmarks.sh @@ -3,9 +3,9 @@ # `cargo build --release --features runtime-benchmarks` chains=( - "./runtime/composable/src/weights,composable-dev" - "./runtime/picasso/src/weights,picasso-dev" "./runtime/dali/src/weights,dali-dev" + "./runtime/picasso/src/weights,picasso-dev" + "./runtime/composable/src/weights,composable-dev" ) steps=50 diff --git a/setup/yarn.lock b/setup/yarn.lock index 75d9bd7a4df..26c872314d0 100644 --- a/setup/yarn.lock +++ b/setup/yarn.lock @@ -533,9 +533,11 @@ next-tick@~1.0.0: integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= node-fetch@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" - integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" node-gyp-build@^4.2.0: version "4.2.3" @@ -603,6 +605,11 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" @@ -642,6 +649,11 @@ util-deprecate@^1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + websocket@^1.0.34: version "1.0.34" resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" @@ -654,6 +666,14 @@ websocket@^1.0.34: utf-8-validate "^5.0.2" yaeti "^0.0.6" +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + xxhashjs@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/xxhashjs/-/xxhashjs-0.2.2.tgz#8a6251567621a1c46a5ae204da0249c7f8caa9d8" diff --git a/integration-tests/simnode/common/Cargo.toml b/simnode/common/Cargo.toml similarity index 54% rename from integration-tests/simnode/common/Cargo.toml rename to simnode/common/Cargo.toml index f541dafbbcc..716d8b74d10 100644 --- a/integration-tests/simnode/common/Cargo.toml +++ b/simnode/common/Cargo.toml @@ -1,32 +1,34 @@ [package] +edition = "2021" name = "simnode-common" version = "0.1.0" -edition = "2021" [dependencies] -substrate-simnode = { git = "https://github.com/polytope-labs/substrate-simnode", branch = "master"} simnode-apis = { package = "simnode-runtime-apis", git = "https://github.com/polytope-labs/substrate-simnode", default-features = false, branch = "master" } +substrate-simnode = { git = "https://github.com/polytope-labs/substrate-simnode", branch = "master" } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +system = { package = "frame-system", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +transaction-payment = { package = "pallet-transaction-payment", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-consensus-manual-seal = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-consensus-manual-seal = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -picasso-runtime = { path = "../../../runtime/picasso", features = ["sim-node"] } -dali-runtime = { path = "../../../runtime/dali", features = ["sim-node"] } -common = { path = "../../../runtime/common" } -node = { package = "composable-node", path = "../../../node", features = ["dali"] } -parachain-inherent = { package = "cumulus-primitives-parachain-inherent", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16" } +common = { path = "../../runtime/common" } +composable-runtime = { path = "../../runtime/composable" } +dali-runtime = { path = "../../runtime/dali" } +node = { package = "composable-node", path = "../../node", features = ["dali"] } +parachain-inherent = { package = "cumulus-primitives-parachain-inherent", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17" } +picasso-runtime = { path = "../../runtime/picasso" } +derive_more = "0.99.17" jsonrpc-core = "18.0" - -derive_more = "0.99.17" \ No newline at end of file diff --git a/integration-tests/simnode/common/src/chains.rs b/simnode/common/src/chains.rs similarity index 63% rename from integration-tests/simnode/common/src/chains.rs rename to simnode/common/src/chains.rs index b10460b13ae..1451cb8de40 100644 --- a/integration-tests/simnode/common/src/chains.rs +++ b/simnode/common/src/chains.rs @@ -1,3 +1,5 @@ +/// utilities for composable-runtime +pub mod composable; /// utilities for the dali-runtime pub mod dali; /// utilities for picasso-runtime diff --git a/simnode/common/src/chains/composable.rs b/simnode/common/src/chains/composable.rs new file mode 100644 index 00000000000..dee347235b6 --- /dev/null +++ b/simnode/common/src/chains/composable.rs @@ -0,0 +1,68 @@ +use crate::cli::ComposableCli; +use parachain_inherent::ParachainInherentData; +use sc_consensus_manual_seal::consensus::timestamp::SlotTimestampProvider; +use sc_service::TFullBackend; +use sp_runtime::generic::Era; +use std::sync::Arc; +use substrate_simnode::{FullClientFor, RpcHandlerArgs, SignatureVerificationOverride}; + +/// A unit struct which implements `NativeExecutionDispatch` feeding in the +/// hard-coded runtime. +pub struct ExecutorDispatch; + +impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { + type ExtendHostFunctions = + (frame_benchmarking::benchmarking::HostFunctions, SignatureVerificationOverride); + + fn dispatch(method: &str, data: &[u8]) -> Option> { + composable_runtime::api::dispatch(method, data) + } + + fn native_version() -> sc_executor::NativeVersion { + composable_runtime::native_version() + } +} + +/// ChainInfo implementation. +pub struct ChainInfo; + +impl substrate_simnode::ChainInfo for ChainInfo { + type Block = common::OpaqueBlock; + type ExecutorDispatch = ExecutorDispatch; + type Runtime = composable_runtime::Runtime; + type RuntimeApi = composable_runtime::RuntimeApi; + type SelectChain = sc_consensus::LongestChain, Self::Block>; + type BlockImport = Arc>; + type InherentDataProviders = ( + SlotTimestampProvider, + sp_consensus_aura::inherents::InherentDataProvider, + ParachainInherentData, + ); + type SignedExtras = composable_runtime::SignedExtra; + type Cli = ComposableCli; + + fn create_rpc_io_handler( + deps: RpcHandlerArgs, + ) -> jsonrpc_core::MetaIoHandler { + let full_deps = node::rpc::FullDeps { + client: deps.client, + pool: deps.pool, + deny_unsafe: deps.deny_unsafe, + }; + node::rpc::create::<_, _, Self::Block>(full_deps) + } + + fn signed_extras(from: ::AccountId) -> Self::SignedExtras { + let nonce = system::Pallet::::account_nonce(from); + ( + system::CheckNonZeroSender::::new(), + system::CheckSpecVersion::::new(), + system::CheckTxVersion::::new(), + system::CheckGenesis::::new(), + system::CheckEra::::from(Era::Immortal), + system::CheckNonce::::from(nonce), + system::CheckWeight::::new(), + transaction_payment::ChargeTransactionPayment::::from(0), + ) + } +} diff --git a/integration-tests/simnode/common/src/chains/dali.rs b/simnode/common/src/chains/dali.rs similarity index 68% rename from integration-tests/simnode/common/src/chains/dali.rs rename to simnode/common/src/chains/dali.rs index 46baf3e55af..0503ff8f129 100644 --- a/integration-tests/simnode/common/src/chains/dali.rs +++ b/simnode/common/src/chains/dali.rs @@ -2,6 +2,7 @@ use crate::cli::ComposableCli; use parachain_inherent::ParachainInherentData; use sc_consensus_manual_seal::consensus::timestamp::SlotTimestampProvider; use sc_service::TFullBackend; +use sp_runtime::generic::Era; use std::sync::Arc; use substrate_simnode::{FullClientFor, RpcHandlerArgs, SignatureVerificationOverride}; @@ -37,18 +38,12 @@ impl substrate_simnode::ChainInfo for ChainInfo { sp_consensus_aura::inherents::InherentDataProvider, ParachainInherentData, ); + type SignedExtras = dali_runtime::SignedExtra; type Cli = ComposableCli; fn create_rpc_io_handler( deps: RpcHandlerArgs, - ) -> jsonrpc_core::MetaIoHandler - where - <::RuntimeApi as sp_api::ConstructRuntimeApi< - Self::Block, - FullClientFor, - >>::RuntimeApi: sp_api::Core - + sp_transaction_pool::runtime_api::TaggedTransactionQueue, - { + ) -> jsonrpc_core::MetaIoHandler { let full_deps = node::rpc::FullDeps { client: deps.client, pool: deps.pool, @@ -56,4 +51,18 @@ impl substrate_simnode::ChainInfo for ChainInfo { }; node::rpc::create::<_, _, Self::Block>(full_deps) } + + fn signed_extras(from: ::AccountId) -> Self::SignedExtras { + let nonce = system::Pallet::::account_nonce(from); + ( + system::CheckNonZeroSender::::new(), + system::CheckSpecVersion::::new(), + system::CheckTxVersion::::new(), + system::CheckGenesis::::new(), + system::CheckEra::::from(Era::Immortal), + system::CheckNonce::::from(nonce), + system::CheckWeight::::new(), + transaction_payment::ChargeTransactionPayment::::from(0), + ) + } } diff --git a/integration-tests/simnode/common/src/chains/picasso.rs b/simnode/common/src/chains/picasso.rs similarity index 68% rename from integration-tests/simnode/common/src/chains/picasso.rs rename to simnode/common/src/chains/picasso.rs index 87c37636b76..0fbe79f3ef6 100644 --- a/integration-tests/simnode/common/src/chains/picasso.rs +++ b/simnode/common/src/chains/picasso.rs @@ -2,6 +2,7 @@ use crate::cli::ComposableCli; use parachain_inherent::ParachainInherentData; use sc_consensus_manual_seal::consensus::timestamp::SlotTimestampProvider; use sc_service::TFullBackend; +use sp_runtime::generic::Era; use std::sync::Arc; use substrate_simnode::{FullClientFor, RpcHandlerArgs, SignatureVerificationOverride}; @@ -37,17 +38,11 @@ impl substrate_simnode::ChainInfo for ChainInfo { sp_consensus_aura::inherents::InherentDataProvider, ParachainInherentData, ); + type SignedExtras = picasso_runtime::SignedExtra; type Cli = ComposableCli; fn create_rpc_io_handler( deps: RpcHandlerArgs, - ) -> jsonrpc_core::MetaIoHandler - where - <::RuntimeApi as sp_api::ConstructRuntimeApi< - Self::Block, - FullClientFor, - >>::RuntimeApi: sp_api::Core - + sp_transaction_pool::runtime_api::TaggedTransactionQueue, - { + ) -> jsonrpc_core::MetaIoHandler { let full_deps = node::rpc::FullDeps { client: deps.client, pool: deps.pool, @@ -55,4 +50,18 @@ impl substrate_simnode::ChainInfo for ChainInfo { }; node::rpc::create::<_, _, Self::Block>(full_deps) } + + fn signed_extras(from: ::AccountId) -> Self::SignedExtras { + let nonce = system::Pallet::::account_nonce(from); + ( + system::CheckNonZeroSender::::new(), + system::CheckSpecVersion::::new(), + system::CheckTxVersion::::new(), + system::CheckGenesis::::new(), + system::CheckEra::::from(Era::Immortal), + system::CheckNonce::::from(nonce), + system::CheckWeight::::new(), + transaction_payment::ChargeTransactionPayment::::from(0), + ) + } } diff --git a/integration-tests/simnode/common/src/cli.rs b/simnode/common/src/cli.rs similarity index 100% rename from integration-tests/simnode/common/src/cli.rs rename to simnode/common/src/cli.rs diff --git a/integration-tests/simnode/common/src/events.rs b/simnode/common/src/events.rs similarity index 89% rename from integration-tests/simnode/common/src/events.rs rename to simnode/common/src/events.rs index fa324d2327b..3bb1037e0c1 100644 --- a/integration-tests/simnode/common/src/events.rs +++ b/simnode/common/src/events.rs @@ -6,6 +6,8 @@ pub enum AllRuntimeEvents { Picasso(picasso_runtime::Event), /// Dali runtime events Dali(dali_runtime::Event), + /// Composable runtime events + Composable(composable_runtime::Event), } /// Convenience method to match on [`AllRuntimeEvents`] diff --git a/integration-tests/simnode/common/src/lib.rs b/simnode/common/src/lib.rs similarity index 100% rename from integration-tests/simnode/common/src/lib.rs rename to simnode/common/src/lib.rs diff --git a/integration-tests/simnode/simnode-node/Cargo.toml b/simnode/simnode-node/Cargo.toml similarity index 68% rename from integration-tests/simnode/simnode-node/Cargo.toml rename to simnode/simnode-node/Cargo.toml index f84b08f6e4f..2614b7399d0 100644 --- a/integration-tests/simnode/simnode-node/Cargo.toml +++ b/simnode/simnode-node/Cargo.toml @@ -1,14 +1,14 @@ [package] +edition = "2021" name = "simnode-node" version = "0.1.0" -edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -substrate-simnode = { git = "https://github.com/polytope-labs/substrate-simnode", branch = "master"} common = { package = "simnode-common", path = "../common" } -node = { package = "composable-node", path = "../../../node", features = ["dali"] } +node = { package = "composable-node", path = "../../node", features = ["dali"] } +substrate-simnode = { git = "https://github.com/polytope-labs/substrate-simnode", branch = "master" } -sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -structopt = "0.3.25" \ No newline at end of file +sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +structopt = "0.3.25" diff --git a/simnode/simnode-node/README.md b/simnode/simnode-node/README.md new file mode 100644 index 00000000000..6dc66bd7afb --- /dev/null +++ b/simnode/simnode-node/README.md @@ -0,0 +1,45 @@ +# Simnode Binary +This is a special binary that can be run without being connected to a relay chain and exposes an rpc method `engine_createBlock` that you can call in order to seal a block. Its method signature is: + +```rust + +#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)] +pub struct CreatedBlock { + /// hash of the created block. + pub hash: Hash, + /// some extra details about the import operation + pub aux: ImportedAux, +} + +#[derive(Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +pub struct ImportedAux { + /// Only the header has been imported. Block body verification was skipped. + pub header_only: bool, + /// Clear all pending justification requests. + pub clear_justification_requests: bool, + /// Request a justification for the given block. + pub needs_justification: bool, + /// Received a bad justification. + pub bad_justification: bool, + /// Whether the block that was imported is the new best block. + pub is_new_best: bool, +} + +#[rpc(name = "engine_createBlock")] +fn create_block( + &self, + create_empty: bool, + finalize: bool, + parent_hash: Option, +) -> FutureResult>; +``` + +Because you are in control of block production, the node will not create blocks until you call this rpc method. + +# Build Instructions + +```bash +cargo build --release -p simnode-node +# run like so +./target/release/simnode-node --chain=picasso # pass all the args you would normally pass to the collator +``` \ No newline at end of file diff --git a/integration-tests/simnode/simnode-node/src/main.rs b/simnode/simnode-node/src/main.rs similarity index 75% rename from integration-tests/simnode/simnode-node/src/main.rs rename to simnode/simnode-node/src/main.rs index 13c84a27017..c6d372d5216 100644 --- a/integration-tests/simnode/simnode-node/src/main.rs +++ b/simnode/simnode-node/src/main.rs @@ -22,6 +22,14 @@ fn main() -> Result<(), Box> { Ok(()) }, )?, + chain if chain.contains("composable") => + substrate_simnode::parachain_node::( + |node| async move { + node.seal_blocks(10).await; + node.until_shutdown().await; + Ok(()) + }, + )?, _ => panic!("Unsupported chain_id: {}", chain_id), }; diff --git a/integration-tests/simnode/simnode-tests/Cargo.toml b/simnode/simnode-tests/Cargo.toml similarity index 65% rename from integration-tests/simnode/simnode-tests/Cargo.toml rename to simnode/simnode-tests/Cargo.toml index 60881b6425c..d981af14df5 100644 --- a/integration-tests/simnode/simnode-tests/Cargo.toml +++ b/simnode/simnode-tests/Cargo.toml @@ -1,41 +1,42 @@ [package] +edition = "2021" name = "simnode-tests" version = "0.1.0" -edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -substrate-simnode = { git = "https://github.com/polytope-labs/substrate-simnode", branch = "master"} simnode-apis = { package = "simnode-runtime-apis", git = "https://github.com/polytope-labs/substrate-simnode", default-features = false, branch = "master" } +substrate-simnode = { git = "https://github.com/polytope-labs/substrate-simnode", branch = "master" } -system = { package = "frame-system", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16", default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17", default-features = false } +system = { package = "frame-system", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -parachain-system = { package = "cumulus-pallet-parachain-system", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16" } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.16" } +parachain-system = { package = "cumulus-pallet-parachain-system", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.17" } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } -picasso-runtime = { path = "../../../runtime/picasso", features = ["sim-node"] } -dali-runtime = { path = "../../../runtime/dali", features = ["sim-node"] } -node = { package = "composable-node", path = "../../../node", features = ["dali"] } -common = { path = "../../../runtime/common" } +common = { path = "../../runtime/common" } +composable-runtime = { path = "../../runtime/composable" } +dali-runtime = { path = "../../runtime/dali" } +node = { package = "composable-node", path = "../../node", features = ["dali"] } +picasso-runtime = { path = "../../runtime/picasso" } simnode-common = { path = "../common" } -sudo = { package = "pallet-sudo", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } +codec = { package = "parity-scale-codec", version = "2.0.0" } +hex = "0.4.3" num-traits = "0.2.14" structopt = "0.3.25" -hex = "0.4.3" -codec = { package = "parity-scale-codec", version = "2.0.0" } +sudo = { package = "pallet-sudo", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } diff --git a/integration-tests/simnode/simnode-tests/src/chains.rs b/simnode/simnode-tests/src/chains.rs similarity index 63% rename from integration-tests/simnode/simnode-tests/src/chains.rs rename to simnode/simnode-tests/src/chains.rs index b10460b13ae..1451cb8de40 100644 --- a/integration-tests/simnode/simnode-tests/src/chains.rs +++ b/simnode/simnode-tests/src/chains.rs @@ -1,3 +1,5 @@ +/// utilities for composable-runtime +pub mod composable; /// utilities for the dali-runtime pub mod dali; /// utilities for picasso-runtime diff --git a/simnode/simnode-tests/src/chains/composable.rs b/simnode/simnode-tests/src/chains/composable.rs new file mode 100644 index 00000000000..97ebc3c2584 --- /dev/null +++ b/simnode/simnode-tests/src/chains/composable.rs @@ -0,0 +1,20 @@ +use crate::tests; +use common::DAYS; +use simnode_common::chains::composable::ChainInfo; +use std::error::Error; + +/// run all integration tests +pub fn run() -> Result<(), Box> { + substrate_simnode::parachain_node::(|node| async move { + // test code-substitute for dali, by authoring blocks past the launch period + node.seal_blocks(10).await; + // test runtime upgrades + let code = composable_runtime::WASM_BINARY.ok_or("Composable wasm not available")?.to_vec(); + tests::runtime_upgrade::parachain_runtime_upgrades(&node, code).await?; + + // try to create blocks for a month, if it doesn't panic, all good. + node.seal_blocks((30 * DAYS) as usize).await; + + Ok(()) + }) +} diff --git a/integration-tests/simnode/simnode-tests/src/chains/dali.rs b/simnode/simnode-tests/src/chains/dali.rs similarity index 100% rename from integration-tests/simnode/simnode-tests/src/chains/dali.rs rename to simnode/simnode-tests/src/chains/dali.rs diff --git a/integration-tests/simnode/simnode-tests/src/chains/picasso.rs b/simnode/simnode-tests/src/chains/picasso.rs similarity index 100% rename from integration-tests/simnode/simnode-tests/src/chains/picasso.rs rename to simnode/simnode-tests/src/chains/picasso.rs diff --git a/integration-tests/simnode/simnode-tests/src/main.rs b/simnode/simnode-tests/src/main.rs similarity index 87% rename from integration-tests/simnode/simnode-tests/src/main.rs rename to simnode/simnode-tests/src/main.rs index ffd8d55701d..5ad3e265c0e 100644 --- a/integration-tests/simnode/simnode-tests/src/main.rs +++ b/simnode/simnode-tests/src/main.rs @@ -12,6 +12,7 @@ fn main() -> Result<(), Box> { match &*chain_id { chain if chain.contains("picasso") => picasso::run()?, chain if chain.contains("dali") => dali::run()?, + chain if chain.contains("composable") => composable::run()?, _ => panic!("Unsupported chain_id: {}", chain_id), }; diff --git a/integration-tests/simnode/simnode-tests/src/tests.rs b/simnode/simnode-tests/src/tests.rs similarity index 100% rename from integration-tests/simnode/simnode-tests/src/tests.rs rename to simnode/simnode-tests/src/tests.rs diff --git a/integration-tests/simnode/simnode-tests/src/tests/runtime_upgrade.rs b/simnode/simnode-tests/src/tests/runtime_upgrade.rs similarity index 100% rename from integration-tests/simnode/simnode-tests/src/tests/runtime_upgrade.rs rename to simnode/simnode-tests/src/tests/runtime_upgrade.rs diff --git a/utils/collator-sidecar/Cargo.toml b/utils/collator-sidecar/Cargo.toml index d63312b489f..3a26ceb3ef9 100644 --- a/utils/collator-sidecar/Cargo.toml +++ b/utils/collator-sidecar/Cargo.toml @@ -1,20 +1,17 @@ [package] -name = "collator-sidecar" -version = "0.1.0" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2018" +homepage = "https://composable.finance" +name = "collator-sidecar" +version = "0.1.0" [dependencies] -env_logger = "0.8.4" -tide = "0.16" async-std = { version = "1", features = ["attributes", "tokio1"] } +env_logger = "0.8.4" serde = { version = "1", features = ["derive"] } -url = "1" -tokio = { version = "1.12.0", features = ["macros", "rt-multi-thread"] } structopt = "0.3.25" +tide = "0.16" +tokio = { version = "1.12.0", features = ["macros", "rt-multi-thread"] } +url = "1.7.0" -jsonrpc-core-client = { version = "18", features = ["ws"] } -sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -picasso = { package = "picasso-runtime", path = "../../runtime/picasso" } -common = { path = "../../runtime/common" } +jsonrpsee = { version = "0.9", features = ["http-client", "macros"] } diff --git a/utils/collator-sidecar/src/main.rs b/utils/collator-sidecar/src/main.rs index b6fcaddc4ae..dcbef93aee2 100644 --- a/utils/collator-sidecar/src/main.rs +++ b/utils/collator-sidecar/src/main.rs @@ -1,19 +1,23 @@ -use jsonrpc_core_client::transports::ws; -use sc_rpc::system::SystemClient; +use jsonrpsee::{ + core::client::ClientT, + http_client::{HttpClient, HttpClientBuilder}, + rpc_params, +}; use serde::Deserialize; -use std::str::FromStr; +use std::sync::Arc; use structopt::StructOpt; -use tide::Request; +use tide::{log, Request}; #[derive(Debug, Deserialize, StructOpt, Clone)] struct Main { + #[structopt(long)] + rpc_port: String, #[structopt(long)] port: String, } -#[derive(Clone)] struct State { - system: SystemClient, + client: HttpClient, } #[tokio::main] @@ -21,24 +25,29 @@ async fn main() -> tide::Result<()> { env_logger::init(); let args = Main::from_args(); - let url = url::Url::from_str(&format!("127.0.0.1:{}", args.port)).unwrap(); - let system = ws::connect(&url).await.expect("failed to connect to collator node"); + let url = format!("http://127.0.0.1:{}", args.rpc_port); + let client = HttpClientBuilder::default().max_request_body_size(u32::MAX).build(url).unwrap(); - let mut app = tide::with_state(State { system }); + let mut app = tide::with_state(Arc::new(State { client })); app.at("/").post(log_handler); app.listen(format!("0.0.0.0:{}", args.port)).await?; Ok(()) } -async fn log_handler(mut req: Request) -> tide::Result { +async fn log_handler(mut req: Request>) -> tide::Result { let targets = req.body_string().await?; + log::info!("got new targets: {}", targets); - let result = if targets.is_empty() { - req.state().system.system_add_log_filter(targets).await + let result = if !targets.is_empty() { + req.state() + .client + .request::<()>("system_addLogFilter", rpc_params!(targets)) + .await } else { - req.state().system.system_reset_log_filter().await + req.state().client.request::<()>("system_resetLogFilter", None).await }; + log::info!("result: {:?}", result); if let Err(e) = result { return Ok(format!("Error: {:?}", e).into()) diff --git a/utils/faucet-server/Cargo.toml b/utils/faucet-server/Cargo.toml index e66e3ef89ee..fc61ee75512 100644 --- a/utils/faucet-server/Cargo.toml +++ b/utils/faucet-server/Cargo.toml @@ -1,25 +1,25 @@ [package] -name = "faucet-server" -version = "0.1.0" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2018" +homepage = "https://composable.finance" +name = "faucet-server" +version = "0.1.0" [dependencies] -tide = "0.16" async-std = { version = "1", features = ["attributes", "tokio1"] } -serde = { version = "1", features = ["derive"] } -structopt = "0.3.25" -sha2 = "0.9.8" -hmac = "0.11.0" -serde_urlencoded = "0.7.0" +common = { package = "common", path = "../../runtime/common" } +dotenv = "0.15.0" env_logger = "0.8.4" +envy = "0.4" hex = "0.4.3" +hmac = "0.11.0" log = "0.4.14" -envy = "0.4" -dotenv = "0.15.0" -tokio = { version = "1.12.0", features = ["macros", "rt-multi-thread"] } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -common = { package = "common", path = "../../runtime/common" } +serde = { version = "1", features = ["derive"] } +serde_urlencoded = "0.7.0" +sha2 = "0.9.8" +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +structopt = "0.3.25" subxt = { git = "https://github.com/composableFi/subxt", branch = "seun-0.9.13" } subxt-clients = { path = "../subxt-clients" } +tide = "0.16" +tokio = { version = "1.12.0", features = ["macros", "rt-multi-thread"] } diff --git a/utils/parachain-utils/Cargo.toml b/utils/parachain-utils/Cargo.toml index b7d0bed11f5..1dbddd093d2 100644 --- a/utils/parachain-utils/Cargo.toml +++ b/utils/parachain-utils/Cargo.toml @@ -1,39 +1,39 @@ [package] -name = "parachain-utils" -version = "0.1.0" authors = ["Composable Developers"] -homepage = "https://composable.finance" edition = "2018" +homepage = "https://composable.finance" +name = "parachain-utils" +version = "0.1.0" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] [dependencies] -env_logger = "0.8.4" -log = "0.4.14" -url = "1.7" -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -transaction-payment = { package = "pallet-transaction-payment", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -parachain-system = { package = "cumulus-pallet-parachain-system", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.16" } -derive_more = "0.99.16" -tokio = {version = "1", features = ["full"]} codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } +derive_more = "0.99.16" +env_logger = "0.8.4" envy = "0.4.2" +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +log = "0.4.14" +parachain-system = { package = "cumulus-pallet-parachain-system", git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.17" } serde = { version = "1", features = ["derive"] } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +tokio = { version = "1", features = ["full"] } +transaction-payment = { package = "pallet-transaction-payment", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +url = "1.7.0" jsonrpc-core-client = { version = "18", features = ["ws"] } +sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.17" } structopt = "0.3.23" -sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.16" } common = { package = "common", path = "../../runtime/common" } substrate-xt = { git = "https://github.com/polytope-labs/substrate-xt", branch = "master" } # runtimes -picasso-runtime = { path = "../../runtime/picasso" } dali-runtime = { path = "../../runtime/dali" } +picasso-runtime = { path = "../../runtime/picasso" } [dev-dependencies] hex = "0.4.3" diff --git a/utils/price-feed/Cargo.toml b/utils/price-feed/Cargo.toml index 427f972fc35..28af3da9838 100644 --- a/utils/price-feed/Cargo.toml +++ b/utils/price-feed/Cargo.toml @@ -1,26 +1,26 @@ [package] +edition = "2021" name = "price-feed" version = "0.1.0" -edition = "2021" [dependencies] -enum_derive = "0.1.7" +binance = "0.17" +chrono = "0.4.19" +clap = { version = "3.0.0-rc.4", features = ["derive"] } custom_derive = "0.1.7" +enum_derive = "0.1.7" env_logger = "0.9.0" +futures = "0.3" +jsonrpc-client-transports = "18.0.0" +jsonrpc-core = "18.0.0" +lazy_static = "1.4.0" log = "0.4.14" -tokio = { version = "1.9", features = [ "full" ] } +serde = { version = "1.0.130", features = ["derive"] } +serde_json = "1.0.45" +signal-hook = "0.3" +signal-hook-tokio = { version = "0.3", features = ["futures-v0_3"] } +tokio = { version = "1.9", features = ["full"] } tokio-stream = "0.1" url = "1.7.0" -chrono = "0.4.19" -serde = { version = "1.0", features = [ "derive" ] } -serde_json = "1.0" -jsonrpc-core = "18.0.0" -jsonrpc-client-transports = "18.0.0" -clap = { version = "3.0.0-rc.4", features = [ "derive" ] } warp = "0.3" -signal-hook = "0.3" -signal-hook-tokio = { version = "0.3", features = [ "futures-v0_3" ] } -futures = "0.3" -lazy_static = "1.4.0" -binance = "0.17"