From 3583fa19a909aaa4113bcdb23b35c5bede6866ae Mon Sep 17 00:00:00 2001 From: dafyddd Date: Sun, 16 Jan 2022 19:08:54 -0600 Subject: [PATCH] V3.3.0 (#91) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add instructions for closing a mango account * Check owner account is signer * Use checked functions to load mango accounts * add wip create_dust_account and resolve_dust * Make resolve_dust fail silently * Add max account checking * Add upgrade mango account instruction * Update version * Run cargo fmt * Fix instruction number, make owner read, fix padding * added cancel_all_side functions to mathcing * added cancel_perp_orders_side; haven't tested * added not_upgradable flag to MangoAccount and amended InitMangoAccount to set that flag to true. * logging for cancel all perp orders; get_complete_base_pos for reduce only check * complete_base_pos for trigger order exec as well * added changelog * fixed check enter bankruptcy bug * added deploy time * merged in v3.2.12 and updated cancel_side to do logging * Most code review changes, check dust account health * Remove whitespace * changed dust_account owner to admin * make resolve_dust not take in OpenOrders for DustAccount because it doesn't have any; Add more checks for MangoAccount in resolve_dust * merged in main v3.2.13 * do in_margin_basket check in CloseSpotOpenOrders * do in_margin_basket check in CloseSpotOpenOrders * small edits to errors * upgrade anchor and packages * added some additional info to PlacePerpOrder in instruction.rs * mc/add alternative authority which cant withdraw (#97) * Support account delegation, delegate should be able to trade, but not withdraw assets to his own wallet Signed-off-by: microwavedcola1 * comment Signed-off-by: microwavedcola1 * comment Signed-off-by: microwavedcola1 * comment Signed-off-by: microwavedcola1 * newline Signed-off-by: microwavedcola1 * bump solana in tests Signed-off-by: microwavedcola1 * cargo-fmt Signed-off-by: microwavedcola1 * bump rust Signed-off-by: microwavedcola1 * fix solana verison Signed-off-by: microwavedcola1 * linter Signed-off-by: microwavedcola1 * note Signed-off-by: microwavedcola1 * typo Signed-off-by: microwavedcola1 * changed name from alternative_authority to delegate to be consistent with Solana naming and more accurate Co-authored-by: dd * Fixes from code review Signed-off-by: microwavedcola1 * Tests: Fix program log output The log scope for these changed in solana 1.9 * Remove unnecessary owner check * fix: remove not used account from ix interface spec * Fix instruction builder, owner will pay, and his lamports would need to be adjusted Signed-off-by: microwavedcola1 * implement price limit in place_spot_order and place_spot_order2 * remove print * CI: add apt-get update (#116) Installing libudev-dev failed * README: Document branches (#114) * remove a todo; cleanup devnet_deploy.sh * mc/change spot market params (#110) * Soteria and Cargo Audit Automation (#106) * Create audit.toml Cargo audit configuration file * Create ci-cargo-audit.yml Action to build and run cargo audit using arguments from the .cargo/audit.toml file * Update and rename program.yml to ci-lint-test.yml Minor name changes and addition of Soteria * Update ci-lint-test.yml update environment settings * Update ci-lint-test.yml adding apt-get update as the job fails to find packages * Update ci-cargo-audit.yml * Ignore tokio upstream vuln Reported to Solana for upstream patching * impose price limits (#108) * impose price limits * update deploy time Co-authored-by: dd * checked math in all areas touched by place_perp_order (#109) * checked math in all areas touched by place_perp_order * update deploy time * update deploy time Co-authored-by: dd * change_spot_market_params Signed-off-by: microwavedcola1 * linter Signed-off-by: microwavedcola1 * in ci, perform apt-get update to prevent failure to install apt packages Signed-off-by: microwavedcola1 * fix from review Signed-off-by: microwavedcola1 * remove a todo; cleanup devnet_deploy.sh Co-authored-by: silas <95582913+silas-x@users.noreply.github.com> Co-authored-by: dafyddd Co-authored-by: dd * fix integer overflow issue in get_total_native_borrow * update changelog.md * optimize create_dust_account * added some checked math in execute_perp_trigger_order where dealing with bids_quantity * Do pyth price filtering only on mainnet * Add CreateSpotOpenOrders * add tests for CreateSpotOpenOrders * upgrade anchor version to 0.20.1 * update deploy time Co-authored-by: Riordan Panayides Co-authored-by: dd Co-authored-by: microwavedcola1 <89031858+microwavedcola1@users.noreply.github.com> Co-authored-by: microwavedcola1 Co-authored-by: Christian Kamm Co-authored-by: Jakob Povšič Co-authored-by: silas <95582913+silas-x@users.noreply.github.com> --- .gitignore | 2 + Anchor.toml | 2 +- Cargo.lock | 1250 ++++++++++----------- README.md | 15 +- changelog.md | 12 + mango-logs/Cargo.toml | 2 +- mango-macro/Cargo.toml | 2 +- program/Cargo.toml | 4 +- program/devnet_deploy.sh | 3 +- program/src/error.rs | 2 + program/src/instruction.rs | 408 ++++++- program/src/matching.rs | 150 ++- program/src/processor.rs | 840 +++++++++++++- program/src/state.rs | 50 +- program/tests/program_test/cookies.rs | 83 ++ program/tests/program_test/mod.rs | 232 +++- program/tests/program_test/scenarios.rs | 68 ++ program/tests/test_compute.rs | 9 - program/tests/test_delegate.rs | 103 ++ program/tests/test_deposit.rs | 9 - program/tests/test_funding_rate.rs | 9 - program/tests/test_interest_rate.rs | 9 - program/tests/test_liquidation.rs | 14 - program/tests/test_perp_markets.rs | 27 - program/tests/test_perp_trigger_orders.rs | 14 - program/tests/test_sanity.rs | 7 - program/tests/test_spot_markets.rs | 108 +- program/tests/test_worst_case.rs | 18 - 28 files changed, 2527 insertions(+), 925 deletions(-) create mode 100644 program/tests/test_delegate.rs diff --git a/.gitignore b/.gitignore index 5e600210..0a218e16 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ program/target common/target mango-macro/target target + +.idea diff --git a/Anchor.toml b/Anchor.toml index c06216e7..56af1efd 100644 --- a/Anchor.toml +++ b/Anchor.toml @@ -1,4 +1,4 @@ -anchor_version = "0.18.0" +anchor_version = "0.20.1" [workspace] members = [ diff --git a/Cargo.lock b/Cargo.lock index 5689c961..be2e5be9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,9 +10,9 @@ checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" [[package]] name = "addr2line" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" dependencies = [ "gimli", ] @@ -52,126 +52,140 @@ checksum = "6b2d54853319fd101b8dd81de382bcbf3e03410a64d8928bbee85a3e7dcde483" [[package]] name = "anchor-attribute-access-control" -version = "0.18.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cb6a4b9c53ca04146d47df41db96e79ca3fd1fe60ba2691b317648a5e314bbd" +checksum = "105c443a613f29212755fb6c5f946fa82dcf94a80528f643e0faa9d9faeb626b" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2 1.0.30", - "quote 1.0.10", + "proc-macro2", + "quote", "regex", - "syn 1.0.74", + "syn", ] [[package]] name = "anchor-attribute-account" -version = "0.18.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "568fdd7655eca414649cba63c10d34856569aa07acc5996d50eaf74e28495f80" +checksum = "fdae15851aa41972e9c18c987613c50a916c48c88c97ea3316156a5c772e5faa" dependencies = [ "anchor-syn", "anyhow", "bs58 0.4.0", - "proc-macro2 1.0.30", - "quote 1.0.10", + "proc-macro2", + "quote", "rustversion", - "syn 1.0.74", + "syn", +] + +[[package]] +name = "anchor-attribute-constant" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6356865217881d0bbea8aa70625937bec6d9952610f1ba2a2452a8e427000687" +dependencies = [ + "anchor-syn", + "proc-macro2", + "syn", ] [[package]] name = "anchor-attribute-error" -version = "0.18.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1653f067f9830a3851d3171c3a5b94b4a25780369e7d57961a3d8eff0dff5272" +checksum = "ebe998ce4e6e0cb0e291d1a1626bd30791cdfdd9d05523111bdf4fd053f08636" dependencies = [ "anchor-syn", - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "anchor-attribute-event" -version = "0.18.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0e5631befc10143e6c64dea1ce4d1106300ab06f8b82e33c33bacb076057402" +checksum = "c5810498a20554c20354f5648b6041172f2035e58d09ad40dc051dc0d1501f80" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "anchor-attribute-interface" -version = "0.18.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f56e9d28f58effb298763e6397ebadfb7b84e3a853fd1995d8316d4d76fe5d" +checksum = "ac83f085b2be8b3a3412989cf96cf7f683561db7d357c5aa4aa11d48bbb22213" dependencies = [ "anchor-syn", "anyhow", "heck", - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "anchor-attribute-program" -version = "0.18.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c1f2ba3fe5da5f5653742781d0fcecbddb7105e4f933ba968802a2e10db294c" +checksum = "73c56be575d89abcb192afa29deb87b2cdb3c39033abc02f2d16e6af999b23b7" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "anchor-attribute-state" -version = "0.18.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3086b3196184a98f8ff1fe4584c4f391c686bf38cfab2cbfac9f224cdcfef5cd" +checksum = "62ab002353b01fcb4f72cca256d5d62db39f9ff39b1d072280deee9798f1f524" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "anchor-derive-accounts" -version = "0.18.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "640ae4b58427c05900d4903bd5a042fc7841272977d643b3e7f3ea73f6704720" +checksum = "e9e653cdb322078d95221384c4a527a403560e509ac7cb2b53d3bd664b23c4d6" dependencies = [ "anchor-syn", "anyhow", - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "anchor-lang" -version = "0.18.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c38773566b5111c76f47cb33c93a82b86131cb35405587a90be639de904cf00" +checksum = "4815ad6334fd2f561f7ddcc3cfbeed87ed3003724171bd80ebe6383d5173ee8f" dependencies = [ "anchor-attribute-access-control", "anchor-attribute-account", + "anchor-attribute-constant", "anchor-attribute-error", "anchor-attribute-event", "anchor-attribute-interface", "anchor-attribute-program", "anchor-attribute-state", "anchor-derive-accounts", + "arrayref", "base64 0.13.0", + "bincode", "borsh", "bytemuck", "solana-program", @@ -180,28 +194,28 @@ dependencies = [ [[package]] name = "anchor-syn" -version = "0.18.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dda645a57fe2222560ebb5fde2e22d6fd1e2b65dd7ba14250c468b285bd615f" +checksum = "3be7bfb6991d79cce3495fb6ce0892f58a5c75a74c8d1c2fc6f62926066eb9f4" dependencies = [ "anyhow", "bs58 0.3.1", "heck", - "proc-macro2 1.0.30", + "proc-macro2", "proc-macro2-diagnostics", - "quote 1.0.10", + "quote", "serde", "serde_json", "sha2", - "syn 1.0.74", + "syn", "thiserror", ] [[package]] name = "anyhow" -version = "1.0.44" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1" +checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203" [[package]] name = "arrayref" @@ -215,6 +229,12 @@ 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 = "ascii" version = "0.9.3" @@ -229,13 +249,13 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "async-trait" -version = "0.1.51" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e" +checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -257,24 +277,23 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "az" -version = "1.1.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6dff4a1892b54d70af377bf7a17064192e822865791d812957f21e3108c325" +checksum = "f771a5d1f5503f7f4279a30f3643d3421ba149848b89ecaaec0ea2acf04a5ac4" [[package]] name = "backtrace" -version = "0.3.62" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "091bcdf2da9950f96aa522681ce805e6857f6ca8df73833d35736ab2dc78e152" +checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" dependencies = [ "addr2line", "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", - "serde", ] [[package]] @@ -306,17 +325,17 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "blake3" -version = "0.3.8" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b64485778c4f16a6a5a9d335e80d449ac6c70cdd6a06d2af18a6f6f775a125b3" +checksum = "526c210b4520e416420759af363083471656e819a75e831b8d2c9d5a584f2413" dependencies = [ "arrayref", - "arrayvec", + "arrayvec 0.7.2", "cc", - "cfg-if 0.1.10", + "cfg-if", "constant_time_eq", - "crypto-mac 0.8.0", - "digest 0.9.0", + "crypto-mac 0.11.1", + "digest", ] [[package]] @@ -326,7 +345,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ "block-padding", - "generic-array 0.14.4", + "generic-array", ] [[package]] @@ -354,8 +373,8 @@ dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", "proc-macro-crate 0.1.5", - "proc-macro2 1.0.30", - "syn 1.0.74", + "proc-macro2", + "syn", ] [[package]] @@ -364,9 +383,9 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2102f62f8b6d3edeab871830782285b64cc1830168094db05c8e458f209bc5c3" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -375,9 +394,9 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "196c978c4c9b0b142d446ef3240690bf5a8a33497074a113ff9a337ccb750483" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -410,9 +429,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.7.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72957246c41db82b8ef88a5486143830adeb8227ef9837740bdec67724cf2c5b" +checksum = "439989e6b8c38d1b6570a384ef1e49c8848128f5a97f3914baef02920842712f" dependencies = [ "bytemuck_derive", ] @@ -423,9 +442,9 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e215f8c2f9f79cb53c8335e687ffd07d5bfcb6fe5fc80723762d0be46e7cc54" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -434,17 +453,6 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" -[[package]] -name = "bytes" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -dependencies = [ - "byteorder", - "either", - "iovec", -] - [[package]] name = "bytes" version = "1.1.0" @@ -453,9 +461,9 @@ checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" [[package]] name = "bzip2" -version = "0.3.3" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b" +checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0" dependencies = [ "bzip2-sys", "libc", @@ -474,19 +482,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.71" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" dependencies = [ "jobserver", ] -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -529,6 +531,26 @@ dependencies = [ "unreachable", ] +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "console_log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501a375961cef1a0d44767200e66e4a559283097e91d0730b1d75dfb2f8a1494" +dependencies = [ + "log", + "web-sys", +] + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -546,21 +568,11 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "crossbeam-channel" -version = "0.4.4" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" +checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836" dependencies = [ - "crossbeam-utils 0.7.2", - "maybe-uninit", + "cfg-if", ] [[package]] @@ -569,8 +581,8 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils 0.8.5", + "cfg-if", + "crossbeam-utils", ] [[package]] @@ -579,9 +591,9 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crossbeam-epoch", - "crossbeam-utils 0.8.5", + "crossbeam-utils", ] [[package]] @@ -590,31 +602,20 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils 0.8.5", + "cfg-if", + "crossbeam-utils", "lazy_static", "memoffset", "scopeguard", ] -[[package]] -name = "crossbeam-utils" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" -dependencies = [ - "autocfg", - "cfg-if 0.1.10", - "lazy_static", -] - [[package]] name = "crossbeam-utils" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "lazy_static", ] @@ -630,7 +631,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ - "generic-array 0.14.4", + "generic-array", "subtle", ] @@ -640,33 +641,20 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58bcd97a54c7ca5ce2f6eb16f6bede5b0ab5f0055fedc17d2f0b4466e21671ca" dependencies = [ - "generic-array 0.14.4", + "generic-array", "subtle", ] [[package]] name = "crypto-mac" -version = "0.10.1" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" dependencies = [ - "generic-array 0.14.4", + "generic-array", "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" @@ -674,7 +662,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" dependencies = [ "byteorder", - "digest 0.9.0", + "digest", "rand_core 0.5.1", "subtle", "zeroize", @@ -686,7 +674,7 @@ version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "num_cpus", "rayon", ] @@ -706,18 +694,9 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", -] - -[[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", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -726,7 +705,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.4", + "generic-array", ] [[package]] @@ -740,11 +719,10 @@ dependencies = [ [[package]] name = "ed25519" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4620d40f6d2601794401d6dd95a5cf69b6c157852539470eeda433a99b3c0efc" +checksum = "74e1069e39f1454367eb2de793ed062fac4c35c2934b76a81d90dd9abcd28816" dependencies = [ - "serde", "signature", ] @@ -754,11 +732,10 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" dependencies = [ - "curve25519-dalek 3.2.0", + "curve25519-dalek", "ed25519", "rand 0.7.3", "serde", - "serde_bytes", "sha2", "zeroize", ] @@ -783,9 +760,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f86b50932a01e7ec5c06160492ab660fb19b6bb2a7878030dd6cd68d21df9d4d" dependencies = [ "enum-ordinalize", - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -796,11 +773,11 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "encoding_rs" -version = "0.8.29" +version = "0.8.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a74ea89a0a1b98f6332de42c95baff457ada66d1cb4030f9ff151b2041a1c746" +checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -811,9 +788,9 @@ checksum = "0b166c9e378360dd5a6666a9604bb4f54ae0cac39023ffbac425e917a2a04fef" dependencies = [ "num-bigint", "num-traits", - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -831,16 +808,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "env_logger" -version = "0.8.4" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" +checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" dependencies = [ "atty", "humantime", @@ -865,9 +842,9 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", "synstructure", ] @@ -893,7 +870,7 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "redox_syscall", "winapi", @@ -932,9 +909,9 @@ dependencies = [ "fixed", "paste", "proc-macro-error", - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -953,7 +930,7 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crc32fast", "libc", "miniz_oxide", @@ -975,6 +952,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" + [[package]] name = "futures" version = "0.3.17" @@ -1031,9 +1014,9 @@ checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb" dependencies = [ "autocfg", "proc-macro-hack", - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1069,15 +1052,6 @@ dependencies = [ "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.4" @@ -1105,9 +1079,11 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", + "js-sys", "libc", "wasi 0.9.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -1116,28 +1092,22 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", - "wasi 0.10.0+wasi-snapshot-preview1", + "wasi 0.10.2+wasi-snapshot-preview1", ] [[package]] name = "gimli" -version = "0.25.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7" - -[[package]] -name = "glob" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" [[package]] name = "goblin" -version = "0.3.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "669cdc3826f69a51d3f8fc3f86de81c2378110254f678b8407977736122057a4" +checksum = "32401e89c6446dcd28185931a01b1093726d0356820ac744023e6850689bf926" dependencies = [ "log", "plain", @@ -1146,11 +1116,11 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd819562fcebdac5afc5c113c3ec36f902840b70fd4fc458799c8ce4607ae55" +checksum = "8f072413d126e57991455e0a922b31e4c8ba7c2ffbebf6b78b4f8521397d65cd" dependencies = [ - "bytes 1.1.0", + "bytes", "fnv", "futures-core", "futures-sink", @@ -1211,18 +1181,6 @@ dependencies = [ "libc", ] -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "histogram" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cb882ccb290b8646e554b157ab0b71e64e8d5bef775cd66b6531e52d302669" - [[package]] name = "hmac" version = "0.8.1" @@ -1230,7 +1188,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" dependencies = [ "crypto-mac 0.8.0", - "digest 0.9.0", + "digest", ] [[package]] @@ -1240,17 +1198,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "deae6d9dbb35ec2c502d62b8f7b1c000a0822c3b0794ba36b3149c0a1c840dff" dependencies = [ "crypto-mac 0.9.1", - "digest 0.9.0", + "digest", ] [[package]] name = "hmac" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" dependencies = [ - "crypto-mac 0.10.1", - "digest 0.9.0", + "crypto-mac 0.11.1", + "digest", ] [[package]] @@ -1259,8 +1217,8 @@ 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.4", + "digest", + "generic-array", "hmac 0.8.1", ] @@ -1270,9 +1228,9 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" dependencies = [ - "bytes 1.1.0", + "bytes", "fnv", - "itoa", + "itoa 0.4.8", ] [[package]] @@ -1281,7 +1239,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" dependencies = [ - "bytes 1.1.0", + "bytes", "http", "pin-project-lite", ] @@ -1294,9 +1252,9 @@ checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" [[package]] name = "httpdate" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "humantime" @@ -1306,11 +1264,11 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.14" +version = "0.14.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b91bb1f221b6ea1f1e4371216b70f40748774c2fb5971b450c07773fb92d26b" +checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" dependencies = [ - "bytes 1.1.0", + "bytes", "futures-channel", "futures-core", "futures-util", @@ -1319,7 +1277,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa", + "itoa 0.4.8", "pin-project-lite", "socket2", "tokio", @@ -1330,17 +1288,15 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.22.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64" +checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" dependencies = [ - "futures-util", + "http", "hyper", - "log", "rustls", "tokio", "tokio-rustls", - "webpki", ] [[package]] @@ -1370,16 +1326,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", + "cfg-if", ] [[package]] @@ -1397,12 +1344,27 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + [[package]] name = "jobserver" version = "0.1.24" @@ -1432,35 +1394,32 @@ name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -dependencies = [ - "spin", -] [[package]] name = "libc" -version = "0.2.105" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" [[package]] name = "libloading" -version = "0.6.7" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" +checksum = "afe203d669ec979b7128619bae5a63b7b42e9203c1b29146079ee05e2f604b52" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "winapi", ] [[package]] name = "libsecp256k1" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd1137239ab33b41aa9637a88a28249e5e70c40a42ccc92db7f12cc356c1fcd7" +checksum = "c9d220bc1feda2ac231cb78c3d26f27676b8cf82c96971f7aeef3d0cf2797c73" dependencies = [ "arrayref", "base64 0.12.3", - "digest 0.9.0", + "digest", "hmac-drbg", "libsecp256k1-core", "libsecp256k1-gen-ecmult", @@ -1478,7 +1437,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80" dependencies = [ "crunchy", - "digest 0.9.0", + "digest", "subtle", ] @@ -1515,12 +1474,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] name = "mango" -version = "3.2.13" +version = "3.3.0" dependencies = [ "anchor-lang", "arrayref", @@ -1544,7 +1503,7 @@ dependencies = [ "spl-token", "static_assertions", "switchboard-program", - "tarpc 0.26.2", + "tarpc", "thiserror", ] @@ -1569,10 +1528,10 @@ version = "3.0.0" dependencies = [ "bytemuck", "mango-common", - "quote 1.0.10", + "quote", "safe-transmute", "solana-program", - "syn 1.0.74", + "syn", ] [[package]] @@ -1581,12 +1540,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - [[package]] name = "memchr" version = "2.4.1" @@ -1595,18 +1548,18 @@ checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "memmap2" -version = "0.1.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b70ca2a6103ac8b665dc150b142ef0e4e89df640c9e6cf295d189c3caebe5a" +checksum = "4647a11b578fead29cdbb34d4adef8dd3dc35b876c9c6d5240d83f205abfe96e" dependencies = [ "libc", ] [[package]] name = "memoffset" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ "autocfg", ] @@ -1660,9 +1613,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74e768dff5fb39a41b3bcd30bb25cf989706c90d028d1ad71971987aa309d535" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" dependencies = [ "autocfg", "num-integer", @@ -1675,9 +1628,9 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1726,9 +1679,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "486ea01961c4a818096de679a8b740b26d9033146ac5291b1c98557658f8cdd9" dependencies = [ "proc-macro-crate 1.1.0", - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1742,9 +1695,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" [[package]] name = "opaque-debug" @@ -1770,9 +1723,9 @@ dependencies = [ [[package]] name = "ouroboros" -version = "0.10.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84236d64f1718c387232287cf036eb6632a5ecff226f4ff9dccb8c2b79ba0bde" +checksum = "f357ef82d1b4db66fbed0b8d542cbd3c22d0bf5b393b3c257b9ba4568e70c9c3" dependencies = [ "aliasable", "ouroboros_macro", @@ -1781,15 +1734,15 @@ dependencies = [ [[package]] name = "ouroboros_macro" -version = "0.10.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f463857a6eb96c0136b1d56e56c718350cef30412ec065b48294799a088bca68" +checksum = "44a0b52c2cbaef7dffa5fec1a43274afe8bd2a644fa9fc50a9ef4ff0269b1257" dependencies = [ "Inflector", "proc-macro-error", - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1809,7 +1762,7 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "instant", "libc", "redox_syscall", @@ -1819,17 +1772,17 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58" +checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" [[package]] name = "pbkdf2" -version = "0.6.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3b8c0d71734018084da0c0354193a5edfb81b20d2d57a92c5b154aefc554a4a" +checksum = "f05894bce6a1ba4be299d0c5f29563e08af2bc18bb7d48313113bed71e904739" dependencies = [ - "crypto-mac 0.10.1", + "crypto-mac 0.11.1", ] [[package]] @@ -1862,9 +1815,9 @@ version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1881,9 +1834,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.22" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" [[package]] name = "plain" @@ -1923,9 +1876,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", "version_check", ] @@ -1935,8 +1888,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", + "proc-macro2", + "quote", "version_check", ] @@ -1954,20 +1907,11 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" [[package]] name = "proc-macro2" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -dependencies = [ - "unicode-xid 0.1.0", -] - -[[package]] -name = "proc-macro2" -version = "1.0.30" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70" +checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1" dependencies = [ - "unicode-xid 0.2.2", + "unicode-xid", ] [[package]] @@ -1976,9 +1920,9 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bf29726d67464d49fa6224a1d07936a8c08bb3fba727c7493f6cf1616fdaada" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", "version_check", "yansi", ] @@ -2001,22 +1945,13 @@ dependencies = [ "byteorder", ] -[[package]] -name = "quote" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" -dependencies = [ - "proc-macro2 0.4.30", -] - [[package]] name = "quote" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" dependencies = [ - "proc-macro2 1.0.30", + "proc-macro2", ] [[package]] @@ -2128,9 +2063,9 @@ version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" dependencies = [ - "crossbeam-channel 0.5.1", + "crossbeam-channel", "crossbeam-deque", - "crossbeam-utils 0.8.5", + "crossbeam-utils", "lazy_static", "num_cpus", ] @@ -2172,12 +2107,12 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.6" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d2927ca2f685faf0fc620ac4834690d29e7abb153add10f5812eef20b5e280" +checksum = "07bea77bc708afa10e59905c3d4af7c8fd43c9214251673095ff8b14345fcbc5" dependencies = [ "base64 0.13.0", - "bytes 1.1.0", + "bytes", "encoding_rs", "futures-core", "futures-util", @@ -2193,6 +2128,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "rustls", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", @@ -2223,22 +2159,22 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353775f96a1f400edcca737f843cb201af3645912e741e64456a257c770173e8" +checksum = "71b5a9625a7e6060b23db692facf49082cc78889a7e6ac94a735356ae49db4b0" dependencies = [ - "arrayvec", + "arrayvec 0.5.2", "num-traits", "serde", ] [[package]] name = "rust_decimal_macros" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0847e5bbcded958275518f18a567fea27e53b22b52b549cc3557c88d780b22e" +checksum = "f2a71e447554613b11da876d63d04e78fc3e8e86769488d3b58887671e23bc86" dependencies = [ - "quote 1.0.10", + "quote", "rust_decimal", ] @@ -2250,46 +2186,54 @@ checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" [[package]] name = "rustc_version" -version = "0.2.3" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" dependencies = [ - "semver 0.9.0", + "semver 0.11.0", ] [[package]] name = "rustc_version" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 0.11.0", + "semver 1.0.4", ] [[package]] name = "rustls" -version = "0.19.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" +checksum = "d37e5e2290f3e040b594b1a9e04377c2c671f1a1cfd9bfdef82106ac1c113f84" dependencies = [ - "base64 0.13.0", "log", "ring", "sct", - "webpki", + "webpki 0.22.0", +] + +[[package]] +name = "rustls-pemfile" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +dependencies = [ + "base64 0.13.0", ] [[package]] name = "rustversion" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" [[package]] name = "ryu" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" [[package]] name = "safe-transmute" @@ -2327,44 +2271,35 @@ version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aaaae8f38bb311444cfb7f1979af0bc9240d95795f75f9ceddf6a59b79ceffa0" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "sct" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" dependencies = [ "ring", "untrusted", ] -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser 0.7.0", -] - [[package]] name = "semver" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" dependencies = [ - "semver-parser 0.10.2", + "semver-parser", ] [[package]] -name = "semver-parser" -version = "0.7.0" +name = "semver" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012" [[package]] name = "semver-parser" @@ -2377,9 +2312,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.130" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008" dependencies = [ "serde_derive", ] @@ -2395,22 +2330,22 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.130" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +checksum = "ecc0db5cb2556c0e558887d9bbdcf6ac4471e83ff66cf696e5419024d1606276" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "serde_json" -version = "1.0.68" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8" +checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5" dependencies = [ - "itoa", + "itoa 1.0.1", "ryu", "serde", ] @@ -2422,7 +2357,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" dependencies = [ "form_urlencoded", - "itoa", + "itoa 0.4.8", "ryu", "serde", ] @@ -2438,7 +2373,7 @@ dependencies = [ "byteorder", "enumflags2", "field-offset", - "itertools", + "itertools 0.9.0", "num-traits", "num_enum", "safe-transmute", @@ -2457,9 +2392,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" dependencies = [ "block-buffer", - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", - "digest 0.9.0", + "digest", "opaque-debug", ] @@ -2470,7 +2405,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" dependencies = [ "block-buffer", - "digest 0.9.0", + "digest", "keccak", "opaque-debug", ] @@ -2522,51 +2457,65 @@ dependencies = [ ] [[package]] -name = "solana-banks-client" -version = "1.8.1" +name = "solana-address-lookup-table-program" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eab68373f57d2944165df23d0befd3e94cbc13b5850115a73c80ea1c737efcd" +checksum = "6f2b93bfd2381644ca97283dafafbd2432c18d019a9db9e969f6a83974e3d633" dependencies = [ "bincode", + "bytemuck", + "log", + "num-derive", + "num-traits", + "rustc_version 0.4.0", + "serde", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-program-runtime", + "solana-sdk", + "thiserror", +] + +[[package]] +name = "solana-banks-client" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "611126ff3a87494fc34ff9e87531557c6c3bc884a783b97c93d1a928a66cdcef" +dependencies = [ "borsh", - "borsh-derive", "futures", - "mio", "solana-banks-interface", "solana-program", "solana-sdk", - "tarpc 0.24.1", + "tarpc", "tokio", "tokio-serde", ] [[package]] name = "solana-banks-interface" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2443eb038c46e41716fd2e8815f7d3529a7635759d52efee7a97a77ff1b03eaf" +checksum = "903d4f54f987662515a88cef02d00b71eb5814151ae482fc586271db85d1667f" dependencies = [ - "mio", "serde", "solana-sdk", - "tarpc 0.24.1", + "tarpc", ] [[package]] name = "solana-banks-server" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56d33f0d61e4dadc01dbb51725c9547ca8f69a014df5c7bb6a0843d77345efc4" +checksum = "df569d5d66d960f9e0442fac2b987d89677408a3bb91977dbe5b2ab564cfbaa1" dependencies = [ "bincode", "futures", - "log", - "mio", "solana-banks-interface", - "solana-metrics", "solana-runtime", "solana-sdk", - "tarpc 0.24.1", + "solana-send-transaction-service", + "tarpc", "tokio", "tokio-serde", "tokio-stream", @@ -2574,94 +2523,74 @@ dependencies = [ [[package]] name = "solana-bpf-loader-program" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bc793a7b9f29e44c0555fcfddc61be52566d683f79cfef306585624730231e2" +checksum = "23c46a06de01b525331888629aa52b3d599d2965445e003ed0e9faf4b88e0acc" dependencies = [ "bincode", "byteorder", "libsecp256k1", "log", - "num-derive", - "num-traits", - "rand_core 0.6.3", - "sha3", "solana-measure", - "solana-runtime", + "solana-program-runtime", "solana-sdk", "solana_rbpf", "thiserror", ] [[package]] -name = "solana-compute-budget-program" -version = "1.8.1" +name = "solana-bucket-map" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1fbeaf9f36f6a65ac24ebd8e5e3e6d4c7ff3d2c8dd3fdd13840d172224f9da7" +checksum = "c38d7dcd4031fd0a987153b58e0b29380849f7fdacd27bda0f2a7f1bbd0d0003" dependencies = [ + "fs_extra", + "log", + "memmap2", + "rand 0.7.3", + "rayon", + "solana-logger", + "solana-measure", "solana-sdk", + "tempfile", ] [[package]] -name = "solana-config-program" -version = "1.8.1" +name = "solana-compute-budget-program" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5ddaa6d56b916be20844b3b9c63eb00ed85d380fb81b16980597e28e42735c" +checksum = "3e2fa312af223ddd96c5499a8bbd2f5d1f262ed57096d87e452d4ddce84685a8" dependencies = [ - "bincode", - "chrono", - "log", - "rand_core 0.6.3", - "serde", - "serde_derive", + "solana-program-runtime", "solana-sdk", ] [[package]] -name = "solana-crate-features" -version = "1.8.1" +name = "solana-config-program" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea5bf3b209175e533816fe77c095b3dd33d5bb03fcb084063a3ed3d0ccb369bb" +checksum = "e47862d56d8ea98e604c92e0ff8c2c2a0eb8e34ad0cc27f7da788a674006b2af" dependencies = [ - "backtrace", - "bytes 0.4.12", - "cc", - "curve25519-dalek 2.1.3", - "ed25519-dalek", - "either", - "lazy_static", - "libc", - "rand_chacha 0.2.2", - "regex-syntax", - "reqwest", - "ring", + "bincode", + "chrono", "serde", - "syn 0.15.44", - "syn 1.0.74", - "winapi", -] - -[[package]] -name = "solana-ed25519-program" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecaf98fc6fd00997bbadc71c77875bb22c03375f44ec131807806910b3c155eb" -dependencies = [ + "serde_derive", + "solana-program-runtime", "solana-sdk", ] [[package]] name = "solana-frozen-abi" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487f0d6f041e5b753e18004eed1e9b61a4044389d9d67b98e7b82cf185ae1437" +checksum = "bd0c18abe9d7b525215f3de16db3fca6057affdd73464ca027786b42455257b9" dependencies = [ - "bs58 0.3.1", + "bs58 0.4.0", "bv", - "generic-array 0.14.4", + "generic-array", "log", "memmap2", - "rustc_version 0.2.3", + "rustc_version 0.4.0", "serde", "serde_derive", "sha2", @@ -2672,21 +2601,21 @@ dependencies = [ [[package]] name = "solana-frozen-abi-macro" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da3f4c84ab2308a310a6fc0457e7ad234b2f375ee62d9c4ef3d83319df6f3df9" +checksum = "4221e1b9cfad821fa097a61c1827f8214c2ef97057c270d5f68a52d90929ae2a" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "rustc_version 0.2.3", - "syn 1.0.74", + "proc-macro2", + "quote", + "rustc_version 0.4.0", + "syn", ] [[package]] name = "solana-logger" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0397bbbbf03e7a40db4d722d417d876e8b6cecb0cc4f757dbd82313bca33e54" +checksum = "e0a5b4d8fe05eab74ca3c7afd79e6143bed4028997bf36de06b7f503b55b125c" dependencies = [ "env_logger", "lazy_static", @@ -2695,20 +2624,19 @@ dependencies = [ [[package]] name = "solana-measure" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56b3e28a507832dad70ce60249ce78b7d1049f6eaaceb7b642f616b880f634b" +checksum = "95d84878a3a0b72347082622d48729490eecd0a90bbdf4cf42c5a15616a7b59f" dependencies = [ "log", - "solana-metrics", "solana-sdk", ] [[package]] name = "solana-metrics" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2af9cec93596c79479874772d974105c6ea388858f431d8defaa3f42d9da3c" +checksum = "5f787e354ed0868239f751ad1ed2759fbf6f320af28952389873e08250fcf9cd" dependencies = [ "env_logger", "gethostname", @@ -2720,28 +2648,33 @@ dependencies = [ [[package]] name = "solana-program" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3b963b0d276b6bb5a747ea2918276067fb915b38e68acd6562d1776e4c32e91" +checksum = "32d577959f537ba4435db97588fe2ea5520c98483ef5fcf6a0fb8ca096f82213" dependencies = [ "base64 0.13.0", "bincode", + "bitflags", "blake3", "borsh", "borsh-derive", - "bs58 0.3.1", + "bs58 0.4.0", "bv", "bytemuck", - "curve25519-dalek 2.1.3", - "hex", - "itertools", + "console_error_panic_hook", + "console_log", + "curve25519-dalek", + "getrandom 0.1.16", + "itertools 0.10.3", + "js-sys", "lazy_static", "libsecp256k1", "log", "num-derive", "num-traits", + "parking_lot", "rand 0.7.3", - "rustc_version 0.2.3", + "rustc_version 0.4.0", "rustversion", "serde", "serde_bytes", @@ -2753,27 +2686,47 @@ dependencies = [ "solana-logger", "solana-sdk-macro", "thiserror", + "wasm-bindgen", +] + +[[package]] +name = "solana-program-runtime" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a5f9d3ffed08c8aac0bff87957ddc9d62596cb55355dd0ec300d0454393cde8" +dependencies = [ + "base64 0.13.0", + "bincode", + "itertools 0.10.3", + "libc", + "libloading", + "log", + "num-derive", + "num-traits", + "rustc_version 0.4.0", + "serde", + "solana-logger", + "solana-sdk", + "thiserror", ] [[package]] name = "solana-program-test" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "160b9fbf27e859e5294bc3eac0f9312869c74aeab820ea4d506f484f21b0926b" +checksum = "fba681326ba093d5e7681ed56798bb561b4ef6ef1cd7673b5240d4630319c170" dependencies = [ "async-trait", "base64 0.12.3", "bincode", - "chrono", "chrono-humanize", "log", - "mio", "serde", - "serde_derive", "solana-banks-client", "solana-banks-server", "solana-bpf-loader-program", "solana-logger", + "solana-program-runtime", "solana-runtime", "solana-sdk", "solana-vote-program", @@ -2783,9 +2736,9 @@ dependencies = [ [[package]] name = "solana-rayon-threadlimit" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3df83f803a2e80a593b9281b8709a5a4f02327173609d417bfeb222b6a189b66" +checksum = "e818a20dc5260d3cb93779af9f78dc54c4b99e5c759d99a901faf0a1669c1a89" dependencies = [ "lazy_static", "num_cpus", @@ -2793,9 +2746,9 @@ dependencies = [ [[package]] name = "solana-runtime" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b50380b43b0bd74e2f3d37db958816de33f562e6721943b414adf4d7d2a11a" +checksum = "80b0b55b47cf724bb9824704912eb194f4752e27de4fbfd59d78829501005029" dependencies = [ "arrayref", "bincode", @@ -2803,16 +2756,13 @@ dependencies = [ "bv", "byteorder", "bzip2", - "crossbeam-channel 0.4.4", + "crossbeam-channel", "dashmap", "dir-diff", "flate2", "fnv", - "histogram", - "itertools", + "itertools 0.10.3", "lazy_static", - "libc", - "libloading", "log", "memmap2", "num-derive", @@ -2822,20 +2772,21 @@ dependencies = [ "rand 0.7.3", "rayon", "regex", - "rustc_version 0.2.3", + "rustc_version 0.4.0", "serde", "serde_derive", + "solana-address-lookup-table-program", + "solana-bucket-map", "solana-compute-budget-program", "solana-config-program", - "solana-ed25519-program", "solana-frozen-abi", "solana-frozen-abi-macro", "solana-logger", "solana-measure", "solana-metrics", + "solana-program-runtime", "solana-rayon-threadlimit", "solana-sdk", - "solana-secp256k1-program", "solana-stake-program", "solana-vote-program", "symlink", @@ -2847,28 +2798,26 @@ dependencies = [ [[package]] name = "solana-sdk" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2011ffd22e5ae4af04dd811153b3ba677de2bf314f6f9ae669e1d051e678b18" +checksum = "90ef66f3e69f3b0d2675b9a80fbb92514eaf6fb24755f2c63b274983d990a947" dependencies = [ "assert_matches", "base64 0.13.0", "bincode", "borsh", - "borsh-derive", "bs58 0.4.0", - "bv", "bytemuck", "byteorder", "chrono", "derivation-path", - "digest 0.9.0", + "digest", "ed25519-dalek", "ed25519-dalek-bip32", - "generic-array 0.14.4", - "hex", - "hmac 0.10.1", - "itertools", + "generic-array", + "hmac 0.11.0", + "itertools 0.10.3", + "js-sys", "lazy_static", "libsecp256k1", "log", @@ -2879,8 +2828,7 @@ dependencies = [ "qstring", "rand 0.7.3", "rand_chacha 0.2.2", - "rand_core 0.6.3", - "rustc_version 0.2.3", + "rustc_version 0.4.0", "rustversion", "serde", "serde_bytes", @@ -2888,7 +2836,6 @@ dependencies = [ "serde_json", "sha2", "sha3", - "solana-crate-features", "solana-frozen-abi", "solana-frozen-abi-macro", "solana-logger", @@ -2896,47 +2843,53 @@ dependencies = [ "solana-sdk-macro", "thiserror", "uriparse", + "wasm-bindgen", ] [[package]] name = "solana-sdk-macro" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0743f2383bb6848f239f4e28d6a2a6fedb04c8ca8f4e5be019c46676c3695178" +checksum = "0664789b09d768bfab1fc34c532d8cd1abfc63b2ec8174c7b65e6b17f08e7841" dependencies = [ - "bs58 0.3.1", - "proc-macro2 1.0.30", - "quote 1.0.10", + "bs58 0.4.0", + "proc-macro2", + "quote", "rustversion", - "syn 1.0.74", + "syn", ] [[package]] -name = "solana-secp256k1-program" -version = "1.8.1" +name = "solana-send-transaction-service" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02899da50b8fed16f5e67563a49b37bd61601cc8347420ffb7cb0e6970f67d9" +checksum = "e2a1ad50ef3bcf43e68a16e6301bd3ef2c4043f5ab9ac3c99c1dbe8122c2a4d2" dependencies = [ + "log", + "solana-logger", + "solana-metrics", + "solana-runtime", "solana-sdk", ] [[package]] name = "solana-stake-program" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d0e1070259405f1060541c23db58f522c035b332e020300ad7f716eddcc21" +checksum = "2e77b1d008c08d8c0acb6e243bbaacb12b5be9d75ba18a422d327a400b98151a" dependencies = [ "bincode", "log", "num-derive", "num-traits", - "rustc_version 0.2.3", + "rustc_version 0.4.0", "serde", "serde_derive", "solana-config-program", "solana-frozen-abi", "solana-frozen-abi-macro", "solana-metrics", + "solana-program-runtime", "solana-sdk", "solana-vote-program", "thiserror", @@ -2944,30 +2897,31 @@ dependencies = [ [[package]] name = "solana-vote-program" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c796ecb8b4db6274ba93a5a5d4a6f29ef824a1c69ba5974b17ebda3313025c9c" +checksum = "2a1f5e96eddd7ad93437ef6c66c3233e2cdc96f73090a6798b376dd460a4cab4" dependencies = [ "bincode", "log", "num-derive", "num-traits", - "rustc_version 0.2.3", + "rustc_version 0.4.0", "serde", "serde_derive", "solana-frozen-abi", "solana-frozen-abi-macro", "solana-logger", "solana-metrics", + "solana-program-runtime", "solana-sdk", "thiserror", ] [[package]] name = "solana_rbpf" -version = "0.2.11" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c1c5bdfa63c68d848d95024c7f4335bae4b1917f7df2e48e2d945f4664a8b45" +checksum = "4b4ea641d81290842c822f1348ce9f35ff3e11d09553e709c894af9765b7934c" dependencies = [ "byteorder", "combine", @@ -3022,9 +2976,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "switchboard-program" -version = "0.1.57" +version = "0.1.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc25b7b5f6dc1e19dcca7b126c14134b809247ffbb79a350daf33a34c0050221" +checksum = "57445d78029687264e245eb949e5c928e3aecd64a0afea770fc4fb2a826e60e0" dependencies = [ "bincode", "borsh", @@ -3050,9 +3004,9 @@ dependencies = [ [[package]] name = "switchboard-utils" -version = "0.1.29" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e23312fc25d692af16e609c636a1ecd00c1f7c8b08c10ac53cb65ac3689c6ad" +checksum = "0bc027ee269f663f2a6a848ee3c819936dbdbd35d74b9c4fb2aaf3f0360d903f" dependencies = [ "bincode", "borsh", @@ -3073,24 +3027,13 @@ checksum = "a7973cce6668464ea31f176d85b13c7ab3bba2cb3b77a2ed26abd7801688010a" [[package]] name = "syn" -version = "0.15.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "unicode-xid 0.1.0", -] - -[[package]] -name = "syn" -version = "1.0.74" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "unicode-xid 0.2.2", + "proc-macro2", + "quote", + "unicode-xid", ] [[package]] @@ -3099,44 +3042,23 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", - "unicode-xid 0.2.2", + "proc-macro2", + "quote", + "syn", + "unicode-xid", ] [[package]] name = "tar" -version = "0.4.37" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f5515d3add52e0bbdcad7b83c388bb36ba7b754dda3b5f5bc2d38640cdba5c" +checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" dependencies = [ "filetime", "libc", "xattr", ] -[[package]] -name = "tarpc" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e325774dd5b35d979e9f4db2b0f0d7d85dc2ff2b676a3150af56c09eafc14b07" -dependencies = [ - "anyhow", - "fnv", - "futures", - "humantime", - "log", - "pin-project", - "rand 0.7.3", - "serde", - "static_assertions", - "tarpc-plugins 0.9.0", - "tokio", - "tokio-serde", - "tokio-util", -] - [[package]] name = "tarpc" version = "0.26.2" @@ -3152,7 +3074,7 @@ dependencies = [ "rand 0.8.4", "serde", "static_assertions", - "tarpc-plugins 0.11.0", + "tarpc-plugins", "thiserror", "tokio", "tokio-serde", @@ -3161,26 +3083,15 @@ dependencies = [ "tracing-opentelemetry", ] -[[package]] -name = "tarpc-plugins" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3240378a22b1195734e085ba71d1d4188d50f034aea82635acc430b7005afb5" -dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", -] - [[package]] name = "tarpc-plugins" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea80818e6c75f81d961d7426c1b938cbea6b3a51533b5ee71b61f82166b7ef3d" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -3189,7 +3100,7 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "rand 0.8.4", "redox_syscall", @@ -3221,9 +3132,9 @@ version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -3237,20 +3148,19 @@ dependencies = [ [[package]] name = "time" -version = "0.1.44" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ "libc", - "wasi 0.10.0+wasi-snapshot-preview1", "winapi", ] [[package]] name = "tinyvec" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83b2a3d4d9091d0abd7eba4dc2710b1718583bd4d8992e2190720ea38f391f7" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" dependencies = [ "tinyvec_macros", ] @@ -3263,12 +3173,11 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.12.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2c2416fdedca8443ae44b4527de1ea633af61d8f7169ffa6e72c5b53d24efcc" +checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" dependencies = [ - "autocfg", - "bytes 1.1.0", + "bytes", "libc", "memchr", "mio", @@ -3283,24 +3192,24 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.5.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2dd85aeaba7b68df939bd357c6afb36c87951be9e80bf9c859f2fc3e9fca0fd" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "tokio-rustls" -version = "0.22.0" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" +checksum = "a27d5f2b839802bd8267fa19b0530f5a08b9c08cd417976be2a65d130fe1c11b" dependencies = [ "rustls", "tokio", - "webpki", + "webpki 0.22.0", ] [[package]] @@ -3310,20 +3219,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "911a61637386b789af998ee23f50aa30d5fd7edcec8d6d3dedae5e5815205466" dependencies = [ "bincode", - "bytes 1.1.0", + "bytes", "educe", "futures-core", "futures-sink", "pin-project", "serde", - "serde_json", ] [[package]] name = "tokio-stream" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b2f3f698253f03119ac0102beaa64f67a67e08074d03a22d18784104543727f" +checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" dependencies = [ "futures-core", "pin-project-lite", @@ -3332,11 +3240,11 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d3725d3efa29485e87311c5b699de63cde14b00ed4d256b8318aa30ca452cd" +checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" dependencies = [ - "bytes 1.1.0", + "bytes", "futures-core", "futures-sink", "log", @@ -3366,7 +3274,7 @@ version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "log", "pin-project-lite", "tracing-attributes", @@ -3379,9 +3287,9 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -3455,12 +3363,6 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" - [[package]] name = "unicode-xid" version = "0.2.2" @@ -3545,9 +3447,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" +version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm-bindgen" @@ -3555,7 +3457,7 @@ version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "wasm-bindgen-macro", ] @@ -3568,9 +3470,9 @@ dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", "wasm-bindgen-shared", ] @@ -3580,7 +3482,7 @@ version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", @@ -3592,7 +3494,7 @@ version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" dependencies = [ - "quote 1.0.10", + "quote", "wasm-bindgen-macro-support", ] @@ -3602,9 +3504,9 @@ version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3635,13 +3537,23 @@ 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]] @@ -3724,46 +3636,46 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d498dbd1fd7beb83c86709ae1c33ca50942889473473d287d56ce4770a18edfb" dependencies = [ - "proc-macro2 1.0.30", - "syn 1.0.74", + "proc-macro2", + "syn", "synstructure", ] [[package]] name = "zeroize" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf68b08513768deaa790264a7fac27a58cbf2705cfcdc9448362229217d7e970" +checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdff2024a851a322b08f179173ae2ba620445aef1e838f0c196820eade4ae0c7" +checksum = "65f1a51723ec88c66d5d1fe80c841f17f63587d6691901d66be9bec6c3b51f73" dependencies = [ - "proc-macro2 1.0.30", - "quote 1.0.10", - "syn 1.0.74", + "proc-macro2", + "quote", + "syn", "synstructure", ] [[package]] name = "zstd" -version = "0.5.4+zstd.1.4.7" +version = "0.9.0+zstd.1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69996ebdb1ba8b1517f61387a883857818a66c8a295f487b1ffd8fd9d2c82910" +checksum = "07749a5dc2cb6b36661290245e350f15ec3bbb304e493db54a1d354480522ccd" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "2.0.6+zstd.1.4.7" +version = "4.1.1+zstd.1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98aa931fb69ecee256d44589d19754e61851ae4769bf963b385119b1cc37a49e" +checksum = "c91c90f2c593b003603e5e0493c837088df4469da25aafff8bce42ba48caf079" dependencies = [ "libc", "zstd-sys", @@ -3771,12 +3683,10 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "1.4.18+zstd.1.4.7" +version = "1.6.1+zstd.1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e6e8778706838f43f771d80d37787cb2fe06dafe89dd3aebaf6721b9eaec81" +checksum = "615120c7a2431d16cf1cf979e7fc31ba7a5b5e5707b29c8a99e5dbf8a8392a33" dependencies = [ "cc", - "glob", - "itertools", "libc", ] diff --git a/README.md b/README.md index 2ac9de52..3e99f18b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # Mango Markets V3 - Decentralized Margin Trading ## ⚠️ Warning - Any content produced by Blockworks, or developer resources that Blockworks provides, are for educational and inspiration purposes only. Blockworks does not encourage, induce or sanction the deployment of any such applications in violation of applicable laws or regulations. ## Contribute @@ -11,4 +10,16 @@ Significant contributions to the source code may be compensated with a grant fro Mango is currently unaudited software. Use at your own risk. You will be compensated by the Mango DAO for privately reporting vulnerabilities to the maintainers of this repo. -Email hello@blockworks.foundation \ No newline at end of file +Email hello@blockworks.foundation + +## Branches and Tags +- New development happens on `main`. Pull requests should always target `main` by default. +- Release branches have names like `release/3.3.0` and are branched off of `main` or a parent release branch. + + - Bugfixes for releases should usually be merged into `main` and then be cherry-picked to + the release branch. + - Only push to release branches after talking to the release owner. + - When a release is done, the released version is tagged and the release branch is + deleted. +- Release tags have names like `v3.3.1`. +- To know what is deployed on mainnet, check the [Anchor Builds](https://anchor.projectserum.com/program/mv3ekLzLbnVPNxjSKvqBpU3ZeZXPQdEC3bp5MDEBG68). diff --git a/changelog.md b/changelog.md index b0499825..e2ddd892 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,17 @@ # Mango Program Change Log +## v3.3.0 +Deployed: Jan 17, 2022 at 00:45:05 UTC | Slot: 116,585,405 +1. CancelAllPerpOrdersSide - cancels all order on one side +2. CloseMangoAccount - close account and retrieve lamports +3. ResolveDust - settle anything below 1 native SPL against the dust account +4. CreateDustAccount - create a PDA tied to the MangoGroup useful for settling dust against +5. SetDelegate - delegate authority to operate MangoAccount to another account +6. upgrade packages +7. impose price limits for placing limit orders +8. ChangeSpotMarketParams +9. CreateSpotOpenOrders using PDA for better UX + ## v3.2.16 Deployed: Jan 11, 2022 at 01:59:05 UTC | Slot: 115,691,635 1. Checked math in all areas touched by place_perp_order diff --git a/mango-logs/Cargo.toml b/mango-logs/Cargo.toml index 2ec604c0..7bf06206 100644 --- a/mango-logs/Cargo.toml +++ b/mango-logs/Cargo.toml @@ -17,4 +17,4 @@ devnet = [] default = [] [dependencies] -anchor-lang = "0.18.0" +anchor-lang = "0.20.1" diff --git a/mango-macro/Cargo.toml b/mango-macro/Cargo.toml index e337ae8a..5a756f36 100644 --- a/mango-macro/Cargo.toml +++ b/mango-macro/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" proc-macro = true [dependencies] -syn = "=1.0.74" +syn = "=1.0.82" solana-program = "^1.8.1" bytemuck = "^1.7.2" quote = "^1.0.9" diff --git a/program/Cargo.toml b/program/Cargo.toml index a3a389b2..8449ae67 100644 --- a/program/Cargo.toml +++ b/program/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mango" -version = "3.2.13" +version = "3.3.0" authors = ["blockworks"] edition = "2018" @@ -29,7 +29,7 @@ mango-macro = { path = "../mango-macro" } mango-common = { path = "../common" } mango-logs = { path = "../mango-logs", features=["no-entrypoint"] } switchboard-program = "^0.1.52" -anchor-lang = "0.18.0" +anchor-lang = "0.20.1" [dev-dependencies] solana-sdk = "^1.8.1" diff --git a/program/devnet_deploy.sh b/program/devnet_deploy.sh index 20c38f0e..71e0887f 100644 --- a/program/devnet_deploy.sh +++ b/program/devnet_deploy.sh @@ -6,8 +6,7 @@ if [ $# -eq 0 ] KEYPAIR=$1 fi -# deploy mango program and new mango group -source ~/mango/cli/devnet.env $KEYPAIR +CLUSTER_URL="https://mango.devnet.rpcpool.com" solana config set --url $CLUSTER_URL cd ~/blockworks-foundation/mango-v3/ diff --git a/program/src/error.rs b/program/src/error.rs index 1830b064..ff0ad2f4 100644 --- a/program/src/error.rs +++ b/program/src/error.rs @@ -121,6 +121,8 @@ pub enum MangoErrorCode { InvalidOracleType, #[error("MangoErrorCode::InvalidOraclePrice")] InvalidOraclePrice, + #[error("MangoErrorCode::MaxAccountsReached The maximum number of accounts for this group has been reached")] + MaxAccountsReached, #[error("MangoErrorCode::Default Check the source code for more info")] Default = u32::MAX_VALUE, diff --git a/program/src/instruction.rs b/program/src/instruction.rs index 14830539..ab8496ef 100644 --- a/program/src/instruction.rs +++ b/program/src/instruction.rs @@ -38,7 +38,8 @@ pub enum MangoInstruction { quote_max_rate: I80F48, }, - /// Initialize a mango account for a user + /// DEPRECATED Initialize a mango account for a user + /// Accounts created with this function cannot be closed without upgrading with UpgradeMangoAccountV0V1 /// /// Accounts expected by this instruction (3): /// @@ -78,8 +79,7 @@ pub enum MangoInstruction { /// 7. `[write]` token_account_ai, - /// 8. `[read]` signer_ai, - /// 9. `[read]` token_prog_ai, - - /// 10. `[read]` clock_ai, - - /// 11..+ `[]` open_orders_accs - open orders for each of the spot market + /// 10..+ `[]` open_orders_accs - open orders for each of the spot market Withdraw { quantity: u64, allow_borrow: bool, @@ -207,6 +207,16 @@ pub enum MangoInstruction { }, /// Place an order on a perp market + /// + /// In case this order is matched, the corresponding order structs on both + /// PerpAccounts (taker & maker) will be adjusted, and the position size + /// will be adjusted w/o accounting for fees. + /// In addition a FillEvent will be placed on the event queue. + /// Through a subsequent invocation of ConsumeEvents the FillEvent can be + /// executed and the perp account balances (base/quote) and fees will be + /// paid from the quote position. Only at this point the position balance + /// is 100% refelecting the trade. + /// /// Accounts expected by this instruction (8): /// 0. `[]` mango_group_ai - MangoGroup /// 1. `[writable]` mango_account_ai - the MangoAccount of owner @@ -615,7 +625,7 @@ pub enum MangoInstruction { /// 5. `[]` root_bank_ai - RootBank /// 6. `[writable]` node_bank_ai - NodeBank /// 7+... `[]` liqee_open_orders_ais - Liqee open orders accs - ForceSettleQuotePositions, + ForceSettleQuotePositions, // instruction 40 /// Place an order on the Serum Dex using Mango account. Improved over PlaceSpotOrder /// by reducing the tx size @@ -770,6 +780,149 @@ pub enum MangoInstruction { ChangeMaxMangoAccounts { max_mango_accounts: u32, }, + /// Delete a mango account and return lamports + /// + /// Accounts expected by this instruction (3): + /// + /// 0. `[writable]` mango_group_ai - MangoGroup that this mango account is for + /// 1. `[writable]` mango_account_ai - the mango account data + /// 2. `[signer]` owner_ai - Solana account of owner of the mango account + CloseMangoAccount, // instruction 50 + + /// Delete a spot open orders account and return lamports + /// + /// Accounts expected by this instruction (7): + /// + /// 0. `[]` mango_group_ai - MangoGroup that this mango account is for + /// 1. `[writable]` mango_account_ai - the mango account data + /// 2. `[signer, writable]` owner_ai - Solana account of owner of the mango account + /// 3. `[]` dex_prog_ai - The serum dex program id + /// 4. `[writable]` open_orders_ai - The open orders account to close + /// 5. `[]` spot_market_ai - The spot market for the account + /// 6. `[]` signer_ai - Mango group signer key + CloseSpotOpenOrders, + + /// Delete an advanced orders account and return lamports + /// + /// Accounts expected by this instruction (4): + /// + /// 0. `[]` mango_group_ai - MangoGroup that this mango account is for + /// 1. `[writable]` mango_account_ai - the mango account data + /// 2. `[signer, writable]` owner_ai - Solana account of owner of the mango account + /// 3. `[writable]` advanced_orders_ai - the advanced orders account + CloseAdvancedOrders, + + /// Create a PDA Mango Account for collecting dust owned by a group + /// + /// Accounts expected by this instruction (4) + /// 0. `[]` mango_group_ai - MangoGroup to create the dust account for + /// 1. `[writable]` mango_account_ai - the mango account data + /// 2. `[signer, writable]` signer_ai - Signer and fee payer account + /// 3. `[writable]` system_prog_ai - System program + CreateDustAccount, + + /// Transfer dust (< 1 native SPL token) assets and liabilities for a single token to the group's dust account + /// + /// Accounts expected by this instruction (7) + /// + /// 0. `[]` mango_group_ai - MangoGroup of the mango account + /// 1. `[writable]` mango_account_ai - the mango account data + /// 2. `[signer, writable]` owner_ai - Solana account of owner of the mango account + /// 3. `[writable]` dust_account_ai - Dust Account for the group + /// 4. `[]` root_bank_ai - The root bank for the token + /// 5. `[writable]` node_bank_ai - A node bank for the token + /// 6. `[]` mango_cache_ai - The cache for the group + ResolveDust, + + /// Create a PDA mango account for a user + /// + /// Accounts expected by this instruction (4): + /// + /// 0. `[writable]` mango_group_ai - MangoGroup that this mango account is for + /// 1. `[writable]` mango_account_ai - the mango account data + /// 2. `[signer]` owner_ai - Solana account of owner of the mango account + /// 3. `[]` system_prog_ai - System program + CreateMangoAccount { + account_num: u64, + }, + + /// Upgrade a V0 Mango Account to V1 allowing it to be closed + /// + /// Accounts expected by this instruction (3): + /// + /// 0. `[writable]` mango_group_ai - MangoGroup + /// 1. `[writable]` mango_account_ai - MangoAccount + /// 2. `[signer]` owner_ai - Solana account of owner of the mango account + UpgradeMangoAccountV0V1, + + /// Cancel all perp open orders for one side of the book + /// + /// Accounts expected: 6 + /// 0. `[]` mango_group_ai - MangoGroup + /// 1. `[writable]` mango_account_ai - MangoAccount + /// 2. `[signer]` owner_ai - Owner of Mango Account + /// 3. `[writable]` perp_market_ai - PerpMarket + /// 4. `[writable]` bids_ai - Bids acc + /// 5. `[writable]` asks_ai - Asks acc + CancelPerpOrdersSide { + side: Side, + limit: u8, + }, + + /// https://github.com/blockworks-foundation/mango-v3/pull/97/ + /// Set delegate authority to mango account which can do everything regular account can do + /// except Withdraw and CloseMangoAccount. Set to Pubkey::default() to revoke delegate + /// + /// Accounts expected: 4 + /// 0. `[]` mango_group_ai - MangoGroup + /// 1. `[writable]` mango_account_ai - MangoAccount + /// 2. `[signer]` owner_ai - Owner of Mango Account + /// 3. `[]` delegate_ai - delegate + SetDelegate, + + /// Change the params for a spot market. + /// + /// Accounts expected by this instruction (4): + /// 0. `[writable]` mango_group_ai - MangoGroup + /// 1. `[writable]` spot_market_ai - Market + /// 2. `[writable]` root_bank_ai - RootBank + /// 3. `[signer]` admin_ai - MangoGroup admin + ChangeSpotMarketParams { + #[serde(serialize_with = "serialize_option_fixed_width")] + maint_leverage: Option, + + #[serde(serialize_with = "serialize_option_fixed_width")] + init_leverage: Option, + + #[serde(serialize_with = "serialize_option_fixed_width")] + liquidation_fee: Option, + + #[serde(serialize_with = "serialize_option_fixed_width")] + optimal_util: Option, + + #[serde(serialize_with = "serialize_option_fixed_width")] + optimal_rate: Option, + + #[serde(serialize_with = "serialize_option_fixed_width")] + max_rate: Option, + + #[serde(serialize_with = "serialize_option_fixed_width")] + version: Option, + }, + + /// Create an OpenOrders PDA and initialize it with InitOpenOrders call to serum dex + /// + /// Accounts expected by this instruction (8): + /// + /// 0. `[]` mango_group_ai - MangoGroup that this mango account is for + /// 1. `[writable]` mango_account_ai - MangoAccount + /// 2. `[signer]` owner_ai - MangoAccount owner + /// 3. `[]` dex_prog_ai - program id of serum dex + /// 4. `[writable]` open_orders_ai - open orders PDA + /// 5. `[]` spot_market_ai - dex MarketState account + /// 6. `[]` signer_ai - Group Signer Account + /// 7. `[]` system_prog_ai - System program + CreateSpotOpenOrders, // instruction 60 } impl MangoInstruction { @@ -1167,14 +1320,57 @@ impl MangoInstruction { } } 48 => MangoInstruction::UpdateMarginBasket, - 49 => { let data_arr = array_ref![data, 0, 4]; MangoInstruction::ChangeMaxMangoAccounts { max_mango_accounts: u32::from_le_bytes(*data_arr), } } + 50 => MangoInstruction::CloseMangoAccount, + 51 => MangoInstruction::CloseSpotOpenOrders, + 52 => MangoInstruction::CloseAdvancedOrders, + 53 => MangoInstruction::CreateDustAccount, + 54 => MangoInstruction::ResolveDust, + 55 => { + let account_num = array_ref![data, 0, 8]; + MangoInstruction::CreateMangoAccount { + account_num: u64::from_le_bytes(*account_num), + } + } + 56 => MangoInstruction::UpgradeMangoAccountV0V1, + 57 => { + let data_arr = array_ref![data, 0, 2]; + let (side, limit) = array_refs![data_arr, 1, 1]; + MangoInstruction::CancelPerpOrdersSide { + side: Side::try_from_primitive(side[0]).ok()?, + limit: u8::from_le_bytes(*limit), + } + } + 58 => MangoInstruction::SetDelegate, + 59 => { + let data_arr = array_ref![data, 0, 104]; + let ( + maint_leverage, + init_leverage, + liquidation_fee, + optimal_util, + optimal_rate, + max_rate, + version, + ) = array_refs![data_arr, 17, 17, 17, 17, 17, 17, 2]; + + MangoInstruction::ChangeSpotMarketParams { + maint_leverage: unpack_i80f48_opt(maint_leverage), + init_leverage: unpack_i80f48_opt(init_leverage), + liquidation_fee: unpack_i80f48_opt(liquidation_fee), + optimal_util: unpack_i80f48_opt(optimal_util), + optimal_rate: unpack_i80f48_opt(optimal_rate), + max_rate: unpack_i80f48_opt(max_rate), + version: unpack_u8_opt(version), + } + } + 60 => MangoInstruction::CreateSpotOpenOrders, _ => { return None; } @@ -1320,6 +1516,79 @@ pub fn init_mango_account( Ok(Instruction { program_id: *program_id, accounts, data }) } +pub fn close_mango_account( + program_id: &Pubkey, + mango_group_pk: &Pubkey, + mango_account_pk: &Pubkey, + owner_pk: &Pubkey, +) -> Result { + let accounts = vec![ + AccountMeta::new(*mango_group_pk, false), + AccountMeta::new(*mango_account_pk, false), + AccountMeta::new_readonly(*owner_pk, true), + ]; + + let instr = MangoInstruction::CloseMangoAccount; + let data = instr.pack(); + Ok(Instruction { program_id: *program_id, accounts, data }) +} + +pub fn create_mango_account( + program_id: &Pubkey, + mango_group_pk: &Pubkey, + mango_account_pk: &Pubkey, + owner_pk: &Pubkey, + system_prog_pk: &Pubkey, + account_num: u64, +) -> Result { + let accounts = vec![ + AccountMeta::new(*mango_group_pk, false), + AccountMeta::new(*mango_account_pk, false), + AccountMeta::new(*owner_pk, true), + AccountMeta::new_readonly(*system_prog_pk, false), + ]; + + let instr = MangoInstruction::CreateMangoAccount { account_num }; + let data = instr.pack(); + Ok(Instruction { program_id: *program_id, accounts, data }) +} + +pub fn set_delegate( + program_id: &Pubkey, + mango_group_pk: &Pubkey, + mango_account_pk: &Pubkey, + owner_pk: &Pubkey, + delegate_pk: &Pubkey, +) -> Result { + let accounts = vec![ + AccountMeta::new_readonly(*mango_group_pk, false), + AccountMeta::new(*mango_account_pk, false), + AccountMeta::new_readonly(*owner_pk, true), + AccountMeta::new_readonly(*delegate_pk, false), + ]; + + let instr = MangoInstruction::SetDelegate {}; + let data = instr.pack(); + Ok(Instruction { program_id: *program_id, accounts, data }) +} + +pub fn upgrade_mango_account_v0_v1( + program_id: &Pubkey, + mango_group_pk: &Pubkey, + mango_account_pk: &Pubkey, + owner_pk: &Pubkey, +) -> Result { + let accounts = vec![ + AccountMeta::new(*mango_group_pk, false), + AccountMeta::new(*mango_account_pk, false), + AccountMeta::new_readonly(*owner_pk, true), + ]; + + let instr = MangoInstruction::UpgradeMangoAccountV0V1; + let data = instr.pack(); + Ok(Instruction { program_id: *program_id, accounts, data }) +} + pub fn deposit( program_id: &Pubkey, mango_group_pk: &Pubkey, @@ -1559,6 +1828,30 @@ pub fn cancel_all_perp_orders( Ok(Instruction { program_id: *program_id, accounts, data }) } +pub fn cancel_perp_orders_side( + program_id: &Pubkey, + mango_group_pk: &Pubkey, // read + mango_account_pk: &Pubkey, // write + owner_pk: &Pubkey, // read, signer + perp_market_pk: &Pubkey, // write + bids_pk: &Pubkey, // write + asks_pk: &Pubkey, // write + side: Side, + limit: u8, +) -> Result { + let accounts = vec![ + AccountMeta::new_readonly(*mango_group_pk, false), + AccountMeta::new(*mango_account_pk, false), + AccountMeta::new_readonly(*owner_pk, true), + AccountMeta::new(*perp_market_pk, false), + AccountMeta::new(*bids_pk, false), + AccountMeta::new(*asks_pk, false), + ]; + let instr = MangoInstruction::CancelPerpOrdersSide { side, limit }; + let data = instr.pack(); + Ok(Instruction { program_id: *program_id, accounts, data }) +} + pub fn force_cancel_perp_orders( program_id: &Pubkey, mango_group_pk: &Pubkey, // read @@ -1604,6 +1897,25 @@ pub fn init_advanced_orders( Ok(Instruction { program_id: *program_id, accounts, data }) } +pub fn close_advanced_orders( + program_id: &Pubkey, + mango_group_pk: &Pubkey, + mango_account_pk: &Pubkey, + advanced_orders_pk: &Pubkey, + owner_pk: &Pubkey, +) -> Result { + let accounts = vec![ + AccountMeta::new_readonly(*mango_group_pk, false), + AccountMeta::new(*mango_account_pk, false), + AccountMeta::new(*owner_pk, true), + AccountMeta::new(*advanced_orders_pk, false), + ]; + + let instr = MangoInstruction::CloseAdvancedOrders; + let data = instr.pack(); + Ok(Instruction { program_id: *program_id, accounts, data }) +} + pub fn add_perp_trigger_order( program_id: &Pubkey, mango_group_pk: &Pubkey, // read @@ -1900,6 +2212,58 @@ pub fn init_spot_open_orders( Ok(Instruction { program_id: *program_id, accounts, data }) } +pub fn create_spot_open_orders( + program_id: &Pubkey, + mango_group_pk: &Pubkey, + mango_account_pk: &Pubkey, + owner_pk: &Pubkey, + dex_prog_pk: &Pubkey, + open_orders_pk: &Pubkey, + spot_market_pk: &Pubkey, + signer_pk: &Pubkey, +) -> Result { + let accounts = vec![ + AccountMeta::new_readonly(*mango_group_pk, false), + AccountMeta::new(*mango_account_pk, false), + AccountMeta::new(*owner_pk, true), + AccountMeta::new_readonly(*dex_prog_pk, false), + AccountMeta::new(*open_orders_pk, false), + AccountMeta::new_readonly(*spot_market_pk, false), + AccountMeta::new_readonly(*signer_pk, false), + AccountMeta::new_readonly(solana_program::system_program::ID, false), + ]; + + let instr = MangoInstruction::CreateSpotOpenOrders; + let data = instr.pack(); + + Ok(Instruction { program_id: *program_id, accounts, data }) +} + +pub fn close_spot_open_orders( + program_id: &Pubkey, + mango_group_pk: &Pubkey, + mango_account_pk: &Pubkey, + owner_pk: &Pubkey, + dex_prog_pk: &Pubkey, + open_orders_pk: &Pubkey, + spot_market_pk: &Pubkey, + signer_pk: &Pubkey, +) -> Result { + let accounts = vec![ + AccountMeta::new_readonly(*mango_group_pk, false), + AccountMeta::new(*mango_account_pk, false), + AccountMeta::new(*owner_pk, true), + AccountMeta::new_readonly(*dex_prog_pk, false), + AccountMeta::new(*open_orders_pk, false), + AccountMeta::new_readonly(*spot_market_pk, false), + AccountMeta::new_readonly(*signer_pk, false), + ]; + + let instr = MangoInstruction::CloseSpotOpenOrders; + let data = instr.pack(); + Ok(Instruction { program_id: *program_id, accounts, data }) +} + pub fn place_spot_order( program_id: &Pubkey, mango_group_pk: &Pubkey, @@ -2105,6 +2469,40 @@ pub fn liquidate_token_and_token( Ok(Instruction { program_id: *program_id, accounts, data }) } +pub fn change_spot_market_params( + program_id: &Pubkey, + mango_group_pk: &Pubkey, + spot_market_pk: &Pubkey, + root_bank_pk: &Pubkey, + admin_pk: &Pubkey, + maint_leverage: Option, + init_leverage: Option, + liquidation_fee: Option, + optimal_util: Option, + optimal_rate: Option, + max_rate: Option, + version: Option, +) -> Result { + let accounts = vec![ + AccountMeta::new(*mango_group_pk, false), + AccountMeta::new(*spot_market_pk, false), + AccountMeta::new(*root_bank_pk, false), + AccountMeta::new_readonly(*admin_pk, true), + ]; + + let instr = MangoInstruction::ChangeSpotMarketParams { + maint_leverage, + init_leverage, + liquidation_fee, + optimal_util, + optimal_rate, + max_rate, + version, + }; + let data = instr.pack(); + Ok(Instruction { program_id: *program_id, accounts, data }) +} + /// Serialize Option as (bool, T). This gives the binary representation /// a fixed width, instead of it becoming one byte for None. fn serialize_option_fixed_width( diff --git a/program/src/matching.rs b/program/src/matching.rs index ad670548..e4000b97 100644 --- a/program/src/matching.rs +++ b/program/src/matching.rs @@ -248,7 +248,7 @@ pub struct BookSide { pub free_list_head: u32, pub root_node: u32, pub leaf_count: usize, - pub nodes: [AnyNode; MAX_BOOK_NODES], // TODO make this variable length + pub nodes: [AnyNode; MAX_BOOK_NODES], } pub struct BookSideIter<'a> { @@ -1268,7 +1268,7 @@ impl<'a> Book<'a> { mango_account: &mut MangoAccount, market_index: usize, mut limit: u8, - ) -> MangoResult<()> { + ) -> MangoResult { let market_index = market_index as u8; for i in 0..MAX_PERP_OPEN_ORDERS { if mango_account.order_market[i] != market_index { @@ -1293,6 +1293,54 @@ impl<'a> Book<'a> { Ok(()) } + pub fn cancel_all_side_with_size_incentives( + &mut self, + mango_account: &mut MangoAccount, + perp_market: &mut PerpMarket, + market_index: usize, + side: Side, + mut limit: u8, + ) -> MangoResult<(Vec, Vec)> { + // TODO - test different limits + let now_ts = Clock::get()?.unix_timestamp as u64; + let max_depth: i64 = perp_market.liquidity_mining_info.max_depth_bps.to_num(); + + let mut all_order_ids = vec![]; + let mut canceled_order_ids = vec![]; + let mut keys = vec![]; + let market_index_u8 = market_index as u8; + for i in 0..MAX_PERP_OPEN_ORDERS { + if mango_account.order_market[i] == market_index_u8 + && mango_account.order_side[i] == side + { + all_order_ids.push(mango_account.orders[i]); + keys.push(mango_account.orders[i]) + } + } + match side { + Side::Bid => self.cancel_all_bids_with_size_incentives( + mango_account, + perp_market, + market_index, + max_depth, + now_ts, + &mut limit, + keys, + &mut canceled_order_ids, + )?, + Side::Ask => self.cancel_all_asks_with_size_incentives( + mango_account, + perp_market, + market_index, + max_depth, + now_ts, + &mut limit, + keys, + &mut canceled_order_ids, + )?, + }; + Ok((all_order_ids, canceled_order_ids)) + } pub fn cancel_all_with_size_incentives( &mut self, mango_account: &mut MangoAccount, @@ -1303,26 +1351,59 @@ impl<'a> Book<'a> { // TODO - test different limits let now_ts = Clock::get()?.unix_timestamp as u64; let max_depth: i64 = perp_market.liquidity_mining_info.max_depth_bps.to_num(); - // For logging + let mut all_order_ids = vec![]; let mut canceled_order_ids = vec![]; - let mut my_bids = vec![]; - let mut my_asks = vec![]; + let market_index_u8 = market_index as u8; + let mut bids_keys = vec![]; + let mut asks_keys = vec![]; for i in 0..MAX_PERP_OPEN_ORDERS { - if mango_account.order_market[i] != market_index as u8 { + if mango_account.order_market[i] != market_index_u8 { continue; } all_order_ids.push(mango_account.orders[i]); match mango_account.order_side[i] { - Side::Bid => my_bids.push(mango_account.orders[i]), - Side::Ask => my_asks.push(mango_account.orders[i]), + Side::Bid => bids_keys.push(mango_account.orders[i]), + Side::Ask => asks_keys.push(mango_account.orders[i]), } } - my_bids.sort_unstable(); - my_asks.sort_by(|a, b| b.cmp(a)); + self.cancel_all_bids_with_size_incentives( + mango_account, + perp_market, + market_index, + max_depth, + now_ts, + &mut limit, + bids_keys, + &mut canceled_order_ids, + )?; + self.cancel_all_asks_with_size_incentives( + mango_account, + perp_market, + market_index, + max_depth, + now_ts, + &mut limit, + asks_keys, + &mut canceled_order_ids, + )?; + Ok((all_order_ids, canceled_order_ids)) + } - // First do bids + /// Internal + fn cancel_all_bids_with_size_incentives( + &mut self, + mango_account: &mut MangoAccount, + perp_market: &mut PerpMarket, + market_index: usize, + max_depth: i64, + now_ts: u64, + limit: &mut u8, + mut my_bids: Vec, + canceled_order_ids: &mut Vec, + ) -> MangoResult { + my_bids.sort_unstable(); let mut bids_and_sizes = vec![]; let mut cuml_bids = 0; @@ -1331,14 +1412,11 @@ impl<'a> Book<'a> { None => break, Some(&my_highest_bid) => { if bid.key > my_highest_bid { - // If book bid is greater than my highest bid continue cuml_bids += bid.quantity; } else if bid.key == my_highest_bid { - // If order id matches, push my bid key and total cuml bids above it bids_and_sizes.push((bid.key, cuml_bids)); my_bids.pop(); } else { - // This means my bid is not on the book; Possibly on event queue waiting to be processed cuml_bids += bid.quantity; my_bids.pop(); } @@ -1354,9 +1432,12 @@ impl<'a> Book<'a> { } for (key, cuml_size) in bids_and_sizes { - if limit == 0 { - return Ok((all_order_ids, canceled_order_ids)); + if *limit == 0 { + return Ok(()); + } else { + *limit -= 1; } + match self.cancel_order(key, Side::Bid) { Ok(order) => { mango_account.remove_order(order.owner_slot as usize, order.quantity)?; @@ -1378,10 +1459,23 @@ impl<'a> Book<'a> { msg!("Failed to cancel bid oid: {}; Either error state or bid is on EventQueue unprocessed", key) } } - limit -= 1; } + Ok(()) + } - // Asks + /// Internal + fn cancel_all_asks_with_size_incentives( + &mut self, + mango_account: &mut MangoAccount, + perp_market: &mut PerpMarket, + market_index: usize, + max_depth: i64, + now_ts: u64, + limit: &mut u8, + mut my_asks: Vec, + canceled_order_ids: &mut Vec, + ) -> MangoResult { + my_asks.sort_unstable_by(|a, b| b.cmp(a)); let mut asks_and_sizes = vec![]; let mut cuml_asks = 0; for ask in self.asks.iter() { @@ -1389,20 +1483,17 @@ impl<'a> Book<'a> { None => break, Some(&my_lowest_ask) => { if ask.key < my_lowest_ask { - // If book ask is less than my lowest ask, continue cuml_asks += ask.quantity; } else if ask.key == my_lowest_ask { - // If order id matches, push my ask key and total cuml asks ahead of it asks_and_sizes.push((ask.key, cuml_asks)); my_asks.pop(); } else { - // This means my ask is not on the book; Possibly on event queue waiting to be processed cuml_asks += ask.quantity; my_asks.pop(); } if cuml_asks >= max_depth { - for ask_key in my_asks { - asks_and_sizes.push((ask_key, max_depth)); + for key in my_asks { + asks_and_sizes.push((key, max_depth)) } break; } @@ -1411,8 +1502,10 @@ impl<'a> Book<'a> { } for (key, cuml_size) in asks_and_sizes { - if limit == 0 { - return Ok((all_order_ids, canceled_order_ids)); + if *limit == 0 { + return Ok(()); + } else { + *limit -= 1; } match self.cancel_order(key, Side::Ask) { Ok(order) => { @@ -1432,14 +1525,13 @@ impl<'a> Book<'a> { } Err(_) => { // Invalid state because we know it's on the book - msg!("Failed to cancel ask oid: {}; Either error state or ask is on EventQueue unprocessed", key) + msg!("Failed to cancel ask oid: {}; Either error state or ask is on EventQueue unprocessed", key); } } - limit -= 1; } - Ok((all_order_ids, canceled_order_ids)) - } + Ok(()) + } /// Cancel all the orders for MangoAccount for this PerpMarket up to `limit` /// Only used when PerpMarket version == 0 pub fn cancel_all_with_price_incentives( diff --git a/program/src/processor.rs b/program/src/processor.rs index 0352acf2..029d2b63 100644 --- a/program/src/processor.rs +++ b/program/src/processor.rs @@ -37,16 +37,20 @@ use crate::ids::msrm_token; use crate::ids::srm_token; use crate::instruction::MangoInstruction; use crate::matching::{Book, BookSide, OrderType, Side}; -use crate::oracle::{determine_oracle_type, OracleType, Price, PriceStatus, StubOracle}; +#[cfg(not(feature = "devnet"))] +use crate::oracle::PriceStatus; +use crate::oracle::{determine_oracle_type, OracleType, Price, StubOracle}; use crate::queue::{EventQueue, EventType, FillEvent, LiquidateEvent, OutEvent}; +#[cfg(not(feature = "devnet"))] +use crate::state::PYTH_CONF_FILTER; use crate::state::{ check_open_orders, load_asks_mut, load_bids_mut, load_market_state, load_open_orders, AdvancedOrderType, AdvancedOrders, AssetType, DataType, HealthCache, HealthType, MangoAccount, MangoCache, MangoGroup, MetaData, NodeBank, PerpMarket, PerpMarketCache, PerpMarketInfo, PerpTriggerOrder, PriceCache, RootBank, RootBankCache, SpotMarketInfo, TokenInfo, TriggerCondition, UserActiveAssets, ADVANCED_ORDER_FEE, FREE_ORDER_SLOT, INFO_LEN, - MAX_ADVANCED_ORDERS, MAX_NODE_BANKS, MAX_PAIRS, MAX_PERP_OPEN_ORDERS, NEG_ONE_I80F48, - ONE_I80F48, PYTH_CONF_FILTER, QUOTE_INDEX, ZERO_I80F48, + MAX_ADVANCED_ORDERS, MAX_NODE_BANKS, MAX_PAIRS, MAX_PERP_OPEN_ORDERS, MAX_TOKENS, + NEG_ONE_I80F48, ONE_I80F48, QUOTE_INDEX, ZERO_I80F48, }; use crate::utils::{gen_signer_key, gen_signer_seeds}; @@ -164,6 +168,7 @@ impl Processor { check!(!mango_cache.meta_data.is_initialized, MangoErrorCode::Default)?; mango_cache.meta_data = MetaData::new(DataType::MangoCache, 0, true); mango_group.mango_cache = *mango_cache_ai.key; + mango_group.max_mango_accounts = 100_000; // check size Ok(()) @@ -174,8 +179,7 @@ impl Processor { todo!() } #[inline(never)] - /// TODO figure out how to do docs for functions with link to instruction.rs instruction documentation - /// TODO make the mango account a derived address + /// DEPRECATED - if you use this instruction after v3.3.0 you will not be able to close your MangoAccount fn init_mango_account(program_id: &Pubkey, accounts: &[AccountInfo]) -> MangoResult<()> { const NUM_FIXED: usize = 3; let accounts = array_ref![accounts, 0, NUM_FIXED]; @@ -189,20 +193,201 @@ impl Processor { let rent = Rent::get()?; check!( rent.is_exempt(mango_account_ai.lamports(), size_of::()), - MangoErrorCode::Default + MangoErrorCode::AccountNotRentExempt )?; check!(owner_ai.is_signer, MangoErrorCode::SignerNecessary)?; - let _mango_group = MangoGroup::load_checked(mango_group_ai, program_id)?; + let mango_group = MangoGroup::load_checked(mango_group_ai, program_id)?; + check!( + mango_group.num_mango_accounts < mango_group.max_mango_accounts, + MangoErrorCode::MaxAccountsReached + )?; let mut mango_account: RefMut = MangoAccount::load_mut(mango_account_ai)?; check_eq!(&mango_account_ai.owner, &program_id, MangoErrorCode::InvalidOwner)?; - check!(!mango_account.meta_data.is_initialized, MangoErrorCode::Default)?; + check!(!mango_account.meta_data.is_initialized, MangoErrorCode::InvalidAccountState)?; mango_account.mango_group = *mango_group_ai.key; mango_account.owner = *owner_ai.key; mango_account.order_market = [FREE_ORDER_SLOT; MAX_PERP_OPEN_ORDERS]; mango_account.meta_data = MetaData::new(DataType::MangoAccount, 0, true); + mango_account.not_upgradable = true; + Ok(()) + } + + #[inline(never)] + fn close_mango_account(program_id: &Pubkey, accounts: &[AccountInfo]) -> MangoResult<()> { + const NUM_FIXED: usize = 3; + let accounts = array_ref![accounts, 0, NUM_FIXED]; + + let [ + mango_group_ai, // write + mango_account_ai, // write + owner_ai, // write, signer + ] = accounts; + + let mut mango_account = + MangoAccount::load_mut_checked(mango_account_ai, program_id, &mango_group_ai.key)?; + check_eq!(&mango_account.owner, owner_ai.key, MangoErrorCode::InvalidOwner)?; + check!(owner_ai.is_signer, MangoErrorCode::InvalidSignerKey)?; + check!(mango_account.meta_data.version > 0, MangoErrorCode::InvalidAccountState)?; + + // Check deposits and borrows are zero + for i in 0..MAX_TOKENS { + check_eq!(mango_account.deposits[i], ZERO_I80F48, MangoErrorCode::InvalidAccountState)?; + check_eq!(mango_account.borrows[i], ZERO_I80F48, MangoErrorCode::InvalidAccountState)?; + } + // Check no perp positions or orders + for perp_account in mango_account.perp_accounts.iter() { + check_eq!(perp_account.base_position, 0, MangoErrorCode::InvalidAccountState)?; + check_eq!( + perp_account.quote_position, + ZERO_I80F48, + MangoErrorCode::InvalidAccountState + )?; + check!(perp_account.mngo_accrued == 0, MangoErrorCode::InvalidAccountState)?; + check!(perp_account.has_no_open_orders(), MangoErrorCode::InvalidAccountState)?; + } + // Check no msrm + check_eq!(mango_account.msrm_amount, 0, MangoErrorCode::InvalidAccountState)?; + // Check not being liquidated/bankrupt + check!(!mango_account.being_liquidated, MangoErrorCode::BeingLiquidated)?; + check!(!mango_account.is_bankrupt, MangoErrorCode::Bankrupt)?; + + // Check open orders accounts closed + for open_orders_key in mango_account.spot_open_orders.iter() { + check_eq!(open_orders_key, &Pubkey::default(), MangoErrorCode::InvalidAccountState)?; + } + // Check advanced orders account closed + check_eq!( + &mango_account.advanced_orders_key, + &Pubkey::default(), + MangoErrorCode::InvalidAccountState + )?; + + // Transfer lamports to owner + program_transfer_lamports(mango_account_ai, owner_ai, mango_account_ai.lamports())?; + + let mut mango_group = MangoGroup::load_mut_checked(mango_group_ai, program_id)?; + mango_group.num_mango_accounts = mango_group.num_mango_accounts.checked_sub(1).unwrap(); + + // Prevent account being loaded by program and zero all unchecked data + mango_account.meta_data.is_initialized = false; + mango_account.mango_group = Pubkey::default(); + mango_account.owner = Pubkey::default(); + mango_account.delegate = Pubkey::default(); + mango_account.in_margin_basket = [false; MAX_PAIRS]; + mango_account.info = [0; INFO_LEN]; + + Ok(()) + } + + #[inline(never)] + fn resolve_dust(program_id: &Pubkey, accounts: &[AccountInfo]) -> MangoResult { + const NUM_FIXED: usize = 7; + let accounts = array_ref![accounts, 0, NUM_FIXED]; + let [ + mango_group_ai, // read + mango_account_ai, // write + owner_ai, // read, signer + dust_account_ai, // write + root_bank_ai, // read + node_bank_ai, // write + mango_cache_ai // read + ] = accounts; + + let mango_group = MangoGroup::load_checked(mango_group_ai, program_id)?; + let mut mango_account = + MangoAccount::load_mut_checked(mango_account_ai, program_id, &mango_group_ai.key)?; + check!( + &mango_account.owner == owner_ai.key || &mango_account.delegate == owner_ai.key, + MangoErrorCode::InvalidOwner + )?; + check!(owner_ai.is_signer, MangoErrorCode::InvalidSignerKey)?; + check!(!mango_account.being_liquidated, MangoErrorCode::BeingLiquidated)?; + check!(!mango_account.is_bankrupt, MangoErrorCode::Bankrupt)?; + + let token_index = mango_group + .find_root_bank_index(root_bank_ai.key) + .ok_or(throw_err!(MangoErrorCode::InvalidRootBank))?; + + if mango_account.deposits[token_index].is_zero() + && mango_account.borrows[token_index].is_zero() + { + // Nothing to settle. Just return + return Ok(()); + } + + let mut dust_account = + MangoAccount::load_mut_checked(dust_account_ai, program_id, &mango_group_ai.key)?; + + // Check dust account + let (pda_address, _bump_seed) = Pubkey::find_program_address( + &[&mango_group_ai.key.as_ref(), b"DustAccount"], + program_id, + ); + check!(&pda_address == dust_account_ai.key, MangoErrorCode::InvalidAccount)?; + + // Find the node_bank pubkey in root_bank, if not found error + let root_bank = RootBank::load_checked(root_bank_ai, program_id)?; + check!(root_bank.node_banks.contains(node_bank_ai.key), MangoErrorCode::InvalidNodeBank)?; + let mut node_bank = NodeBank::load_mut_checked(node_bank_ai, program_id)?; + + let mango_cache = MangoCache::load_checked(mango_cache_ai, program_id, &mango_group)?; + let active_assets = UserActiveAssets::new( + &mango_group, + &dust_account, + vec![(AssetType::Token, token_index)], + ); + let clock = Clock::get()?; + let now_ts = clock.unix_timestamp as u64; + mango_cache.check_valid(&mango_group, &active_assets, now_ts)?; + + // No need to check validity here because it's part of active_assets + let root_bank_cache = &mango_cache.root_bank_cache[token_index]; + + let borrow_amount = mango_account.get_native_borrow(root_bank_cache, token_index)?; + let deposit_amount = mango_account.get_native_deposit(root_bank_cache, token_index)?; + + // Amount must be dust aka < 1 native spl token + if borrow_amount > ZERO_I80F48 && borrow_amount < ONE_I80F48 { + transfer_token_internal( + root_bank_cache, + &mut node_bank, + &mut dust_account, + &mut mango_account, + dust_account_ai.key, + mango_account_ai.key, + token_index, + borrow_amount, + )?; + + // We know DustAccount doesn't have any open orders; but check it just in case + check!(dust_account.num_in_margin_basket == 0, MangoErrorCode::InvalidAccountState)?; + + // Make sure DustAccount satisfies health check only when it has taken on more borrows + let mut health_cache = HealthCache::new(active_assets); + let open_orders_ais = vec![None; MAX_PAIRS]; + health_cache.init_vals_with_orders_vec( + &mango_group, + &mango_cache, + &dust_account, + &open_orders_ais, + )?; + let health = health_cache.get_health(&mango_group, HealthType::Init); + check!(health >= ZERO_I80F48, MangoErrorCode::InsufficientFunds)?; + } else if deposit_amount > ZERO_I80F48 && deposit_amount < ONE_I80F48 { + transfer_token_internal( + root_bank_cache, + &mut node_bank, + &mut mango_account, + &mut dust_account, + mango_account_ai.key, + dust_account_ai.key, + token_index, + deposit_amount, + )?; + } Ok(()) } @@ -711,6 +896,9 @@ impl Processor { let mut mango_account = MangoAccount::load_mut_checked(mango_account_ai, program_id, mango_group_ai.key)?; + // Note: a check for &mango_account.owner == owner_ai.key doesn't exist on purpose + // this is how mango currently reimburses users + check!(!mango_account.is_bankrupt, MangoErrorCode::Bankrupt)?; let mango_cache = MangoCache::load_checked(mango_cache_ai, program_id, &mango_group)?; @@ -1192,12 +1380,14 @@ impl Processor { let mut mango_account = MangoAccount::load_mut_checked(mango_account_ai, program_id, mango_group_ai.key)?; - check!(&mango_account.owner == owner_ai.key, MangoErrorCode::InvalidOwner)?; + check!( + &mango_account.owner == owner_ai.key || &mango_account.delegate == owner_ai.key, + MangoErrorCode::InvalidOwner + )?; check!(owner_ai.is_signer, MangoErrorCode::InvalidSignerKey)?; check!(!mango_account.is_bankrupt, MangoErrorCode::Bankrupt)?; { - // TODO OPT - Unnecessary check because serum dex also checks account flags 0 let open_orders = load_open_orders(open_orders_ai)?; // Make sure this open orders account has not been initialized already @@ -1225,6 +1415,146 @@ impl Processor { Ok(()) } + #[inline(never)] + /// Create a new OpenOrders PDA then + /// Call the init_open_orders instruction in serum dex and add this OpenOrders account to margin account + fn create_spot_open_orders(program_id: &Pubkey, accounts: &[AccountInfo]) -> MangoResult { + const NUM_FIXED: usize = 8; + let accounts = array_ref![accounts, 0, NUM_FIXED]; + let [ + mango_group_ai, // read + mango_account_ai, // write + owner_ai, // read + dex_prog_ai, // read + open_orders_ai, // write + spot_market_ai, // read + signer_ai, // read + system_prog_ai, // read + ] = accounts; + check!( + system_prog_ai.key == &solana_program::system_program::id(), + MangoErrorCode::InvalidProgramId + )?; + + let mango_group = MangoGroup::load_checked(mango_group_ai, program_id)?; + check_eq!(dex_prog_ai.key, &mango_group.dex_program_id, MangoErrorCode::InvalidProgramId)?; + check!(&mango_group.signer_key == signer_ai.key, MangoErrorCode::InvalidSignerKey)?; + + let market_index = mango_group + .find_spot_market_index(spot_market_ai.key) + .ok_or(throw_err!(MangoErrorCode::InvalidMarket))?; + + let mut mango_account = + MangoAccount::load_mut_checked(mango_account_ai, program_id, mango_group_ai.key)?; + check!( + &mango_account.owner == owner_ai.key || &mango_account.delegate == owner_ai.key, + MangoErrorCode::InvalidOwner + )?; + check!(owner_ai.is_signer, MangoErrorCode::InvalidSignerKey)?; + check!(!mango_account.is_bankrupt, MangoErrorCode::Bankrupt)?; + + let open_orders_seeds: &[&[u8]] = + &[&mango_account_ai.key.as_ref(), &market_index.to_le_bytes(), b"OpenOrders"]; + seed_and_create_pda( + program_id, + owner_ai, + &Rent::get()?, + size_of::() + 12, + dex_prog_ai.key, + system_prog_ai, + open_orders_ai, + open_orders_seeds, + &[], + )?; + + { + let open_orders = load_open_orders(open_orders_ai)?; + + // Make sure this open orders account has not been initialized already + check_eq!(open_orders.account_flags, 0, MangoErrorCode::Default)?; + } + + // Make sure there isn't already an open orders account for this market + check!( + mango_account.spot_open_orders[market_index] == Pubkey::default(), + MangoErrorCode::Default + )?; + + let signers_seeds = gen_signer_seeds(&mango_group.signer_nonce, mango_group_ai.key); + invoke_init_open_orders( + dex_prog_ai, + open_orders_ai, + signer_ai, + spot_market_ai, + system_prog_ai, // no need to send in rent ai + &[&signers_seeds], + )?; + + mango_account.spot_open_orders[market_index] = *open_orders_ai.key; + + Ok(()) + } + + #[inline(never)] + fn close_spot_open_orders(program_id: &Pubkey, accounts: &[AccountInfo]) -> MangoResult<()> { + const NUM_FIXED: usize = 7; + let accounts = array_ref![accounts, 0, NUM_FIXED]; + + let [ + mango_group_ai, // read + mango_account_ai, // write + owner_ai, // write, signer + dex_prog_ai, // read + open_orders_ai, // write + spot_market_ai, // read + signer_ai, // read + ] = accounts; + + check!(owner_ai.is_signer, MangoErrorCode::InvalidSignerKey)?; + + let mango_group = MangoGroup::load_checked(mango_group_ai, program_id)?; + check_eq!(dex_prog_ai.key, &mango_group.dex_program_id, MangoErrorCode::InvalidProgramId)?; + check_eq!(signer_ai.key, &mango_group.signer_key, MangoErrorCode::InvalidParam)?; + + let market_index = mango_group + .find_spot_market_index(spot_market_ai.key) + .ok_or(throw_err!(MangoErrorCode::InvalidMarket))?; + + let mut mango_account = + MangoAccount::load_mut_checked(mango_account_ai, program_id, &mango_group_ai.key)?; + check_eq!(&mango_account.owner, owner_ai.key, MangoErrorCode::InvalidOwner)?; + check!(!mango_account.being_liquidated, MangoErrorCode::BeingLiquidated)?; + check!(!mango_account.is_bankrupt, MangoErrorCode::Bankrupt)?; + check_eq!( + &mango_account.spot_open_orders[market_index], + open_orders_ai.key, + MangoErrorCode::InvalidOpenOrdersAccount + )?; + + if mango_account.in_margin_basket[market_index] { + let open_orders = load_open_orders(open_orders_ai)?; + mango_account.update_basket(market_index, &open_orders)?; + check!( + !mango_account.in_margin_basket[market_index], + MangoErrorCode::InvalidAccountState + )?; + } + + let signers_seeds = gen_signer_seeds(&mango_group.signer_nonce, mango_group_ai.key); + invoke_close_open_orders( + dex_prog_ai, + open_orders_ai, + signer_ai, + owner_ai, + spot_market_ai, + &[&signers_seeds], + )?; + + mango_account.spot_open_orders[market_index] = Pubkey::default(); + + Ok(()) + } + #[inline(never)] /// DEPRECATED fn place_spot_order( @@ -1276,7 +1606,10 @@ impl Processor { let mut mango_account = MangoAccount::load_mut_checked(mango_account_ai, program_id, mango_group_ai.key)?; - check!(&mango_account.owner == owner_ai.key, MangoErrorCode::InvalidOwner)?; + check!( + &mango_account.owner == owner_ai.key || &mango_account.delegate == owner_ai.key, + MangoErrorCode::InvalidOwner + )?; check!(owner_ai.is_signer, MangoErrorCode::InvalidSignerKey)?; check!(!mango_account.is_bankrupt, MangoErrorCode::Bankrupt)?; @@ -1547,7 +1880,10 @@ impl Processor { let mut mango_account = MangoAccount::load_mut_checked(mango_account_ai, program_id, mango_group_ai.key)?; - check!(&mango_account.owner == owner_ai.key, MangoErrorCode::InvalidOwner)?; + check!( + &mango_account.owner == owner_ai.key || &mango_account.delegate == owner_ai.key, + MangoErrorCode::InvalidOwner + )?; check!(owner_ai.is_signer, MangoErrorCode::InvalidSignerKey)?; check!(!mango_account.is_bankrupt, MangoErrorCode::Bankrupt)?; @@ -1817,7 +2153,10 @@ impl Processor { let mango_account = MangoAccount::load_checked(mango_account_ai, program_id, mango_group_ai.key)?; - check!(&mango_account.owner == owner_ai.key, MangoErrorCode::InvalidOwner)?; + check!( + &mango_account.owner == owner_ai.key || &mango_account.delegate == owner_ai.key, + MangoErrorCode::InvalidOwner + )?; check!(owner_ai.is_signer, MangoErrorCode::InvalidSignerKey)?; check!(!mango_account.is_bankrupt, MangoErrorCode::Bankrupt)?; @@ -1888,7 +2227,10 @@ impl Processor { let mut mango_account = MangoAccount::load_mut_checked(mango_account_ai, program_id, mango_group_ai.key)?; - check!(owner_ai.key == &mango_account.owner, MangoErrorCode::InvalidOwner)?; + check!( + &mango_account.owner == owner_ai.key || &mango_account.delegate == owner_ai.key, + MangoErrorCode::InvalidOwner + )?; check!(owner_ai.is_signer, MangoErrorCode::SignerNecessary)?; check!(!mango_account.is_bankrupt, MangoErrorCode::Bankrupt)?; @@ -2042,7 +2384,10 @@ impl Processor { MangoAccount::load_mut_checked(mango_account_ai, program_id, mango_group_ai.key)?; check!(!mango_account.is_bankrupt, MangoErrorCode::Bankrupt)?; check!(owner_ai.is_signer, MangoErrorCode::SignerNecessary)?; - check_eq!(&mango_account.owner, owner_ai.key, MangoErrorCode::InvalidOwner)?; + check!( + &mango_account.owner == owner_ai.key || &mango_account.delegate == owner_ai.key, + MangoErrorCode::InvalidOwner + )?; mango_account.check_open_orders(&mango_group, open_orders_ais)?; let clock = Clock::get()?; @@ -2151,7 +2496,10 @@ impl Processor { MangoAccount::load_mut_checked(mango_account_ai, program_id, mango_group_ai.key)?; check!(!mango_account.is_bankrupt, MangoErrorCode::Bankrupt)?; check!(owner_ai.is_signer, MangoErrorCode::SignerNecessary)?; - check_eq!(&mango_account.owner, owner_ai.key, MangoErrorCode::InvalidOwner)?; + check!( + &mango_account.owner == owner_ai.key || &mango_account.delegate == owner_ai.key, + MangoErrorCode::InvalidOwner + )?; let mut perp_market = PerpMarket::load_mut_checked(perp_market_ai, program_id, mango_group_ai.key)?; @@ -2244,7 +2592,10 @@ impl Processor { MangoAccount::load_mut_checked(mango_account_ai, program_id, mango_group_ai.key)?; check!(!mango_account.is_bankrupt, MangoErrorCode::Bankrupt)?; check!(owner_ai.is_signer, MangoErrorCode::SignerNecessary)?; - check_eq!(&mango_account.owner, owner_ai.key, MangoErrorCode::InvalidOwner)?; + check!( + &mango_account.owner == owner_ai.key || &mango_account.delegate == owner_ai.key, + MangoErrorCode::InvalidOwner + )?; let mut perp_market = PerpMarket::load_mut_checked(perp_market_ai, program_id, mango_group_ai.key)?; @@ -2332,8 +2683,11 @@ impl Processor { let mut mango_account = MangoAccount::load_mut_checked(mango_account_ai, program_id, mango_group_ai.key)?; check!(!mango_account.is_bankrupt, MangoErrorCode::Bankrupt)?; - check!(owner_ai.is_signer, MangoErrorCode::Default)?; - check_eq!(&mango_account.owner, owner_ai.key, MangoErrorCode::InvalidOwner)?; + check!(owner_ai.is_signer, MangoErrorCode::SignerNecessary)?; + check!( + &mango_account.owner == owner_ai.key || &mango_account.delegate == owner_ai.key, + MangoErrorCode::InvalidOwner + )?; let mut perp_market = PerpMarket::load_mut_checked(perp_market_ai, program_id, mango_group_ai.key)?; @@ -2864,7 +3218,10 @@ impl Processor { let mut liqor_ma = MangoAccount::load_mut_checked(liqor_mango_account_ai, program_id, mango_group_ai.key)?; - check_eq!(liqor_ai.key, &liqor_ma.owner, MangoErrorCode::InvalidOwner)?; + check!( + &liqor_ma.owner == liqor_ai.key || &liqor_ma.delegate == liqor_ai.key, + MangoErrorCode::InvalidOwner + )?; check!(liqor_ai.is_signer, MangoErrorCode::InvalidSignerKey)?; check!(!liqor_ma.is_bankrupt, MangoErrorCode::Bankrupt)?; liqor_ma.check_open_orders(&mango_group, liqor_open_orders_ais)?; @@ -2900,7 +3257,7 @@ impl Processor { // Make sure orders are cancelled for perps and check orders for i in 0..mango_group.num_oracles { if liqee_active_assets.perps[i] { - check!(liqee_ma.perp_accounts[i].is_liquidatable(), MangoErrorCode::Default)?; + check!(liqee_ma.perp_accounts[i].has_no_open_orders(), MangoErrorCode::Default)?; } } @@ -3089,7 +3446,10 @@ impl Processor { let mut liqor_ma = MangoAccount::load_mut_checked(liqor_mango_account_ai, program_id, mango_group_ai.key)?; - check_eq!(liqor_ai.key, &liqor_ma.owner, MangoErrorCode::InvalidOwner)?; + check!( + &liqor_ma.owner == liqor_ai.key || &liqor_ma.delegate == liqor_ai.key, + MangoErrorCode::InvalidOwner + )?; check!(liqor_ai.is_signer, MangoErrorCode::InvalidSignerKey)?; check!(!liqor_ma.is_bankrupt, MangoErrorCode::Bankrupt)?; liqor_ma.check_open_orders(&mango_group, liqor_open_orders_ais)?; @@ -3115,7 +3475,7 @@ impl Processor { // Make sure orders are cancelled for perps and check orders for i in 0..mango_group.num_oracles { if liqee_active_assets.perps[i] { - check!(liqee_ma.perp_accounts[i].is_liquidatable(), MangoErrorCode::Default)?; + check!(liqee_ma.perp_accounts[i].has_no_open_orders(), MangoErrorCode::Default)?; } } @@ -3384,7 +3744,10 @@ impl Processor { let mut liqor_ma = MangoAccount::load_mut_checked(liqor_mango_account_ai, program_id, mango_group_ai.key)?; check!(!liqor_ma.is_bankrupt, MangoErrorCode::Bankrupt)?; - check_eq!(liqor_ai.key, &liqor_ma.owner, MangoErrorCode::InvalidOwner)?; + check!( + &liqor_ma.owner == liqor_ai.key || &liqor_ma.delegate == liqor_ai.key, + MangoErrorCode::InvalidOwner + )?; check!(liqor_ai.is_signer, MangoErrorCode::InvalidSignerKey)?; liqor_ma.check_open_orders(&mango_group, liqor_open_orders_ais)?; @@ -3415,7 +3778,7 @@ impl Processor { // Make sure orders are cancelled for perps before liquidation for i in 0..mango_group.num_oracles { if liqee_active_assets.perps[i] { - check!(liqee_ma.perp_accounts[i].is_liquidatable(), MangoErrorCode::Default)?; + check!(liqee_ma.perp_accounts[i].has_no_open_orders(), MangoErrorCode::Default)?; } } @@ -3583,7 +3946,10 @@ impl Processor { let mut liqor_ma = MangoAccount::load_mut_checked(liqor_mango_account_ai, program_id, mango_group_ai.key)?; - check_eq!(liqor_ai.key, &liqor_ma.owner, MangoErrorCode::InvalidOwner)?; + check!( + &liqor_ma.owner == liqor_ai.key || &liqor_ma.delegate == liqor_ai.key, + MangoErrorCode::InvalidOwner + )?; check!(liqor_ai.is_signer, MangoErrorCode::InvalidSignerKey)?; check!(!liqor_ma.is_bankrupt, MangoErrorCode::Bankrupt)?; liqor_ma.check_open_orders(&mango_group, liqor_open_orders_ais)?; @@ -3746,7 +4112,10 @@ impl Processor { // Load the liqor's mango account let mut liqor_ma = MangoAccount::load_mut_checked(liqor_mango_account_ai, program_id, mango_group_ai.key)?; - check_eq!(liqor_ai.key, &liqor_ma.owner, MangoErrorCode::InvalidOwner)?; + check!( + &liqor_ma.owner == liqor_ai.key || &liqor_ma.delegate == liqor_ai.key, + MangoErrorCode::InvalidOwner + )?; check!(liqor_ai.is_signer, MangoErrorCode::InvalidSignerKey)?; check!(!liqor_ma.is_bankrupt, MangoErrorCode::Bankrupt)?; liqor_ma.check_open_orders(&mango_group, liqor_open_orders_ais)?; @@ -4187,7 +4556,10 @@ impl Processor { let mut mango_account = MangoAccount::load_mut_checked(mango_account_ai, program_id, mango_group_ai.key)?; - check!(&mango_account.owner == owner_ai.key, MangoErrorCode::InvalidOwner)?; + check!( + &mango_account.owner == owner_ai.key || &mango_account.delegate == owner_ai.key, + MangoErrorCode::InvalidOwner + )?; check!(!mango_account.is_bankrupt, MangoErrorCode::Bankrupt)?; check!(owner_ai.is_signer, MangoErrorCode::SignerNecessary)?; @@ -4259,7 +4631,10 @@ impl Processor { let mut mango_account = MangoAccount::load_mut_checked(mango_account_ai, program_id, mango_group_ai.key)?; - check!(&mango_account.owner == owner_ai.key, MangoErrorCode::InvalidOwner)?; + check!( + &mango_account.owner == owner_ai.key || &mango_account.delegate == owner_ai.key, + MangoErrorCode::InvalidOwner + )?; check!(owner_ai.is_signer, MangoErrorCode::InvalidSignerKey)?; mango_account.info = info; @@ -4384,7 +4759,10 @@ impl Processor { let mut mango_account = MangoAccount::load_mut_checked(mango_account_ai, program_id, mango_group_ai.key)?; - check!(&mango_account.owner == owner_ai.key, MangoErrorCode::InvalidOwner)?; + check!( + &mango_account.owner == owner_ai.key || &mango_account.delegate == owner_ai.key, + MangoErrorCode::InvalidOwner + )?; check!(owner_ai.is_signer, MangoErrorCode::InvalidSignerKey)?; check!(!mango_account.is_bankrupt, MangoErrorCode::Bankrupt)?; @@ -4419,6 +4797,41 @@ impl Processor { Ok(()) } + #[inline(never)] + fn close_advanced_orders(program_id: &Pubkey, accounts: &[AccountInfo]) -> MangoResult<()> { + const NUM_FIXED: usize = 4; + let accounts = array_ref![accounts, 0, NUM_FIXED]; + + let [ + mango_group_ai, // read + mango_account_ai, // write + owner_ai, // write, signer + advanced_orders_ai, // write + ] = accounts; + + check!(owner_ai.is_signer, MangoErrorCode::InvalidSignerKey)?; + + let mut mango_account = + MangoAccount::load_mut_checked(mango_account_ai, program_id, &mango_group_ai.key)?; + check!(&mango_account.owner == owner_ai.key, MangoErrorCode::InvalidOwner)?; + check!(!mango_account.being_liquidated, MangoErrorCode::BeingLiquidated)?; + check!(!mango_account.is_bankrupt, MangoErrorCode::Bankrupt)?; + + let mut advanced_orders = + AdvancedOrders::load_mut_checked(advanced_orders_ai, program_id, &mango_account)?; + for i in 0..MAX_ADVANCED_ORDERS { + advanced_orders.orders[i].is_active = false; + } + advanced_orders.meta_data.is_initialized = false; + + // Transfer lamports to owner + program_transfer_lamports(advanced_orders_ai, owner_ai, advanced_orders_ai.lamports())?; + + mango_account.advanced_orders_key = Pubkey::default(); + + Ok(()) + } + /// Add a perp trigger order to the AdvancedOrders account /// The TriggerCondition specifies if trigger_price must be above or below oracle price /// When the condition is met, the order is executed as a regular perp order @@ -4460,7 +4873,10 @@ impl Processor { MangoAccount::load_mut_checked(mango_account_ai, program_id, mango_group_ai.key)?; check!(!mango_account.is_bankrupt, MangoErrorCode::Bankrupt)?; check!(owner_ai.is_signer, MangoErrorCode::SignerNecessary)?; - check_eq!(&mango_account.owner, owner_ai.key, MangoErrorCode::InvalidOwner)?; + check!( + &mango_account.owner == owner_ai.key || &mango_account.delegate == owner_ai.key, + MangoErrorCode::InvalidOwner + )?; let open_orders_ais = mango_account.checked_unpack_open_orders(&mango_group, open_orders_ais)?; @@ -4561,7 +4977,10 @@ impl Processor { let mango_account = MangoAccount::load_checked(mango_account_ai, program_id, mango_group_ai.key)?; - check!(&mango_account.owner == owner_ai.key, MangoErrorCode::InvalidOwner)?; + check!( + &mango_account.owner == owner_ai.key || &mango_account.delegate == owner_ai.key, + MangoErrorCode::InvalidOwner + )?; check!(owner_ai.is_signer, MangoErrorCode::InvalidSignerKey)?; // No bankruptcy check; removing order is fine @@ -4742,8 +5161,8 @@ impl Processor { ( pa.taker_base + taker_base, pa.taker_quote + taker_quote, - pa.bids_quantity + bids_quantity, - pa.asks_quantity + asks_quantity, + pa.bids_quantity.checked_add(bids_quantity).unwrap(), + pa.asks_quantity.checked_add(asks_quantity).unwrap(), ) }; @@ -4792,7 +5211,6 @@ impl Processor { /// *** Create a MangoAccount PDA and initialize it #[inline(never)] - #[allow(dead_code)] fn create_mango_account( program_id: &Pubkey, accounts: &[AccountInfo], @@ -4801,7 +5219,7 @@ impl Processor { const NUM_FIXED: usize = 4; let accounts = array_ref![accounts, 0, NUM_FIXED]; let [ - mango_group_ai, // read + mango_group_ai, // write mango_account_ai, // write owner_ai, // write & signer system_prog_ai, // read @@ -4812,7 +5230,11 @@ impl Processor { )?; check!(owner_ai.is_signer, MangoErrorCode::SignerNecessary)?; - let _mango_group = MangoGroup::load_checked(mango_group_ai, program_id)?; + let mut mango_group = MangoGroup::load_mut_checked(mango_group_ai, program_id)?; + check!( + mango_group.num_mango_accounts < mango_group.max_mango_accounts, + MangoErrorCode::MaxAccountsReached + )?; let rent = Rent::get()?; let mango_account_seeds: &[&[u8]] = @@ -4830,11 +5252,14 @@ impl Processor { &[], )?; let mut mango_account: RefMut = MangoAccount::load_mut(mango_account_ai)?; + check!(!mango_account.meta_data.is_initialized, MangoErrorCode::InvalidAccountState)?; mango_account.mango_group = *mango_group_ai.key; mango_account.owner = *owner_ai.key; mango_account.order_market = [FREE_ORDER_SLOT; MAX_PERP_OPEN_ORDERS]; - mango_account.meta_data = MetaData::new(DataType::MangoAccount, 0, true); + mango_account.meta_data = MetaData::new(DataType::MangoAccount, 1, true); + + mango_group.num_mango_accounts += 1; Ok(()) } @@ -4874,6 +5299,7 @@ impl Processor { Ok(()) } + #[inline(never)] /// Change the maximum number of MangoAccounts.v1 allowed fn change_max_mango_accounts( @@ -4896,6 +5322,242 @@ impl Processor { Ok(()) } + /// *** Create a DustAccount PDA and initialize it + #[inline(never)] + fn create_dust_account(program_id: &Pubkey, accounts: &[AccountInfo]) -> MangoResult { + const NUM_FIXED: usize = 4; + let accounts = array_ref![accounts, 0, NUM_FIXED]; + let [ + mango_group_ai, // read + mango_account_ai, // write + payer_ai, // write & signer + system_prog_ai, // read + ] = accounts; + check!( + system_prog_ai.key == &solana_program::system_program::id(), + MangoErrorCode::InvalidProgramId + )?; + check!(payer_ai.is_signer, MangoErrorCode::SignerNecessary)?; + + let mango_group = MangoGroup::load_checked(mango_group_ai, program_id)?; + let rent = Rent::get()?; + + let mango_account_seeds: &[&[u8]] = &[&mango_group_ai.key.as_ref(), b"DustAccount"]; + seed_and_create_pda( + program_id, + payer_ai, + &rent, + size_of::(), + program_id, + system_prog_ai, + mango_account_ai, + mango_account_seeds, + &[], + )?; + let mut mango_account: RefMut = MangoAccount::load_mut(mango_account_ai)?; + check!(!mango_account.meta_data.is_initialized, MangoErrorCode::InvalidAccountState)?; + + mango_account.mango_group = *mango_group_ai.key; + mango_account.owner = mango_group.admin; + mango_account.order_market = [FREE_ORDER_SLOT; MAX_PERP_OPEN_ORDERS]; + mango_account.meta_data = MetaData::new(DataType::MangoAccount, 0, true); + mango_account.not_upgradable = true; + + Ok(()) + } + + #[inline(never)] + fn upgrade_mango_account_v0_v1(program_id: &Pubkey, accounts: &[AccountInfo]) -> MangoResult { + const NUM_FIXED: usize = 3; + let accounts = array_ref![accounts, 0, NUM_FIXED]; + let [ + mango_group_ai, // write + mango_account_ai, // write + owner_ai // signer + ] = accounts; + + let mut mango_group = MangoGroup::load_mut_checked(mango_group_ai, program_id)?; + let mut mango_account = + MangoAccount::load_mut_checked(mango_account_ai, program_id, mango_group_ai.key)?; + + check!(owner_ai.is_signer, MangoErrorCode::SignerNecessary)?; + check!( + &mango_account.owner == owner_ai.key || &mango_account.delegate == owner_ai.key, + MangoErrorCode::InvalidOwner + )?; + check_eq!(mango_account.meta_data.version, 0, MangoErrorCode::InvalidAccountState)?; + check!(!mango_account.not_upgradable, MangoErrorCode::InvalidAccountState)?; + check!( + mango_group.num_mango_accounts < mango_group.max_mango_accounts, + MangoErrorCode::MaxAccountsReached + )?; + + mango_group.num_mango_accounts += 1; + mango_account.meta_data.version = 1; + + Ok(()) + } + + #[inline(never)] + fn cancel_perp_orders_side( + program_id: &Pubkey, + accounts: &[AccountInfo], + side: Side, + limit: u8, + ) -> MangoResult { + const NUM_FIXED: usize = 6; + let accounts = array_ref![accounts, 0, NUM_FIXED]; + let [ + mango_group_ai, // read + mango_account_ai, // write + owner_ai, // read, signer + perp_market_ai, // write + bids_ai, // write + asks_ai, // write + ] = accounts; + + let mango_group = MangoGroup::load_checked(mango_group_ai, program_id)?; + + let mut mango_account = + MangoAccount::load_mut_checked(mango_account_ai, program_id, mango_group_ai.key)?; + check!(!mango_account.is_bankrupt, MangoErrorCode::Bankrupt)?; + check!(owner_ai.is_signer, MangoErrorCode::SignerNecessary)?; + check!( + &mango_account.owner == owner_ai.key || &mango_account.delegate == owner_ai.key, + MangoErrorCode::InvalidOwner + )?; + + let mut perp_market = + PerpMarket::load_mut_checked(perp_market_ai, program_id, mango_group_ai.key)?; + + let market_index = mango_group.find_perp_market_index(perp_market_ai.key).unwrap(); + + let mut book = Book::load_checked(program_id, bids_ai, asks_ai, &perp_market)?; + let mngo_start = mango_account.perp_accounts[market_index].mngo_accrued; + + if perp_market.meta_data.version == 0 { + return Err(throw_err!(MangoErrorCode::InvalidParam)); + } else { + let (all_order_ids, canceled_order_ids) = book.cancel_all_side_with_size_incentives( + &mut mango_account, + &mut perp_market, + market_index, + side, + limit, + )?; + mango_emit!(CancelAllPerpOrdersLog { + mango_group: *mango_group_ai.key, + mango_account: *mango_account_ai.key, + market_index: market_index as u64, + all_order_ids, + canceled_order_ids + }); + } + + mango_emit!(MngoAccrualLog { + mango_group: *mango_group_ai.key, + mango_account: *mango_account_ai.key, + market_index: market_index as u64, + mngo_accrual: mango_account.perp_accounts[market_index].mngo_accrued - mngo_start + }); + Ok(()) + } + + #[inline(never)] + fn set_delegate(program_id: &Pubkey, accounts: &[AccountInfo]) -> MangoResult { + const NUM_FIXED: usize = 4; + let accounts = array_ref![accounts, 0, NUM_FIXED]; + let [ + mango_group_ai, // read + mango_account_ai, // write + owner_ai, // read, signer + delegate_ai, // read + ] = accounts; + + let mut mango_account = + MangoAccount::load_mut_checked(mango_account_ai, program_id, mango_group_ai.key)?; + + check!(owner_ai.is_signer, MangoErrorCode::SignerNecessary)?; + check!(&mango_account.owner == owner_ai.key, MangoErrorCode::InvalidOwner)?; + check!(&mango_account.delegate != delegate_ai.key, MangoErrorCode::InvalidAccount)?; + + mango_account.delegate = *delegate_ai.key; + + Ok(()) + } + + #[inline(never)] + fn change_spot_market_params( + program_id: &Pubkey, + accounts: &[AccountInfo], + maint_leverage: Option, + init_leverage: Option, + liquidation_fee: Option, + optimal_util: Option, + optimal_rate: Option, + max_rate: Option, + version: Option, + ) -> MangoResult { + const NUM_FIXED: usize = 4; + let accounts = array_ref![accounts, 0, NUM_FIXED]; + + let [ + mango_group_ai, // write + spot_market_ai, // write + root_bank_ai, // write + admin_ai // read, signer + ] = accounts; + + let mut mango_group = MangoGroup::load_mut_checked(mango_group_ai, program_id)?; + check_eq!(admin_ai.key, &mango_group.admin, MangoErrorCode::InvalidAdminKey)?; + check!(admin_ai.is_signer, MangoErrorCode::SignerNecessary)?; + + let market_index = mango_group + .find_spot_market_index(spot_market_ai.key) + .ok_or(throw_err!(MangoErrorCode::InvalidMarket))?; + + // checks rootbank is part of the group + let _root_bank_index = mango_group + .find_root_bank_index(root_bank_ai.key) + .ok_or(throw_err!(MangoErrorCode::InvalidRootBank))?; + + let mut root_bank = RootBank::load_mut_checked(&root_bank_ai, program_id)?; + let mut info = &mut mango_group.spot_markets[market_index]; + + // Unwrap params. Default to current state if Option is None + let (init_asset_weight, init_liab_weight) = init_leverage + .map_or((info.init_asset_weight, info.init_liab_weight), |x| get_leverage_weights(x)); + let (maint_asset_weight, maint_liab_weight) = maint_leverage + .map_or((info.maint_asset_weight, info.maint_liab_weight), |x| get_leverage_weights(x)); + + let liquidation_fee = liquidation_fee.unwrap_or(info.liquidation_fee); + let optimal_util = optimal_util.unwrap_or(root_bank.optimal_util); + let optimal_rate = optimal_rate.unwrap_or(root_bank.optimal_rate); + let max_rate = max_rate.unwrap_or(root_bank.max_rate); + let version = version.unwrap_or(root_bank.meta_data.version); + + // params check + check!(init_asset_weight > ZERO_I80F48, MangoErrorCode::InvalidParam)?; + check!(maint_asset_weight > init_asset_weight, MangoErrorCode::InvalidParam)?; + // maint leverage may only increase to prevent unforeseen liquidations + check!(maint_asset_weight >= info.maint_asset_weight, MangoErrorCode::InvalidParam)?; + + // set the params on the RootBank + root_bank.set_rate_params(optimal_util, optimal_rate, max_rate)?; + + // set the params on MangoGroup SpotMarketInfo + info.liquidation_fee = liquidation_fee; + info.maint_asset_weight = maint_asset_weight; + info.init_asset_weight = init_asset_weight; + info.maint_liab_weight = maint_liab_weight; + info.init_liab_weight = init_liab_weight; + + check!(version == 0, MangoErrorCode::InvalidParam)?; + + root_bank.meta_data.version = version; + Ok(()) + } + pub fn process(program_id: &Pubkey, accounts: &[AccountInfo], data: &[u8]) -> MangoResult { let instruction = MangoInstruction::unpack(data).ok_or(ProgramError::InvalidInstructionData)?; @@ -4919,9 +5581,21 @@ impl Processor { ) } MangoInstruction::InitMangoAccount => { - msg!("Mango: InitMangoAccount"); + msg!("Mango: InitMangoAccount DEPRECATED"); Self::init_mango_account(program_id, accounts) } + MangoInstruction::CreateMangoAccount { account_num } => { + msg!("Mango: CreateMangoAccount"); + Self::create_mango_account(program_id, accounts, account_num) + } + MangoInstruction::CloseMangoAccount => { + msg!("Mango: CloseMangoAccount"); + Self::close_mango_account(program_id, accounts) + } + MangoInstruction::UpgradeMangoAccountV0V1 => { + msg!("Mango: UpgradeMangoAccountV0V1"); + Self::upgrade_mango_account_v0_v1(program_id, accounts) + } MangoInstruction::Deposit { quantity } => { msg!("Mango: Deposit"); Self::deposit(program_id, accounts, quantity) @@ -5143,6 +5817,10 @@ impl Processor { msg!("Mango: InitSpotOpenOrders"); Self::init_spot_open_orders(program_id, accounts) } + MangoInstruction::CloseSpotOpenOrders => { + msg!("Mango: CloseSpotOpenOrders"); + Self::close_spot_open_orders(program_id, accounts) + } MangoInstruction::RedeemMngo => { msg!("Mango: RedeemMngo"); Self::redeem_mngo(program_id, accounts) @@ -5183,6 +5861,10 @@ impl Processor { msg!("Mango: InitAdvancedOrders"); Self::init_advanced_orders(program_id, accounts) } + MangoInstruction::CloseAdvancedOrders => { + msg!("Mango: CloseAdvancedOrders"); + Self::close_advanced_orders(program_id, accounts) + } MangoInstruction::AddPerpTriggerOrder { order_type, side, @@ -5302,6 +5984,48 @@ impl Processor { msg!("Mango: ChangeMaxMangoAccounts"); Self::change_max_mango_accounts(program_id, accounts, max_mango_accounts) } + MangoInstruction::CreateDustAccount => { + msg!("Mango: CreateDustAccount"); + Self::create_dust_account(program_id, accounts) + } + MangoInstruction::ResolveDust => { + msg!("Mango: ResolveDust"); + Self::resolve_dust(program_id, accounts) + } + MangoInstruction::CancelPerpOrdersSide { side, limit } => { + msg!("Mango: CancelSidePerpOrders"); + Self::cancel_perp_orders_side(program_id, accounts, side, limit) + } + MangoInstruction::SetDelegate => { + msg!("Mango: SetDelegate"); + Self::set_delegate(program_id, accounts) + } + MangoInstruction::ChangeSpotMarketParams { + maint_leverage, + init_leverage, + liquidation_fee, + optimal_util, + optimal_rate, + max_rate, + version, + } => { + msg!("Mango: ChangeSpotMarketParams"); + Self::change_spot_market_params( + program_id, + accounts, + maint_leverage, + init_leverage, + liquidation_fee, + optimal_util, + optimal_rate, + max_rate, + version, + ) + } + MangoInstruction::CreateSpotOpenOrders => { + msg!("Mango: CreateSpotOpenOrders"); + Self::create_spot_open_orders(program_id, accounts) + } } } } @@ -5465,9 +6189,12 @@ fn read_oracle( OracleType::Pyth => { let price_account = Price::get_price(oracle_ai)?; let value = I80F48::from_num(price_account.agg.price); + + // Filter out bad prices on mainnet + #[cfg(not(feature = "devnet"))] let conf = I80F48::from_num(price_account.agg.conf).checked_div(value).unwrap(); - // Filter out bad prices + #[cfg(not(feature = "devnet"))] if price_account.agg.status != PriceStatus::Trading { msg!("Pyth status invalid: {}", price_account.agg.status as u8); return Err(throw_err!(MangoErrorCode::InvalidOraclePrice)); @@ -5886,6 +6613,37 @@ fn invoke_init_open_orders<'a>( solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds) } +fn invoke_close_open_orders<'a>( + dex_prog_ai: &AccountInfo<'a>, // Have to add account of the program id + open_orders_ai: &AccountInfo<'a>, + signer_ai: &AccountInfo<'a>, + destination_ai: &AccountInfo<'a>, + spot_market_ai: &AccountInfo<'a>, + signers_seeds: &[&[&[u8]]], +) -> ProgramResult { + let data = serum_dex::instruction::MarketInstruction::CloseOpenOrders.pack(); + + let instruction = Instruction { + program_id: *dex_prog_ai.key, + data, + accounts: vec![ + AccountMeta::new(*open_orders_ai.key, false), + AccountMeta::new_readonly(*signer_ai.key, true), + AccountMeta::new(*destination_ai.key, false), + AccountMeta::new_readonly(*spot_market_ai.key, false), + ], + }; + + let account_infos = [ + dex_prog_ai.clone(), + open_orders_ai.clone(), + signer_ai.clone(), + destination_ai.clone(), + spot_market_ai.clone(), + ]; + solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds) +} + /* TODO test order types */ @@ -6013,7 +6771,7 @@ fn cancel_all_advanced_orders<'a>( } // Returns asset_weight and liab_weight -fn get_leverage_weights(leverage: I80F48) -> (I80F48, I80F48) { +pub fn get_leverage_weights(leverage: I80F48) -> (I80F48, I80F48) { ( (leverage - ONE_I80F48).checked_div(leverage).unwrap(), (leverage + ONE_I80F48).checked_div(leverage).unwrap(), diff --git a/program/src/state.rs b/program/src/state.rs index 0ab676e6..82ff4199 100644 --- a/program/src/state.rs +++ b/program/src/state.rs @@ -16,10 +16,10 @@ use solana_program::program_pack::Pack; use solana_program::pubkey::Pubkey; use solana_program::sysvar::{clock::Clock, rent::Rent, Sysvar}; use spl_token::state::Account; +use static_assertions::const_assert_eq; use mango_common::Loadable; use mango_macro::{Loadable, Pod, TriviallyTransmutable}; -use static_assertions::const_assert_eq; use crate::error::{check_assert, MangoError, MangoErrorCode, MangoResult, SourceFileId}; use crate::ids::mngo_token; @@ -202,7 +202,8 @@ pub struct MangoGroup { pub max_mango_accounts: u32, // limits maximum number of MangoAccounts.v1 (closeable) accounts pub num_mango_accounts: u32, // number of MangoAccounts.v1 - pub padding: [u8; 24], // padding used for future expansions + + pub padding: [u8; 24], // padding used for future expansions } impl MangoGroup { @@ -571,11 +572,11 @@ impl NodeBank { } pub fn get_total_native_borrow(&self, root_bank_cache: &RootBankCache) -> u64 { let native: I80F48 = self.borrows * root_bank_cache.borrow_index; - native.checked_ceil().unwrap().to_num() // rounds toward +inf + native.checked_ceil().unwrap().checked_to_num().unwrap() // rounds toward +inf } pub fn get_total_native_deposit(&self, root_bank_cache: &RootBankCache) -> u64 { let native: I80F48 = self.deposits * root_bank_cache.deposit_index; - native.checked_floor().unwrap().to_num() // rounds toward -inf + native.checked_floor().unwrap().checked_to_num().unwrap() // rounds toward -inf } } @@ -1110,8 +1111,17 @@ pub struct MangoAccount { /// Starts off as zero pubkey and points to the AdvancedOrders account pub advanced_orders_key: Pubkey, + /// Can this account be upgraded to v1 so it can be closed + pub not_upgradable: bool, + + // Alternative authority/signer of transactions for a mango account + pub delegate: Pubkey, + /// padding for expansions - pub padding: [u8; 38], + /// Note: future expansion can also be just done via isolated PDAs + /// which can be computed independently and dont need to be linked from + /// this account + pub padding: [u8; 5], } impl MangoAccount { @@ -1236,10 +1246,34 @@ impl MangoAccount { let (quote_free, quote_locked, base_free, base_locked) = split_open_orders(&open_orders); - // Simulate the health if all bids are executed at current price - let bids_base_net: I80F48 = base_net + quote_locked / price + base_free + base_locked; + // Two "worst-case" scenarios are considered: + // 1. All bids are executed at current price, producing a base amount of bids_base_net + // when all quote_locked are converted to base. + // 2. All asks are executed at current price, producing a base amount of asks_base_net + // because base_locked would be converted to quote. + let bids_base_net: I80F48 = base_net + base_free + base_locked + quote_locked / price; let asks_base_net = base_net + base_free; + // Report the scenario that would have a worse outcome on health. + // + // Explanation: This function returns (base, quote) and the values later get used in + // health += (if base > 0 { asset_weight } else { liab_weight }) * base + quote + // and here we return the scenario that will increase health the least. + // + // Correctness proof: + // - always bids_base_net >= asks_base_net + // - note that scenario 1 returns (a + b, c) + // and scenario 2 returns (a, c + b), and b >= 0, c >= 0 + // - if a >= 0: scenario 1 will lead to less health as asset_weight <= 1. + // - if a < 0 and b <= -a: scenario 2 will lead to less health as liab_weight >= 1. + // - if a < 0 and b > -a: + // The health contributions of both scenarios are identical if + // asset_weight * (a + b) + c = liab_weight * a + c + b + // <=> b = (asset_weight - liab_weight) / (1 - asset_weight) * a + // <=> b = -2 a since asset_weight + liab_weight = 2 by weight construction + // So the worse scenario switches when a + b = -a. + // That means scenario 1 leads to less health whenever |a + b| > |a|. + if bids_base_net.abs() > asks_base_net.abs() { Ok((bids_base_net * price, quote_free)) } else { @@ -1884,7 +1918,7 @@ impl PerpAccount { } /// All orders must be canceled and there must be no unprocessed FillEvents for this PerpAccount - pub fn is_liquidatable(&self) -> bool { + pub fn has_no_open_orders(&self) -> bool { self.bids_quantity == 0 && self.asks_quantity == 0 && self.taker_quote == 0 diff --git a/program/tests/program_test/cookies.rs b/program/tests/program_test/cookies.rs index b98bfce4..9379bace 100644 --- a/program/tests/program_test/cookies.rs +++ b/program/tests/program_test/cookies.rs @@ -1,4 +1,5 @@ use fixed::types::I80F48; +use fixed::FixedI128; use std::mem::size_of; use std::num::NonZeroU64; @@ -494,6 +495,46 @@ impl SpotMarketCookie { spot_market_cookie } + #[allow(dead_code)] + pub async fn change_params( + &mut self, + test: &mut MangoProgramTest, + mango_group_pk: &Pubkey, + root_bank_pk: &Pubkey, + mint_index: usize, + init_leverage: Option, + maint_leverage: Option, + liquidation_fee: Option, + optimal_util: Option, + optimal_rate: Option, + max_rate: Option, + version: Option, + ) { + let mango_program_id = test.mango_program_id; + let mango_group_pk = mango_group_pk; + let spot_market_pk = self.market; + let root_bank_pk = root_bank_pk; + let admin_pk = test.get_payer_pk(); + + let instructions = [mango::instruction::change_spot_market_params( + &mango_program_id, + &mango_group_pk, + &spot_market_pk, + &root_bank_pk, + &admin_pk, + maint_leverage, + init_leverage, + liquidation_fee, + optimal_util, + optimal_rate, + max_rate, + version, + ) + .unwrap()]; + + test.process_transaction(&instructions, None).await.unwrap(); + } + #[allow(dead_code)] pub async fn place_order( &mut self, @@ -532,6 +573,48 @@ impl SpotMarketCookie { .await; mango_group_cookie.current_spot_order_id += 1; } + + #[allow(dead_code)] + pub async fn place_order_with_delegate( + &mut self, + test: &mut MangoProgramTest, + mango_group_cookie: &mut MangoGroupCookie, + user_index: usize, + delegate_user_index: usize, + side: serum_dex::matching::Side, + size: f64, + price: f64, + ) -> Result<(), TransportError> { + let limit_price = test.price_number_to_lots(&self.mint, price); + let max_coin_qty = test.base_size_number_to_lots(&self.mint, size); + let max_native_pc_qty_including_fees = match side { + serum_dex::matching::Side::Bid => { + self.mint.quote_lot as u64 * limit_price * max_coin_qty + } + serum_dex::matching::Side::Ask => std::u64::MAX, + }; + + let order = serum_dex::instruction::NewOrderInstructionV3 { + side: side, + limit_price: NonZeroU64::new(limit_price).unwrap(), + max_coin_qty: NonZeroU64::new(max_coin_qty).unwrap(), + max_native_pc_qty_including_fees: NonZeroU64::new(max_native_pc_qty_including_fees) + .unwrap(), + self_trade_behavior: serum_dex::instruction::SelfTradeBehavior::DecrementTake, + order_type: serum_dex::matching::OrderType::Limit, + client_order_id: mango_group_cookie.current_spot_order_id, + limit: u16::MAX, + }; + + test.place_spot_order_with_delegate( + &mango_group_cookie, + self, + user_index, + delegate_user_index, + order, + ) + .await + } } #[derive(Copy, Clone)] diff --git a/program/tests/program_test/mod.rs b/program/tests/program_test/mod.rs index 49fcfe66..f5707780 100644 --- a/program/tests/program_test/mod.rs +++ b/program/tests/program_test/mod.rs @@ -1,3 +1,4 @@ +use anchor_lang::Key; use std::borrow::Borrow; use std::mem::size_of; @@ -32,6 +33,12 @@ pub mod cookies; pub mod scenarios; use self::cookies::*; +const RUST_LOG_DEFAULT: &str = "solana_rbpf::vm=info,\ + solana_program_runtime::stable_log=debug,\ + solana_runtime::message_processor=debug,\ + solana_runtime::system_instruction_processor=info,\ + solana_program_test=info"; + trait AddPacked { fn add_packable_account( &mut self, @@ -258,6 +265,9 @@ impl MangoProgramTest { // limit to track compute unit increase test.set_bpf_compute_max_units(config.compute_limit); + // Supress some of the logs + solana_logger::setup_with_default(RUST_LOG_DEFAULT); + // Add MNGO mint test.add_packable_account( mngo_token::ID, @@ -997,6 +1007,40 @@ impl MangoProgramTest { open_orders_pk } + #[allow(dead_code)] + pub async fn create_spot_open_orders( + &mut self, + mango_group_pk: &Pubkey, + mango_group: &MangoGroup, + mango_account_pk: &Pubkey, + mango_account: &MangoAccount, + user_index: usize, + market_index: usize, + ) -> Pubkey { + let open_orders_seeds: &[&[u8]] = + &[&mango_account_pk.as_ref(), &market_index.to_le_bytes(), b"OpenOrders"]; + let (open_orders_pk, _) = + Pubkey::find_program_address(open_orders_seeds, &self.mango_program_id); + + let create_spot_open_orders_instruction = create_spot_open_orders( + &self.mango_program_id, + mango_group_pk, + mango_account_pk, + &mango_account.owner, + &self.serum_program_id, + &open_orders_pk, + &mango_group.spot_markets[market_index].spot_market, + &mango_group.signer_key, + ) + .unwrap(); + + let instructions = vec![create_spot_open_orders_instruction]; + let user = Keypair::from_bytes(&self.users[user_index].to_bytes()).unwrap(); + let signers = vec![&user]; + self.process_transaction(&instructions, Some(&signers)).await.unwrap(); + open_orders_pk + } + #[allow(dead_code)] pub async fn init_open_orders(&mut self) -> Pubkey { let (orders_key, instruction) = @@ -1169,7 +1213,7 @@ impl MangoProgramTest { for x in 0..mango_account.spot_open_orders.len() { if x == mint_index && mango_account.spot_open_orders[x] == Pubkey::default() { open_orders_pks.push( - self.init_spot_open_orders( + self.create_spot_open_orders( &mango_group_pk, &mango_group, &mango_account_pk, @@ -1221,6 +1265,94 @@ impl MangoProgramTest { self.process_transaction(&instructions, Some(&signers)).await.unwrap(); } + #[allow(dead_code)] + pub async fn place_spot_order_with_delegate( + &mut self, + mango_group_cookie: &MangoGroupCookie, + spot_market_cookie: &SpotMarketCookie, + user_index: usize, + delegate_user_index: usize, + order: NewOrderInstructionV3, + ) -> Result<(), TransportError> { + let mango_program_id = self.mango_program_id; + let serum_program_id = self.serum_program_id; + let mango_group = mango_group_cookie.mango_group; + let mango_group_pk = mango_group_cookie.address; + let mango_account = mango_group_cookie.mango_accounts[user_index].mango_account; + let mango_account_pk = mango_group_cookie.mango_accounts[user_index].address; + let mint_index = spot_market_cookie.mint.index; + + let delegate_user = + Keypair::from_base58_string(&self.users[delegate_user_index].to_base58_string()); + + let (signer_pk, _signer_nonce) = + create_signer_key_and_nonce(&mango_program_id, &mango_group_pk); + + let (mint_root_bank_pk, mint_root_bank) = + self.with_root_bank(&mango_group, mint_index).await; + let (mint_node_bank_pk, mint_node_bank) = self.with_node_bank(&mint_root_bank, 0).await; + let (quote_root_bank_pk, quote_root_bank) = + self.with_root_bank(&mango_group, self.quote_index).await; + let (quote_node_bank_pk, quote_node_bank) = self.with_node_bank("e_root_bank, 0).await; + + // Only pass in open orders if in margin basket or current market index, and + // the only writable account should be OpenOrders for current market index + let mut open_orders_pks = Vec::new(); + for x in 0..mango_account.spot_open_orders.len() { + if x == mint_index && mango_account.spot_open_orders[x] == Pubkey::default() { + open_orders_pks.push( + self.create_spot_open_orders( + &mango_group_pk, + &mango_group, + &mango_account_pk, + &mango_account, + user_index, + x, + ) + .await, + ); + } else { + open_orders_pks.push(mango_account.spot_open_orders[x]); + } + } + + let (dex_signer_pk, _dex_signer_nonce) = + create_signer_key_and_nonce(&serum_program_id, &spot_market_cookie.market); + + let instructions = [mango::instruction::place_spot_order( + &mango_program_id, + &mango_group_pk, + &mango_account_pk, + &delegate_user.pubkey(), + &mango_group.mango_cache, + &serum_program_id, + &spot_market_cookie.market, + &spot_market_cookie.bids, + &spot_market_cookie.asks, + &spot_market_cookie.req_q, + &spot_market_cookie.event_q, + &spot_market_cookie.coin_vault, + &spot_market_cookie.pc_vault, + &mint_root_bank_pk, + &mint_node_bank_pk, + &mint_node_bank.vault, + "e_root_bank_pk, + "e_node_bank_pk, + "e_node_bank.vault, + &signer_pk, + &dex_signer_pk, + &mango_group.msrm_vault, + &open_orders_pks, // oo ais + mint_index, + order, + ) + .unwrap()]; + + let signers = vec![&delegate_user]; + + self.process_transaction(&instructions, Some(&signers)).await + } + #[allow(dead_code)] pub async fn settle_spot_funds( &mut self, @@ -1353,6 +1485,104 @@ impl MangoProgramTest { allow_borrow, ) .unwrap()]; + self.process_transaction(&instructions, Some(&[&user])).await; + } + + #[allow(dead_code)] + pub async fn perform_withdraw_with_delegate( + &mut self, + mango_group_cookie: &MangoGroupCookie, + user_index: usize, + delegate_user_index: usize, + mint_index: usize, + quantity: u64, + allow_borrow: bool, + ) -> Result<(), TransportError> { + let mango_program_id = self.mango_program_id; + let mango_group = mango_group_cookie.mango_group; + let mango_group_pk = mango_group_cookie.address; + let mango_account = mango_group_cookie.mango_accounts[user_index].mango_account; + let mango_account_pk = mango_group_cookie.mango_accounts[user_index].address; + + let user = Keypair::from_base58_string(&self.users[user_index].to_base58_string()); + let delegate_user = + Keypair::from_base58_string(&self.users[delegate_user_index].to_base58_string()); + let user_token_account = self.with_user_token_account(user_index, mint_index); + + let (signer_pk, _signer_nonce) = + create_signer_key_and_nonce(&mango_program_id, &mango_group_pk); + + let (root_bank_pk, root_bank) = self.with_root_bank(&mango_group, mint_index).await; + let (node_bank_pk, node_bank) = self.with_node_bank(&root_bank, 0).await; // Note: not sure if nb_index is ever anything else than 0 + + let instructions = [withdraw( + &mango_program_id, + &mango_group_pk, + &mango_account_pk, + &delegate_user.pubkey(), + &mango_group.mango_cache, + &root_bank_pk, + &node_bank_pk, + &node_bank.vault, + &user_token_account, + &signer_pk, + &mango_account.spot_open_orders, + quantity, + allow_borrow, + ) + .unwrap()]; + self.process_transaction(&instructions, Some(&[&delegate_user])).await + } + + #[allow(dead_code)] + pub async fn perform_set_delegate( + &mut self, + mango_group_cookie: &MangoGroupCookie, + user_index: usize, + delegate_user_index: usize, + ) { + let mango_program_id = self.mango_program_id; + let mango_group_pk = mango_group_cookie.address; + let mango_account_pk = mango_group_cookie.mango_accounts[user_index].address; + + let user = Keypair::from_base58_string(&self.users[user_index].to_base58_string()); + let delegate = + Keypair::from_base58_string(&self.users[delegate_user_index].to_base58_string()); + + let instructions = [set_delegate( + &mango_program_id, + &mango_group_pk, + &mango_account_pk, + &user.pubkey(), + &delegate.pubkey(), + ) + .unwrap()]; + self.process_transaction(&instructions, Some(&[&user])).await.unwrap(); + } + + #[allow(dead_code)] + pub async fn perform_reset_delegate( + &mut self, + mango_group_cookie: &MangoGroupCookie, + user_index: usize, + delegate_user_index: usize, + ) { + let mango_program_id = self.mango_program_id; + let mango_group_pk = mango_group_cookie.address; + let mango_account_pk = mango_group_cookie.mango_accounts[user_index].address; + + let user = Keypair::from_base58_string(&self.users[user_index].to_base58_string()); + let delegate = + Keypair::from_base58_string(&self.users[delegate_user_index].to_base58_string()); + + let instructions = [set_delegate( + &mango_program_id, + &mango_group_pk, + &mango_account_pk, + &user.pubkey(), + &Pubkey::default(), + ) + .unwrap()]; self.process_transaction(&instructions, Some(&[&user])).await.unwrap(); } diff --git a/program/tests/program_test/scenarios.rs b/program/tests/program_test/scenarios.rs index cd8fcdaa..b68208e0 100644 --- a/program/tests/program_test/scenarios.rs +++ b/program/tests/program_test/scenarios.rs @@ -1,4 +1,5 @@ use crate::*; +use solana_sdk::transport::TransportError; #[allow(dead_code)] pub fn arrange_deposit_all_scenario( @@ -54,6 +55,48 @@ pub async fn withdraw_scenario( } } +#[allow(dead_code)] +pub async fn withdraw_scenario_with_delegate( + test: &mut MangoProgramTest, + mango_group_cookie: &mut MangoGroupCookie, + withdraw: &(usize, usize, usize, f64, bool), +) -> Result<(), TransportError> { + mango_group_cookie.run_keeper(test).await; + + let (user_index, delegate_user_index, mint_index, amount, allow_borrow) = withdraw; + let mint = test.with_mint(*mint_index); + let withdraw_amount = (*amount * mint.unit) as u64; + test.perform_withdraw_with_delegate( + &mango_group_cookie, + *user_index, + *delegate_user_index, + *mint_index, + withdraw_amount, + *allow_borrow, + ) + .await +} + +#[allow(dead_code)] +pub async fn delegate_scenario( + test: &mut MangoProgramTest, + mango_group_cookie: &mut MangoGroupCookie, + user_index: usize, + delegate_user_index: usize, +) { + test.perform_set_delegate(&mango_group_cookie, user_index, delegate_user_index).await; +} + +#[allow(dead_code)] +pub async fn reset_delegate_scenario( + test: &mut MangoProgramTest, + mango_group_cookie: &mut MangoGroupCookie, + user_index: usize, + delegate_user_index: usize, +) { + test.perform_reset_delegate(&mango_group_cookie, user_index, delegate_user_index).await; +} + #[allow(dead_code)] pub async fn place_spot_order_scenario( test: &mut MangoProgramTest, @@ -73,6 +116,31 @@ pub async fn place_spot_order_scenario( } } +#[allow(dead_code)] +pub async fn place_spot_order_scenario_with_delegate( + test: &mut MangoProgramTest, + mango_group_cookie: &mut MangoGroupCookie, + spot_order: &(usize, usize, usize, serum_dex::matching::Side, f64, f64), +) -> Result<(), TransportError> { + mango_group_cookie.run_keeper(test).await; + + let (user_index, delegate_user_index, market_index, order_side, order_size, order_price) = + *spot_order; + let mut spot_market_cookie = mango_group_cookie.spot_markets[market_index]; + mango_group_cookie.users_with_spot_event[market_index].push(user_index); + spot_market_cookie + .place_order_with_delegate( + test, + mango_group_cookie, + user_index, + delegate_user_index, + order_side, + order_size, + order_price, + ) + .await +} + #[allow(dead_code)] pub async fn place_perp_order_scenario( test: &mut MangoProgramTest, diff --git a/program/tests/test_compute.rs b/program/tests/test_compute.rs index d1eec7b4..591b2531 100644 --- a/program/tests/test_compute.rs +++ b/program/tests/test_compute.rs @@ -9,15 +9,6 @@ async fn test_add_all_markets_to_mango_group() { // === Arrange === let config = MangoProgramTestConfig { compute_limit: 200_000, num_users: 1, num_mints: 16 }; let mut test = MangoProgramTest::start_new(&config).await; - // Supress some of the logs - solana_logger::setup_with_default( - "solana_rbpf::vm=info,\ - solana_runtime::message_processor=debug,\ - solana_runtime::system_instruction_processor=info,\ - solana_program_test=info", - ); - // Disable all logs except error - // solana_logger::setup_with("error"); let mut mango_group_cookie = MangoGroupCookie::default(&mut test).await; mango_group_cookie.full_setup(&mut test, config.num_users, config.num_mints - 1).await; diff --git a/program/tests/test_delegate.rs b/program/tests/test_delegate.rs new file mode 100644 index 00000000..4967d31d --- /dev/null +++ b/program/tests/test_delegate.rs @@ -0,0 +1,103 @@ +use std::collections::HashMap; +use std::time::Duration; + +use fixed::types::I80F48; +use solana_program_test::*; + +use crate::tokio::time::sleep; +use mango::state::{QUOTE_INDEX, ZERO_I80F48}; +use program_test::assertions::*; +use program_test::cookies::*; +use program_test::scenarios::*; +use program_test::*; + +mod program_test; + +#[tokio::test] +async fn test_delegate() { + // === Arrange === + let config = MangoProgramTestConfig { compute_limit: 200_000, num_users: 2, num_mints: 2 }; + let mut test = MangoProgramTest::start_new(&config).await; + + let mut mango_group_cookie = MangoGroupCookie::default(&mut test).await; + mango_group_cookie.full_setup(&mut test, config.num_users, config.num_mints - 1).await; + + // General parameters + let user_index: usize = 0; + let delegate_user_index: usize = 1; + let mint_index: usize = 0; + let base_price: f64 = 10_000.0; + let base_size: f64 = 1.0; + let quote_mint = test.quote_mint; + + // Set oracles + mango_group_cookie.set_oracle(&mut test, mint_index, base_price).await; + + // Deposit amounts + let user_deposits = vec![(user_index, test.quote_index, base_price * 3.)]; + + // Withdraw amounts + let user_withdraw_with_delegate = + (user_index, delegate_user_index, test.quote_index, base_price, false); + + // Spot Orders + let user_spot_orders = ( + user_index, + delegate_user_index, + mint_index, + serum_dex::matching::Side::Bid, + base_size, + base_price, + ); + + // === Act === + // Step 1: Make deposits + deposit_scenario(&mut test, &mut mango_group_cookie, &user_deposits).await; + + // Step2: Setup delegate authority which can place orders on behalf + delegate_scenario(&mut test, &mut mango_group_cookie, user_index, delegate_user_index).await; + + // Step 3: Place spot orders + place_spot_order_scenario_with_delegate(&mut test, &mut mango_group_cookie, &user_spot_orders) + .await + .unwrap(); + + // === Assert === + mango_group_cookie.run_keeper(&mut test).await; + + let expected_values_vec: Vec<(usize, usize, HashMap<&str, I80F48>)> = vec![( + mint_index, // Mint index + user_index, // User index + [ + ("quote_free", ZERO_I80F48), + ("quote_locked", test.to_native("e_mint, base_price * base_size)), + ("base_free", ZERO_I80F48), + ("base_locked", ZERO_I80F48), + ] + .iter() + .cloned() + .collect(), + )]; + + for expected_values in expected_values_vec { + assert_user_spot_orders(&mut test, &mango_group_cookie, expected_values).await; + } + + // Step 4: Withdraw, should fail + withdraw_scenario_with_delegate( + &mut test, + &mut mango_group_cookie, + &user_withdraw_with_delegate, + ) + .await + .unwrap_err(); + + // Step5: Reset delegate + reset_delegate_scenario(&mut test, &mut mango_group_cookie, user_index, delegate_user_index) + .await; + + // Step6: Test placing orders again, should fail + place_spot_order_scenario_with_delegate(&mut test, &mut mango_group_cookie, &user_spot_orders) + .await + .unwrap_err(); +} diff --git a/program/tests/test_deposit.rs b/program/tests/test_deposit.rs index 6815e598..99500dbd 100644 --- a/program/tests/test_deposit.rs +++ b/program/tests/test_deposit.rs @@ -11,15 +11,6 @@ async fn test_deposit_succeeds() { // === Arrange === let config = MangoProgramTestConfig { compute_limit: 200_000, num_users: 2, num_mints: 2 }; let mut test = MangoProgramTest::start_new(&config).await; - // Supress some of the logs - solana_logger::setup_with_default( - "solana_rbpf::vm=info,\ - solana_runtime::message_processor=debug,\ - solana_runtime::system_instruction_processor=info,\ - solana_program_test=info", - ); - // Disable all logs except error - // solana_logger::setup_with("error"); let user_index = 0; let amount = 10_000; diff --git a/program/tests/test_funding_rate.rs b/program/tests/test_funding_rate.rs index 459148d8..4f30cc1a 100644 --- a/program/tests/test_funding_rate.rs +++ b/program/tests/test_funding_rate.rs @@ -10,15 +10,6 @@ async fn test_funding_rate() { // === Arrange === let config = MangoProgramTestConfig { compute_limit: 200_000, num_users: 2, num_mints: 2 }; let mut test = MangoProgramTest::start_new(&config).await; - // Supress some of the logs - solana_logger::setup_with_default( - "solana_rbpf::vm=info,\ - solana_runtime::message_processor=debug,\ - solana_runtime::system_instruction_processor=info,\ - solana_program_test=info", - ); - // Disable all logs except error - // solana_logger::setup_with("error"); let mut mango_group_cookie = MangoGroupCookie::default(&mut test).await; mango_group_cookie.full_setup(&mut test, config.num_users, config.num_mints - 1).await; diff --git a/program/tests/test_interest_rate.rs b/program/tests/test_interest_rate.rs index 60a69e6f..9c4da6b7 100644 --- a/program/tests/test_interest_rate.rs +++ b/program/tests/test_interest_rate.rs @@ -11,15 +11,6 @@ async fn test_interest_rate() { // === Arrange === let config = MangoProgramTestConfig { compute_limit: 200_000, num_users: 2, num_mints: 2 }; let mut test = MangoProgramTest::start_new(&config).await; - // Supress some of the logs - solana_logger::setup_with_default( - "solana_rbpf::vm=info,\ - solana_runtime::message_processor=debug,\ - solana_runtime::system_instruction_processor=info,\ - solana_program_test=info", - ); - // Disable all logs except error - // solana_logger::setup_with("error"); let mut mango_group_cookie = MangoGroupCookie::default(&mut test).await; mango_group_cookie.full_setup(&mut test, config.num_users, config.num_mints - 1).await; diff --git a/program/tests/test_liquidation.rs b/program/tests/test_liquidation.rs index 6baca753..6e341979 100644 --- a/program/tests/test_liquidation.rs +++ b/program/tests/test_liquidation.rs @@ -12,13 +12,6 @@ async fn test_token_and_token_liquidation_v1() { // === Arrange === let config = MangoProgramTestConfig { compute_limit: 200_000, num_users: 3, num_mints: 2 }; let mut test = MangoProgramTest::start_new(&config).await; - // Supress some of the logs - solana_logger::setup_with_default( - "solana_rbpf::vm=info,\ - solana_runtime::message_processor=debug,\ - solana_runtime::system_instruction_processor=info,\ - solana_program_test=info", - ); let mut mango_group_cookie = MangoGroupCookie::default(&mut test).await; mango_group_cookie.full_setup(&mut test, config.num_users, config.num_mints - 1).await; @@ -124,13 +117,6 @@ async fn test_token_and_token_liquidation_v2() { // === Arrange === let config = MangoProgramTestConfig { compute_limit: 200_000, num_users: 3, num_mints: 16 }; let mut test = MangoProgramTest::start_new(&config).await; - // Supress some of the logs - solana_logger::setup_with_default( - "solana_rbpf::vm=info,\ - solana_runtime::message_processor=debug,\ - solana_runtime::system_instruction_processor=info,\ - solana_program_test=info", - ); let mut mango_group_cookie = MangoGroupCookie::default(&mut test).await; mango_group_cookie.full_setup(&mut test, config.num_users, config.num_mints - 1).await; diff --git a/program/tests/test_perp_markets.rs b/program/tests/test_perp_markets.rs index db819f22..650cfdbf 100644 --- a/program/tests/test_perp_markets.rs +++ b/program/tests/test_perp_markets.rs @@ -12,15 +12,6 @@ async fn test_init_perp_markets() { // === Arrange === let config = MangoProgramTestConfig::default(); let mut test = MangoProgramTest::start_new(&config).await; - // Supress some of the logs - solana_logger::setup_with_default( - "solana_rbpf::vm=info,\ - solana_runtime::message_processor=debug,\ - solana_runtime::system_instruction_processor=info,\ - solana_program_test=info", - ); - // Disable all logs except error - // solana_logger::setup_with("error"); let mut mango_group_cookie = MangoGroupCookie::default(&mut test).await; @@ -44,15 +35,6 @@ async fn test_place_perp_order() { // === Arrange === let config = MangoProgramTestConfig { compute_limit: 200_000, num_users: 2, num_mints: 2 }; let mut test = MangoProgramTest::start_new(&config).await; - // Supress some of the logs - solana_logger::setup_with_default( - "solana_rbpf::vm=info,\ - solana_runtime::message_processor=debug,\ - solana_runtime::system_instruction_processor=info,\ - solana_program_test=info", - ); - // // Disable all logs except error - // solana_logger::setup_with("error"); let mut mango_group_cookie = MangoGroupCookie::default(&mut test).await; mango_group_cookie.full_setup(&mut test, config.num_users, config.num_mints - 1).await; @@ -96,15 +78,6 @@ async fn test_match_perp_order() { // === Arrange === let config = MangoProgramTestConfig { compute_limit: 200_000, num_users: 2, num_mints: 2 }; let mut test = MangoProgramTest::start_new(&config).await; - // Supress some of the logs - solana_logger::setup_with_default( - "solana_rbpf::vm=info,\ - solana_runtime::message_processor=debug,\ - solana_runtime::system_instruction_processor=info,\ - solana_program_test=info", - ); - // Disable all logs except error - // solana_logger::setup_with("error"); let mut mango_group_cookie = MangoGroupCookie::default(&mut test).await; mango_group_cookie.full_setup(&mut test, config.num_users, config.num_mints - 1).await; diff --git a/program/tests/test_perp_trigger_orders.rs b/program/tests/test_perp_trigger_orders.rs index 12d31882..f16175b5 100644 --- a/program/tests/test_perp_trigger_orders.rs +++ b/program/tests/test_perp_trigger_orders.rs @@ -15,13 +15,6 @@ async fn test_perp_trigger_orders_basic() { // === Arrange === let config = MangoProgramTestConfig { compute_limit: 200_000, num_users: 2, num_mints: 2 }; let mut test = MangoProgramTest::start_new(&config).await; - // Supress some of the logs - solana_logger::setup_with_default( - "solana_rbpf::vm=info,\ - solana_runtime::message_processor=debug,\ - solana_runtime::system_instruction_processor=info,\ - solana_program_test=info", - ); // Disable all logs except error // solana_logger::setup_with("error"); let mut mango_group_cookie = MangoGroupCookie::default(&mut test).await; @@ -167,13 +160,6 @@ async fn test_perp_trigger_orders_health() { // === Arrange === let config = MangoProgramTestConfig { compute_limit: 200_000, num_users: 2, num_mints: 2 }; let mut test = MangoProgramTest::start_new(&config).await; - // Supress some of the logs - solana_logger::setup_with_default( - "solana_rbpf::vm=info,\ - solana_runtime::message_processor=debug,\ - solana_runtime::system_instruction_processor=info,\ - solana_program_test=info", - ); // Disable all logs except error // solana_logger::setup_with("error"); let mut mango_group_cookie = MangoGroupCookie::default(&mut test).await; diff --git a/program/tests/test_sanity.rs b/program/tests/test_sanity.rs index f3f8834b..91284650 100644 --- a/program/tests/test_sanity.rs +++ b/program/tests/test_sanity.rs @@ -10,13 +10,6 @@ async fn test_vault_net_deposit_diff() { // === Arrange === let config = MangoProgramTestConfig { compute_limit: 200_000, num_users: 4, num_mints: 2 }; let mut test = MangoProgramTest::start_new(&config).await; - // Supress some of the logs - solana_logger::setup_with_default( - "solana_rbpf::vm=info,\ - solana_runtime::message_processor=debug,\ - solana_runtime::system_instruction_processor=info,\ - solana_program_test=info", - ); let mut mango_group_cookie = MangoGroupCookie::default(&mut test).await; mango_group_cookie.full_setup(&mut test, config.num_users, config.num_mints - 1).await; diff --git a/program/tests/test_spot_markets.rs b/program/tests/test_spot_markets.rs index 2bf09644..da93a9c4 100644 --- a/program/tests/test_spot_markets.rs +++ b/program/tests/test_spot_markets.rs @@ -1,6 +1,7 @@ mod program_test; use fixed::types::I80F48; -use mango::state::{QUOTE_INDEX, ZERO_I80F48}; +use mango::processor::get_leverage_weights; +use mango::state::{MangoGroup, RootBank, SpotMarketInfo, QUOTE_INDEX, ZERO_I80F48}; use program_test::assertions::*; use program_test::cookies::*; use program_test::scenarios::*; @@ -13,15 +14,6 @@ async fn test_list_spot_market_on_serum() { // === Arrange === let config = MangoProgramTestConfig::default(); let mut test = MangoProgramTest::start_new(&config).await; - // Supress some of the logs - solana_logger::setup_with_default( - "solana_rbpf::vm=info,\ - solana_runtime::message_processor=debug,\ - solana_runtime::system_instruction_processor=info,\ - solana_program_test=info", - ); - // Disable all logs except error - // solana_logger::setup_with("error"); let mint_index: usize = 0; // === Act === @@ -36,15 +28,7 @@ async fn test_init_spot_markets() { // === Arrange === let config = MangoProgramTestConfig::default(); let mut test = MangoProgramTest::start_new(&config).await; - // Supress some of the logs - solana_logger::setup_with_default( - "solana_rbpf::vm=info,\ - solana_runtime::message_processor=debug,\ - solana_runtime::system_instruction_processor=info,\ - solana_program_test=info", - ); - // Disable all logs except error - // solana_logger::setup_with("error"); + let mut mango_group_cookie = MangoGroupCookie::default(&mut test).await; // === Act === @@ -55,20 +39,70 @@ async fn test_init_spot_markets() { // TODO: Figure out how to assert } +#[tokio::test] +async fn test_change_spot_market_params() { + // === Arrange === + let config = MangoProgramTestConfig::default(); + let mut test = MangoProgramTest::start_new(&config).await; + + let mut mango_group_cookie = MangoGroupCookie::default(&mut test).await; + + // === Act === + let oracle_pks = test.add_oracles_to_mango_group(&mango_group_cookie.address).await; + let mut spot_markets = + mango_group_cookie.add_spot_markets(&mut test, config.num_mints - 1, &oracle_pks).await; + + // == Change spot market params, and verify them == + let init_leverage = Option::from(I80F48::from_num(20)); + let maint_leverage = Option::from(init_leverage.unwrap() * 2); + let liquidation_fee = Option::from(I80F48::from_num(0.015)); + let optimal_util = Option::from(I80F48::from_num(0.8)); + let optimal_rate = Option::from(I80F48::from_num(0.09)); + let max_rate = Option::from(I80F48::from_num(1.4)); + let version = Option::from(0); + + // load anew, after adding spot market + let mango_group = test.load_account::(mango_group_cookie.address).await; + let root_bank_pk = mango_group.tokens[0].root_bank; + + spot_markets[0] + .change_params( + &mut test, + &mango_group_cookie.address, + &root_bank_pk, + 0, + init_leverage, + maint_leverage, + liquidation_fee, + optimal_util, + optimal_rate, + max_rate, + version, + ) + .await; + + // load anew, after changing spot market params + let mango_group = test.load_account::(mango_group_cookie.address).await; + let spot_market_info = mango_group.spot_markets[0]; + let (init_asset_weight, init_liab_weight) = get_leverage_weights(init_leverage.unwrap()); + assert!(spot_market_info.init_asset_weight == init_asset_weight); + assert!(spot_market_info.init_liab_weight == init_liab_weight); + let (maint_asset_weight, maint_liab_weight) = get_leverage_weights(maint_leverage.unwrap()); + assert!(spot_market_info.maint_asset_weight == maint_asset_weight); + assert!(spot_market_info.maint_liab_weight == maint_liab_weight); + + let root_bank = test.load_account::(root_bank_pk).await; + assert!(root_bank.optimal_util == optimal_util.unwrap()); + assert!(root_bank.optimal_rate == optimal_rate.unwrap()); + assert!(root_bank.max_rate == max_rate.unwrap()); + assert_eq!(root_bank.meta_data.version, version.unwrap()); +} + #[tokio::test] async fn test_place_spot_order() { // === Arrange === let config = MangoProgramTestConfig { compute_limit: 200_000, num_users: 2, num_mints: 2 }; let mut test = MangoProgramTest::start_new(&config).await; - // Supress some of the logs - solana_logger::setup_with_default( - "solana_rbpf::vm=info,\ - solana_runtime::message_processor=debug,\ - solana_runtime::system_instruction_processor=info,\ - solana_program_test=info", - ); - // Disable all logs except error - // solana_logger::setup_with("error"); let mut mango_group_cookie = MangoGroupCookie::default(&mut test).await; mango_group_cookie.full_setup(&mut test, config.num_users, config.num_mints - 1).await; @@ -124,15 +158,6 @@ async fn test_match_spot_order() { // === Arrange === let config = MangoProgramTestConfig { compute_limit: 200_000, num_users: 2, num_mints: 2 }; let mut test = MangoProgramTest::start_new(&config).await; - // Supress some of the logs - solana_logger::setup_with_default( - "solana_rbpf::vm=info,\ - solana_runtime::message_processor=debug,\ - solana_runtime::system_instruction_processor=info,\ - solana_program_test=info", - ); - // Disable all logs except error - // solana_logger::setup_with("error"); let mut mango_group_cookie = MangoGroupCookie::default(&mut test).await; mango_group_cookie.full_setup(&mut test, config.num_users, config.num_mints - 1).await; @@ -230,15 +255,6 @@ async fn test_match_and_settle_spot_order() { // === Arrange === let config = MangoProgramTestConfig { compute_limit: 200_000, num_users: 2, num_mints: 2 }; let mut test = MangoProgramTest::start_new(&config).await; - // Supress some of the logs - solana_logger::setup_with_default( - "solana_rbpf::vm=info,\ - solana_runtime::message_processor=debug,\ - solana_runtime::system_instruction_processor=info,\ - solana_program_test=info", - ); - // Disable all logs except error - // solana_logger::setup_with("error"); let mut mango_group_cookie = MangoGroupCookie::default(&mut test).await; mango_group_cookie.full_setup(&mut test, config.num_users, config.num_mints - 1).await; diff --git a/program/tests/test_worst_case.rs b/program/tests/test_worst_case.rs index f70fbd7b..94c8c6ac 100644 --- a/program/tests/test_worst_case.rs +++ b/program/tests/test_worst_case.rs @@ -13,15 +13,6 @@ async fn test_worst_case_v1() { // === Arrange === let config = MangoProgramTestConfig { compute_limit: 200_000, num_users: 2, num_mints: 16 }; let mut test = MangoProgramTest::start_new(&config).await; - // Supress some of the logs - solana_logger::setup_with_default( - "solana_rbpf::vm=info,\ - solana_runtime::message_processor=debug,\ - solana_runtime::system_instruction_processor=info,\ - solana_program_test=info", - ); - // Disable all logs except error - // solana_logger::setup_with("error"); let mut mango_group_cookie = MangoGroupCookie::default(&mut test).await; mango_group_cookie.full_setup(&mut test, config.num_users, config.num_mints - 1).await; @@ -108,15 +99,6 @@ async fn test_worst_case_v2() { // === Arrange === let config = MangoProgramTestConfig { compute_limit: 200_000, num_users: 2, num_mints: 16 }; let mut test = MangoProgramTest::start_new(&config).await; - // Supress some of the logs - solana_logger::setup_with_default( - "solana_rbpf::vm=info,\ - solana_runtime::message_processor=debug,\ - solana_runtime::system_instruction_processor=info,\ - solana_program_test=info", - ); - // Disable all logs except error - // solana_logger::setup_with("error"); let mut mango_group_cookie = MangoGroupCookie::default(&mut test).await; mango_group_cookie.full_setup(&mut test, config.num_users, config.num_mints - 1).await;