diff --git a/.cargo/config b/.cargo/config.toml similarity index 100% rename from .cargo/config rename to .cargo/config.toml diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 6c4a01e..29455ea 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -22,6 +22,9 @@ jobs: - name: Checkout uses: actions/checkout@v3 + - name: Install cargo-near + run: curl --proto '=https' --tlsv1.2 -LsSf https://github.com/near/cargo-near/releases/download/cargo-near-v0.19.0/cargo-near-installer.sh | sh + - name: Build run: make build @@ -39,5 +42,8 @@ jobs: - name: Checkout uses: actions/checkout@v3 + - name: Install cargo-near + run: curl --proto '=https' --tlsv1.2 -LsSf https://github.com/near/cargo-near/releases/download/cargo-near-v0.19.0/cargo-near-installer.sh | sh + - name: Integration tests run: make integration diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cf83fd3..a63e4c9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,6 +22,9 @@ jobs: - name: Checkout uses: actions/checkout@v3 + - name: Install cargo-near + run: curl --proto '=https' --tlsv1.2 -LsSf https://github.com/near/cargo-near/releases/download/cargo-near-v0.19.0/cargo-near-installer.sh | sh + - name: Build run: make build @@ -39,5 +42,8 @@ jobs: - name: Checkout uses: actions/checkout@v3 + - name: Install cargo-near + run: curl --proto '=https' --tlsv1.2 -LsSf https://github.com/near/cargo-near/releases/download/cargo-near-v0.19.0/cargo-near-installer.sh | sh + - name: Integration tests run: make integration diff --git a/.zed/settings.json b/.zed/settings.json new file mode 100644 index 0000000..f239190 --- /dev/null +++ b/.zed/settings.json @@ -0,0 +1,12 @@ +{ + "lsp": { + "rust-analyzer": { + "initialization_options": { + "linkedProjects": [ + "Cargo.toml", + "integration-tests/Cargo.toml" + ], + } + } + } +} diff --git a/Cargo.lock b/Cargo.lock index 67ea09e..ae9c6e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "Inflector" @@ -9,109 +9,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" [[package]] -name = "actix" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cba56612922b907719d4a01cf11c8d5b458e7d3dba946d0435f20f58d6795ed2" -dependencies = [ - "actix-macros", - "actix-rt", - "actix_derive", - "bitflags 2.4.1", - "bytes", - "crossbeam-channel", - "futures-core", - "futures-sink", - "futures-task", - "futures-util", - "log", - "once_cell", - "parking_lot", - "pin-project-lite", - "smallvec", - "tokio", - "tokio-util 0.7.10", -] - -[[package]] -name = "actix-macros" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" -dependencies = [ - "quote", - "syn 2.0.38", -] - -[[package]] -name = "actix-rt" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28f32d40287d3f402ae0028a9d54bef51af15c8769492826a69d28f81893151d" -dependencies = [ - "futures-core", - "tokio", -] - -[[package]] -name = "actix_derive" -version = "0.6.1" +name = "addr2line" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c7db3d5a9718568e4cf4a537cfd7070e6e6ff7481510d0237fb529ac850f6d3" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aes" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" -dependencies = [ - "cfg-if 1.0.0", - "cipher 0.4.4", - "cpufeatures", -] - -[[package]] -name = "ahash" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" -dependencies = [ - "getrandom 0.2.10", - "once_cell", - "version_check", + "gimli", ] [[package]] -name = "ahash" -version = "0.8.6" +name = "aho-corasick" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ - "cfg-if 1.0.0", - "once_cell", - "version_check", - "zerocopy", + "memchr", ] [[package]] -name = "aho-corasick" -version = "1.1.2" +name = "allocator-api2" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "android-tzdata" @@ -130,134 +49,85 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.4" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", - "windows-sys", + "once_cell_polyfill", + "windows-sys 0.61.2", ] [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "arbitrary" -version = "1.3.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2e1373abdaa212b704512ec2bd8b26bd0b7d5c3f70117411a5d9a451383c859" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" dependencies = [ "derive_arbitrary", ] -[[package]] -name = "arrayref" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" - -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - -[[package]] -name = "assert_matches" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" - -[[package]] -name = "async-stream" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.117", ] [[package]] -name = "atty" -version = "0.2.14" +name = "atomic-waker" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" @@ -267,45 +137,15 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" - -[[package]] -name = "base64" -version = "0.13.1" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64" -version = "0.21.5" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - -[[package]] -name = "binary-install" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93bff426ff93f3610dd2b946f3eb8cb2d1285ca8682834d43be531a3f93db2ff" -dependencies = [ - "anyhow", - "dirs-next", - "flate2", - "fs2", - "hex", - "is_executable", - "siphasher", - "tar", - "ureq", - "zip 0.6.6", -] +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" @@ -315,21 +155,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" - -[[package]] -name = "bitvec" -version = "0.20.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7774144344a4faa177370406a7ff5f1da24303817368584c6206c8303eb07848" -dependencies = [ - "funty 1.1.0", - "radium 0.6.2", - "tap", - "wyz 0.2.0", -] +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" [[package]] name = "bitvec" @@ -337,30 +165,19 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ - "funty 2.0.0", - "radium 0.7.0", + "funty", + "radium", "tap", - "wyz 0.5.1", + "wyz", ] [[package]] name = "blake2" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a4e37d16930f5459780f5621038b6382b9bb37c19016f39fb6b5808d831f174" -dependencies = [ - "crypto-mac", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "block-buffer" -version = "0.9.0" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ - "generic-array", + "digest", ] [[package]] @@ -373,23 +190,15 @@ dependencies = [ ] [[package]] -name = "borsh" -version = "0.9.3" +name = "blst" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" +checksum = "dcdb4c7013139a150f9fc55d123186dbfaba0d912817466282c73ac49e71fb45" dependencies = [ - "borsh-derive 0.9.3", - "hashbrown 0.11.2", -] - -[[package]] -name = "borsh" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" -dependencies = [ - "borsh-derive 0.10.3", - "hashbrown 0.13.2", + "cc", + "glob", + "threadpool", + "zeroize", ] [[package]] @@ -398,36 +207,10 @@ version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f58b559fd6448c6e2fd0adb5720cd98a2506594cafa4737ff98c396f3e82f667" dependencies = [ - "borsh-derive 1.3.1", + "borsh-derive", "cfg_aliases", ] -[[package]] -name = "borsh-derive" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" -dependencies = [ - "borsh-derive-internal 0.9.3", - "borsh-schema-derive-internal 0.9.3", - "proc-macro-crate 0.1.5", - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "borsh-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" -dependencies = [ - "borsh-derive-internal 0.10.3", - "borsh-schema-derive-internal 0.10.3", - "proc-macro-crate 0.1.5", - "proc-macro2", - "syn 1.0.109", -] - [[package]] name = "borsh-derive" version = "1.3.1" @@ -438,63 +221,10 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.117", "syn_derive", ] -[[package]] -name = "borsh-derive-internal" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "borsh-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "brownstone" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030ea61398f34f1395ccbeb046fb68c87b631d1f34567fed0f0f11fa35d18d8d" -dependencies = [ - "arrayvec 0.7.4", -] - [[package]] name = "bs58" version = "0.4.0" @@ -512,15 +242,12 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" - -[[package]] -name = "byte-slice-cast" -version = "1.2.2" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +dependencies = [ + "allocator-api2", +] [[package]] name = "byteorder" @@ -530,381 +257,359 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "bytesize" -version = "1.3.0" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc" +checksum = "2e93abca9e28e0a1b9877922aacb20576e05d4679ffa78c3d6dc22a26a216659" dependencies = [ "serde", ] [[package]] -name = "bzip2" -version = "0.4.4" +name = "cc" +version = "1.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" dependencies = [ - "bzip2-sys", + "find-msvc-tools", + "jobserver", "libc", + "shlex", ] [[package]] -name = "bzip2-sys" -version = "0.1.11+1.0.8" +name = "cfg-if" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" -dependencies = [ - "cc", - "libc", - "pkg-config", -] +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] -name = "c2-chacha" -version = "0.3.3" +name = "cfg-if" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d27dae93fe7b1e0424dc57179ac396908c26b035a87234809f5c4dfd1b47dc80" -dependencies = [ - "cipher 0.2.5", - "ppv-lite86", -] +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "camino" -version = "1.1.6" +name = "cfg_aliases" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" -dependencies = [ - "serde", -] +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] -name = "cargo-near" -version = "0.3.1" +name = "chrono" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f73eb01da3b6737778d2006645533e75563d1080c64bf714bfb88d3fb0ac09b" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ - "anyhow", - "atty", - "bs58 0.4.0", - "camino", - "cargo_metadata", - "clap 3.2.25", - "colored", - "env_logger", - "libloading", - "log", - "near-abi", - "rustc_version", - "schemars", - "serde_json", - "sha2 0.10.8", - "symbolic-debuginfo", - "zstd", + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets 0.48.5", ] [[package]] -name = "cargo-platform" -version = "0.1.4" +name = "clap" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12024c4645c97566567129c204f65d5815a8c9aecf30fcbe682b2fe034996d36" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ - "serde", + "clap_builder", + "clap_derive", ] [[package]] -name = "cargo_metadata" -version = "0.14.2" +name = "clap_builder" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ - "camino", - "cargo-platform", - "semver", - "serde", - "serde_json", + "anstream", + "anstyle", + "clap_lex", + "strsim", ] [[package]] -name = "cc" -version = "1.0.83" +name = "clap_derive" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ - "jobserver", - "libc", + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] -name = "cfg-if" -version = "0.1.10" +name = "clap_lex" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] -name = "cfg-if" -version = "1.0.0" +name = "cobs" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror 2.0.18", +] [[package]] -name = "cfg_aliases" -version = "0.1.1" +name = "colorchoice" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] -name = "chrono" -version = "0.4.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +name = "contract" +version = "1.3.0" dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-targets", + "near-contract-standards", + "near-plugins", + "near-sdk", + "static_assertions", ] [[package]] -name = "cipher" -version = "0.2.5" +name = "convert_case" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" dependencies = [ - "generic-array", + "unicode-segmentation", ] [[package]] -name = "cipher" -version = "0.4.4" +name = "core-foundation-sys" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", -] +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] -name = "clap" -version = "3.2.25" +name = "cpufeatures" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ - "atty", - "bitflags 1.3.2", - "clap_derive 3.2.25", - "clap_lex 0.2.4", - "indexmap 1.9.3", - "once_cell", - "strsim", - "termcolor", - "textwrap", + "libc", ] [[package]] -name = "clap" -version = "4.4.7" +name = "cranelift-assembler-x64" +version = "0.123.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" +checksum = "44f81cede359311706057b689b91b59f464926de0316f389898a2b028cb494fa" dependencies = [ - "clap_builder", - "clap_derive 4.4.7", + "cranelift-assembler-x64-meta", ] [[package]] -name = "clap_builder" -version = "4.4.7" +name = "cranelift-assembler-x64-meta" +version = "0.123.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" +checksum = "fa6ca11305de425ea08884097b913ebe1a83875253b3c0063ce28411e226bfdc" dependencies = [ - "anstream", - "anstyle", - "clap_lex 0.6.0", - "strsim", + "cranelift-srcgen", ] [[package]] -name = "clap_derive" -version = "3.2.25" +name = "cranelift-bforest" +version = "0.123.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" +checksum = "7537341a9a4ba9812141927be733e7254bf2318aab6597d567af9cad90609f27" dependencies = [ - "heck 0.4.1", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", + "cranelift-entity", ] [[package]] -name = "clap_derive" -version = "4.4.7" +name = "cranelift-bitset" +version = "0.123.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "d28a4ca5faf25ff821fcc768f26e68ffef505e9f71bb06e608862d941fa65086" dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "syn 2.0.38", + "serde", + "serde_derive", ] [[package]] -name = "clap_lex" -version = "0.2.4" +name = "cranelift-codegen" +version = "0.123.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +checksum = "d891057fe1b73910c41e73b32a70fa8454092fce65942b5fa6f72aa6d5487f8a" dependencies = [ - "os_str_bytes", + "bumpalo", + "cranelift-assembler-x64", + "cranelift-bforest", + "cranelift-bitset", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-control", + "cranelift-entity", + "cranelift-isle", + "gimli", + "hashbrown 0.15.5", + "log", + "pulley-interpreter", + "regalloc2", + "rustc-hash", + "serde", + "smallvec", + "target-lexicon", + "wasmtime-internal-math", ] [[package]] -name = "clap_lex" -version = "0.6.0" +name = "cranelift-codegen-meta" +version = "0.123.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "c29a66028a78eedc534b3a94e5ebfbaeb4e1f6b09038afe41bb24afd614faa4b" +dependencies = [ + "cranelift-assembler-x64-meta", + "cranelift-codegen-shared", + "cranelift-srcgen", + "heck 0.5.0", + "pulley-interpreter", +] [[package]] -name = "colorchoice" -version = "1.0.0" +name = "cranelift-codegen-shared" +version = "0.123.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "95809ad251fe9422087b4a72d61e584d6ab6eff44dee1335f93cfaea0bedc9ac" [[package]] -name = "colored" -version = "2.0.4" +name = "cranelift-control" +version = "0.123.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" +checksum = "f79d0cacf063c297e5e8d5b73cb355b41b87f6d248e252d1b284e7a7b73673c2" dependencies = [ - "is-terminal", - "lazy_static", - "windows-sys", + "arbitrary", ] [[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - -[[package]] -name = "convert_case" -version = "0.4.0" +name = "cranelift-entity" +version = "0.123.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +checksum = "b2d73297a195ce3be55997c6307142c4b1e58dd0c2f18ceaa0179444024e312a" +dependencies = [ + "cranelift-bitset", + "serde", + "serde_derive", +] [[package]] -name = "core-foundation" -version = "0.9.3" +name = "cranelift-frontend" +version = "0.123.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "3be38d1ae29ef7c5d611fc6cb694f698dc4ca44152dcaa112ec0fef8d4d34858" dependencies = [ - "core-foundation-sys", - "libc", + "cranelift-codegen", + "log", + "smallvec", + "target-lexicon", ] [[package]] -name = "core-foundation-sys" -version = "0.8.4" +name = "cranelift-isle" +version = "0.123.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "6761926f6636209de7ac568be28b206890f2181761375b9722e0a1e7a7e1637a" [[package]] -name = "cpufeatures" -version = "0.2.11" +name = "cranelift-native" +version = "0.123.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "0893472f73f0d530a28e9a573ada6d1f93b9659bb6734dfe17061ac967bd1830" dependencies = [ + "cranelift-codegen", "libc", + "target-lexicon", ] +[[package]] +name = "cranelift-srcgen" +version = "0.123.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1daccebabb1ccd034dbab0eacc0722af27d3cccc7929dea27a3546cb3562e40" + [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ - "cfg-if 1.0.0", "crossbeam-utils", ] [[package]] -name = "crossbeam-utils" -version = "0.8.16" +name = "crossbeam-deque" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ - "cfg-if 1.0.0", + "crossbeam-epoch", + "crossbeam-utils", ] [[package]] -name = "crunchy" -version = "0.2.2" +name = "crossbeam-epoch" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] [[package]] -name = "crypto-common" -version = "0.1.6" +name = "crossbeam-utils" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] -name = "crypto-mac" -version = "0.8.0" +name = "crunchy" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" -dependencies = [ - "generic-array", - "subtle", -] +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] -name = "curve25519-dalek" -version = "3.2.1" +name = "crypto-common" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", - "subtle", - "zeroize", + "generic-array", + "typenum", ] [[package]] name = "curve25519-dalek" -version = "4.1.1" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if 1.0.0", "cpufeatures", "curve25519-dalek-derive", - "digest 0.10.7", + "digest", "fiat-crypto", - "platforms", - "rand_core 0.6.4", "rustc_version", "subtle", "zeroize", @@ -918,14 +623,14 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.117", ] [[package]] name = "darling" -version = "0.20.3" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ "darling_core", "darling_macro", @@ -933,43 +638,34 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.3" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.38", + "syn 2.0.117", ] [[package]] name = "darling_macro" -version = "0.20.3" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn 2.0.38", -] - -[[package]] -name = "debugid" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ee87af31d84ef885378aebca32be3d682b0e0dc119d5b4860a2c5bb5046730" -dependencies = [ - "uuid", + "syn 2.0.117", ] [[package]] name = "deranged" -version = "0.3.9" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" dependencies = [ "powerfmt", "serde", @@ -977,92 +673,102 @@ dependencies = [ [[package]] name = "derive_arbitrary" -version = "1.3.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e0efad4403bfc52dc201159c4b842a246a14b98c64b55dfd0f2d89729dfeb8" +checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.117", ] [[package]] -name = "derive_more" -version = "0.99.17" +name = "derive_builder" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version", - "syn 1.0.109", + "derive_builder_macro", ] [[package]] -name = "deunicode" -version = "1.4.1" +name = "derive_builder_core" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a1abaf4d861455be59f64fd2b55606cb151fce304ede7165f410243ce96bde6" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] -name = "digest" -version = "0.9.0" +name = "derive_builder_macro" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ - "generic-array", + "derive_builder_core", + "syn 2.0.117", ] [[package]] -name = "digest" -version = "0.10.7" +name = "derive_more" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ - "block-buffer 0.10.4", - "crypto-common", - "subtle", + "derive_more-impl", ] [[package]] -name = "dirs-next" -version = "2.0.0" +name = "derive_more-impl" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ - "cfg-if 1.0.0", - "dirs-sys-next", + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.117", + "unicode-xid", ] [[package]] -name = "dirs-sys-next" -version = "0.1.2" +name = "digest" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "libc", - "redox_users", - "winapi", + "block-buffer", + "crypto-common", + "subtle", ] [[package]] -name = "dmsort" -version = "1.0.2" +name = "displaydoc" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0bc8fbe9441c17c9f46f75dfe27fa1ddb6c68a461ccaed0481419219d4f10d3" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] -name = "dotenv" -version = "0.15.0" +name = "dissimilar" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" +checksum = "aeda16ab4059c5fd2a83f2b9c9e9c981327b18aa8e3b313f7e6563799d4f093e" [[package]] name = "dyn-clone" -version = "1.0.14" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "easy-ext" @@ -1070,107 +776,63 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53aff6fdc1b181225acdcb5b14c47106726fd8e486707315b1b138baed68ee31" -[[package]] -name = "ed25519" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" -dependencies = [ - "signature 1.6.4", -] - [[package]] name = "ed25519" version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ - "signature 2.2.0", -] - -[[package]] -name = "ed25519-dalek" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" -dependencies = [ - "curve25519-dalek 3.2.1", - "ed25519 1.5.3", - "rand 0.7.3", - "serde", - "sha2 0.9.9", - "zeroize", + "signature", ] [[package]] name = "ed25519-dalek" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" dependencies = [ - "curve25519-dalek 4.1.1", - "ed25519 2.2.3", - "rand_core 0.6.4", - "sha2 0.10.8", + "curve25519-dalek", + "ed25519", + "sha2", "subtle", ] [[package]] name = "either" -version = "1.9.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] -name = "elementtree" -version = "0.7.0" +name = "embedded-io" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6319c9433cf1e95c60c8533978bccf0614f27f03bb4e514253468eeeaa7fe3" -dependencies = [ - "string_cache", - "xml-rs", -] +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" [[package]] -name = "encoding_rs" -version = "0.8.33" +name = "embedded-io" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" -dependencies = [ - "cfg-if 1.0.0", -] +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" [[package]] name = "enum-map" -version = "2.7.0" +version = "2.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53337c2dbf26a3c31eccc73a37b10c1614e8d4ae99b6a50d553e8936423c1f16" +checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9" dependencies = [ "enum-map-derive", ] [[package]] name = "enum-map-derive" -version = "0.14.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04d0b288e3bb1d861c4403c1774a6f7a798781dfc519b3647df2a3dd4ae95f25" +checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", -] - -[[package]] -name = "env_logger" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", + "syn 2.0.117", ] [[package]] @@ -1181,12 +843,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.5" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -1196,44 +858,58 @@ dependencies = [ "near-sdk", ] -[[package]] -name = "fake" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26221445034074d46b276e13eb97a265ebdb8ed8da705c4dddd3dd20b66b45d2" -dependencies = [ - "deunicode", - "rand 0.8.5", -] - [[package]] name = "fallible-iterator" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "fastrand" -version = "2.0.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "fiat-crypto" -version = "0.2.5" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "finite-wasm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d81b511929c2669eaf64e36471cf27c2508133e62ade9d49e608e8d675e7854" +dependencies = [ + "bitvec", + "dissimilar", + "num-traits", + "prefix-sum-vec", + "thiserror 1.0.69", + "wasm-encoder 0.27.0", + "wasmparser 0.105.0", + "wasmprinter 0.2.57", +] [[package]] -name = "filetime" -version = "0.2.22" +name = "finite-wasm" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +checksum = "4dce601f45d7bbc875827d3c35fa00f7dfc00ec63cdf327ff34b54ab1f2ac1ad" dependencies = [ - "cfg-if 1.0.0", - "libc", - "redox_syscall 0.3.5", - "windows-sys", + "bitvec", + "dissimilar", + "num-traits", + "prefix-sum-vec", + "thiserror 1.0.69", + "wasmparser 0.228.0", ] [[package]] @@ -1242,28 +918,9 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" dependencies = [ - "byteorder", - "rand 0.8.5", - "rustc-hex", "static_assertions", ] -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - -[[package]] -name = "flate2" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - [[package]] name = "fnv" version = "1.0.7" @@ -1271,137 +928,92 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "foreign-types" -version = "0.3.2" +name = "foldhash" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] -name = "foreign-types-shared" -version = "0.1.1" +name = "foldhash" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] -[[package]] -name = "fs2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "funty" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" - [[package]] name = "funty" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" -[[package]] -name = "futures" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", - "futures-sink", ] [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", "futures-util", ] -[[package]] -name = "futures-io" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" - [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.117", ] [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ - "futures-channel", "futures-core", - "futures-io", "futures-macro", "futures-sink", "futures-task", - "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -1417,75 +1029,76 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.16" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi 0.9.0+wasi-snapshot-preview1", + "r-efi 5.3.0", + "wasip2", ] [[package]] name = "getrandom" -version = "0.2.10" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "r-efi 6.0.0", + "wasip2", + "wasip3", ] [[package]] name = "gimli" -version = "0.26.2" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" dependencies = [ "fallible-iterator", + "indexmap 2.14.0", "stable_deref_trait", ] [[package]] -name = "goblin" -version = "0.5.4" +name = "glob" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7666983ed0dd8d21a6f6576ee00053ca0926fb281a5522577a4dbd0f1b54143" -dependencies = [ - "log", - "plain", - "scroll 0.11.0", -] +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "h2" -version = "0.3.21" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733" dependencies = [ + "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "futures-util", "http", - "indexmap 1.9.3", + "indexmap 2.14.0", "slab", "tokio", - "tokio-util 0.7.10", + "tokio-util", "tracing", ] -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash 0.7.7", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -1494,27 +1107,30 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.13.2" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "ahash 0.8.6", + "foldhash 0.1.5", + "serde", ] [[package]] name = "hashbrown" -version = "0.14.2" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] [[package]] -name = "heck" -version = "0.3.3" +name = "hashbrown" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "heck" @@ -1523,19 +1139,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "heck" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -1547,110 +1160,96 @@ dependencies = [ ] [[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "home" -version = "0.5.5" +name = "http" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ - "windows-sys", + "bytes", + "itoa", ] [[package]] -name = "http" -version = "0.2.9" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "fnv", - "itoa", + "http", ] [[package]] -name = "http-body" -version = "0.4.5" +name = "http-body-util" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", + "futures-core", "http", + "http-body", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "humantime" -version = "2.1.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "hyper" -version = "0.14.27" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" dependencies = [ + "atomic-waker", "bytes", "futures-channel", "futures-core", - "futures-util", "h2", "http", "http-body", "httparse", - "httpdate", "itoa", "pin-project-lite", - "socket2", + "smallvec", "tokio", - "tower-service", - "tracing", "want", ] [[package]] name = "hyper-timeout" -version = "0.4.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ "hyper", + "hyper-util", "pin-project-lite", "tokio", - "tokio-io-timeout", + "tower-service", ] [[package]] -name = "hyper-tls" -version = "0.5.0" +name = "hyper-util" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", "hyper", - "native-tls", + "libc", + "pin-project-lite", + "socket2", "tokio", - "tokio-native-tls", + "tower-service", + "tracing", ] [[package]] @@ -1677,155 +1276,154 @@ dependencies = [ ] [[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "0.4.0" +name = "icu_collections" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", ] [[package]] -name = "impl-codec" -version = "0.5.1" +name = "icu_locale_core" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "161ebdfec3c8e3b52bf61c4f3550a1eea4f9579d10dc1b936f3171ebdcd6c443" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ - "parity-scale-codec", + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", ] [[package]] -name = "impl-trait-for-tuples" -version = "0.2.2" +name = "icu_normalizer" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", ] [[package]] -name = "indent_write" +name = "icu_normalizer_data" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cfe9645a18782869361d9c8732246be7b410ad4e919d3609ebabdac00ba12c3" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] -name = "indexmap" -version = "1.9.3" +name = "icu_properties" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", ] [[package]] -name = "indexmap" -version = "2.0.2" +name = "icu_properties_data" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" -dependencies = [ - "equivalent", - "hashbrown 0.14.2", - "serde", -] +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] -name = "inout" -version = "0.1.3" +name = "icu_provider" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ - "generic-array", + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", ] [[package]] -name = "integration-tests" -version = "1.0.0" -dependencies = [ - "anyhow", - "async-trait", - "borsh 0.10.3", - "integration-utils", - "maplit", - "near-contract-standards", - "near-sdk", - "near-units", - "near-workspaces", - "pkg-config", - "sweat-model", - "tokio", - "tracing", - "tracing-subscriber", -] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] -name = "integration-trait" -version = "0.1.0" -source = "git+https://github.com/sweatco/integration-utils.git?rev=e54dc392ef42837123dd2c0ad19b6d6b815192d7#e54dc392ef42837123dd2c0ad19b6d6b815192d7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] -name = "integration-utils" -version = "0.1.0" -source = "git+https://github.com/sweatco/integration-utils.git?rev=e54dc392ef42837123dd2c0ad19b6d6b815192d7#e54dc392ef42837123dd2c0ad19b6d6b815192d7" +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ - "anyhow", - "async-trait", - "dotenv", - "fake", - "futures", - "near-sdk", - "near-units", - "near-workspaces", - "tokio", + "idna_adapter", + "smallvec", + "utf8_iter", ] [[package]] -name = "ipnet" -version = "2.9.0" +name = "idna_adapter" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" +dependencies = [ + "icu_normalizer", + "icu_properties", +] [[package]] -name = "is-terminal" -version = "0.4.9" +name = "indexmap" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ - "hermit-abi 0.3.3", - "rustix", - "windows-sys", + "autocfg", + "hashbrown 0.12.3", + "serde", ] [[package]] -name = "is_executable" -version = "0.1.2" +name = "indexmap" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d553b8abc8187beb7d663e34c065ac4570b273bc9511a50e940e99409c577" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ - "winapi", + "equivalent", + "hashbrown 0.17.1", + "serde", + "serde_core", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + [[package]] name = "itertools" -version = "0.10.5" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ "either", ] @@ -1838,417 +1436,266 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ + "getrandom 0.3.4", "libc", ] -[[package]] -name = "joinery" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5" - [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" dependencies = [ + "cfg-if 1.0.0", + "futures-util", + "once_cell", "wasm-bindgen", ] -[[package]] -name = "json-patch" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ff1e1486799e3f64129f8ccad108b38290df9cd7015cd31bed17239f0789d6" -dependencies = [ - "serde", - "serde_json", - "thiserror", - "treediff", -] - [[package]] name = "json_comments" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ee439ee368ba4a77ac70d04f14015415af8600d6c894dc1f11bd79758c57d5" +checksum = "9dbbfed4e59ba9750e15ba154fdfd9329cee16ff3df539c2666b70f58cc32105" [[package]] name = "keccak" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" dependencies = [ "cpufeatures", ] [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + +[[package]] +name = "leb128" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -dependencies = [ - "spin 0.5.2", -] +checksum = "6cc46bac87ef8093eed6f272babb833b6443374399985ac8ed28471ee0918545" [[package]] -name = "lazycell" -version = "1.3.0" +name = "leb128fmt" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.149" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] -name = "libloading" -version = "0.7.4" +name = "libm" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if 1.0.0", - "winapi", -] +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "maplit" -version = "1.0.2" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] -name = "matchers" -version = "0.1.0" +name = "lru" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39" dependencies = [ - "regex-automata 0.1.10", + "hashbrown 0.16.1", ] [[package]] -name = "memchr" -version = "2.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "memmap2" -version = "0.5.10" +name = "mach2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" dependencies = [ "libc", ] [[package]] -name = "memoffset" -version = "0.8.0" +name = "matchers" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ - "autocfg", + "regex-automata", ] [[package]] -name = "memory_units" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.7.1" +name = "memchr" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] -name = "mio" -version = "0.8.9" +name = "memfd" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "ad38eb12aea514a0466ea40a80fd8cc83637065948eb4a426e4aa46261175227" dependencies = [ - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "rustix", ] [[package]] -name = "multimap" -version = "0.8.3" +name = "memory_units" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" +checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" [[package]] -name = "native-tls" -version = "0.2.11" +name = "mio" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ - "lazy_static", "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", + "wasi", + "windows-sys 0.61.2", ] [[package]] name = "near-abi" -version = "0.3.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "885db39b08518fa700b73fa2214e8adbbfba316ba82dd510f50519173eadaf73" +checksum = "7c49593c9e94454a2368a4c0a511bf4bf1413aff4d23f16e1d8f4e64b5215351" dependencies = [ - "borsh 0.9.3", - "schemars", + "borsh", + "schemars 0.8.22", "semver", "serde", ] [[package]] name = "near-account-id" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d258582a1878e6db67400b0504a5099db85718d22c2e07f747fe1706ae7150" -dependencies = [ - "borsh 0.9.3", - "serde", -] - -[[package]] -name = "near-account-id" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35cbb989542587b47205e608324ddd391f0cee1c22b4b64ae49f458334b95907" -dependencies = [ - "borsh 1.3.1", - "serde", -] - -[[package]] -name = "near-chain-configs" -version = "0.20.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e5a8ace81c09d7eb165dffc1742358a021b2fa761f2160943305f83216003" +checksum = "702dbca982e748975658812c7be2ca53211f454137486f98f6cf768934e2cb29" dependencies = [ - "anyhow", - "bytesize", - "chrono", - "derive_more", - "near-config-utils", - "near-crypto 0.20.1", - "near-parameters", - "near-primitives 0.20.1", - "num-rational", - "once_cell", + "borsh", + "schemars 0.8.22", "serde", - "serde_json", - "sha2 0.10.8", - "smart-default", - "tracing", ] [[package]] name = "near-config-utils" -version = "0.20.1" +version = "0.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ae1eaab1d545a9be7a55b6ef09f365c2017f93a03063547591d12c0c6d27e58" +checksum = "2ec642cfa4996ff9d4bc813abe2cb0ace9f42ffbdd3a5e1a551c3acfd1e7d3ce" dependencies = [ "anyhow", "json_comments", - "thiserror", + "thiserror 2.0.18", "tracing", ] [[package]] name = "near-contract-standards" -version = "4.1.1" -source = "git+https://github.com/sweatco/near-sdk-rs?rev=8c48b26cc48d969c1e5f3162141fe9c824fccecd#8c48b26cc48d969c1e5f3162141fe9c824fccecd" +version = "5.26.1" dependencies = [ "near-sdk", - "schemars", - "serde", - "serde_json", -] - -[[package]] -name = "near-crypto" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e75673d69fd7365508f3d32483669fe45b03bfb34e4d9363e90adae9dfb416c" -dependencies = [ - "arrayref", - "blake2", - "borsh 0.9.3", - "bs58 0.4.0", - "c2-chacha", - "curve25519-dalek 3.2.1", - "derive_more", - "ed25519-dalek 1.0.1", - "near-account-id 0.14.0", - "once_cell", - "parity-secp256k1", - "primitive-types", - "rand 0.7.3", - "rand_core 0.5.1", - "serde", - "serde_json", - "subtle", - "thiserror", ] [[package]] name = "near-crypto" -version = "0.20.1" +version = "0.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2991d2912218a80ec0733ac87f84fa803accea105611eea209d4419271957667" +checksum = "500f7b87df742cc0660c3111b67a6304e5ff95710ceee05e52e5d21e50af57bc" dependencies = [ "blake2", - "borsh 1.3.1", + "borsh", "bs58 0.4.0", - "c2-chacha", - "curve25519-dalek 4.1.1", + "curve25519-dalek", "derive_more", - "ed25519-dalek 2.1.0", + "ed25519-dalek", "hex", - "near-account-id 1.0.0", + "near-account-id", "near-config-utils", + "near-schema-checker-lib", "near-stdx", - "once_cell", "primitive-types", - "rand 0.7.3", "secp256k1", "serde", "serde_json", "subtle", - "thiserror", + "thiserror 2.0.18", ] [[package]] name = "near-fmt" -version = "0.20.1" +version = "0.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7d998dfc1e04001608899b2498ad5a782c7d036b73769d510de21964db99286" +checksum = "e0f87e301ffb364a91c51746fc6f7f8ca809c22e1393459ecef560d086b3745a" dependencies = [ - "near-primitives-core 0.20.1", + "near-primitives-core", ] [[package]] name = "near-gas" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e75c875026229902d065e4435804497337b631ec69ba746b102954273e9ad1" -dependencies = [ - "borsh 1.3.1", - "schemars", - "serde", -] - -[[package]] -name = "near-jsonrpc-client" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18ad81e015f7aced8925d5b9ba3f369b36da9575c15812cfd0786bc1213284ca" -dependencies = [ - "borsh 1.3.1", - "lazy_static", - "log", - "near-chain-configs", - "near-crypto 0.20.1", - "near-jsonrpc-primitives", - "near-primitives 0.20.1", - "reqwest", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "near-jsonrpc-primitives" -version = "0.20.1" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0ce745e954ae776eef05957602e638ee9581106a3675946fb43c2fe7e38ef03" +checksum = "559c33c9c86e05da946358485fa6e7e881a09726f909fbd8bcf357f998d7d03d" dependencies = [ - "arbitrary", - "near-chain-configs", - "near-crypto 0.20.1", - "near-primitives 0.20.1", - "near-rpc-error-macro 0.20.1", + "borsh", + "schemars 0.8.22", "serde", - "serde_json", - "thiserror", ] [[package]] name = "near-o11y" -version = "0.20.1" +version = "0.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d20762631bc8253030013bbae9b5f0542691edc1aa6722f1e8141cc9b928ae5b" +checksum = "80944dc4ec487bfb5140f7b5e54c743f0dbc0a3ad45ea41bd1d7c78ad7e5512f" dependencies = [ - "actix", - "base64 0.21.5", - "clap 4.4.7", - "near-crypto 0.20.1", - "near-fmt", - "near-primitives-core 0.20.1", - "once_cell", + "base64 0.21.7", + "clap", + "near-crypto", + "near-primitives-core", "opentelemetry", "opentelemetry-otlp", "opentelemetry-semantic-conventions", + "opentelemetry_sdk", + "parking_lot", "prometheus", "serde", "serde_json", - "strum", - "thiserror", - "tokio", + "thiserror 2.0.18", "tracing", "tracing-appender", "tracing-opentelemetry", @@ -2257,413 +1704,263 @@ dependencies = [ [[package]] name = "near-parameters" -version = "0.20.1" +version = "0.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f16a59b6c3e69b0585be951af6fe42a0ba86c0e207cb8c63badd19efd16680" +checksum = "67aae312a7529a6067d67df4dc606622b6bdea3cb94f3ef096c3c4e9c9f28184" dependencies = [ - "assert_matches", - "borsh 1.3.1", + "borsh", "enum-map", - "near-account-id 1.0.0", - "near-primitives-core 0.20.1", + "near-account-id", + "near-primitives-core", + "near-schema-checker-lib", "num-rational", "serde", "serde_repr", "serde_yaml", - "strum", - "thiserror", + "strum 0.24.1", + "thiserror 2.0.18", ] [[package]] -name = "near-primitives" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad1a9a1640539c81f065425c31bffcfbf6b31ef1aeaade59ce905f5df6ac860" +name = "near-plugins" +version = "0.5.1" +source = "git+https://github.com/near/near-plugins.git?tag=v0.5.1#312e016e0574d5756f6eba37acc82d9a237b2e3e" dependencies = [ - "borsh 0.9.3", - "byteorder", - "bytesize", - "chrono", - "derive_more", - "easy-ext", - "hex", - "near-crypto 0.14.0", - "near-primitives-core 0.14.0", - "near-rpc-error-macro 0.14.0", - "near-vm-errors", - "num-rational", - "once_cell", - "primitive-types", - "rand 0.7.3", - "reed-solomon-erasure", + "bitflags 1.3.2", + "near-plugins-derive", + "near-sdk", "serde", - "serde_json", - "smart-default", - "strum", - "thiserror", +] + +[[package]] +name = "near-plugins-derive" +version = "0.5.1" +source = "git+https://github.com/near/near-plugins.git?tag=v0.5.1#312e016e0574d5756f6eba37acc82d9a237b2e3e" +dependencies = [ + "darling", + "proc-macro-crate 0.1.5", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] name = "near-primitives" -version = "0.20.1" +version = "0.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0462b067732132babcc89d5577db3bfcb0a1bcfbaaed3f2db4c11cd033666314" +checksum = "5ad915ada7ceed7aafa5bfc9ccdc8b57d72972c485f69753c3c37c042d8cd5da" dependencies = [ "arbitrary", - "base64 0.21.5", - "borsh 1.3.1", + "base64 0.21.7", + "bitvec", + "borsh", + "bytes", "bytesize", - "cfg-if 1.0.0", "chrono", + "derive_builder", "derive_more", "easy-ext", "enum-map", "hex", - "near-crypto 0.20.1", + "itertools", + "near-crypto", "near-fmt", - "near-o11y", "near-parameters", - "near-primitives-core 0.20.1", - "near-rpc-error-macro 0.20.1", + "near-primitives-core", + "near-schema-checker-lib", "near-stdx", - "near-vm-runner", + "near-time", "num-rational", - "once_cell", + "ordered-float", "primitive-types", - "rand 0.8.5", - "rand_chacha 0.3.1", - "reed-solomon-erasure", "serde", "serde_json", "serde_with", - "serde_yaml", "sha3", + "smallvec", "smart-default", - "strum", - "thiserror", - "time", + "strum 0.24.1", + "thiserror 2.0.18", "tracing", + "zstd", ] [[package]] name = "near-primitives-core" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d508f0fc340f6461e4e256417685720d3c4c00bb5a939b105160e49137caba" -dependencies = [ - "base64 0.11.0", - "borsh 0.9.3", - "bs58 0.4.0", - "derive_more", - "near-account-id 0.14.0", - "num-rational", - "serde", - "sha2 0.10.8", - "strum", -] - -[[package]] -name = "near-primitives-core" -version = "0.20.1" +version = "0.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8443eb718606f572c438be6321a097a8ebd69f8e48d953885b4f16601af88225" +checksum = "0840a2e187c91aec833de7a001738bb4b07384ad28e449366ea481a5fe02e861" dependencies = [ "arbitrary", - "base64 0.21.5", - "borsh 1.3.1", + "base64 0.21.7", + "borsh", "bs58 0.4.0", "derive_more", "enum-map", - "near-account-id 1.0.0", + "near-account-id", + "near-gas", + "near-schema-checker-lib", + "near-token", "num-rational", "serde", "serde_repr", "serde_with", - "sha2 0.10.8", - "strum", - "thiserror", -] - -[[package]] -name = "near-rpc-error-core" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ee0b41c75ef859c193a8ff1dadfa0c8207bc0ac447cc22259721ad769a1408" -dependencies = [ - "quote", - "serde", - "syn 1.0.109", -] - -[[package]] -name = "near-rpc-error-core" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80fca203c51edd9595ec14db1d13359fb9ede32314990bf296b6c5c4502f6ab7" -dependencies = [ - "quote", - "serde", - "syn 2.0.38", + "sha2", + "thiserror 2.0.18", ] [[package]] -name = "near-rpc-error-macro" -version = "0.14.0" +name = "near-schema-checker-core" +version = "0.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e837bd4bacd807073ec5ceb85708da7f721b46a4c2a978de86027fb0034ce31" -dependencies = [ - "near-rpc-error-core 0.14.0", - "serde", - "syn 1.0.109", -] +checksum = "d573e560c907f9f89602cf1c748505f1bf93adc1ea11de1eae96579a4e23fee9" [[package]] -name = "near-rpc-error-macro" -version = "0.20.1" +name = "near-schema-checker-lib" +version = "0.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897a445de2102f6732c8a185d922f5e3bf7fd0a41243ce40854df2197237f799" +checksum = "0e4daf9accc21c16ea994d309de64f996afffa2f9846ae7386fe98e3c8043bd1" dependencies = [ - "fs2", - "near-rpc-error-core 0.20.1", - "serde", - "syn 2.0.38", + "near-schema-checker-core", + "near-schema-checker-macro", ] [[package]] -name = "near-sandbox-utils" -version = "0.7.0" +name = "near-schema-checker-macro" +version = "0.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2de216bb0152bfb64f59016d9e6a5b1ac56dd85f729e5fde08461571e2182c8f" -dependencies = [ - "anyhow", - "binary-install", - "chrono", - "fs2", - "home", - "tokio", -] +checksum = "fee4669ee1f3f8d0fe467c367188d6bf7ba17c215f5b2c0edec593cf4b76bbb3" [[package]] name = "near-sdk" -version = "4.1.1" -source = "git+https://github.com/sweatco/near-sdk-rs?rev=8c48b26cc48d969c1e5f3162141fe9c824fccecd#8c48b26cc48d969c1e5f3162141fe9c824fccecd" +version = "5.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f78c9d9392f3a0c5acba9e1dd3ea89554804a2c1b533170cc5cce00e483a4e" dependencies = [ - "base64 0.13.1", - "borsh 0.9.3", - "bs58 0.4.0", + "base64 0.22.1", + "borsh", + "bs58 0.5.0", "near-abi", - "near-crypto 0.14.0", - "near-primitives 0.14.0", - "near-primitives-core 0.14.0", + "near-account-id", + "near-crypto", + "near-gas", + "near-parameters", + "near-primitives", + "near-primitives-core", "near-sdk-macros", "near-sys", - "near-vm-logic", + "near-token", + "near-vm-runner", "once_cell", - "schemars", + "schemars 0.8.22", "serde", "serde_json", + "serde_with", + "unicode-segmentation", "wee_alloc", ] [[package]] name = "near-sdk-macros" -version = "4.1.1" -source = "git+https://github.com/sweatco/near-sdk-rs?rev=8c48b26cc48d969c1e5f3162141fe9c824fccecd#8c48b26cc48d969c1e5f3162141fe9c824fccecd" +version = "5.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b0bdc1666723a140e41ec8a14cf0b11b5e3ecf8ab55ed7e66d995c962fbac77" dependencies = [ "Inflector", + "darling", "proc-macro2", "quote", - "syn 1.0.109", + "serde", + "serde_json", + "strum 0.26.3", + "strum_macros 0.26.4", + "syn 2.0.117", ] [[package]] name = "near-stdx" -version = "0.20.1" +version = "0.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "855fd5540e3b4ff6fedf12aba2db1ee4b371b36f465da1363a6d022b27cb43b8" +checksum = "586d4ca605c2540a158a4c89d46de0d2649fe52bb94db6a0ddff42a243d37d04" [[package]] name = "near-sys" -version = "0.2.0" -source = "git+https://github.com/sweatco/near-sdk-rs?rev=8c48b26cc48d969c1e5f3162141fe9c824fccecd#8c48b26cc48d969c1e5f3162141fe9c824fccecd" - -[[package]] -name = "near-token" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b68f3f8a2409f72b43efdbeff8e820b81e70824c49fee8572979d789d1683fb" -dependencies = [ - "serde", -] - -[[package]] -name = "near-units" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a2b77f295d398589eeee51ad0887905ef1734fb12b45cb6d77bd7e401988b9" -dependencies = [ - "near-units-core", - "near-units-macro", -] - -[[package]] -name = "near-units-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89aa2a7985de87a08ca35f28abd8d00f0f901e704257e6e029aadef981386bc6" -dependencies = [ - "num-format", - "regex", -] - -[[package]] -name = "near-units-macro" -version = "0.2.0" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ab45d066220846f9bd5c21e9ab88c47c892edd36f962ada78bf8308523171a" -dependencies = [ - "near-units-core", - "proc-macro2", - "quote", - "syn 1.0.109", -] +checksum = "c7c212278351251aa342eab33a9d64f99294bc5784cda10107867a72dda699bb" [[package]] -name = "near-vm-errors" -version = "0.14.0" +name = "near-time" +version = "0.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0da466a30f0446639cbd788c30865086fac3e8dcb07a79e51d2b0775ed4261e" +checksum = "1e058f77b8ea607c03f77727bd39282bf55222841cd084e921e1037647f38cac" dependencies = [ - "borsh 0.9.3", - "near-account-id 0.14.0", - "near-rpc-error-macro 0.14.0", + "parking_lot", "serde", + "time", ] [[package]] -name = "near-vm-logic" -version = "0.14.0" +name = "near-token" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b534828419bacbf1f7b11ef7b00420f248c548c485d3f0cfda8bb6931152f2" +checksum = "2a8000d5859172ce4cd29d51ae1af18a80571939f2975ffcae2c00d241ef4507" dependencies = [ - "base64 0.13.1", - "borsh 0.9.3", - "bs58 0.4.0", - "byteorder", - "near-account-id 0.14.0", - "near-crypto 0.14.0", - "near-primitives 0.14.0", - "near-primitives-core 0.14.0", - "near-vm-errors", - "ripemd", + "borsh", + "schemars 0.8.22", "serde", - "sha2 0.10.8", - "sha3", - "zeropool-bn", ] [[package]] name = "near-vm-runner" -version = "0.20.1" +version = "0.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c56c80bdb1954808f59bd36a9112377197b38d424991383bf05f52d0fe2e0da5" +checksum = "a154d855ac0c32e41b671a4c3a34d206fed24c16d7e73ebe6fe36495bae97b51" dependencies = [ - "base64 0.21.5", - "borsh 1.3.1", - "ed25519-dalek 2.1.0", + "anyhow", + "blst", + "borsh", + "bytesize", + "ed25519-dalek", "enum-map", - "memoffset", - "near-crypto 0.20.1", + "finite-wasm 0.5.0", + "finite-wasm 0.6.0", + "lru", + "near-crypto", + "near-o11y", "near-parameters", - "near-primitives-core 0.20.1", + "near-primitives-core", + "near-schema-checker-lib", "near-stdx", "num-rational", - "once_cell", + "parking_lot", "prefix-sum-vec", + "prometheus", + "rand 0.8.6", + "rayon", "ripemd", + "rustix", "serde", - "serde_repr", - "serde_with", - "sha2 0.10.8", + "sha2", "sha3", - "strum", - "thiserror", - "tracing", - "zeropool-bn", -] - -[[package]] -name = "near-workspaces" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e597da87d0c1a722e23efb8c24ae42a0ad99a15f37101dad45c15defb051c1" -dependencies = [ - "async-trait", - "base64 0.21.5", - "bs58 0.5.0", - "cargo-near", - "chrono", - "fs2", - "json-patch", - "libc", - "near-account-id 1.0.0", - "near-crypto 0.20.1", - "near-gas", - "near-jsonrpc-client", - "near-jsonrpc-primitives", - "near-primitives 0.20.1", - "near-sandbox-utils", - "near-token", - "rand 0.8.5", - "reqwest", - "serde", - "serde_json", - "sha2 0.10.8", + "strum 0.24.1", "tempfile", - "thiserror", - "tokio", - "tokio-retry", + "thiserror 2.0.18", "tracing", - "url", -] - -[[package]] -name = "new_debug_unreachable" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "nom-supreme" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aadc66631948f6b65da03be4c4cd8bd104d481697ecbb9bbd65719b1ec60bc9f" -dependencies = [ - "brownstone", - "indent_write", - "joinery", - "memchr", - "nom", + "wasm-encoder 0.236.1", + "wasmparser 0.236.1", + "wasmparser 0.78.2", + "wasmtime", + "zeropool-bn", ] [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "overload", - "winapi", + "windows-sys 0.61.2", ] [[package]] @@ -2678,22 +1975,17 @@ dependencies = [ ] [[package]] -name = "num-format" -version = "0.4.4" +name = "num-conv" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" -dependencies = [ - "arrayvec 0.7.4", - "itoa", -] +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] @@ -2721,173 +2013,121 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.3", - "libc", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "openssl" -version = "0.10.57" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ - "bitflags 2.4.1", - "cfg-if 1.0.0", - "foreign-types", + "hermit-abi", "libc", - "once_cell", - "openssl-macros", - "openssl-sys", ] [[package]] -name = "openssl-macros" -version = "0.1.1" +name = "object" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", + "crc32fast", + "hashbrown 0.15.5", + "indexmap 2.14.0", + "memchr", ] [[package]] -name = "openssl-probe" -version = "0.1.5" +name = "once_cell" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] -name = "openssl-sys" -version = "0.9.93" +name = "once_cell_polyfill" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "opentelemetry" -version = "0.17.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6105e89802af13fdf48c49d7646d3b533a70e536d818aae7e78ba0433d01acb8" +checksum = "aaf416e4cb72756655126f7dd7bb0af49c674f4c1b9903e80c009e0c37e552e6" dependencies = [ - "async-trait", - "crossbeam-channel", - "futures-channel", - "futures-executor", - "futures-util", + "futures-core", + "futures-sink", "js-sys", - "lazy_static", - "percent-encoding", - "pin-project", - "rand 0.8.5", - "thiserror", - "tokio", - "tokio-stream", + "pin-project-lite", + "thiserror 2.0.18", + "tracing", ] [[package]] name = "opentelemetry-otlp" -version = "0.10.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1a6ca9de4c8b00aa7f1a153bd76cb263287155cec642680d79d98706f3d28a" +checksum = "dbee664a43e07615731afc539ca60c6d9f1a9425e25ca09c57bc36c87c55852b" dependencies = [ - "async-trait", - "futures", - "futures-util", "http", "opentelemetry", + "opentelemetry-proto", + "opentelemetry_sdk", "prost", - "thiserror", + "thiserror 2.0.18", "tokio", "tonic", - "tonic-build", ] [[package]] -name = "opentelemetry-semantic-conventions" -version = "0.9.0" +name = "opentelemetry-proto" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "985cc35d832d412224b2cffe2f9194b1b89b6aa5d0bef76d080dce09d90e62bd" +checksum = "2e046fd7660710fe5a05e8748e70d9058dc15c94ba914e7c4faa7c728f0e8ddc" dependencies = [ "opentelemetry", + "opentelemetry_sdk", + "prost", + "tonic", ] [[package]] -name = "os_str_bytes" -version = "6.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "parity-scale-codec" -version = "2.3.1" +name = "opentelemetry-semantic-conventions" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373b1a4c1338d9cd3d1fa53b3a11bdab5ab6bd80a20f7f7becd76953ae2be909" -dependencies = [ - "arrayvec 0.7.4", - "bitvec 0.20.4", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "serde", -] +checksum = "83d059a296a47436748557a353c5e6c5705b9470ef6c95cfc52c21a8814ddac2" [[package]] -name = "parity-scale-codec-derive" -version = "2.3.1" +name = "opentelemetry_sdk" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" +checksum = "11f644aa9e5e31d11896e024305d7e3c98a88884d9f8919dbf37a9991bc47a4b" dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 1.0.109", + "futures-channel", + "futures-executor", + "futures-util", + "opentelemetry", + "percent-encoding", + "rand 0.9.4", + "serde_json", + "thiserror 2.0.18", + "tokio", + "tokio-stream", ] [[package]] -name = "parity-secp256k1" -version = "0.7.0" +name = "ordered-float" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fca4f82fccae37e8bbdaeb949a4a218a1bbc485d11598f193d2a908042e5fc1" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" dependencies = [ - "arrayvec 0.5.2", - "cc", - "cfg-if 0.1.10", - "rand 0.7.3", + "borsh", + "num-traits", + "rand 0.8.6", + "serde", ] [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -2895,125 +2135,75 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.4.1", + "redox_syscall", "smallvec", - "windows-targets", -] - -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest 0.10.7", - "hmac", - "password-hash", - "sha2 0.10.8", -] - -[[package]] -name = "pdb" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13f4d162ecaaa1467de5afbe62d597757b674b51da8bb4e587430c5fdb2af7aa" -dependencies = [ - "fallible-iterator", - "scroll 0.10.2", - "uuid", + "windows-link", ] [[package]] name = "percent-encoding" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" - -[[package]] -name = "petgraph" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" -dependencies = [ - "fixedbitset", - "indexmap 2.0.2", -] - -[[package]] -name = "phf_shared" -version = "0.10.0" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher", -] +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.117", ] [[package]] name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pin-utils" -version = "0.1.0" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] -name = "plain" -version = "0.2.3" +name = "postcard" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "serde", +] [[package]] -name = "platforms" -version = "3.3.0" +name = "potential_utf" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +dependencies = [ + "zerovec", +] [[package]] name = "powerfmt" @@ -3023,15 +2213,12 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "precomputed-hash" -version = "0.1.1" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] [[package]] name = "prefix-sum-vec" @@ -3039,6 +2226,16 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa06bd51638b6e76ac9ba9b6afb4164fa647bd2916d722f2623fbb6d1ed8bdba" +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.117", +] + [[package]] name = "primitive-types" version = "0.10.1" @@ -3046,7 +2243,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" dependencies = [ "fixed-hash", - "impl-codec", "uint", ] @@ -3059,23 +2255,13 @@ dependencies = [ "toml", ] -[[package]] -name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit 0.19.15", -] - [[package]] name = "proc-macro-crate" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "toml_edit 0.21.0", + "toml_edit", ] [[package]] @@ -3087,7 +2273,6 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn 1.0.109", "version_check", ] @@ -3104,140 +2289,120 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "prometheus" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c" +checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" dependencies = [ "cfg-if 1.0.0", "fnv", "lazy_static", "memchr", "parking_lot", - "protobuf", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "prost" -version = "0.9.0" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" dependencies = [ "bytes", "prost-derive", ] -[[package]] -name = "prost-build" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" -dependencies = [ - "bytes", - "heck 0.3.3", - "itertools", - "lazy_static", - "log", - "multimap", - "petgraph", - "prost", - "prost-types", - "regex", - "tempfile", - "which", -] - [[package]] name = "prost-derive" -version = "0.9.0" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", "itertools", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.117", ] [[package]] -name = "prost-types" -version = "0.9.0" +name = "pulley-interpreter" +version = "36.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" +checksum = "8b78fdec962b639b921badfcfe77db7d18aa3c0c1e292ac2aa268c0efe8fe683" dependencies = [ - "bytes", - "prost", + "cranelift-bitset", + "log", + "pulley-macros", + "wasmtime-internal-math", ] [[package]] -name = "protobuf" -version = "2.28.0" +name = "pulley-macros" +version = "36.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" +checksum = "f718f4e8cd5fdfa08b3b1d2d25fe288350051be330544305f0a9b93a937b3d42" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] [[package]] -name = "radium" -version = "0.6.2" +name = "r-efi" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] -name = "radium" -version = "0.7.0" +name = "r-efi" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] -name = "rand" -version = "0.7.3" +name = "radium" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", + "serde", ] [[package]] -name = "rand_chacha" -version = "0.2.2" +name = "rand" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", + "rand_chacha 0.9.0", + "rand_core 0.9.5", ] [[package]] @@ -3251,12 +2416,13 @@ dependencies = [ ] [[package]] -name = "rand_core" -version = "0.5.1" +name = "rand_chacha" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ - "getrandom 0.1.16", + "ppv-lite86", + "rand_core 0.9.5", ] [[package]] @@ -3265,160 +2431,98 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.17", + "serde", ] [[package]] -name = "rand_hc" -version = "0.2.0" +name = "rand_core" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ - "rand_core 0.5.1", + "getrandom 0.3.4", ] [[package]] -name = "redox_syscall" -version = "0.2.16" +name = "rayon" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ - "bitflags 1.3.2", + "either", + "rayon-core", ] [[package]] -name = "redox_syscall" -version = "0.3.5" +name = "rayon-core" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ - "bitflags 1.3.2", + "crossbeam-deque", + "crossbeam-utils", ] [[package]] name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_users" -version = "0.4.3" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "getrandom 0.2.10", - "redox_syscall 0.2.16", - "thiserror", + "bitflags 2.11.1", ] [[package]] -name = "reed-solomon-erasure" -version = "4.0.2" +name = "ref-cast" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a415a013dd7c5d4221382329a5a3482566da675737494935cbbbcdec04662f9d" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" dependencies = [ - "smallvec", + "ref-cast-impl", ] [[package]] -name = "regex" -version = "1.10.2" +name = "ref-cast-impl" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.3", - "regex-syntax 0.8.2", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] -name = "regex-automata" -version = "0.1.10" +name = "regalloc2" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +checksum = "5216b1837de2149f8bc8e6d5f88a9326b63b8c836ed58ce4a0a29ec736a59734" dependencies = [ - "regex-syntax 0.6.29", + "allocator-api2", + "bumpalo", + "hashbrown 0.15.5", + "log", + "rustc-hash", + "smallvec", ] [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "reqwest" -version = "0.11.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" -dependencies = [ - "base64 0.21.5", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-tls", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "serde", - "serde_json", - "serde_urlencoded", - "system-configuration", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg", -] - -[[package]] -name = "ring" -version = "0.17.5" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" -dependencies = [ - "cc", - "getrandom 0.2.10", - "libc", - "spin 0.9.8", - "untrusted", - "windows-sys", -] +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "ripemd" @@ -3426,9 +2530,15 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" dependencies = [ - "digest 0.10.7", + "digest", ] +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + [[package]] name = "rustc-hex" version = "2.1.0" @@ -3437,46 +2547,24 @@ checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.21" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.11.1", "errno", "libc", "linux-raw-sys", - "windows-sys", -] - -[[package]] -name = "rustls" -version = "0.21.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "446e14c5cda4f3f30fe71863c34ec70f5ac79d6087097ad0bb433e1be5edf04c" -dependencies = [ - "log", - "ring", - "rustls-webpki", - "sct", -] - -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "untrusted", + "windows-sys 0.61.2", ] [[package]] @@ -3487,41 +2575,44 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] -name = "schannel" -version = "0.1.22" +name = "schemars" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" dependencies = [ - "windows-sys", + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", ] [[package]] name = "schemars" -version = "0.8.15" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f7b0ce13155372a76ee2e1c5ffba1fe61ede73fbea5630d61eee6fac4929c0c" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" dependencies = [ "dyn-clone", - "schemars_derive", + "ref-cast", "serde", "serde_json", ] [[package]] name = "schemars_derive" -version = "0.8.15" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e85e2a16b12bdb763244c69ab79363d71db2b4b918a2def53f80b02e0574b13c" +checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 1.0.109", + "syn 2.0.117", ] [[package]] @@ -3530,170 +2621,111 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "scroll" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda28d4b4830b807a8b43f7b0e6b5df875311b3e7621d84577188c175b6ec1ec" - -[[package]] -name = "scroll" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" -dependencies = [ - "scroll_derive", -] - -[[package]] -name = "scroll_derive" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "secp256k1" version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" dependencies = [ - "rand 0.8.5", "secp256k1-sys", ] [[package]] name = "secp256k1-sys" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +checksum = "4473013577ec77b4ee3668179ef1186df3146e2cf2d927bd200974c6fe60fd99" dependencies = [ "cc", ] [[package]] -name = "security-framework" -version = "2.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.1" +name = "semver" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" -dependencies = [ - "core-foundation-sys", - "libc", -] +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] -name = "semver" -version = "1.0.20" +name = "serde" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ - "serde", + "serde_core", + "serde_derive", ] [[package]] -name = "serde" -version = "1.0.190" +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.190" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.117", ] [[package]] name = "serde_derive_internals" -version = "0.26.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.117", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ + "indexmap 2.14.0", "itoa", - "ryu", + "memchr", "serde", + "serde_core", + "zmij", ] [[package]] name = "serde_repr" -version = "0.1.17" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", + "syn 2.0.117", ] [[package]] name = "serde_with" -version = "3.4.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" +checksum = "bf65a400f8f66fb7b0552869ad70157166676db75ed8181f8104ea91cf9d0b42" dependencies = [ - "base64 0.21.5", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.0.2", + "indexmap 2.14.0", + "schemars 0.8.22", + "schemars 0.9.0", "serde", + "serde_derive", "serde_json", "serde_with_macros", "time", @@ -3701,71 +2733,47 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.4.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788" +checksum = "81679d9ed988d5e9a5e6531dc3f2c28efbd639cbd1dfb628df08edea6004da77" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.117", ] [[package]] name = "serde_yaml" -version = "0.9.27" +version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.14.0", "itoa", "ryu", "serde", "unsafe-libyaml", ] -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] name = "sha3" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874" dependencies = [ - "digest 0.10.7", + "digest", "keccak", ] @@ -3779,19 +2787,10 @@ dependencies = [ ] [[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - -[[package]] -name = "signature" -version = "1.6.4" +name = "shlex" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signature" @@ -3799,54 +2798,42 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -[[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - [[package]] name = "slab" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.11.1" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +dependencies = [ + "serde", +] [[package]] name = "smart-default" -version = "0.6.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6" +checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.117", ] [[package]] name = "socket2" -version = "0.4.10" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "winapi", + "windows-sys 0.61.2", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" @@ -3855,9 +2842,9 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" @@ -3865,25 +2852,11 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "string_cache" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" -dependencies = [ - "new_debug_unreachable", - "once_cell", - "parking_lot", - "phf_shared", - "precomputed-hash", - "serde", -] - [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" @@ -3891,9 +2864,15 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" dependencies = [ - "strum_macros", + "strum_macros 0.24.3", ] +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" + [[package]] name = "strum_macros" version = "0.24.3" @@ -3908,75 +2887,29 @@ dependencies = [ ] [[package]] -name = "subtle" -version = "2.5.0" +name = "strum_macros" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" - -[[package]] -name = "sweat" -version = "1.2.1" -dependencies = [ - "near-contract-standards", - "near-sdk", - "static_assertions", - "sweat-model", -] - -[[package]] -name = "sweat-model" -version = "0.1.0" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "anyhow", - "async-trait", - "integration-trait", - "integration-utils", - "near-contract-standards", - "near-sdk", - "near-workspaces", + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.117", ] [[package]] -name = "symbolic-common" -version = "8.8.0" +name = "subtle" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f551f902d5642e58039aee6a9021a61037926af96e071816361644983966f540" -dependencies = [ - "debugid", - "memmap2", - "stable_deref_trait", - "uuid", -] +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] -name = "symbolic-debuginfo" -version = "8.8.0" +name = "symlink" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1165dabf9fc1d6bb6819c2c0e27c8dd0e3068d2c53cf186d319788e96517f0d6" -dependencies = [ - "bitvec 1.0.1", - "dmsort", - "elementtree", - "fallible-iterator", - "flate2", - "gimli", - "goblin", - "lazy_static", - "lazycell", - "nom", - "nom-supreme", - "parking_lot", - "pdb", - "regex", - "scroll 0.11.0", - "serde", - "serde_json", - "smallvec", - "symbolic-common", - "thiserror", - "wasmparser", - "zip 0.5.13", -] +checksum = "a7973cce6668464ea31f176d85b13c7ab3bba2cb3b77a2ed26abd7801688010a" [[package]] name = "syn" @@ -3991,9 +2924,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -4009,28 +2942,24 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.117", ] [[package]] -name = "system-configuration" -version = "0.5.1" +name = "sync_wrapper" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" [[package]] -name = "system-configuration-sys" -version = "0.5.0" +name = "synstructure" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ - "core-foundation-sys", - "libc", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] @@ -4040,82 +2969,100 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] -name = "tar" -version = "0.4.40" +name = "target-lexicon" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" -dependencies = [ - "filetime", - "libc", - "xattr", -] +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" [[package]] name = "tempfile" -version = "3.8.1" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ - "cfg-if 1.0.0", "fastrand", - "redox_syscall 0.4.1", + "getrandom 0.4.2", + "once_cell", "rustix", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] name = "termcolor" -version = "1.3.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] -name = "textwrap" -version = "0.16.0" +name = "thiserror" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] [[package]] name = "thiserror" -version = "1.0.50" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ - "thiserror-impl", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.117", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if 1.0.0", - "once_cell", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", ] [[package]] name = "time" -version = "0.3.30" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa", + "num-conv", "powerfmt", "serde", "time-core", @@ -4124,19 +3071,30 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" dependencies = [ + "num-conv", "time-core", ] +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -4154,102 +3112,40 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.28.2" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ - "autocfg", "bytes", "libc", "mio", - "num_cpus", - "parking_lot", "pin-project-lite", - "signal-hook-registry", "socket2", - "tokio-macros", - "windows-sys", -] - -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-macros" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-retry" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f" -dependencies = [ - "pin-project", - "rand 0.8.5", - "tokio", + "windows-sys 0.61.2", ] [[package]] name = "tokio-stream" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.6.10" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ - "bytes", "futures-core", - "futures-sink", - "log", "pin-project-lite", "tokio", ] [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] @@ -4267,86 +3163,57 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap 2.0.2", - "toml_datetime", - "winnow", -] - [[package]] name = "toml_edit" version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.14.0", "toml_datetime", "winnow", ] [[package]] name = "tonic" -version = "0.6.2" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff08f4649d10a70ffa3522ca559031285d8e421d727ac85c60825761818f5d0a" +checksum = "7e581ba15a835f4d9ea06c55ab1bd4dce26fc53752c69a04aac00703bfb49ba9" dependencies = [ - "async-stream", "async-trait", - "base64 0.13.1", + "base64 0.22.1", "bytes", - "futures-core", - "futures-util", - "h2", "http", "http-body", + "http-body-util", "hyper", "hyper-timeout", + "hyper-util", "percent-encoding", "pin-project", "prost", - "prost-derive", "tokio", "tokio-stream", - "tokio-util 0.6.10", "tower", "tower-layer", "tower-service", "tracing", - "tracing-futures", -] - -[[package]] -name = "tonic-build" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9403f1bafde247186684b230dc6f38b5cd514584e8bec1dd32514be4745fa757" -dependencies = [ - "proc-macro2", - "prost-build", - "quote", - "syn 1.0.109", ] [[package]] name = "tower" -version = "0.4.13" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", - "indexmap 1.9.3", - "pin-project", + "indexmap 2.14.0", "pin-project-lite", - "rand 0.8.5", "slab", + "sync_wrapper", "tokio", - "tokio-util 0.7.10", + "tokio-util", "tower-layer", "tower-service", "tracing", @@ -4354,23 +3221,22 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ - "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -4378,51 +3244,43 @@ dependencies = [ [[package]] name = "tracing-appender" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e" +checksum = "050686193eb999b4bb3bc2acfa891a13da00f79734704c4b8b4ef1a10b368a3c" dependencies = [ "crossbeam-channel", + "symlink", + "thiserror 2.0.18", "time", "tracing-subscriber", ] [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.117", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", ] -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "pin-project", - "tracing", -] - [[package]] name = "tracing-log" -version = "0.1.4" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ "log", "once_cell", @@ -4431,28 +3289,32 @@ dependencies = [ [[package]] name = "tracing-opentelemetry" -version = "0.17.4" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbbe89715c1dbbb790059e2565353978564924ee85017b5fff365c872ff6721f" +checksum = "ddcf5959f39507d0d04d6413119c04f33b623f4f951ebcbdddddfad2d0623a9c" dependencies = [ + "js-sys", "once_cell", "opentelemetry", + "opentelemetry_sdk", + "smallvec", "tracing", "tracing-core", "tracing-log", "tracing-subscriber", + "web-time", ] [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "matchers", "nu-ansi-term", "once_cell", - "regex", + "regex-automata", "sharded-slab", "smallvec", "thread_local", @@ -4461,26 +3323,17 @@ dependencies = [ "tracing-log", ] -[[package]] -name = "treediff" -version = "4.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52984d277bdf2a751072b5df30ec0377febdb02f7696d64c2d7d54630bac4303" -dependencies = [ - "serde_json", -] - [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" -version = "1.17.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "uint" @@ -4494,12 +3347,6 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "unicode-bidi" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" - [[package]] name = "unicode-ident" version = "1.0.12" @@ -4507,199 +3354,441 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] -name = "unicode-normalization" -version = "0.1.22" +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + +[[package]] +name = "url" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ - "tinyvec", + "form_urlencoded", + "idna", + "percent-encoding", + "serde", ] [[package]] -name = "unicode-segmentation" -version = "1.10.1" +name = "utf8_iter" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] -name = "unsafe-libyaml" -version = "0.2.9" +name = "utf8parse" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] -name = "untrusted" -version = "0.9.0" +name = "valuable" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] -name = "ureq" -version = "2.8.0" +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "want" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5ccd538d4a604753ebc2f17cd9946e89b77bf87f6a8e2309667c6f2e87855e3" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "base64 0.21.5", - "flate2", - "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.3+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +dependencies = [ + "wit-bindgen 0.57.1", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" +dependencies = [ + "cfg-if 1.0.0", "once_cell", - "rustls", - "rustls-webpki", - "url", - "webpki-roots", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", ] [[package]] -name = "url" -version = "2.4.1" +name = "wasm-bindgen-macro" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.117", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e77053dc709db790691d3732cfc458adc5acc881dec524965c608effdcd9c581" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasm-encoder" +version = "0.236.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "724fccfd4f3c24b7e589d333fc0429c68042897a7e8a5f8694f31792471841e7" +dependencies = [ + "leb128fmt", + "wasmparser 0.236.1", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser 0.244.0", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.14.0", + "wasm-encoder 0.244.0", + "wasmparser 0.244.0", +] + +[[package]] +name = "wasmparser" +version = "0.78.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52144d4c78e5cf8b055ceab8e5fa22814ce4315d6002ad32cfd914f37c12fd65" + +[[package]] +name = "wasmparser" +version = "0.105.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83be9e0b3f9570dc1979a33ae7b89d032c73211564232b99976553e5c155ec32" +dependencies = [ + "indexmap 1.9.3", + "url", +] + +[[package]] +name = "wasmparser" +version = "0.228.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "4abf1132c1fdf747d56bbc1bb52152400c70f336870f968b85e89ea422198ae3" dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", + "bitflags 2.11.1", + "hashbrown 0.15.5", + "indexmap 2.14.0", + "semver", "serde", ] [[package]] -name = "utf8parse" -version = "0.2.1" +name = "wasmparser" +version = "0.236.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "a9b1e81f3eb254cf7404a82cee6926a4a3ccc5aad80cc3d43608a070c67aa1d7" +dependencies = [ + "bitflags 2.11.1", + "hashbrown 0.15.5", + "indexmap 2.14.0", + "semver", + "serde", +] [[package]] -name = "uuid" -version = "0.8.2" +name = "wasmparser" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.1", + "hashbrown 0.15.5", + "indexmap 2.14.0", + "semver", +] [[package]] -name = "valuable" -version = "0.1.0" +name = "wasmprinter" +version = "0.2.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "50b0e5ed7a74a065637f0d7798ce5f29cadb064980d24b0c82af5200122fa0d8" +dependencies = [ + "anyhow", + "wasmparser 0.105.0", +] [[package]] -name = "vcpkg" -version = "0.2.15" +name = "wasmprinter" +version = "0.236.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +checksum = "2df225df06a6df15b46e3f73ca066ff92c2e023670969f7d50ce7d5e695abbb1" +dependencies = [ + "anyhow", + "termcolor", + "wasmparser 0.236.1", +] [[package]] -name = "version_check" -version = "0.9.4" +name = "wasmtime" +version = "36.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "b10306ead921db2c4645ff99867b7539b65e18afd8816d471547f5e6f3b09492" +dependencies = [ + "addr2line", + "anyhow", + "bitflags 2.11.1", + "bumpalo", + "cc", + "cfg-if 1.0.0", + "hashbrown 0.15.5", + "indexmap 2.14.0", + "libc", + "log", + "mach2", + "memfd", + "object", + "once_cell", + "postcard", + "pulley-interpreter", + "rayon", + "rustix", + "serde", + "serde_derive", + "smallvec", + "target-lexicon", + "wasmparser 0.236.1", + "wasmtime-environ", + "wasmtime-internal-asm-macros", + "wasmtime-internal-cranelift", + "wasmtime-internal-fiber", + "wasmtime-internal-jit-debug", + "wasmtime-internal-jit-icache-coherence", + "wasmtime-internal-math", + "wasmtime-internal-slab", + "wasmtime-internal-unwinder", + "wasmtime-internal-versioned-export-macros", + "windows-sys 0.60.2", +] [[package]] -name = "want" -version = "0.3.1" +name = "wasmtime-environ" +version = "36.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +checksum = "e7fb2c37ca263d444f33871bf0221e7de0707b2b2bb88165df6db6d58c73375f" dependencies = [ - "try-lock", + "anyhow", + "cranelift-bitset", + "cranelift-entity", + "gimli", + "indexmap 2.14.0", + "log", + "object", + "postcard", + "serde", + "serde_derive", + "smallvec", + "target-lexicon", + "wasm-encoder 0.236.1", + "wasmparser 0.236.1", + "wasmprinter 0.236.1", ] [[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" +name = "wasmtime-internal-asm-macros" +version = "36.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +checksum = "19c6c0d3c8d2db554a3af8e8d413ff2815362ebce0911808ecfdaaa257438f93" +dependencies = [ + "cfg-if 1.0.0", +] [[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +name = "wasmtime-internal-cranelift" +version = "36.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "5a2412f2afb0a5db2a4ac1cfff73247e240aeaa90bf41497ad0a5084b6a24eca" +dependencies = [ + "anyhow", + "cfg-if 1.0.0", + "cranelift-codegen", + "cranelift-control", + "cranelift-entity", + "cranelift-frontend", + "cranelift-native", + "gimli", + "itertools", + "log", + "object", + "pulley-interpreter", + "smallvec", + "target-lexicon", + "thiserror 2.0.18", + "wasmparser 0.236.1", + "wasmtime-environ", + "wasmtime-internal-math", + "wasmtime-internal-versioned-export-macros", +] [[package]] -name = "wasm-bindgen" -version = "0.2.87" +name = "wasmtime-internal-fiber" +version = "36.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "ecfdc460dd5d343d88ff1ffaf65ae019feeb6124ddcfd3f39d28331068d25b1f" dependencies = [ + "anyhow", + "cc", "cfg-if 1.0.0", - "wasm-bindgen-macro", + "libc", + "rustix", + "wasmtime-internal-asm-macros", + "wasmtime-internal-versioned-export-macros", + "windows-sys 0.60.2", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.87" +name = "wasmtime-internal-jit-debug" +version = "36.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "b5abb428a71827b7f90fc64406749883ccc6e58addf6d36974d5e06942011707" dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.38", - "wasm-bindgen-shared", + "cc", + "wasmtime-internal-versioned-export-macros", ] [[package]] -name = "wasm-bindgen-futures" -version = "0.4.37" +name = "wasmtime-internal-jit-icache-coherence" +version = "36.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "ba6cc13f14c3fb83fb877cb1d5c605e93f7ec1bf7fc1a5e8b361209d2f8ca028" dependencies = [ + "anyhow", "cfg-if 1.0.0", - "js-sys", - "wasm-bindgen", - "web-sys", + "libc", + "windows-sys 0.60.2", ] [[package]] -name = "wasm-bindgen-macro" -version = "0.2.87" +name = "wasmtime-internal-math" +version = "36.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "1cb209473a09f4dbd9c87bb9f18b8dcb0c9da30d12a260e3eacf7a1a53b41480" dependencies = [ - "quote", - "wasm-bindgen-macro-support", + "libm", ] [[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.87" +name = "wasmtime-internal-slab" +version = "36.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] +checksum = "aab4df5a04752106e1ecef9d40145ef28fa033b0d5dd3c839c9b208b2d522183" [[package]] -name = "wasm-bindgen-shared" -version = "0.2.87" +name = "wasmtime-internal-unwinder" +version = "36.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "5359875d29bddb6f7e65e698157714d8d35ebd8ea2a92893d05d6b062147b639" +dependencies = [ + "anyhow", + "cfg-if 1.0.0", + "cranelift-codegen", + "log", + "object", +] [[package]] -name = "wasmparser" -version = "0.83.0" +name = "wasmtime-internal-versioned-export-macros" +version = "36.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718ed7c55c2add6548cca3ddd6383d738cd73b892df400e96b9aa876f0141d7a" +checksum = "2e247bcdd69701743ba386c933b26ebad2ce912ff9cb68b5b71fdb29d39ba04a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] -name = "web-sys" -version = "0.3.64" +name = "web-time" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", ] -[[package]] -name = "webpki-roots" -version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" - [[package]] name = "wee_alloc" version = "0.4.5" @@ -4712,18 +3801,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - [[package]] name = "winapi" version = "0.3.9" @@ -4742,11 +3819,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "winapi", + "windows-sys 0.61.2", ] [[package]] @@ -4761,16 +3838,31 @@ version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", ] [[package]] name = "windows-sys" -version = "0.48.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-targets", + "windows-link", ] [[package]] @@ -4779,13 +3871,30 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -4794,42 +3903,90 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + [[package]] name = "winnow" version = "0.5.17" @@ -4840,20 +3997,104 @@ dependencies = [ ] [[package]] -name = "winreg" -version = "0.50.0" +name = "wit-bindgen" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" dependencies = [ - "cfg-if 1.0.0", - "windows-sys", + "wit-bindgen-rust-macro", ] [[package]] -name = "wyz" -version = "0.2.0" +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.14.0", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.1", + "indexmap 2.14.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder 0.244.0", + "wasm-metadata", + "wasmparser 0.244.0", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.14.0", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser 0.244.0", +] + +[[package]] +name = "writeable" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "wyz" @@ -4865,58 +4106,87 @@ dependencies = [ ] [[package]] -name = "xattr" -version = "1.0.1" +name = "yoke" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" dependencies = [ - "libc", + "stable_deref_trait", + "yoke-derive", + "zerofrom", ] [[package]] -name = "xml-rs" -version = "0.8.19" +name = "yoke-derive" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] [[package]] name = "zerocopy" -version = "0.7.20" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd66a62464e3ffd4e37bd09950c2b9dd6c4f8767380fabba0d523f9a775bc85a" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.20" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zerofrom" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "255c4596d41e6916ced49cfafea18727b24d67878fa180ddfd69b9df34fd1726" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.117", + "synstructure", ] [[package]] name = "zeroize" -version = "1.3.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.117", ] [[package]] @@ -4925,70 +4195,75 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e61de68ede9ffdd69c01664f65a178c5188b73f78faa21f0936016a888ff7c" dependencies = [ - "borsh 0.9.3", "byteorder", "crunchy", "lazy_static", - "rand 0.8.5", + "rand 0.8.6", "rustc-hex", ] [[package]] -name = "zip" -version = "0.5.13" +name = "zerotrie" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ab48844d61251bb3835145c521d88aa4031d7139e8485990f60ca911fa0815" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ - "byteorder", - "crc32fast", - "flate2", - "thiserror", + "displaydoc", + "yoke", + "zerofrom", ] [[package]] -name = "zip" -version = "0.6.6" +name = "zerovec" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ - "aes", - "byteorder", - "bzip2", - "constant_time_eq", - "crc32fast", - "crossbeam-utils", - "flate2", - "hmac", - "pbkdf2", - "sha1", - "time", - "zstd", + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", ] +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + [[package]] name = "zstd" -version = "0.11.2+zstd.1.5.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" +version = "7.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" dependencies = [ - "libc", "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.9+zstd.1.5.5" +version = "2.0.16+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" dependencies = [ "cc", "pkg-config", diff --git a/Cargo.toml b/Cargo.toml index f7c4544..78843e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,25 +1,24 @@ [workspace] members = [ - "sweat", - "sweat", - "integration-tests", - "exploit-stub" + "contract", + "exploit-stub", + "vendors/near-contract-standards", ] resolver = "2" [workspace.dependencies] -tokio = "1.28.0" -anyhow = "1.0.75" -async-trait = "0.1.74" +near-sdk = "5.26.1" +near-contract-standards = { path = "vendors/near-contract-standards" } +near-plugins = { git = "https://github.com/near/near-plugins.git", tag = "v0.5.1" } -near-units = "0.2.0" -near-workspaces = "0.10.0" - -near-sdk = { git = "https://github.com/sweatco/near-sdk-rs", rev = "8c48b26cc48d969c1e5f3162141fe9c824fccecd" } -near-contract-standards = { git = "https://github.com/sweatco/near-sdk-rs", rev = "8c48b26cc48d969c1e5f3162141fe9c824fccecd" } - -integration-trait = { git = "https://github.com/sweatco/integration-utils.git", rev = "e54dc392ef42837123dd2c0ad19b6d6b815192d7" } -integration-utils = { git = "https://github.com/sweatco/integration-utils.git", rev = "e54dc392ef42837123dd2c0ad19b6d6b815192d7" } - -sweat-model = { path = "model" } +# Clippy configuration lives here (not as CLI flags in lint.sh) so it applies only +# to crates that opt in via `[lints] workspace = true`. The vendored +# `near-contract-standards` deliberately does not opt in, exempting upstream code +# from our pedantic rules. `-D warnings` in lint.sh escalates these to errors. +[workspace.lints.clippy] +all = { level = "warn", priority = -1 } +pedantic = { level = "warn", priority = -1 } +module_name_repetitions = "allow" +needless_pass_by_value = "allow" +must_use_candidate = "allow" diff --git a/Makefile b/Makefile index 293c093..a17b45c 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ help: ##@Miscellaneous Show this help @perl -e '$(HELP_FUN)' $(MAKEFILE_LIST) install: ##@Miscellaneous Install dependencies - @npm i near-cli + @cargo install near-cli-rs @cargo build build: ##@Build the contract locally. @@ -27,19 +27,27 @@ cov: ##@Testing Run unit tests with coverage. cargo llvm-cov --hide-instantiations --open test: ##@Testing Run unit tests. - cargo test --package sweat + cargo test --package contract -integration: ##@Testing Run integration tests. - cargo test --package integration-tests +integration: build-integration ##@Testing Run integration tests. + cd integration-tests && cargo test int: integration ##@Testing Shorthand for `integration` +integration-log: build-integration ##@Testing Run integration tests with logs streamed (serial). Override level via RUST_LOG. + cd integration-tests && RUST_LOG=$${RUST_LOG:-info,near_workspaces=warn} cargo test -- --nocapture --test-threads=1 + +int-log: integration-log ##@Testing Shorthand for `integration-log` + fmt: ##@Chores Format the code using rustfmt nightly. cargo +nightly fmt --all lint: ##@Chores Run lint checks with Clippy. ./scripts/lint.sh +sync: ##@Chores Sync vendored near-contract-standards from upstream and re-apply my_custom_updates.patch. + ./scripts/sync_vendor.sh + HELP_FUN = \ %help; while(<>){push@{$$help{$$2//'options'}},[$$1,$$3] \ if/^([\w-_]+)\s*:.*\#\#(?:@(\w+))?\s(.*)$$/}; \ diff --git a/README.md b/README.md index ffa585d..ec60a46 100644 --- a/README.md +++ b/README.md @@ -1,90 +1,246 @@ # SWEAT the TOKEN -#### 📦 Dependencies +The SWEAT fungible token (NEP-141 / NEP-148) for the Sweat Economy move-to-earn +protocol. Tokens are minted by trusted Oracles in proportion to user steps, using +a decaying issuance formula tied to the global step count since the Token +Generation Event (TGE). + +## What the contract does + +- **Deferred minting.** Oracles submit batches of `(account, steps)` via + `defer_batch`. For each batch the contract computes the SWEAT payout using + the issuance formula in `math.rs`, splits it **95% user / 5% Oracle fee**, + and performs an XCC to the configured **holding contract** + (`holding_account_id`). On a successful callback (`on_record`), the user + portion is minted to the holding contract and the fee to the calling Oracle. + On failure, the `steps_since_tge` counter is rolled back. End users later + claim from the holding contract — see + [sweat-claim](https://github.com/sweatco/sweat-claim). +- **Denylist.** A `DenylistManager` role can mark accounts as restricted via + `set_restricted`. Restricted accounts cannot send, receive, or burn tokens. +- **Pausability.** `PauseManager` / `UnpauseManager` roles can pause/unpause + groups of methods. Two pause groups are defined: `minting` (covers + `defer_batch`) and `token` (covers transfers and `burn`). +- **Access control.** All privileged roles (`Oracle`, `DenylistManager`, + `PauseManager`, `UnpauseManager`, plus the Super Admin) are managed by the + [`near-plugins`](https://github.com/aurora-is-near/near-plugins) + `AccessControllable` plugin. Use `acl_grant_role` / `acl_revoke_role`. +- **NEP-141 / NEP-145 / NEP-148.** Standard FT core, storage management, and + metadata are implemented. Transfers add denylist + pause checks on top of + the standard. + +See `recon-report.md` for a deeper architectural walkthrough. + +## Module layout -- Install near-cli: `npm install -g near-cli` -- Install Rust (>= 1.60.0) `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh` -- `rustup target add wasm32-unknown-unknown` +``` +contract/src/ +├── api.rs Public traits: SweatApi, RestrictionApi, SweatDefer +├── core.rs NEP-141 transfers with denylist + pause checks +├── defer.rs defer_batch / on_record — the deferred-mint flow +├── lib.rs Contract state, init, plugin wiring +├── math.rs Decaying issuance formula +├── meta.rs NEP-148 metadata (SWEAT / SWEAT / 18 decimals) +├── migration.rs Upgrade migration entry point +└── storage.rs NEP-145 storage management +``` -#### Build & Run tests +## Dependencies -```rust -./sweat/build.sh -//The wasm file will be at `res/sweat.wasm` +- Rust toolchain (see `rust-toolchain.toml`) — `rustup target add wasm32-unknown-unknown` +- [`cargo-near`](https://github.com/near/cargo-near) for building the contract +- [`near-cli-rs`](https://github.com/near/near-cli-rs) for deployment / interaction + (the legacy JS `near-cli` is **not** what the commands below use — install via + `cargo install near-cli-rs` or the install script in that repo) +- Docker (only if you want reproducible builds via `make dock`) -cargo test -- --nocapture -cargo run --example mint -cargo run --example transfer -cargo run --example formula -``` +## Vendored `near-contract-standards` -## Usage +`vendors/near-contract-standards/` is a vendored copy of upstream +[`near-contract-standards`](https://crates.io/crates/near-contract-standards) +with local modifications (notably `LookupMapAdapter` for the SWEAT account-id +storage layout). **The vendored directory is the source of truth** — edit it +directly and commit. There is no separate patch file to keep in sync. + +To refresh the vendor from upstream — for example after bumping `near-sdk` in +the workspace `Cargo.toml`: ```bash -export TOKEN_ACCOUNT_ID=your-token-account-id +make sync ``` -Deploy and initialize the contract: +The script reads the currently vendored version, diffs it against pristine +upstream to capture local changes, replaces the vendor with the target +upstream version (from `[workspace.dependencies] near-sdk`), and re-applies +the captured diff. If a hunk fails, `*.rej` files are written and the script +aborts — resolve manually and commit; the next `make sync` will derive a +fresh diff from the resolved state. + +## Build, lint, test + +All common tasks are wired through the `Makefile`: ```bash -near deploy --accountId=$TOKEN_ACCOUNT_ID --wasmFile=res/sweat.wasm --initArgs '{"postfix": ".u.sweat.testnet"}' --initFunction new +make help # list all targets +make install # npm i near-cli && cargo build +make build # local contract build (./scripts/build.sh) +make build-integration # contract build with `integration-test` feature +make build-stub # build the holding-contract stub +make dock # reproducible build in Docker +make test # cargo test --package contract +make int # integration tests (builds with integration-test feature first) +make int-log # same, with logs streamed serially (override RUST_LOG) +make cov # cargo llvm-cov coverage report +make fmt # cargo +nightly fmt --all +make lint # clippy ``` -Add an oracle +## Deploy & initialize + +All examples below use `near-cli-rs`. Swap `network-config testnet` for +`network-config mainnet` as appropriate. ```bash -export ORACLE_ACCOUNT_ID=your-oracle-account-id +export TOKEN_ACCOUNT_ID=your-token-account-id +export HOLDING_ACCOUNT_ID=your-holding-account-id + +near contract deploy $TOKEN_ACCOUNT_ID \ + use-file res/sweat.wasm \ + with-init-call new \ + json-args '{"postfix":".u.sweat.testnet","holding_account_id":"'$HOLDING_ACCOUNT_ID'"}' \ + prepaid-gas '100.0 Tgas' \ + attached-deposit '0 NEAR' \ + network-config testnet \ + sign-with-keychain \ + send ``` +The deploying account becomes the **Super Admin** and can grant any role. + +## Granting roles + +Roles are managed through `near-plugins` ACL. Replace `Oracle` with +`DenylistManager`, `PauseManager`, or `UnpauseManager` as needed. + ```bash -near call $TOKEN_ACCOUNT_ID add_oracle `{"account_id":"${ORACLE_ACCOUNT_ID}"}` --accountId $TOKEN_ACCOUNT_ID --gas=2428088695050 -near view sweat_testing_11.testnet get_oracles -[ 'your-oracle-account-id' ] +export ORACLE_ACCOUNT_ID=your-oracle-account-id + +near contract call-function as-transaction $TOKEN_ACCOUNT_ID acl_grant_role \ + json-args '{"role":"Oracle","account_id":"'$ORACLE_ACCOUNT_ID'"}' \ + prepaid-gas '100.0 Tgas' \ + attached-deposit '0 NEAR' \ + sign-as $TOKEN_ACCOUNT_ID \ + network-config testnet \ + sign-with-keychain \ + send + +near contract call-function as-read-only $TOKEN_ACCOUNT_ID acl_get_grantees \ + json-args '{"role":"Oracle","skip":0,"limit":100}' \ + network-config testnet now ``` -Call view methods +## View methods ```bash -near view $TOKEN_ACCOUNT_ID get_steps_from_tge -'0' +near contract call-function as-read-only $TOKEN_ACCOUNT_ID get_steps_since_tge \ + json-args '{}' network-config testnet now -near view $TOKEN_ACCOUNT_ID formula '{"steps_from_tge":"1", "steps":1000}' -'999999999912699776' +near contract call-function as-read-only $TOKEN_ACCOUNT_ID formula \ + json-args '{"steps_since_tge":"1","steps":1000}' network-config testnet now -near view $TOKEN_ACCOUNT_ID ft_balance_of '{"account_id":"some-random-account.testnet"}' -'0' -``` +near contract call-function as-read-only $TOKEN_ACCOUNT_ID ft_balance_of \ + json-args '{"account_id":"some-account.testnet"}' network-config testnet now -Send steps as an Oracle +near contract call-function as-read-only $TOKEN_ACCOUNT_ID ft_metadata \ + json-args '{}' network-config testnet now -```bash -near call $TOKEN_ACCOUNT_ID record_batch '{"steps_batch": [["random-guy-1.testnet", 10000],["random-gal-2.testnet", 20000] ]}' --accountId $ORACLE_ACCOUNT_ID --gas=300000000000000 +near contract call-function as-read-only $TOKEN_ACCOUNT_ID get_holding_account_id \ + json-args '{}' network-config testnet now + +near contract call-function as-read-only $TOKEN_ACCOUNT_ID is_restricted \ + json-args '{"account_id":"some-account.testnet"}' network-config testnet now ``` -Transfer tokens +## Submit steps as an Oracle (deferred mint) ```bash -# not necessarily $ORACLE_ACCOUNT_ID, can be any local account -near call $TOKEN_ACCOUNT_ID ft_transfer '{"receiver_id":"", "amount":"100", "memo":"hello world!"}' --accountId $ORACLE_ACCOUNT_ID --depositYocto 1 +near contract call-function as-transaction $TOKEN_ACCOUNT_ID defer_batch \ + json-args '{"steps_batch":[["user-1.testnet",10000],["user-2.testnet",20000]]}' \ + prepaid-gas '300.0 Tgas' \ + attached-deposit '0 NEAR' \ + sign-as $ORACLE_ACCOUNT_ID \ + network-config testnet \ + sign-with-keychain \ + send ``` -Pay for storage +For each entry, 95% of the computed payout is minted to the holding contract +(claimable by the user via [sweat-claim](https://github.com/sweatco/sweat-claim)) +and 5% is minted to `$ORACLE_ACCOUNT_ID` as a fee. If the XCC to the holding +contract fails, `steps_since_tge` is rolled back and nothing is minted. -```bash -# not necessarily $ORACLE_ACCOUNT_ID, can be any local account -near call $TOKEN_ACCOUNT_ID storage_deposit '{"account_id":"random-guy-1.testnet"}' --accountId $ORACLE_ACCOUNT_ID --depositYocto 2350000000000000000000 +## Transfers, burn, storage -near view $TOKEN_ACCOUNT_ID storage_balance_of '{"account_id":"random-guy-1.testnet"}' --accountId $ORACLE_ACCOUNT_ID +```bash +# Transfer (subject to pause + denylist on sender & receiver) +near contract call-function as-transaction $TOKEN_ACCOUNT_ID ft_transfer \ + json-args '{"receiver_id":"","amount":"100","memo":"hi"}' \ + prepaid-gas '30.0 Tgas' \ + attached-deposit '1 yoctoNEAR' \ + sign-as \ + network-config testnet sign-with-keychain send + +# Burn (subject to pause + denylist on caller) +near contract call-function as-transaction $TOKEN_ACCOUNT_ID burn \ + json-args '{"amount":"100"}' \ + prepaid-gas '30.0 Tgas' \ + attached-deposit '1 yoctoNEAR' \ + sign-as \ + network-config testnet sign-with-keychain send + +# NEP-145 storage registration +near contract call-function as-transaction $TOKEN_ACCOUNT_ID storage_deposit \ + json-args '{"account_id":"user-1.testnet"}' \ + prepaid-gas '30.0 Tgas' \ + attached-deposit '0.00235 NEAR' \ + sign-as \ + network-config testnet sign-with-keychain send + +near contract call-function as-read-only $TOKEN_ACCOUNT_ID storage_balance_of \ + json-args '{"account_id":"user-1.testnet"}' network-config testnet now ``` -Mint tokens +## Denylist & pause operations ```bash -near call $TOKEN_ACCOUNT_ID mint_tge '{"amount":"100", "account_for":""}' --accountId $TOKEN_ACCOUNT_ID --gas=300000000000000 +# Restrict / unrestrict an account (requires DenylistManager role) +near contract call-function as-transaction $TOKEN_ACCOUNT_ID set_restricted \ + json-args '{"account_id":"bad.testnet","is_restricted":true}' \ + prepaid-gas '30.0 Tgas' \ + attached-deposit '0 NEAR' \ + sign-as \ + network-config testnet sign-with-keychain send + +# Pause / unpause a group of methods (requires PauseManager / UnpauseManager) +# Known pause groups: "minting" (covers defer_batch), "token" (covers transfers + burn) +near contract call-function as-transaction $TOKEN_ACCOUNT_ID pa_pause_feature \ + json-args '{"key":"minting"}' \ + prepaid-gas '30.0 Tgas' \ + attached-deposit '0 NEAR' \ + sign-as \ + network-config testnet sign-with-keychain send + +near contract call-function as-transaction $TOKEN_ACCOUNT_ID pa_unpause_feature \ + json-args '{"key":"minting"}' \ + prepaid-gas '30.0 Tgas' \ + attached-deposit '0 NEAR' \ + sign-as \ + network-config testnet sign-with-keychain send ``` -### Deferring tokens +## Deferred mint — sequence diagram ![Smart contracts interaction](doc/contracts_interaction.png) -For information about claiming tokens from Holding account refer to the [Sweat Claim repo](https://github.com/sweatco/sweat-claim). +For the full claim flow on the receiving side, see the +[sweat-claim repo](https://github.com/sweatco/sweat-claim). diff --git a/sweat/Cargo.lock b/contract/Cargo.lock similarity index 100% rename from sweat/Cargo.lock rename to contract/Cargo.lock diff --git a/contract/Cargo.toml b/contract/Cargo.toml new file mode 100644 index 0000000..de32f0b --- /dev/null +++ b/contract/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "contract" +version = "1.3.0" +authors = [] +edition = "2021" +publish = false +repository = "https://github.com/Sweat-Foundation/sweat-token" + +[package.metadata.near.reproducible_build] +image = "sourcescan/cargo-near:0.19.0-rust-1.86.0" +image_digest = "sha256:772638e343baeeea24e49062c7d424274f3441452cc06ce97fc4e5695b19fecc" +passed_env = [] +container_build_command = ["cargo", "near", "build", "non-reproducible-wasm", "--locked"] + +[lib] +crate-type = ["cdylib"] + +[features] +default = [] +integration-test = [] + +[dependencies] +static_assertions = "1.1.0" +near-sdk = { workspace = true } +near-contract-standards = { workspace = true } +near-plugins = { workspace = true } + +[dev-dependencies] +near-sdk = { workspace = true, features = ["unit-testing"] } + +[lints] +workspace = true diff --git a/contract/src/api.rs b/contract/src/api.rs new file mode 100644 index 0000000..8d6b385 --- /dev/null +++ b/contract/src/api.rs @@ -0,0 +1,67 @@ +use near_sdk::{ + json_types::{U128, U64}, + AccountId, PromiseOrValue, +}; + +use crate::pause::Feature; + +pub trait SweatApi { + fn new( + holding_account_id: AccountId, + super_admin_account_id: AccountId, + oracle_account_ids: Vec, + denylist_manager_account_ids: Vec, + pause_manager_account_ids: Vec, + unpause_manager_account_ids: Vec, + ) -> Self; + /// Sets the trusted holding-account contract that will custody the user + /// portion of every minted batch until end users claim it. See the + /// [`crate::defer`] module docs for the full flow. + fn set_holding_account_id(&mut self, account_id: AccountId); + fn get_holding_account_id(&self) -> AccountId; + fn burn(&mut self, amount: U128); + fn get_steps_since_tge(&self) -> U64; + fn formula(&self, steps_since_tge: U64, steps: u32) -> U128; +} + +pub trait RestrictionApi { + fn is_restricted(&self, account_id: &AccountId) -> bool; + fn set_restricted(&mut self, account_id: &AccountId, is_restricted: bool); +} + +/// Per-feature pause controls. See the [`crate::pause`] module. +pub trait PauseApi { + /// Pauses each of `features`. Requires the `PauseManager` role. Returns + /// whether the paused set changed. + fn pause_features(&mut self, features: Vec) -> bool; + /// Unpauses each of `features`. Requires the `UnpauseManager` role. Returns + /// whether the paused set changed. + fn unpause_features(&mut self, features: Vec) -> bool; + fn is_feature_paused(&self, feature: Feature) -> bool; + fn get_paused_features(&self) -> Vec; +} + +/// Token-minting API. +/// +/// Implementations mint user rewards to the configured holding account rather +/// than directly to end users. See the [`crate::defer`] module docs for the +/// full claim flow and trust model. +pub trait SweatDefer { + fn defer_batch(&mut self, steps_batch: Vec<(AccountId, u32)>) -> PromiseOrValue<()>; +} + +pub struct Payout { + pub amount_for_user: u128, + pub fee: u128, +} + +impl From for Payout { + fn from(value: u128) -> Self { + let fee = value.div_ceil(20); // == value * 5 / 100 + + Self { + fee, + amount_for_user: value - fee, + } + } +} diff --git a/contract/src/core.rs b/contract/src/core.rs new file mode 100644 index 0000000..d9b1b7e --- /dev/null +++ b/contract/src/core.rs @@ -0,0 +1,89 @@ +use near_contract_standards::fungible_token::{core::FungibleTokenCore, resolver::FungibleTokenResolver, Balance}; +use near_sdk::{env, json_types::U128, near, AccountId, PromiseOrValue}; + +use crate::{Contract, ContractExt, Feature}; + +#[near] +impl FungibleTokenCore for Contract { + #[payable] + fn ft_transfer(&mut self, receiver_id: AccountId, amount: U128, memo: Option) { + self.assert_feature_enabled(Feature::Token); + self.assert_not_in_denylist(vec![&env::predecessor_account_id(), &receiver_id]); + + self.token.ft_transfer(receiver_id, amount, memo); + } + + #[payable] + fn ft_transfer_call( + &mut self, + receiver_id: AccountId, + amount: U128, + memo: Option, + msg: String, + ) -> PromiseOrValue { + self.assert_feature_enabled(Feature::Token); + self.assert_not_in_denylist(vec![&env::predecessor_account_id(), &receiver_id]); + + self.token.ft_transfer_call(receiver_id, amount, memo, msg) + } + + fn ft_total_supply(&self) -> U128 { + self.token.ft_total_supply() + } + + fn ft_balance_of(&self, account_id: AccountId) -> U128 { + self.token.ft_balance_of(account_id) + } +} + +#[near] +impl FungibleTokenResolver for Contract { + #[private] + fn ft_resolve_transfer(&mut self, sender_id: AccountId, receiver_id: AccountId, amount: U128) -> U128 { + let (used_amount, _) = self.token.internal_ft_resolve_transfer(&sender_id, receiver_id, amount); + used_amount.into() + } +} + +/// Deposit primitive that does **not** require the recipient to have an existing +/// storage-registered account: if no balance entry exists, it starts from zero +/// instead of panicking. +/// +/// Taken from contract standards but modified to default if an account isn't +/// initialized rather than panicking: +/// +/// +/// # Safety contract +/// +/// Bypassing the storage-registration check is only sound when the recipient is +/// a **trusted protocol account configured by the contract owner**. Callers +/// must restrict use to: +/// +/// - the **fee account** — an [`crate::Role::Oracle`] grantee that submitted the +/// batch via `defer_batch` and earns the minting fee, and +/// - the **holding account** — set via the private +/// [`crate::api::SweatApi::set_holding_account_id`] and used to hold newly +/// minted user rewards. +/// +/// Both are controlled by the protocol, so allowing them to skip registration +/// cannot be used by untrusted parties to occupy contract storage without +/// paying for it. Do **not** call this for arbitrary user-supplied accounts; +/// use the standard `FungibleToken` transfer paths, which enforce registration. +pub(crate) trait InternalDeposit { + fn internal_deposit(&mut self, account_id: &AccountId, amount: Balance); +} + +impl InternalDeposit for Contract { + fn internal_deposit(&mut self, account_id: &AccountId, amount: Balance) { + let balance = self.token.accounts.get(account_id).unwrap_or_default(); + let new_balance = balance + .checked_add(amount) + .unwrap_or_else(|| env::panic_str("Balance overflow")); + self.token.accounts.insert(account_id, &new_balance); + self.token.total_supply = self + .token + .total_supply + .checked_add(amount) + .unwrap_or_else(|| env::panic_str("Total supply overflow")); + } +} diff --git a/contract/src/defer.rs b/contract/src/defer.rs new file mode 100644 index 0000000..69928d5 --- /dev/null +++ b/contract/src/defer.rs @@ -0,0 +1,212 @@ +//! Deferred minting via the holding account. +//! +//! Newly minted user rewards are **not** credited to end-user accounts at mint +//! time. End users must **actively claim** their rewards from a separate +//! protocol-owned contract — the *holding account* — which is the only party +//! (besides the Oracle fee) that this contract ever mints user-portion tokens +//! to. +//! +//! # Roles +//! +//! - **This contract** owns the supply and controls minting. It never keeps a +//! per-user ledger of unclaimed rewards. +//! - **Holding account** ([`Contract::holding_account_id`]) is a separate, +//! protocol-owned smart contract. It is trusted by this contract (which is +//! why [`crate::core::InternalDeposit::internal_deposit`] is allowed to skip +//! storage registration for it — see the doc-comment there). The holding +//! contract maintains the per-user ledger of unclaimed rewards and releases +//! tokens on claim. +//! - **End user** earns steps. After a batch is recorded, the user calls the +//! holding contract to claim their accumulated balance; the holding contract +//! then performs a standard NEP-141 `ft_transfer` from itself to the user. +//! +//! # Batch lifecycle: from steps to a claimable balance +//! +//! 1. An [`Role::Oracle`] grantee calls [`SweatDefer::defer_batch`] with a +//! `Vec<(AccountId, steps)>`. +//! 2. This contract computes `(amount, fee)` per `(user, steps)` pair, sums +//! them, advances `steps_since_tge`, and packs the per-user breakdown into +//! `amounts: Vec<(AccountId, U128)>`. +//! 3. It calls `record_batch_for_hold({ amounts })` on the holding account. +//! This is the hand-off point: the holding account persists the per-user +//! accounting (so it knows exactly how much each user is owed) *before* any +//! tokens exist. +//! 4. The [`FungibleTokenTransferCallback::on_record`] callback: +//! - **on success** mints `total_effective` (the user portion) to +//! [`Contract::holding_account_id`] and `total_fee` to the Oracle that +//! submitted the batch, and emits two [`FtMint`] events. The user portion +//! now sits in the holding account's NEP-141 balance on this contract, +//! earmarked in the holding contract's own storage for the individual +//! users recorded in step 3. +//! - **on failure** rolls back `steps_since_tge` and mints nothing. The +//! holding account is expected to treat its own `record_batch_for_hold` +//! call as transactional and not credit users for a batch whose mint did +//! not land. +//! 5. Later, an end user calls a claim method on the **holding contract** (out +//! of scope of this crate — it is a separately deployed contract). The +//! holding contract decrements that user's internal ledger and issues a +//! standard `ft_transfer` from `holding_account_id` to the user. +//! +//! # Invariants +//! +//! - `ft_balance_of(holding_account_id)` represents the pool of unclaimed user +//! rewards plus any residual rounding dust. The holding account custodies +//! this balance for users; it does not own it economically. +//! - There is no path on this contract by which a user receives newly minted +//! rewards directly. Every reward path for end users goes through the +//! holding contract's claim flow, which uses ordinary NEP-141 transfers and +//! is therefore subject to the standard denylist and pause checks in +//! [`crate::core`]. +//! - This contract has no visibility into per-user pending balances. "What +//! does Alice still have unclaimed?" must be answered by reading the holding +//! contract's state, not this one. +//! - The trust assumption is explicit: a compromised or buggy holding contract +//! could mis-credit users or fail to release claims, but it cannot mint +//! additional supply — minting authority remains with the Oracle role and is +//! gated by [`SweatDefer::defer_batch`]. + +use near_contract_standards::fungible_token::events::FtMint; +use near_sdk::{ + env::{self, panic_str}, + ext_contract, is_promise_success, + json_types::U128, + near, require, + serde_json::json, + AccountId, Gas, NearToken, Promise, PromiseOrValue, +}; + +use crate::{ + api::{RestrictionApi, SweatDefer}, + core::InternalDeposit, + Contract, ContractExt, Feature, Role, +}; +use near_plugins::{access_control_any, AccessControllable}; + +const GAS_FOR_DEFER_CALLBACK: Gas = Gas::from_tgas(5); +const GAS_FOR_DEFER: Gas = Gas::from_tgas(30); + +/// Maximum number of `(account, steps)` pairs accepted in a single +/// [`SweatDefer::defer_batch`] call. The cap keeps a batch within the +/// transaction gas limit and the receipt/log size limit: larger batches risk +/// exhausting the gas reserved for the cross-contract `record_batch_for_hold` +/// call and callback, and overflowing the maximum log size when the per-user +/// breakdown is serialized. +const MAX_BATCH_SIZE: usize = 135; + +#[near] +impl SweatDefer for Contract { + #[access_control_any(roles(Role::Oracle))] + fn defer_batch(&mut self, steps_batch: Vec<(AccountId, u32)>) -> PromiseOrValue<()> { + self.assert_feature_enabled(Feature::Minting); + require!(!steps_batch.is_empty(), "Empty steps batch"); + require!( + steps_batch.len() <= MAX_BATCH_SIZE, + "Batch size exceeds the maximum allowed" + ); + require!( + env::prepaid_gas() > GAS_FOR_DEFER, + "Not enough gas to complete the operation" + ); + + let holding_account_id = self.holding_account_id.clone(); + + let mut accounts_tokens: Vec<(AccountId, U128)> = Vec::new(); + let mut total_effective: U128 = U128(0); + let mut total_fee: U128 = U128(0); + let mut steps_increment: u64 = 0; + + for (account_id, step_count) in steps_batch { + require!(step_count != 0, "Step count must not be zero"); + + if self.is_restricted(&account_id) { + continue; + } + + let (amount, fee) = self.calculate_tokens_amount(step_count); + self.steps_since_tge.0 += u64::from(step_count); + steps_increment += u64::from(step_count); + + accounts_tokens.push((account_id, U128(amount))); + total_effective.0 += amount; + total_fee.0 += fee; + } + + let hold_arguments = json!({ + "amounts": accounts_tokens, + }); + + let record_batch_for_hold_gas = env::prepaid_gas() + .checked_sub(GAS_FOR_DEFER) + .unwrap_or_else(|| panic_str("Prepaid gas overflow")); + + Promise::new(holding_account_id.clone()) + .function_call( + "record_batch_for_hold".to_string(), + hold_arguments.to_string().into_bytes(), + NearToken::ZERO, + record_batch_for_hold_gas, + ) + .then( + ext_ft_transfer_callback::ext(env::current_account_id()) + .with_static_gas(GAS_FOR_DEFER_CALLBACK) + .on_record( + holding_account_id, + total_effective, + env::predecessor_account_id(), + total_fee, + steps_increment, + ), + ) + .into() + } +} + +#[ext_contract(ext_ft_transfer_callback)] +pub trait FungibleTokenTransferCallback { + fn on_record( + &mut self, + receiver_id: AccountId, + amount: U128, + fee_account_id: AccountId, + fee: U128, + steps_increment: u64, + ); +} + +#[near] +impl FungibleTokenTransferCallback for Contract { + #[private] + fn on_record( + &mut self, + receiver_id: AccountId, + amount: U128, + fee_account_id: AccountId, + fee: U128, + steps_increment: u64, + ) { + if !is_promise_success() { + self.steps_since_tge.0 -= steps_increment; + env::log_str("Failed to record data in holding account; rolled back steps counter"); + + return; + } + + let mut events: Vec = Vec::with_capacity(2); + + self.internal_deposit(&fee_account_id, fee.0); + events.push(FtMint { + owner_id: &fee_account_id, + amount: fee, + memo: None, + }); + + self.internal_deposit(&receiver_id, amount.0); + events.push(FtMint { + owner_id: &receiver_id, + amount, + memo: None, + }); + + FtMint::emit_many(&events); + } +} diff --git a/contract/src/event.rs b/contract/src/event.rs new file mode 100644 index 0000000..4a0e239 --- /dev/null +++ b/contract/src/event.rs @@ -0,0 +1,130 @@ +//! SWEAT-specific contract events. +//! +//! These events follow the [events format (nep-297)] but, unlike the fungible +//! token events in `near-contract-standards`, they do not correspond to a NEP +//! standard. They are emitted under the project-specific `sweat` standard +//! namespace. +//! +//! [events format (nep-297)]: https://github.com/near/NEPs/blob/master/specs/Standards/EventsFormat.md +//! +//! To add a new event, add a variant to [`Event`]. Serde maps the variant name +//! (`snake_cased`) to the `event` field and its body to `data`; [`Event::emit`] +//! wraps it in the `standard`/`version` envelope and logs it. + +use near_sdk::{env, serde::Serialize, serde_json, AccountIdRef}; + +use crate::Feature; + +const STANDARD: &str = "sweat"; +const VERSION: &str = "1.3.0"; + +/// A SWEAT contract event. The variant name (`snake_cased`) becomes the NEP-297 +/// `event` discriminator and its fields the `data` payload. +#[must_use = "don't forget to `.emit()` this event"] +#[derive(Serialize, Debug)] +#[serde(crate = "near_sdk::serde")] +#[serde(tag = "event", content = "data", rename_all = "snake_case")] +pub enum Event<'a> { + /// Logged when an account is added to or removed from the denylist. + RestrictionChanged { + account_id: &'a AccountIdRef, + /// The account's new restriction status: `true` if it was added to the + /// denylist, `false` if it was removed. + is_restricted: bool, + }, + /// Logged when a [`Feature`] is paused or unpaused. + FeaturePauseChanged { + feature: Feature, + /// The feature's new state: `true` if it was paused, `false` if it was + /// unpaused. + paused: bool, + }, +} + +impl Event<'_> { + /// Emits the event through [`env::log_str`](near_sdk::env::log_str). This is + /// required to ensure that the event is triggered and to consume the event. + pub fn emit(self) { + let envelope = Envelope { + standard: STANDARD, + version: VERSION, + event: self, + }; + + // Events cannot fail to serialize so fine to panic on error + #[allow(clippy::redundant_closure)] + let json = serde_json::to_string(&envelope).ok().unwrap_or_else(|| env::abort()); + env::log_str(&format!("EVENT_JSON:{json}")); + } +} + +/// The NEP-297 envelope. The flattened [`Event`] contributes the `event` and +/// `data` fields next to `standard` and `version`. +#[derive(Serialize, Debug)] +#[serde(crate = "near_sdk::serde")] +struct Envelope<'a> { + standard: &'static str, + version: &'static str, + #[serde(flatten)] + event: Event<'a>, +} + +#[cfg(test)] +mod tests { + use super::*; + use near_sdk::{test_utils, AccountIdRef}; + + #[test] + fn restriction_added() { + let account_id = AccountIdRef::new_or_panic("bob"); + Event::RestrictionChanged { + account_id, + is_restricted: true, + } + .emit(); + assert_eq!( + test_utils::get_logs()[0], + r#"EVENT_JSON:{"standard":"sweat","version":"1.3.0","event":"restriction_changed","data":{"account_id":"bob","is_restricted":true}}"# + ); + } + + #[test] + fn restriction_removed() { + let account_id = AccountIdRef::new_or_panic("bob"); + Event::RestrictionChanged { + account_id, + is_restricted: false, + } + .emit(); + assert_eq!( + test_utils::get_logs()[0], + r#"EVENT_JSON:{"standard":"sweat","version":"1.3.0","event":"restriction_changed","data":{"account_id":"bob","is_restricted":false}}"# + ); + } + + #[test] + fn feature_paused() { + Event::FeaturePauseChanged { + feature: Feature::Token, + paused: true, + } + .emit(); + assert_eq!( + test_utils::get_logs()[0], + r#"EVENT_JSON:{"standard":"sweat","version":"1.3.0","event":"feature_pause_changed","data":{"feature":"token","paused":true}}"# + ); + } + + #[test] + fn feature_unpaused() { + Event::FeaturePauseChanged { + feature: Feature::Minting, + paused: false, + } + .emit(); + assert_eq!( + test_utils::get_logs()[0], + r#"EVENT_JSON:{"standard":"sweat","version":"1.3.0","event":"feature_pause_changed","data":{"feature":"minting","paused":false}}"# + ); + } +} diff --git a/sweat/src/integration.rs b/contract/src/integration.rs similarity index 75% rename from sweat/src/integration.rs rename to contract/src/integration.rs index 81a2082..e87e6b5 100644 --- a/sweat/src/integration.rs +++ b/contract/src/integration.rs @@ -2,13 +2,19 @@ use near_sdk::{ json_types::{U128, U64}, - near_bindgen, + near, }; -use sweat_model::{IntegrationTestMethods, Payout, SweatApi}; -use crate::{Contract, ContractExt}; +use crate::{ + api::{Payout, SweatApi}, + Contract, ContractExt, +}; + +pub trait IntegrationTestMethods { + fn calculate_payout_with_fee_for_batch(&self, batch_size: u32, claim_amount: u32) -> (U128, U128); +} -#[near_bindgen] +#[near] impl IntegrationTestMethods for Contract { fn calculate_payout_with_fee_for_batch(&self, batch_size: u32, claim_amount: u32) -> (U128, U128) { let mut total_fee = 0; diff --git a/contract/src/lib.rs b/contract/src/lib.rs new file mode 100644 index 0000000..5abbd72 --- /dev/null +++ b/contract/src/lib.rs @@ -0,0 +1,478 @@ +#[macro_use] +extern crate static_assertions; + +use api::{Payout, RestrictionApi, SweatApi}; +use event::Event; +use near_contract_standards::fungible_token::{events::FtBurn, FungibleToken}; +use near_plugins::{access_control, access_control_any, AccessControlRole, AccessControllable}; +use near_sdk::{ + assert_one_yocto, + collections::UnorderedSet, + env, + json_types::{U128, U64}, + near, require, + serde::{Deserialize, Serialize}, + AccountId, PanicOnDefault, +}; + +pub mod api; +mod core; +mod defer; +mod event; +mod integration; +mod math; +mod meta; +mod migration; +mod pause; +mod storage; + +pub use pause::Feature; + +#[derive(AccessControlRole, Deserialize, Serialize, Clone, Copy)] +#[serde(crate = "near_sdk::serde")] +pub enum Role { + Oracle, + PauseManager, + UnpauseManager, + DenylistManager, +} + +#[near(contract_state)] +#[access_control(role_type(Role))] +#[derive(PanicOnDefault)] +pub struct Contract { + token: FungibleToken, + steps_since_tge: U64, + denylist: UnorderedSet, + /// Trusted protocol-owned contract that custodies the user portion of every + /// minted batch until end users claim their rewards. See the [`defer`] + /// module docs for the full claim flow and trust model. + holding_account_id: AccountId, + /// Bitmask of paused [`Feature`]s. See the [`pause`] module. + paused_features: u32, +} + +#[near] +impl SweatApi for Contract { + #[init] + fn new( + holding_account_id: AccountId, + super_admin_account_id: AccountId, + oracle_account_ids: Vec, + denylist_manager_account_ids: Vec, + pause_manager_account_ids: Vec, + unpause_manager_account_ids: Vec, + ) -> Self { + let mut contract = Self { + token: FungibleToken::new(b"t"), + steps_since_tge: U64::from(0), + denylist: UnorderedSet::new(b"d"), + holding_account_id, + paused_features: 0, + }; + + contract.init_acl( + super_admin_account_id, + oracle_account_ids, + denylist_manager_account_ids, + pause_manager_account_ids, + unpause_manager_account_ids, + ); + + contract + } + + #[private] + fn set_holding_account_id(&mut self, account_id: AccountId) { + self.holding_account_id = account_id; + } + + fn get_holding_account_id(&self) -> AccountId { + self.holding_account_id.clone() + } + + #[payable] + fn burn(&mut self, amount: U128) { + self.assert_feature_enabled(Feature::Token); + assert_one_yocto(); + self.assert_not_in_denylist(vec![&env::predecessor_account_id()]); + + if amount.0 == 0 { + return; + } + + self.token.internal_withdraw(&env::predecessor_account_id(), amount.0); + + FtBurn { + amount, + owner_id: &env::predecessor_account_id(), + memo: None, + } + .emit(); + } + + fn get_steps_since_tge(&self) -> U64 { + self.steps_since_tge + } + + #[allow(clippy::cast_precision_loss)] + fn formula(&self, steps_since_tge: U64, steps: u32) -> U128 { + U128(math::formula(steps_since_tge.0 as f64, f64::from(steps))) + } +} + +#[near] +impl RestrictionApi for Contract { + fn is_restricted(&self, account_id: &AccountId) -> bool { + self.denylist.contains(account_id) + } + + #[access_control_any(roles(Role::DenylistManager))] + fn set_restricted(&mut self, account_id: &AccountId, is_restricted: bool) { + if is_restricted { + self.denylist.insert(account_id); + } else { + self.denylist.remove(account_id); + } + + Event::RestrictionChanged { + account_id, + is_restricted, + } + .emit(); + } +} + +impl Contract { + /// Initializes the ACL: sets the super admin and grants the manager roles. + /// + /// Uses the unchecked grant path because the super admin is an arbitrary + /// account rather than the caller, so the permission-checked + /// `acl_grant_role` would silently reject these grants. This must only be + /// called from `#[init]` or `#[private]` methods. + fn init_acl( + &mut self, + super_admin_account_id: AccountId, + oracle_account_ids: Vec, + denylist_manager_account_ids: Vec, + pause_manager_account_ids: Vec, + unpause_manager_account_ids: Vec, + ) { + self.acl_init_super_admin(super_admin_account_id); + + let grants = [ + (Role::Oracle, oracle_account_ids), + (Role::DenylistManager, denylist_manager_account_ids), + (Role::PauseManager, pause_manager_account_ids), + (Role::UnpauseManager, unpause_manager_account_ids), + ]; + + for (role, account_ids) in grants { + for account_id in account_ids { + self.acl_get_or_init().grant_role_unchecked(role, &account_id); + } + } + } + + pub(crate) fn calculate_tokens_amount(&self, steps: u32) -> (u128, u128) { + let sweat_to_mint: u128 = self.formula(self.steps_since_tge, steps).0; + let payout = Payout::from(sweat_to_mint); + + (payout.amount_for_user, payout.fee) + } + + pub(crate) fn assert_not_in_denylist(&self, account_ids: Vec<&AccountId>) { + for account_id in account_ids { + require!( + !self.is_restricted(account_id), + format!("The account {account_id} is restricted") + ); + } + } +} + +#[cfg(test)] +mod tests { + use std::{collections::HashMap, str::FromStr}; + + use near_contract_standards::fungible_token::core::FungibleTokenCore; + use near_plugins::AccessControllable; + use near_sdk::{ + json_types::{U128, U64}, + test_utils::VMContextBuilder, + test_vm_config, testing_env, AccountId, NearToken, PromiseResult, RuntimeFeesConfig, + }; + + use crate::{ + api::{Payout, RestrictionApi, SweatApi, SweatDefer}, + core::InternalDeposit, + defer::FungibleTokenTransferCallback, + Contract, Role, + }; + + const EPS: f64 = 0.00001; + + fn account_id(account_id: &str) -> AccountId { + AccountId::from_str(account_id).unwrap() + } + + fn sweat_the_token() -> AccountId { + account_id("sweat_the_token") + } + fn sweat_oracle() -> AccountId { + account_id("sweat_the_oracle") + } + fn sweat_holding() -> AccountId { + account_id("sweat_the_holding") + } + fn user1() -> AccountId { + account_id("sweat_user1") + } + fn user2() -> AccountId { + account_id("sweat_user2") + } + + fn get_context(owner: AccountId, sender: AccountId) -> VMContextBuilder { + let mut builder = VMContextBuilder::new(); + builder + .current_account_id(owner.clone()) + .signer_account_id(sender.clone()) + .predecessor_account_id(sender) + .attached_deposit(NearToken::from_yoctonear(1)); + + builder + } + + #[test] + fn add_remove_oracle() { + testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); + let mut token = Contract::new(sweat_holding(), sweat_the_token(), vec![], vec![], vec![], vec![]); + assert!(get_oracles(&token).is_empty()); + token.acl_grant_role(Role::Oracle.into(), sweat_oracle()); + assert_eq!(vec![sweat_oracle()], get_oracles(&token)); + token.acl_revoke_role(Role::Oracle.into(), sweat_oracle()); + assert!(get_oracles(&token).is_empty()); + } + + #[test] + fn oracle_fee_test() { + testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); + let mut token = Contract::new(sweat_holding(), sweat_the_token(), vec![], vec![], vec![], vec![]); + assert_eq!(U64(0), token.get_steps_since_tge()); + assert!(get_oracles(&token).is_empty()); + token.acl_grant_role(Role::Oracle.into(), sweat_oracle()); + assert_eq!(vec![sweat_oracle()], get_oracles(&token)); + + let p1 = Payout::from(token.formula(U64(0), 10_000).0); + let p2 = Payout::from(token.formula(U64(10_000), 10_000).0); + let total_effective = U128(p1.amount_for_user + p2.amount_for_user); + let total_fee = U128(p1.fee + p2.fee); + + testing_env!(get_context(sweat_the_token(), sweat_oracle()).build()); + let _ = token.defer_batch(vec![(user1(), 10_000), (user2(), 10_000)]); + assert_eq!(U64(2 * 10_000), token.get_steps_since_tge()); + + testing_env!( + get_context(sweat_the_token(), sweat_the_token()).build(), + test_vm_config(), + RuntimeFeesConfig::test(), + HashMap::default(), + vec![PromiseResult::Successful(vec![])], + ); + token.on_record(sweat_holding(), total_effective, sweat_oracle(), total_fee, 2 * 10_000); + + assert_eq!(token.token.ft_balance_of(sweat_holding()).0, total_effective.0); + assert_eq!(token.token.ft_balance_of(sweat_oracle()).0, total_fee.0); + assert!(((9.499_999_991_723_028 + 9.499_999_975_169_082) - total_effective.0 as f64 / 1e+18).abs() < EPS); + assert!((0.999_999_998_257_479_4 - total_fee.0 as f64 / 1e+18).abs() < EPS); + } + + #[test] + fn defer_batch_skips_denylisted_user() { + testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); + let mut token = Contract::new(sweat_holding(), sweat_the_token(), vec![], vec![], vec![], vec![]); + token.acl_grant_role(Role::Oracle.into(), sweat_oracle()); + + token.acl_grant_role(Role::DenylistManager.into(), sweat_the_token()); + token.set_restricted(&user1(), true); + + testing_env!(get_context(sweat_the_token(), sweat_oracle()).build()); + let _ = token.defer_batch(vec![(user1(), 10_000), (user2(), 10_000)]); + + // Only the non-denylisted user's steps are counted; user1 is skipped + // before its step_count is added. steps_since_tge is the only on-chain + // state defer_batch mutates here — the per-user amounts go out in the + // record_batch_for_hold XCC args, which a unit test can't observe. + assert_eq!(U64(10_000), token.get_steps_since_tge()); + } + + #[test] + fn defer_batch_skips_all_denylisted_users() { + testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); + let mut token = Contract::new(sweat_holding(), sweat_the_token(), vec![], vec![], vec![], vec![]); + token.acl_grant_role(Role::Oracle.into(), sweat_oracle()); + + token.acl_grant_role(Role::DenylistManager.into(), sweat_the_token()); + token.set_restricted(&user1(), true); + token.set_restricted(&user2(), true); + + testing_env!(get_context(sweat_the_token(), sweat_oracle()).build()); + let _ = token.defer_batch(vec![(user1(), 10_000), (user2(), 10_000)]); + + // Every entry skipped -> no steps recorded. + assert_eq!(U64(0), token.get_steps_since_tge()); + } + + #[test] + #[should_panic(expected = "Empty steps batch")] + fn defer_batch_rejects_empty_batch() { + testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); + let mut token = Contract::new(sweat_holding(), sweat_the_token(), vec![], vec![], vec![], vec![]); + token.acl_grant_role(Role::Oracle.into(), sweat_oracle()); + + testing_env!(get_context(sweat_the_token(), sweat_oracle()).build()); + let _ = token.defer_batch(vec![]); + } + + #[test] + #[should_panic(expected = "Step count must not be zero")] + fn defer_batch_rejects_zero_step_count() { + testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); + let mut token = Contract::new(sweat_holding(), sweat_the_token(), vec![], vec![], vec![], vec![]); + token.acl_grant_role(Role::Oracle.into(), sweat_oracle()); + + testing_env!(get_context(sweat_the_token(), sweat_oracle()).build()); + let _ = token.defer_batch(vec![(user1(), 0)]); + } + + #[test] + fn burn() { + testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); + let mut token = Contract::new(sweat_holding(), sweat_the_token(), vec![], vec![], vec![], vec![]); + assert!(get_oracles(&token).is_empty()); + token.acl_grant_role(Role::Oracle.into(), sweat_oracle()); + mint(&mut token, &user1(), 9499999991723028480); + testing_env!(get_context(sweat_the_token(), user1()).build()); + token.burn(U128(9499999991723028480)); + assert!((0.0 - token.token.ft_balance_of(user1()).0 as f64 / 1e+18).abs() < EPS); + } + + #[test] + #[should_panic(expected = r#"Requires attached deposit of exactly 1 yoctoNEAR"#)] + fn burn_without_deposit() { + testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); + let mut token = Contract::new(sweat_holding(), sweat_the_token(), vec![], vec![], vec![], vec![]); + token.acl_grant_role(Role::Oracle.into(), sweat_oracle()); + mint(&mut token, &user1(), 9499999991723028480); + testing_env!(get_context(sweat_the_token(), user1()) + .attached_deposit(NearToken::from_yoctonear(0)) + .build()); + token.burn(U128(9499999991723028480)); + } + + #[test] + #[should_panic(expected = r#"The account sweat_user2 is not registered"#)] + fn transfer_to_unregistered() { + testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); + let mut token = Contract::new(sweat_holding(), sweat_the_token(), vec![], vec![], vec![], vec![]); + assert!(get_oracles(&token).is_empty()); + token.acl_grant_role(Role::Oracle.into(), sweat_oracle()); + mint(&mut token, &user1(), 9499999991723028480); + testing_env!(get_context(sweat_the_token(), user1()).build()); + + token.token.ft_transfer(user2(), U128(9499999991723028480), None); + + assert!((0.0 - token.token.ft_balance_of(user1()).0 as f64 / 1e+18).abs() < EPS); + + assert!((9.499_999_991_723_028 - token.token.ft_balance_of(user2()).0 as f64 / 1e+18).abs() < EPS); + } + + #[test] + fn transfer_to_registered() { + testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); + let mut token = Contract::new(sweat_holding(), sweat_the_token(), vec![], vec![], vec![], vec![]); + assert!(get_oracles(&token).is_empty()); + token.acl_grant_role(Role::Oracle.into(), sweat_oracle()); + mint(&mut token, &user1(), 9499999991723028480); + mint(&mut token, &user2(), 9499999991723028480); + testing_env!(get_context(sweat_the_token(), user1()).build()); + + token.token.ft_transfer(user2(), U128(9499999991723028480), None); + + assert!((0.0 - token.token.ft_balance_of(user1()).0 as f64 / 1e+18).abs() < EPS); + + assert!((9.499_999_991_723_028 * 2.0 - token.token.ft_balance_of(user2()).0 as f64 / 1e+18).abs() < EPS); + } + + #[test] + #[should_panic(expected = r#"The account sweat_user1 is restricted"#)] + fn transfer_from_denied_account() { + testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); + let mut token = Contract::new(sweat_holding(), sweat_the_token(), vec![], vec![], vec![], vec![]); + assert!(get_oracles(&token).is_empty()); + token.acl_grant_role(Role::Oracle.into(), sweat_oracle()); + mint(&mut token, &user1(), 9499999991723028480); + mint(&mut token, &user2(), 9499999991723028480); + token.acl_grant_role(Role::DenylistManager.into(), sweat_the_token()); + token.set_restricted(&user1(), true); + + testing_env!(get_context(sweat_the_token(), user1()).build()); + token.ft_transfer(user2(), U128(9499999991723028480), None); + } + + #[test] + #[should_panic(expected = r#"The account sweat_user2 is restricted"#)] + fn transfer_to_denied_account() { + testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); + let mut token = Contract::new(sweat_holding(), sweat_the_token(), vec![], vec![], vec![], vec![]); + assert!(get_oracles(&token).is_empty()); + token.acl_grant_role(Role::Oracle.into(), sweat_oracle()); + mint(&mut token, &user1(), 9499999991723028480); + mint(&mut token, &user2(), 9499999991723028480); + token.acl_grant_role(Role::DenylistManager.into(), sweat_the_token()); + token.set_restricted(&user2(), true); + + testing_env!(get_context(sweat_the_token(), user1()).build()); + token.ft_transfer(user2(), U128(9499999991723028480), None); + } + + #[test] + #[should_panic(expected = r#"The account sweat_user1 is restricted"#)] + fn ft_transfer_call_from_denied_account() { + testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); + let mut token = Contract::new(sweat_holding(), sweat_the_token(), vec![], vec![], vec![], vec![]); + assert!(get_oracles(&token).is_empty()); + token.acl_grant_role(Role::Oracle.into(), sweat_oracle()); + mint(&mut token, &user1(), 9499999991723028480); + mint(&mut token, &user2(), 9499999991723028480); + token.acl_grant_role(Role::DenylistManager.into(), sweat_the_token()); + token.set_restricted(&user1(), true); + + testing_env!(get_context(sweat_the_token(), user1()).build()); + let _ = token.ft_transfer_call(user2(), U128(9499999991723028480), None, String::from("test")); + } + + #[test] + #[should_panic(expected = r#"The account sweat_user2 is restricted"#)] + fn ft_transfer_call_to_denied_account() { + testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); + let mut token = Contract::new(sweat_holding(), sweat_the_token(), vec![], vec![], vec![], vec![]); + assert!(get_oracles(&token).is_empty()); + token.acl_grant_role(Role::Oracle.into(), sweat_oracle()); + mint(&mut token, &user1(), 9499999991723028480); + mint(&mut token, &user2(), 9499999991723028480); + token.acl_grant_role(Role::DenylistManager.into(), sweat_the_token()); + token.set_restricted(&user2(), true); + + testing_env!(get_context(sweat_the_token(), user1()).build()); + let _ = token.ft_transfer_call(user2(), U128(9499999991723028480), None, String::from("test")); + } + + fn get_oracles(contract: &Contract) -> Vec { + contract.acl_get_grantees(Role::Oracle.into(), 0, 10) + } + + fn mint(contract: &mut Contract, account_id: &AccountId, amount: u128) { + contract.internal_deposit(account_id, amount); + } +} diff --git a/sweat/src/math.rs b/contract/src/math.rs similarity index 100% rename from sweat/src/math.rs rename to contract/src/math.rs diff --git a/contract/src/meta.rs b/contract/src/meta.rs new file mode 100644 index 0000000..c790788 --- /dev/null +++ b/contract/src/meta.rs @@ -0,0 +1,23 @@ +use near_contract_standards::fungible_token::metadata::{ + FungibleTokenMetadata, FungibleTokenMetadataProvider, +}; +use near_sdk::near; + +use crate::{Contract, ContractExt}; + +pub const ICON: &str = "data:image/svg+xml,%3Csvg viewBox='0 0 100 100' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='100' height='100' rx='50' fill='%23FF0D75'/%3E%3Cg clip-path='url(%23clip0_283_2788)'%3E%3Cpath d='M39.4653 77.5455L19.0089 40.02L35.5411 22.2805L55.9975 59.806L39.4653 77.5455Z' stroke='white' stroke-width='10'/%3E%3Cpath d='M66.0253 77.8531L45.569 40.3276L62.1012 22.5882L82.5576 60.1136L66.0253 77.8531Z' stroke='white' stroke-width='10'/%3E%3C/g%3E%3Cdefs%3E%3CclipPath id='clip0_283_2788'%3E%3Crect width='100' height='56' fill='white' transform='translate(0 22)'/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E%0A"; + +#[near] +impl FungibleTokenMetadataProvider for Contract { + fn ft_metadata(&self) -> FungibleTokenMetadata { + FungibleTokenMetadata { + spec: "ft-1.0".to_string(), + name: "SWEAT".to_string(), + symbol: "SWEAT".to_string(), + icon: Some(String::from(ICON)), + reference: None, + reference_hash: None, + decimals: 18, + } + } +} diff --git a/contract/src/migration.rs b/contract/src/migration.rs new file mode 100644 index 0000000..edd124f --- /dev/null +++ b/contract/src/migration.rs @@ -0,0 +1,91 @@ +use near_contract_standards::fungible_token::{Balance, FungibleToken}; +use near_sdk::{ + collections::{LookupMap, UnorderedSet}, + env, + json_types::U64, + near, AccountId, StorageUsage, +}; + +use crate::{Contract, ContractExt}; + +/// State layout of the currently deployed contract (pre-ACL, with denylist). +/// +/// Borsh deserializes fields in declaration order, so this must mirror the +/// deployed struct exactly — including `denylist`, which the live contract +/// already stores. Omitting it leaves trailing bytes in the state blob and +/// makes `state_read` panic with "Cannot deserialize the contract state". +#[near(serializers = [borsh])] +struct OldContract { + oracles: UnorderedSet, + token: OldFungibleToken, + steps_since_tge: U64, + denylist: UnorderedSet, +} + +/// Legacy `FungibleToken` layout from the deployed contract. +/// +/// The current token's `accounts` adapter dropped a `skip_hashing_postfix: +/// Option` field, which still sits in the deployed state blob between +/// the map prefix and `total_supply`. The new struct would mis-deserialize +/// those bytes, so the old state is read through this mirror first. Only the +/// scalar tallies are reused; the account entries stay in place on the trie +/// (their keys are unchanged) and remain addressable by the rebuilt token. +#[near(serializers = [borsh])] +#[allow(dead_code)] +struct OldFungibleToken { + accounts: OldLookupMapAdapter, + total_supply: Balance, + account_storage_usage: StorageUsage, +} + +#[near(serializers = [borsh])] +#[allow(dead_code)] // fields exist only to consume the legacy borsh layout +struct OldLookupMapAdapter { + // `LookupMap` persists nothing but its key prefix, so the key type here is + // irrelevant for deserialization — it only needs to satisfy borsh bounds. + inner: LookupMap<[u8; 32], Balance>, + skip_hashing_postfix: Option, +} + +#[near] +impl Contract { + /// Migrates the contract state from the previous layout to the current one. + /// + /// # Panics + /// + /// Panics if the existing on-chain state cannot be read as [`OldContract`]. + #[private] + #[init(ignore_state)] + pub fn migrate( + holding_account_id: AccountId, + super_admin_account_id: AccountId, + denylist_manager_account_ids: Vec, + pause_manager_account_ids: Vec, + unpause_manager_account_ids: Vec, + ) -> Self { + let mut old: OldContract = env::state_read().expect("failed to read old contract state"); + + // Drain the legacy oracle set into the ACL Oracle role, then reclaim its + // storage. Read it out before moving the other fields into the new struct. + let oracle_account_ids: Vec = old.oracles.iter().collect(); + old.oracles.clear(); + + let mut contract = Self { + token: FungibleToken::from_prefix(b"t", old.token.total_supply, old.token.account_storage_usage), + steps_since_tge: old.steps_since_tge, + denylist: old.denylist, + holding_account_id, + paused_features: 0, + }; + + contract.init_acl( + super_admin_account_id, + oracle_account_ids, + denylist_manager_account_ids, + pause_manager_account_ids, + unpause_manager_account_ids, + ); + + contract + } +} diff --git a/contract/src/pause.rs b/contract/src/pause.rs new file mode 100644 index 0000000..bb0e336 --- /dev/null +++ b/contract/src/pause.rs @@ -0,0 +1,253 @@ +//! Home-made per-feature pause mechanism. +//! +//! Paused features are stored as a bitmask on [`Contract::paused_features`]. +//! Each [`Feature`] owns one bit (see [`Feature::bit`]). Pausing a feature ORs +//! its bit in; unpausing clears it. Guarded methods call +//! [`Contract::assert_feature_enabled`] as their first statement so the pause +//! check fires before any other validation. +//! +//! Pause/unpause are gated by the [`crate::Role::PauseManager`] / +//! [`crate::Role::UnpauseManager`] ACL roles and emit a +//! [`Event::FeaturePauseChanged`] for every feature whose state actually +//! changes. + +use near_plugins::{access_control_any, AccessControllable}; +use near_sdk::{near, require}; + +use crate::{api::PauseApi, event::Event, Contract, ContractExt, Role}; + +/// A contract feature that can be independently paused. +/// +/// Serialized in snake_case so call args read e.g. +/// `{"features": ["token", "minting"]}`. +#[near(serializers = [json])] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[serde(rename_all = "snake_case")] +pub enum Feature { + /// Token movement: `ft_transfer`, `ft_transfer_call`, `burn`, + /// `storage_unregister`. + Token, + /// Reward minting: `defer_batch`. + Minting, +} + +impl Feature { + /// Every feature, used to enumerate the bitmask for view methods. + const ALL: [Feature; 2] = [Feature::Token, Feature::Minting]; + + /// The single bit this feature occupies in [`Contract::paused_features`]. + const fn bit(self) -> u32 { + match self { + Feature::Token => 1 << 0, + Feature::Minting => 1 << 1, + } + } + + /// Human-readable name used in the paused panic message. + const fn name(self) -> &'static str { + match self { + Feature::Token => "token", + Feature::Minting => "minting", + } + } +} + +#[near] +impl PauseApi for Contract { + #[access_control_any(roles(Role::PauseManager))] + fn pause_features(&mut self, features: Vec) -> bool { + self.set_features_paused(features, true) + } + + #[access_control_any(roles(Role::UnpauseManager))] + fn unpause_features(&mut self, features: Vec) -> bool { + self.set_features_paused(features, false) + } + + fn is_feature_paused(&self, feature: Feature) -> bool { + self.paused_features & feature.bit() != 0 + } + + fn get_paused_features(&self) -> Vec { + Feature::ALL + .into_iter() + .filter(|feature| self.is_feature_paused(*feature)) + .collect() + } +} + +impl Contract { + /// Panics if `feature` is currently paused. Call this as the first statement + /// of any guarded method so it fires before other checks. + pub(crate) fn assert_feature_enabled(&self, feature: Feature) { + require!( + !self.is_feature_paused(feature), + format!("Feature '{}' is paused", feature.name()) + ); + } + + /// Sets the paused bit of each feature to `paused`, emitting a + /// [`Event::FeaturePauseChanged`] only for features whose state actually + /// changed. Returns whether the mask changed at all. + fn set_features_paused(&mut self, features: Vec, paused: bool) -> bool { + let before = self.paused_features; + + for feature in features { + let already = self.is_feature_paused(feature); + if already == paused { + continue; + } + + if paused { + self.paused_features |= feature.bit(); + } else { + self.paused_features &= !feature.bit(); + } + + Event::FeaturePauseChanged { feature, paused }.emit(); + } + + self.paused_features != before + } +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use near_contract_standards::fungible_token::core::FungibleTokenCore; + use near_plugins::AccessControllable; + use near_sdk::{json_types::U128, test_utils::VMContextBuilder, testing_env, AccountId, NearToken}; + + use crate::{ + api::{PauseApi, SweatApi}, + core::InternalDeposit, + pause::Feature, + Contract, Role, + }; + + fn account_id(account_id: &str) -> AccountId { + AccountId::from_str(account_id).unwrap() + } + + fn token() -> AccountId { + account_id("sweat_the_token") + } + fn holding() -> AccountId { + account_id("sweat_the_holding") + } + fn user1() -> AccountId { + account_id("sweat_user1") + } + fn user2() -> AccountId { + account_id("sweat_user2") + } + + fn get_context(sender: AccountId) -> VMContextBuilder { + let mut builder = VMContextBuilder::new(); + builder + .current_account_id(token()) + .signer_account_id(sender.clone()) + .predecessor_account_id(sender) + .attached_deposit(NearToken::from_yoctonear(1)); + builder + } + + /// super-admin is `token()`, which can pause/unpause via ACL. + fn setup() -> Contract { + testing_env!(get_context(token()).build()); + let mut contract = Contract::new(holding(), token(), vec![], vec![], vec![], vec![]); + contract.acl_grant_role(Role::PauseManager.into(), token()); + contract.acl_grant_role(Role::UnpauseManager.into(), token()); + contract + } + + #[test] + fn pause_then_unpause_round_trip() { + let mut contract = setup(); + + assert!(contract.get_paused_features().is_empty()); + + assert!(contract.pause_features(vec![Feature::Token])); + assert!(contract.is_feature_paused(Feature::Token)); + assert!(!contract.is_feature_paused(Feature::Minting)); + assert_eq!(contract.get_paused_features(), vec![Feature::Token]); + + assert!(contract.unpause_features(vec![Feature::Token])); + assert!(!contract.is_feature_paused(Feature::Token)); + assert!(contract.get_paused_features().is_empty()); + } + + #[test] + fn pause_is_idempotent() { + let mut contract = setup(); + + assert!(contract.pause_features(vec![Feature::Token])); + // Already paused -> mask unchanged. + assert!(!contract.pause_features(vec![Feature::Token])); + + assert!(contract.unpause_features(vec![Feature::Token])); + // Already unpaused -> mask unchanged. + assert!(!contract.unpause_features(vec![Feature::Token])); + } + + #[test] + fn pause_multiple_features_at_once() { + let mut contract = setup(); + + assert!(contract.pause_features(vec![Feature::Token, Feature::Minting])); + assert!(contract.is_feature_paused(Feature::Token)); + assert!(contract.is_feature_paused(Feature::Minting)); + + // One already paused, one not -> still a change. + assert!(contract.unpause_features(vec![Feature::Token])); + assert!(contract.unpause_features(vec![Feature::Token, Feature::Minting])); + assert!(contract.get_paused_features().is_empty()); + } + + #[test] + #[should_panic(expected = "Feature 'token' is paused")] + fn ft_transfer_blocked_when_token_paused() { + let mut contract = setup(); + contract.internal_deposit(&user1(), 9_000_000_000_000_000_000); + contract.pause_features(vec![Feature::Token]); + + testing_env!(get_context(user1()).build()); + contract.ft_transfer(user2(), U128(1), None); + } + + #[test] + #[should_panic(expected = "Feature 'token' is paused")] + fn burn_blocked_when_token_paused() { + let mut contract = setup(); + contract.internal_deposit(&user1(), 9_000_000_000_000_000_000); + contract.pause_features(vec![Feature::Token]); + + testing_env!(get_context(user1()).build()); + contract.burn(U128(1)); + } + + #[test] + fn ft_transfer_works_after_unpause() { + let mut contract = setup(); + contract.internal_deposit(&user1(), 9_000_000_000_000_000_000); + contract.internal_deposit(&user2(), 9_000_000_000_000_000_000); + + contract.pause_features(vec![Feature::Token]); + contract.unpause_features(vec![Feature::Token]); + + testing_env!(get_context(user1()).build()); + contract.ft_transfer(user2(), U128(1), None); + assert_eq!(contract.ft_balance_of(user2()).0, 9_000_000_000_000_000_001); + } + + #[test] + #[should_panic(expected = "Insufficient permissions for method pause_features")] + fn pause_requires_role() { + testing_env!(get_context(token()).build()); + let mut contract = Contract::new(holding(), token(), vec![], vec![], vec![], vec![]); + + testing_env!(get_context(user1()).build()); + contract.pause_features(vec![Feature::Token]); + } +} diff --git a/contract/src/storage.rs b/contract/src/storage.rs new file mode 100644 index 0000000..4620474 --- /dev/null +++ b/contract/src/storage.rs @@ -0,0 +1,50 @@ +use near_contract_standards::{ + fungible_token::events::FtBurn, + storage_management::{StorageBalance, StorageBalanceBounds, StorageManagement}, +}; +use near_sdk::{env, near, AccountId, NearToken}; + +use crate::{Contract, ContractExt, Feature}; + +#[near] +impl StorageManagement for Contract { + #[payable] + fn storage_deposit(&mut self, account_id: Option, registration_only: Option) -> StorageBalance { + self.token.storage_deposit(account_id, registration_only) + } + + #[payable] + fn storage_withdraw(&mut self, amount: Option) -> StorageBalance { + self.token.storage_withdraw(amount) + } + + #[payable] + fn storage_unregister(&mut self, force: Option) -> bool { + self.assert_feature_enabled(Feature::Token); + self.assert_not_in_denylist(vec![&env::predecessor_account_id()]); + + self.token + .internal_storage_unregister(force) + .inspect(|(account_id, balance)| { + if *balance == 0 { + return; + } + + FtBurn { + owner_id: account_id, + amount: (*balance).into(), + memo: None, + } + .emit(); + }) + .is_some() + } + + fn storage_balance_bounds(&self) -> StorageBalanceBounds { + self.token.storage_balance_bounds() + } + + fn storage_balance_of(&self, account_id: AccountId) -> Option { + self.token.storage_balance_of(account_id) + } +} diff --git a/exploit-stub/Cargo.toml b/exploit-stub/Cargo.toml index c2cc02d..489a386 100644 --- a/exploit-stub/Cargo.toml +++ b/exploit-stub/Cargo.toml @@ -10,3 +10,6 @@ crate-type = ["cdylib"] [dependencies] near-sdk = { workspace = true } + +[lints] +workspace = true diff --git a/exploit-stub/src/lib.rs b/exploit-stub/src/lib.rs index 0875f3b..462a04c 100644 --- a/exploit-stub/src/lib.rs +++ b/exploit-stub/src/lib.rs @@ -1,17 +1,15 @@ use near_sdk::{ - borsh::{self, BorshDeserialize, BorshSerialize}, - env, - env::log_str, + env::{self, log_str}, ext_contract, json_types::U128, - near_bindgen, AccountId, PanicOnDefault, + near, AccountId, PanicOnDefault, Promise, }; -#[near_bindgen] -#[derive(BorshSerialize, BorshDeserialize, PanicOnDefault)] +#[near(contract_state)] +#[derive(PanicOnDefault)] struct Contract {} -#[near_bindgen] +#[near] #[allow(dead_code)] impl Contract { #[init] @@ -25,7 +23,7 @@ impl Contract { } #[allow(clippy::unused_self)] - pub fn exploit_on_record(&mut self, ft_account_id: AccountId, amount: U128) { + pub fn exploit_on_record(&mut self, ft_account_id: AccountId, amount: U128) -> Promise { log_str(&format!( "Try to call on_record in callback, ft account = {ft_account_id}" )); @@ -33,7 +31,7 @@ impl Contract { let intruder_id = env::predecessor_account_id(); ext_self::ext(env::current_account_id()) .some_function() - .then(ext_token::ext(ft_account_id).on_record(intruder_id.clone(), amount, intruder_id, U128(0))); + .then(ext_token::ext(ft_account_id).on_record(intruder_id.clone(), amount, intruder_id, U128(0))) } } @@ -42,7 +40,7 @@ pub trait Callback { fn some_function(&mut self); } -#[near_bindgen] +#[near] impl Callback for Contract { fn some_function(&mut self) { log_str("Call some_function in stub contract"); diff --git a/integration-tests/Cargo.lock b/integration-tests/Cargo.lock index 872ef40..4ea303a 100644 --- a/integration-tests/Cargo.lock +++ b/integration-tests/Cargo.lock @@ -1,12 +1,16 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "Inflector" version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] [[package]] name = "addr2line" @@ -23,17 +27,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom 0.2.10", - "once_cell", - "version_check", -] - [[package]] name = "aho-corasick" version = "1.1.1" @@ -65,87 +58,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] -name = "arrayref" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" - -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - -[[package]] -name = "async-channel" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-io" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" -dependencies = [ - "async-lock", - "autocfg", - "cfg-if 1.0.0", - "concurrent-queue", - "futures-lite", - "log", - "parking", - "polling", - "rustix 0.37.24", - "slab", - "socket2 0.4.9", - "waker-fn", -] - -[[package]] -name = "async-lock" -version = "2.8.0" +name = "approx" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" dependencies = [ - "event-listener", + "num-traits", ] [[package]] -name = "async-process" -version = "1.7.0" +name = "arbitrary" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" dependencies = [ - "async-io", - "async-lock", - "autocfg", - "blocking", - "cfg-if 1.0.0", - "event-listener", - "futures-lite", - "rustix 0.37.24", - "signal-hook", - "windows-sys", + "derive_arbitrary", ] -[[package]] -name = "async-task" -version = "4.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9441c6b2fe128a7c2bf680a44c34d0df31ce09e5b7e401fcca3faa483dbc921" - [[package]] name = "async-trait" version = "0.1.73" @@ -154,7 +83,7 @@ checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.117", ] [[package]] @@ -177,25 +106,13 @@ checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.21.4" @@ -203,21 +120,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" [[package]] -name = "binary-install" -version = "0.0.2" +name = "base64" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5bc5f8c50dd6a80d0b303ddab79f42ddcb52fd43d68107ecf622c551fd4cd4" -dependencies = [ - "curl", - "dirs 1.0.5", - "failure", - "flate2", - "hex 0.3.2", - "is_executable", - "siphasher", - "tar", - "zip", -] +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" @@ -227,15 +133,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" [[package]] name = "bitvec" -version = "0.20.4" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7774144344a4faa177370406a7ff5f1da24303817368584c6206c8303eb07848" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ "funty", "radium", @@ -245,33 +151,11 @@ dependencies = [ [[package]] name = "blake2" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a4e37d16930f5459780f5621038b6382b9bb37c19016f39fb6b5808d831f174" -dependencies = [ - "crypto-mac", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "blake2b_simd" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" -dependencies = [ - "arrayref", - "arrayvec 0.5.2", - "constant_time_eq", -] - -[[package]] -name = "block-buffer" -version = "0.9.0" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ - "generic-array", + "digest", ] [[package]] @@ -283,130 +167,51 @@ dependencies = [ "generic-array", ] -[[package]] -name = "blocking" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94c4ef1f913d78636d78d538eec1f18de81e481f44b1be0a81060090530846e1" -dependencies = [ - "async-channel", - "async-lock", - "async-task", - "fastrand 2.0.1", - "futures-io", - "futures-lite", - "piper", - "tracing", -] - -[[package]] -name = "borsh" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" -dependencies = [ - "borsh-derive 0.9.3", - "hashbrown 0.11.2", -] - [[package]] name = "borsh" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" -dependencies = [ - "borsh-derive 0.10.3", - "hashbrown 0.12.3", -] - -[[package]] -name = "borsh-derive" -version = "0.9.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" +checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" dependencies = [ - "borsh-derive-internal 0.9.3", - "borsh-schema-derive-internal 0.9.3", - "proc-macro-crate 0.1.5", - "proc-macro2", - "syn 1.0.109", + "borsh-derive", + "bytes", + "cfg_aliases", ] [[package]] name = "borsh-derive" -version = "0.10.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" -dependencies = [ - "borsh-derive-internal 0.10.3", - "borsh-schema-derive-internal 0.10.3", - "proc-macro-crate 0.1.5", - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "borsh-derive-internal" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "borsh-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" +checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" dependencies = [ + "once_cell", + "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.117", ] [[package]] -name = "borsh-schema-derive-internal" -version = "0.9.3" +name = "bs58" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] -name = "borsh-schema-derive-internal" -version = "0.10.3" +name = "bs58" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "tinyvec", ] -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" - [[package]] name = "bumpalo" version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" -[[package]] -name = "byte-slice-cast" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" - [[package]] name = "byteorder" version = "1.4.3" @@ -424,58 +229,33 @@ name = "bytesize" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc" - -[[package]] -name = "bzip2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" -dependencies = [ - "bzip2-sys", - "libc", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.11+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - -[[package]] -name = "c2-chacha" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d27dae93fe7b1e0424dc57179ac396908c26b035a87234809f5c4dfd1b47dc80" dependencies = [ - "cipher", - "ppv-lite86", + "serde", ] [[package]] name = "cc" -version = "1.0.83" +version = "1.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" dependencies = [ + "find-msvc-tools", + "jobserver", "libc", + "shlex", ] [[package]] name = "cfg-if" -version = "0.1.10" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "cfg-if" -version = "1.0.0" +name = "cfg_aliases" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" @@ -489,38 +269,52 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] -name = "cipher" -version = "0.2.5" +name = "convert_case" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" -dependencies = [ - "generic-array", -] +checksum = "fb4a24b1aaf0fd0ce8b45161144d6f42cd91677fd5940fd431183eb023b3a2b8" [[package]] -name = "concurrent-queue" -version = "2.3.0" +name = "convert_case" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" dependencies = [ - "crossbeam-utils", + "unicode-segmentation", ] [[package]] -name = "constant_time_eq" -version = "0.1.5" +name = "cookie" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] [[package]] -name = "convert_case" -version = "0.4.0" +name = "cookie_store" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +checksum = "15b2c103cf610ec6cae3da84a766285b42fd16aad564758459e6ecf128c75206" +dependencies = [ + "cookie", + "document-features", + "idna 1.1.0", + "indexmap 2.14.0", + "log", + "serde", + "serde_derive", + "serde_json", + "time", + "url", +] [[package]] name = "core-foundation" @@ -553,16 +347,7 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -582,234 +367,237 @@ dependencies = [ ] [[package]] -name = "crypto-mac" -version = "0.8.0" +name = "curve25519-dalek" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ - "generic-array", + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "rustc_version", "subtle", + "zeroize", ] [[package]] -name = "curl" -version = "0.4.44" +name = "curve25519-dalek-derive" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ - "curl-sys", - "libc", - "openssl-probe", - "openssl-sys", - "schannel", - "socket2 0.4.9", - "winapi", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] -name = "curl-sys" -version = "0.4.66+curl-8.3.0" +name = "darling" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70c44a72e830f0e40ad90dda8a6ab6ed6314d39776599a58a2e5e37fbc6db5b9" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" dependencies = [ - "cc", - "libc", - "libz-sys", - "openssl-sys", - "pkg-config", - "vcpkg", - "windows-sys", + "darling_core", + "darling_macro", ] [[package]] -name = "curve25519-dalek" -version = "3.2.1" +name = "darling_core" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", - "subtle", - "zeroize", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.117", ] [[package]] -name = "derive_more" -version = "0.99.17" +name = "darling_macro" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ - "convert_case", - "proc-macro2", + "darling_core", "quote", - "rustc_version", - "syn 1.0.109", + "syn 2.0.117", ] [[package]] -name = "digest" -version = "0.9.0" +name = "deranged" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ - "generic-array", + "powerfmt", + "serde_core", ] [[package]] -name = "digest" -version = "0.10.7" +name = "derive_arbitrary" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ - "block-buffer 0.10.4", - "crypto-common", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] -name = "dirs" -version = "1.0.5" +name = "derive_more" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ - "libc", - "redox_users 0.3.5", - "winapi", + "derive_more-impl", ] [[package]] -name = "dirs" -version = "3.0.2" +name = "derive_more-impl" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ - "dirs-sys", + "convert_case 0.10.0", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.117", + "unicode-xid", ] [[package]] -name = "dirs-sys" -version = "0.3.7" +name = "digest" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "libc", - "redox_users 0.4.3", - "winapi", + "block-buffer", + "crypto-common", + "subtle", ] [[package]] -name = "dyn-clone" -version = "1.0.14" +name = "displaydoc" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd" - -[[package]] -name = "easy-ext" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + +[[package]] +name = "dyn-clone" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd" + +[[package]] +name = "easy-ext" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53aff6fdc1b181225acdcb5b14c47106726fd8e486707315b1b138baed68ee31" [[package]] name = "ed25519" -version = "1.5.3" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "signature", ] [[package]] name = "ed25519-dalek" -version = "1.0.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" dependencies = [ "curve25519-dalek", "ed25519", - "rand 0.7.3", - "serde", - "sha2 0.9.9", - "zeroize", + "rand_core", + "sha2", + "subtle", ] +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + [[package]] name = "encoding_rs" version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.4" +name = "enum-map" +version = "2.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" +checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9" dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", + "enum-map-derive", ] [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "enum-map-derive" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" dependencies = [ - "cc", - "libc", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "failure" -version = "0.1.8" +name = "equivalent" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" -dependencies = [ - "backtrace", - "failure_derive", -] +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] -name = "failure_derive" -version = "0.1.8" +name = "errno" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "synstructure", + "libc", + "windows-sys 0.61.2", ] [[package]] name = "fastrand" -version = "1.9.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] -name = "fastrand" -version = "2.0.1" +name = "fiat-crypto" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "filetime" @@ -817,21 +605,24 @@ version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", - "redox_syscall 0.3.5", - "windows-sys", + "redox_syscall", + "windows-sys 0.48.0", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + [[package]] name = "fixed-hash" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" dependencies = [ - "byteorder", - "rand 0.8.5", - "rustc-hex", "static_assertions", ] @@ -845,12 +636,27 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "fluent-uri" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17c704e9dbe1ddd863da1e6ff3567795087b1eb201ce80d8fa81162e1516500d" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "foreign-types" version = "0.3.2" @@ -885,11 +691,21 @@ dependencies = [ "winapi", ] +[[package]] +name = "fs4" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8640e34b88f7652208ce9e88b1a37a2ae95227d84abec377ccd3c5cfeb141ed4" +dependencies = [ + "rustix", + "windows-sys 0.59.0", +] + [[package]] name = "funty" -version = "1.1.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures-channel" @@ -906,27 +722,6 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" -[[package]] -name = "futures-io" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" - -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - [[package]] name = "futures-sink" version = "0.3.28" @@ -963,24 +758,38 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.16" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", - "wasi 0.9.0+wasi-snapshot-preview1", + "wasi", ] [[package]] name = "getrandom" -version = "0.2.10" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi 5.3.0", + "wasip2", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "r-efi 6.0.0", + "wasip2", + "wasip3", ] [[package]] @@ -991,17 +800,17 @@ checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "h2" -version = "0.3.21" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733" dependencies = [ + "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "futures-util", "http", - "indexmap 1.9.3", + "indexmap 2.14.0", "slab", "tokio", "tokio-util", @@ -1010,27 +819,24 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "ahash", + "foldhash", ] [[package]] name = "hashbrown" -version = "0.14.1" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "heck" @@ -1039,51 +845,56 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] -name = "hermit-abi" -version = "0.3.3" +name = "heck" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] -name = "hex" -version = "0.3.2" +name = "hermit-abi" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "home" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" dependencies = [ - "windows-sys", + "serde", ] [[package]] name = "http" -version = "0.2.9" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ "bytes", - "fnv", "itoa", ] [[package]] name = "http-body" -version = "0.4.5" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", + "futures-core", "http", + "http-body", "pin-project-lite", ] @@ -1093,47 +904,75 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - [[package]] name = "hyper" -version = "0.14.27" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" dependencies = [ "bytes", "futures-channel", - "futures-core", "futures-util", "h2", "http", "http-body", "httparse", - "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "smallvec", "tokio", - "tower-service", - "tracing", "want", ] +[[package]] +name = "hyper-rustls" +version = "0.27.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "tokio", + "tokio-rustls", + "tower-service", +] + [[package]] name = "hyper-tls" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", + "http-body-util", "hyper", + "hyper-util", "native-tls", "tokio", "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", ] [[package]] @@ -1159,6 +998,100 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" + +[[package]] +name = "icu_properties" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" + +[[package]] +name = "icu_provider" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.4.0" @@ -1170,23 +1103,24 @@ dependencies = [ ] [[package]] -name = "impl-codec" -version = "0.5.1" +name = "idna" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "161ebdfec3c8e3b52bf61c4f3550a1eea4f9579d10dc1b936f3171ebdcd6c443" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ - "parity-scale-codec", + "idna_adapter", + "smallvec", + "utf8_iter", ] [[package]] -name = "impl-trait-for-tuples" -version = "0.2.2" +name = "idna_adapter" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "icu_normalizer", + "icu_properties", ] [[package]] @@ -1197,25 +1131,19 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", + "serde", ] [[package]] name = "indexmap" -version = "2.0.2" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.14.1", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if 1.0.0", + "hashbrown 0.17.1", + "serde", + "serde_core", ] [[package]] @@ -1223,28 +1151,13 @@ name = "integration-tests" version = "1.0.0" dependencies = [ "anyhow", - "async-trait", - "borsh 0.10.3", - "maplit", - "near-sdk", - "near-units", - "pkg-config", + "approx", + "near-workspaces", + "serde", "serde_json", "tokio", "tracing", "tracing-subscriber", - "workspaces", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys", ] [[package]] @@ -1254,12 +1167,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" [[package]] -name = "is_executable" -version = "0.1.2" +name = "itertools" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d553b8abc8187beb7d663e34c065ac4570b273bc9511a50e940e99409c577" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ - "winapi", + "either", ] [[package]] @@ -1268,6 +1181,16 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + [[package]] name = "js-sys" version = "0.3.64" @@ -1278,7 +1201,58 @@ dependencies = [ ] [[package]] -name = "keccak" +name = "json-patch" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b1fb8864823fad91877e6caea0baca82e49e8db50f8e5c9f9a453e27d3330fc" +dependencies = [ + "jsonptr 0.4.7", + "serde", + "serde_json", + "thiserror 1.0.49", +] + +[[package]] +name = "json-patch" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7421438de105a0827e44fadd05377727847d717c80ce29a229f85fd04c427b72" +dependencies = [ + "jsonptr 0.7.1", + "serde", + "serde_json", + "thiserror 2.0.18", +] + +[[package]] +name = "json_comments" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dbbfed4e59ba9750e15ba154fdfd9329cee16ff3df539c2666b70f58cc32105" + +[[package]] +name = "jsonptr" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c6e529149475ca0b2820835d3dce8fcc41c6b943ca608d32f35b449255e4627" +dependencies = [ + "fluent-uri", + "serde", + "serde_json", +] + +[[package]] +name = "jsonptr" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5a3cc660ba5d72bce0b3bb295bf20847ccbb40fd423f3f05b61273672e561fe" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "keccak" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" @@ -1291,39 +1265,36 @@ 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.148" +name = "leb128fmt" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] -name = "libz-sys" -version = "1.1.12" +name = "libc" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] -name = "linux-raw-sys" -version = "0.4.8" +name = "litemap" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + +[[package]] +name = "litrs" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" [[package]] name = "lock_api" @@ -1333,40 +1304,29 @@ checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", + "serde", ] [[package]] name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "maplit" -version = "1.0.2" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "matchers" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ - "regex-automata 0.1.10", + "regex-automata 0.4.14", ] [[package]] name = "memchr" -version = "2.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "memory_units" -version = "0.4.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "mime" @@ -1390,8 +1350,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "wasi", + "windows-sys 0.48.0", ] [[package]] @@ -1414,422 +1374,411 @@ dependencies = [ [[package]] name = "near-abi" -version = "0.3.0" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "885db39b08518fa700b73fa2214e8adbbfba316ba82dd510f50519173eadaf73" +checksum = "2fe0c8cdaf8369d8c78f2577d95673007c7f256c85752a66672be5244e2681a6" dependencies = [ - "borsh 0.9.3", - "schemars", + "borsh", + "schemars 0.8.22", "semver", "serde", ] [[package]] -name = "near-account-id" -version = "0.14.0" +name = "near-abi-client" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d258582a1878e6db67400b0504a5099db85718d22c2e07f747fe1706ae7150" +checksum = "879ac02b2e8d6498294adce1de7a2424a5474b35a73e9262c851be39c89d7f92" dependencies = [ - "borsh 0.9.3", - "serde", + "anyhow", + "convert_case 0.5.0", + "near-abi-client-impl", + "near-abi-client-macros", + "prettyplease 0.1.25", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "near-abi-client-impl" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1139e8a6f60fd8ed1c53c700b67bcecbf6deb4b1f47bbe9a9d5eea760d8a8e91" +dependencies = [ + "anyhow", + "near-abi", + "near_schemafy_lib", + "proc-macro2", + "quote", + "schemars 0.8.22", + "serde_json", +] + +[[package]] +name = "near-abi-client-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebaf2aae80086b310bf96e657bbee0c599c3452afd35e72999f8d6764d6b1899" +dependencies = [ + "near-abi-client-impl", + "syn 1.0.109", ] [[package]] name = "near-account-id" -version = "0.15.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d924011380de759c3dc6fdbcda37a19a5c061f56dab69d28a34ecee765e23e4" +checksum = "702dbca982e748975658812c7be2ca53211f454137486f98f6cf768934e2cb29" dependencies = [ - "borsh 0.9.3", + "borsh", "serde", ] [[package]] name = "near-chain-configs" -version = "0.15.0" +version = "0.34.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1faf676a95bd1718b06e5957e01a9415fedf7900f32d94d5bcf70abd678b10a2" +checksum = "b49e9e2d173d526725d4055ac2af4fa18ba0e3cfd4a6c4c6439ac63a63ad9f41" dependencies = [ "anyhow", + "bytesize", "chrono", "derive_more", - "near-crypto 0.15.0", - "near-primitives 0.15.0", + "near-config-utils", + "near-crypto", + "near-parameters", + "near-primitives", + "near-time", "num-rational", + "parking_lot", "serde", "serde_json", - "sha2 0.10.8", + "sha2", "smart-default", + "time", "tracing", ] [[package]] -name = "near-crypto" -version = "0.14.0" +name = "near-config-utils" +version = "0.34.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e75673d69fd7365508f3d32483669fe45b03bfb34e4d9363e90adae9dfb416c" +checksum = "da2ba8f7129472fc147b867e904e4b8f398aa79f263f54dff6283c4860446ef8" dependencies = [ - "arrayref", - "blake2", - "borsh 0.9.3", - "bs58", - "c2-chacha", - "curve25519-dalek", - "derive_more", - "ed25519-dalek", - "near-account-id 0.14.0", - "once_cell", - "parity-secp256k1", - "primitive-types", - "rand 0.7.3", - "rand_core 0.5.1", - "serde", - "serde_json", - "subtle", - "thiserror", + "anyhow", + "json_comments", + "thiserror 2.0.18", + "tracing", ] [[package]] name = "near-crypto" -version = "0.15.0" +version = "0.34.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7754612b47737d277fb818e9fdbb1406e90f9e57151c55c3584d714421976cb6" +checksum = "7c12a12485f8baafa85d5c413885b795bfa1d7d0ab7fd49b4f7fbe6cd270325b" dependencies = [ - "arrayref", "blake2", - "borsh 0.9.3", - "bs58", - "c2-chacha", + "borsh", + "bs58 0.4.0", "curve25519-dalek", "derive_more", "ed25519-dalek", - "near-account-id 0.15.0", - "once_cell", + "hex", + "near-account-id", + "near-config-utils", + "near-schema-checker-lib", + "near-stdx", "primitive-types", - "rand 0.7.3", + "rand", "secp256k1", "serde", "serde_json", "subtle", - "thiserror", + "thiserror 2.0.18", +] + +[[package]] +name = "near-fmt" +version = "0.34.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31b6d8fb4146cf0a7dcadf7816bf7b8efd5c081d6d2ca524bc80815b5f86812" +dependencies = [ + "near-primitives-core", +] + +[[package]] +name = "near-gas" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "559c33c9c86e05da946358485fa6e7e881a09726f909fbd8bcf357f998d7d03d" +dependencies = [ + "borsh", + "schemars 0.8.22", + "serde", ] [[package]] name = "near-jsonrpc-client" -version = "0.4.1" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1335ffce1476da6516dcd22b26cece1a495fc725c0e8fec1879073752ac068d" +checksum = "94937febf6a8e8d0cfbf194007a426bed81f41d84665a5982fcb7b4e3b21eca6" dependencies = [ - "borsh 0.9.3", + "borsh", "lazy_static", "log", "near-chain-configs", - "near-crypto 0.15.0", + "near-crypto", "near-jsonrpc-primitives", - "near-primitives 0.15.0", + "near-primitives", "reqwest", "serde", "serde_json", - "thiserror", - "uuid", + "thiserror 2.0.18", ] [[package]] name = "near-jsonrpc-primitives" -version = "0.15.0" +version = "0.34.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ada226c74f05508c516f109a97b9f23335120d0bfda208f0d187b6bbfe6eef5a" +checksum = "b245e3de3c64e9c908167322abb4696d7c4e4c8315d715f167661000375af691" dependencies = [ + "arbitrary", "near-chain-configs", - "near-crypto 0.15.0", - "near-primitives 0.15.0", - "near-rpc-error-macro 0.15.0", + "near-crypto", + "near-primitives", + "near-schema-checker-lib", + "near-time", "serde", "serde_json", - "thiserror", + "thiserror 2.0.18", + "time", ] [[package]] -name = "near-primitives" -version = "0.14.0" +name = "near-parameters" +version = "0.34.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad1a9a1640539c81f065425c31bffcfbf6b31ef1aeaade59ce905f5df6ac860" +checksum = "e7a561606a8beb563bf166c8a9ceb7f97058b376d17ea1a9b4b65ebc9bff29ac" dependencies = [ - "borsh 0.9.3", - "byteorder", - "bytesize", - "chrono", - "derive_more", - "easy-ext", - "hex 0.4.3", - "near-crypto 0.14.0", - "near-primitives-core 0.14.0", - "near-rpc-error-macro 0.14.0", - "near-vm-errors 0.14.0", + "borsh", + "enum-map", + "near-account-id", + "near-primitives-core", + "near-schema-checker-lib", "num-rational", - "once_cell", - "primitive-types", - "rand 0.7.3", - "reed-solomon-erasure", "serde", - "serde_json", - "smart-default", + "serde_repr", + "serde_yaml", "strum", - "thiserror", + "thiserror 2.0.18", ] [[package]] name = "near-primitives" -version = "0.15.0" +version = "0.34.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97670b302dce15f09bba50f24c67aa08130fd01528cc61d4415892401e88e974" +checksum = "5ccddcf4a73e19afd681faaa7e83fc4046ec71f4bbe58c58ff4ae4432f36e3aa" dependencies = [ - "borsh 0.9.3", - "byteorder", + "arbitrary", + "base64 0.21.4", + "bitvec", + "borsh", + "bytes", "bytesize", - "cfg-if 1.0.0", "chrono", "derive_more", "easy-ext", - "hex 0.4.3", - "near-crypto 0.15.0", - "near-primitives-core 0.15.0", - "near-rpc-error-macro 0.15.0", - "near-vm-errors 0.15.0", + "enum-map", + "hex", + "itertools", + "near-crypto", + "near-fmt", + "near-parameters", + "near-primitives-core", + "near-schema-checker-lib", + "near-stdx", + "near-time", "num-rational", - "once_cell", + "ordered-float", "primitive-types", - "rand 0.7.3", - "reed-solomon-erasure", + "rand", + "rand_chacha", "serde", "serde_json", + "serde_with", + "sha3", + "smallvec", "smart-default", "strum", - "thiserror", -] - -[[package]] -name = "near-primitives-core" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d508f0fc340f6461e4e256417685720d3c4c00bb5a939b105160e49137caba" -dependencies = [ - "base64 0.11.0", - "borsh 0.9.3", - "bs58", - "derive_more", - "near-account-id 0.14.0", - "num-rational", - "serde", - "sha2 0.10.8", - "strum", + "thiserror 2.0.18", + "tracing", + "zstd", ] [[package]] name = "near-primitives-core" -version = "0.15.0" +version = "0.34.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7929e19d862221949734c4a0063a8f55e7069de3a2ebc2d4f4c13497a5e953cb" +checksum = "7c93d8c5d6aecfec0aa9d60ab34408c68b13d5c1bfc0f3afeee8c99fa521cdb3" dependencies = [ - "base64 0.13.1", - "borsh 0.9.3", - "bs58", + "arbitrary", + "base64 0.21.4", + "borsh", + "bs58 0.4.0", "derive_more", - "near-account-id 0.15.0", + "enum-map", + "near-account-id", + "near-gas", + "near-schema-checker-lib", + "near-token", "num-rational", "serde", "serde_repr", - "sha2 0.10.8", - "strum", + "serde_with", + "sha2", + "thiserror 2.0.18", ] [[package]] -name = "near-rpc-error-core" -version = "0.14.0" +name = "near-sandbox" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ee0b41c75ef859c193a8ff1dadfa0c8207bc0ac447cc22259721ad769a1408" +checksum = "ffb6493715a4b5d18f23abcb3d6438e466373aba66f25764516c4b32433e92e0" dependencies = [ - "quote", + "flate2", + "fs4", + "json-patch 4.2.0", + "libc", + "near-account-id", + "near-token", "serde", - "syn 1.0.109", + "serde_json", + "tar", + "tempfile", + "thiserror 2.0.18", + "tokio", + "tracing", + "ureq", ] [[package]] -name = "near-rpc-error-core" -version = "0.15.0" +name = "near-schema-checker-core" +version = "0.34.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36addf90cc04bd547a627b3a292f59d7de4dd6fb5042115419ae901b93ce6c2d" -dependencies = [ - "quote", - "serde", - "syn 1.0.109", -] +checksum = "f969a965d1ea04e1f085ee4d6c7273ae1064f578711087f3beaf8d400672cc7e" [[package]] -name = "near-rpc-error-macro" -version = "0.14.0" +name = "near-schema-checker-lib" +version = "0.34.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e837bd4bacd807073ec5ceb85708da7f721b46a4c2a978de86027fb0034ce31" +checksum = "e4ae7538880de8a8d75e150dd0f4f685211ddd654ab12a339f40458df6d191dd" dependencies = [ - "near-rpc-error-core 0.14.0", - "serde", - "syn 1.0.109", + "near-schema-checker-core", + "near-schema-checker-macro", ] [[package]] -name = "near-rpc-error-macro" -version = "0.15.0" +name = "near-schema-checker-macro" +version = "0.34.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5beb352f3b91d8c491646c2fa4fdbbbf463c7b9c0226951c28f0197de44f99" -dependencies = [ - "near-rpc-error-core 0.15.0", - "serde", - "syn 1.0.109", -] +checksum = "8a9eb7d4dc413fe39ffa7fe5591ed4c24bc8139b9de8497689178d0101ae5167" [[package]] -name = "near-sandbox-utils" -version = "0.6.2" +name = "near-stdx" +version = "0.34.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7479b0a2c52890000d410c6e4ba4f851334280530fa7446b78bcaf4683fe69b0" -dependencies = [ - "anyhow", - "async-process", - "binary-install", - "chrono", - "fs2", - "hex 0.3.2", - "home", -] +checksum = "2c5dc0456309fcb256a0609d829971fd99f343e1a7f3b72f85364e64250a4555" [[package]] -name = "near-sdk" -version = "4.1.1" +name = "near-time" +version = "0.34.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15eb3de2defe3626260cc209a6cdb985c6b27b0bd4619fad97dcfae002c3c5bd" +checksum = "de9ae070cbd84d16b948fcc335ea82db35919bf856e349f333143ff2894eeafd" dependencies = [ - "base64 0.13.1", - "borsh 0.9.3", - "bs58", - "near-abi", - "near-crypto 0.14.0", - "near-primitives 0.14.0", - "near-primitives-core 0.14.0", - "near-sdk-macros", - "near-sys", - "near-vm-logic", - "once_cell", - "schemars", + "parking_lot", "serde", - "serde_json", - "wee_alloc", -] - -[[package]] -name = "near-sdk-macros" -version = "4.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4907affc9f5ed559456509188ff0024f1f2099c0830e6bdb66eb61d5b75912c0" -dependencies = [ - "Inflector", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "near-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e307313276eaeced2ca95740b5639e1f3125b7c97f0a1151809d105f1aa8c6d3" - -[[package]] -name = "near-units" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a2b77f295d398589eeee51ad0887905ef1734fb12b45cb6d77bd7e401988b9" -dependencies = [ - "near-units-core", - "near-units-macro", -] - -[[package]] -name = "near-units-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89aa2a7985de87a08ca35f28abd8d00f0f901e704257e6e029aadef981386bc6" -dependencies = [ - "num-format", - "regex", + "time", ] [[package]] -name = "near-units-macro" -version = "0.2.0" +name = "near-token" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ab45d066220846f9bd5c21e9ab88c47c892edd36f962ada78bf8308523171a" +checksum = "2a8000d5859172ce4cd29d51ae1af18a80571939f2975ffcae2c00d241ef4507" dependencies = [ - "near-units-core", - "proc-macro2", - "quote", - "syn 1.0.109", + "borsh", + "serde", ] [[package]] -name = "near-vm-errors" -version = "0.14.0" +name = "near-workspaces" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0da466a30f0446639cbd788c30865086fac3e8dcb07a79e51d2b0775ed4261e" +checksum = "1052c6f22494d9fbfb671a8efbc4f4c3a1fed0c8cac07336c97680c6088fca63" dependencies = [ - "borsh 0.9.3", - "near-account-id 0.14.0", - "near-rpc-error-macro 0.14.0", + "async-trait", + "base64 0.22.1", + "bs58 0.5.1", + "chrono", + "fs2", + "json-patch 2.0.0", + "libc", + "near-abi-client", + "near-account-id", + "near-crypto", + "near-gas", + "near-jsonrpc-client", + "near-jsonrpc-primitives", + "near-primitives", + "near-sandbox", + "near-token", + "rand", + "reqwest", "serde", + "serde_json", + "sha2", + "tempfile", + "thiserror 1.0.49", + "tokio", + "tokio-retry", + "tracing", + "url", ] [[package]] -name = "near-vm-errors" -version = "0.15.0" +name = "near_schemafy_core" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5591c9c8afa83a040cb5c3f29bc52b2efae2c32d4bcaee1bba723738da1a5cf6" +checksum = "42d7a1f809a319578773329389529dbf8c8f0abfbb05a429b37f437105f7caf6" dependencies = [ - "borsh 0.9.3", - "near-account-id 0.15.0", - "near-rpc-error-macro 0.15.0", "serde", - "strum", + "serde_json", ] [[package]] -name = "near-vm-logic" -version = "0.14.0" +name = "near_schemafy_lib" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b534828419bacbf1f7b11ef7b00420f248c548c485d3f0cfda8bb6931152f2" +checksum = "c39ccae55df51adaa1a4e567b7a79ab4380826a695121cebf41f518076d8c3dd" dependencies = [ - "base64 0.13.1", - "borsh 0.9.3", - "bs58", - "byteorder", - "near-account-id 0.14.0", - "near-crypto 0.14.0", - "near-primitives 0.14.0", - "near-primitives-core 0.14.0", - "near-vm-errors 0.14.0", - "ripemd", + "Inflector", + "near_schemafy_core", + "proc-macro2", + "quote", "serde", - "sha2 0.10.8", - "sha3", - "zeropool-bn", + "serde_derive", + "serde_json", + "syn 1.0.109", + "uriparse", ] [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "overload", - "winapi", + "windows-sys 0.61.2", ] [[package]] @@ -1844,14 +1793,10 @@ dependencies = [ ] [[package]] -name = "num-format" -version = "0.4.4" +name = "num-conv" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" -dependencies = [ - "arrayvec 0.7.4", - "itoa", -] +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" [[package]] name = "num-integer" @@ -1906,15 +1851,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "opaque-debug" -version = "0.3.0" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "openssl" @@ -1922,8 +1861,8 @@ version = "0.10.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" dependencies = [ - "bitflags 2.4.0", - "cfg-if 1.0.0", + "bitflags 2.11.1", + "cfg-if", "foreign-types", "libc", "once_cell", @@ -1939,7 +1878,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.117", ] [[package]] @@ -1961,55 +1900,17 @@ dependencies = [ ] [[package]] -name = "overload" -version = "0.1.1" +name = "ordered-float" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "parity-scale-codec" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373b1a4c1338d9cd3d1fa53b3a11bdab5ab6bd80a20f7f7becd76953ae2be909" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" dependencies = [ - "arrayvec 0.7.4", - "bitvec", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive", + "borsh", + "num-traits", + "rand", "serde", ] -[[package]] -name = "parity-scale-codec-derive" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "parity-secp256k1" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fca4f82fccae37e8bbdaeb949a4a218a1bbc485d11598f193d2a908042e5fc1" -dependencies = [ - "arrayvec 0.5.2", - "cc", - "cfg-if 0.1.10", - "rand 0.7.3", -] - -[[package]] -name = "parking" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e52c774a4c39359c1d1c52e43f73dd91a75a614652c825408eec30c95a9b2067" - [[package]] name = "parking_lot" version = "0.12.1" @@ -2026,18 +1927,18 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pin-project" @@ -2056,7 +1957,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.117", ] [[package]] @@ -2072,52 +1973,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] -name = "piper" -version = "0.2.1" +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "potential_utf" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ - "atomic-waker", - "fastrand 2.0.1", - "futures-io", + "zerovec", ] [[package]] -name = "pkg-config" -version = "0.3.27" +name = "powerfmt" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] -name = "polling" -version = "2.8.0" +name = "ppv-lite86" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if 1.0.0", - "concurrent-queue", - "libc", - "log", - "pin-project-lite", - "windows-sys", -] +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] -name = "portpicker" -version = "0.1.1" +name = "prettyplease" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be97d76faf1bfab666e1375477b23fde79eccf0276e9b63b92a39d676a889ba9" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" dependencies = [ - "rand 0.8.5", + "proc-macro2", + "syn 1.0.109", ] [[package]] -name = "ppv-lite86" -version = "0.2.17" +name = "prettyplease" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.117", +] [[package]] name = "primitive-types" @@ -2126,65 +2026,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" dependencies = [ "fixed-hash", - "impl-codec", "uint", ] [[package]] name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml", -] - -[[package]] -name = "proc-macro-crate" -version = "1.3.1" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "once_cell", "toml_edit", ] [[package]] name = "proc-macro2" -version = "1.0.67" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] [[package]] -name = "radium" -version = "0.6.2" +name = "r-efi" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] -name = "rand" -version = "0.7.3" +name = "r-efi" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand" @@ -2193,18 +2081,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", + "rand_chacha", + "rand_core", + "serde", ] [[package]] @@ -2214,16 +2093,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", + "rand_core", ] [[package]] @@ -2233,30 +2103,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom 0.2.10", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "redox_syscall" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" - -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", + "serde", ] [[package]] @@ -2269,34 +2116,23 @@ dependencies = [ ] [[package]] -name = "redox_users" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" -dependencies = [ - "getrandom 0.1.16", - "redox_syscall 0.1.57", - "rust-argon2", -] - -[[package]] -name = "redox_users" -version = "0.4.3" +name = "ref-cast" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" dependencies = [ - "getrandom 0.2.10", - "redox_syscall 0.2.16", - "thiserror", + "ref-cast-impl", ] [[package]] -name = "reed-solomon-erasure" -version = "4.0.2" +name = "ref-cast-impl" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a415a013dd7c5d4221382329a5a3482566da675737494935cbbbcdec04662f9d" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ - "smallvec", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] @@ -2313,43 +2149,45 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.1.10" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" dependencies = [ - "regex-syntax 0.6.29", + "aho-corasick", + "memchr", + "regex-syntax 0.7.5", ] [[package]] name = "regex-automata" -version = "0.3.9" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.5", + "regex-syntax 0.8.10", ] [[package]] name = "regex-syntax" -version = "0.6.29" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "regex-syntax" -version = "0.7.5" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reqwest" -version = "0.11.20" +version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" dependencies = [ - "base64 0.21.4", + "base64 0.22.1", "bytes", "encoding_rs", "futures-core", @@ -2357,8 +2195,11 @@ dependencies = [ "h2", "http", "http-body", + "http-body-util", "hyper", + "hyper-rustls", "hyper-tls", + "hyper-util", "ipnet", "js-sys", "log", @@ -2367,9 +2208,12 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", + "system-configuration", "tokio", "tokio-native-tls", "tower-service", @@ -2377,28 +2221,21 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg", -] - -[[package]] -name = "ripemd" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" -dependencies = [ - "digest 0.10.7", + "windows-registry", ] [[package]] -name = "rust-argon2" -version = "0.8.3" +name = "ring" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ - "base64 0.13.1", - "blake2b_simd", - "constant_time_eq", - "crossbeam-utils", + "cc", + "cfg-if", + "getrandom 0.2.10", + "libc", + "untrusted", + "windows-sys 0.52.0", ] [[package]] @@ -2407,12 +2244,6 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - [[package]] name = "rustc_version" version = "0.4.0" @@ -2424,29 +2255,59 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.24" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4279d76516df406a8bd37e7dff53fd37d1a093f997a3c34a5c21658c126db06d" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.11.1", "errno", - "io-lifetimes", "libc", - "linux-raw-sys 0.3.8", - "windows-sys", + "linux-raw-sys", + "windows-sys 0.61.2", ] [[package]] -name = "rustix" -version = "0.38.15" +name = "rustls" +version = "0.23.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f9da0cbd88f9f09e7814e388301c8414c51c62aa6ce1e4b5c551d49d96e531" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" dependencies = [ - "bitflags 2.4.0", - "errno", - "libc", - "linux-raw-sys 0.4.8", - "windows-sys", + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", ] [[package]] @@ -2467,14 +2328,14 @@ version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "schemars" -version = "0.8.15" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f7b0ce13155372a76ee2e1c5ffba1fe61ede73fbea5630d61eee6fac4929c0c" +checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" dependencies = [ "dyn-clone", "schemars_derive", @@ -2482,16 +2343,40 @@ dependencies = [ "serde_json", ] +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1375ba8ef45a6f15d83fa8748f1079428295d403d6ea991d09ab100155fbc06d" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + [[package]] name = "schemars_derive" -version = "0.8.15" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e85e2a16b12bdb763244c69ab79363d71db2b4b918a2def53f80b02e0574b13c" +checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 1.0.109", + "syn 2.0.117", ] [[package]] @@ -2502,19 +2387,19 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "secp256k1" -version = "0.24.3" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" dependencies = [ - "rand 0.8.5", + "rand", "secp256k1-sys", ] [[package]] name = "secp256k1-sys" -version = "0.6.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" +checksum = "4473013577ec77b4ee3668179ef1186df3146e2cf2d927bd200974c6fe60fd99" dependencies = [ "cc", ] @@ -2550,44 +2435,56 @@ checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" [[package]] name = "serde" -version = "1.0.188" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.117", ] [[package]] name = "serde_derive_internals" -version = "0.26.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.117", ] [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", - "ryu", + "memchr", "serde", + "serde_core", + "zmij", ] [[package]] @@ -2598,7 +2495,7 @@ checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.117", ] [[package]] @@ -2614,16 +2511,48 @@ dependencies = [ ] [[package]] -name = "sha2" -version = "0.9.9" +name = "serde_with" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +checksum = "e72c1c2cb7b223fafb600a619537a871c2818583d619401b785e7c0b746ccde2" dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", + "base64 0.22.1", + "bs58 0.5.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.14.0", + "schemars 0.9.0", + "schemars 1.0.3", + "serde_core", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90c488738ecb4fb0262f41f43bc40efc5868d9fb744319ddf5f5317f417bfac" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap 2.14.0", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", ] [[package]] @@ -2632,9 +2561,9 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] @@ -2643,28 +2572,24 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "digest 0.10.7", + "digest", "keccak", ] [[package]] name = "sharded-slab" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b21f559e07218024e7e9f90f96f601825397de0e25420135f7f952453fed0b" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] [[package]] -name = "signal-hook" -version = "0.3.17" +name = "shlex" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" -dependencies = [ - "libc", - "signal-hook-registry", -] +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" @@ -2677,15 +2602,9 @@ dependencies = [ [[package]] name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" - -[[package]] -name = "siphasher" -version = "0.2.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" [[package]] name = "slab" @@ -2698,29 +2617,19 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "smart-default" -version = "0.6.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6" +checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", -] - -[[package]] -name = "socket2" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" -dependencies = [ - "libc", - "winapi", + "syn 2.0.117", ] [[package]] @@ -2730,14 +2639,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] -name = "spin" -version = "0.5.2" +name = "stable_deref_trait" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" @@ -2745,6 +2654,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "strum" version = "0.24.1" @@ -2760,7 +2675,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", @@ -2786,9 +2701,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.37" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -2796,19 +2711,48 @@ dependencies = [ ] [[package]] -name = "synstructure" -version = "0.12.6" +name = "sync_wrapper" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "unicode-xid", + "futures-core", ] [[package]] -name = "tap" +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.11.1", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tap" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" @@ -2821,20 +2765,19 @@ checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" dependencies = [ "filetime", "libc", - "xattr", ] [[package]] name = "tempfile" -version = "3.8.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ - "cfg-if 1.0.0", - "fastrand 2.0.1", - "redox_syscall 0.3.5", - "rustix 0.38.15", - "windows-sys", + "fastrand", + "getrandom 0.4.2", + "once_cell", + "rustix", + "windows-sys 0.61.2", ] [[package]] @@ -2843,7 +2786,16 @@ version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.49", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", ] [[package]] @@ -2854,28 +2806,68 @@ checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.117", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ - "cfg-if 1.0.0", - "once_cell", + "cfg-if", ] [[package]] name = "time" -version = "0.1.45" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", ] [[package]] @@ -2907,9 +2899,9 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.4", + "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -2920,7 +2912,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.117", ] [[package]] @@ -2940,7 +2932,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f" dependencies = [ "pin-project", - "rand 0.8.5", + "rand", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", "tokio", ] @@ -2959,31 +2961,56 @@ dependencies = [ ] [[package]] -name = "toml" -version = "0.5.11" +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" dependencies = [ - "serde", + "serde_core", ] [[package]] -name = "toml_datetime" -version = "0.6.3" +name = "toml_edit" +version = "0.25.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" +dependencies = [ + "indexmap 2.14.0", + "toml_datetime", + "toml_parser", + "winnow", +] [[package]] -name = "toml_edit" -version = "0.19.15" +name = "toml_parser" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "indexmap 2.0.2", - "toml_datetime", "winnow", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + [[package]] name = "tower-service" version = "0.3.2" @@ -2992,11 +3019,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ - "cfg-if 1.0.0", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -3004,20 +3030,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.117", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -3025,25 +3051,25 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "matchers", "nu-ansi-term", "once_cell", - "regex", + "regex-automata 0.4.14", "sharded-slab", "smallvec", "thread_local", @@ -3072,7 +3098,7 @@ checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" dependencies = [ "byteorder", "crunchy", - "hex 0.4.3", + "hex", "static_assertions", ] @@ -3097,12 +3123,71 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" + [[package]] name = "unicode-xid" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "ureq" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea7109cdcd5864d4eeb1b58a1648dc9bf520360d7af16ec26d0a9354bafcfc0" +dependencies = [ + "base64 0.22.1", + "cookie_store", + "log", + "percent-encoding", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "ureq-proto", + "utf8-zero", + "webpki-roots", +] + +[[package]] +name = "ureq-proto" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e994ba84b0bd1b1b0cf92878b7ef898a5c1760108fe7b6010327e274917a808c" +dependencies = [ + "base64 0.22.1", + "http", + "httparse", + "log", +] + +[[package]] +name = "uriparse" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0200d0fc04d809396c2ad43f3c95da3582a2556eba8d453c1087f4120ee352ff" +dependencies = [ + "fnv", + "lazy_static", +] + [[package]] name = "url" version = "2.4.1" @@ -3110,25 +3195,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" dependencies = [ "form_urlencoded", - "idna", + "idna 0.4.0", "percent-encoding", "serde", ] [[package]] -name = "uuid" -version = "1.4.1" +name = "utf8-zero" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" -dependencies = [ - "getrandom 0.2.10", -] +checksum = "b8c0a043c9540bae7c578c88f91dda8bd82e59ae27c21baca69c8b191aaf5a6e" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "valuable" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "vcpkg" @@ -3142,12 +3230,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "waker-fn" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" - [[package]] name = "want" version = "0.3.1" @@ -3159,44 +3241,38 @@ dependencies = [ [[package]] name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +name = "wasip2" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +dependencies = [ + "wit-bindgen 0.57.1", +] [[package]] -name = "wasm-bindgen" -version = "0.2.87" +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "cfg-if 1.0.0", - "wasm-bindgen-macro", + "wit-bindgen 0.51.0", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.87" +name = "wasm-bindgen" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" dependencies = [ - "bumpalo", - "log", + "cfg-if", "once_cell", - "proc-macro2", - "quote", - "syn 2.0.37", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] @@ -3206,7 +3282,7 @@ version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", @@ -3214,9 +3290,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3224,22 +3300,59 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.37", - "wasm-bindgen-backend", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.14.0", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.1", + "hashbrown 0.15.5", + "indexmap 2.14.0", + "semver", +] [[package]] name = "web-sys" @@ -3252,15 +3365,12 @@ dependencies = [ ] [[package]] -name = "wee_alloc" -version = "0.4.5" +name = "webpki-roots" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" dependencies = [ - "cfg-if 0.1.10", - "libc", - "memory_units", - "winapi", + "rustls-pki-types", ] [[package]] @@ -3291,7 +3401,43 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", ] [[package]] @@ -3300,7 +3446,34 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", ] [[package]] @@ -3309,13 +3482,29 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -3324,153 +3513,321 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + [[package]] name = "winnow" -version = "0.5.15" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" dependencies = [ "memchr", ] [[package]] -name = "winreg" -version = "0.50.0" +name = "wit-bindgen" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" dependencies = [ - "cfg-if 1.0.0", - "windows-sys", + "wit-bindgen-rust-macro", ] [[package]] -name = "workspaces" -version = "0.7.0" +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b13d249618f197811e3673decc81459730cf5cc09ee7246dc4bede1e9333bc" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" dependencies = [ - "async-process", - "async-trait", - "base64 0.13.1", - "borsh 0.9.3", - "bs58", - "chrono", - "dirs 3.0.2", - "hex 0.4.3", - "libc", - "near-account-id 0.15.0", - "near-crypto 0.15.0", - "near-jsonrpc-client", - "near-jsonrpc-primitives", - "near-primitives 0.15.0", - "near-sandbox-utils", - "portpicker", - "rand 0.8.5", - "reqwest", + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.14.0", + "prettyplease 0.2.37", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease 0.2.37", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.1", + "indexmap 2.14.0", + "log", "serde", + "serde_derive", "serde_json", - "thiserror", - "tokio", - "tokio-retry", - "tracing", - "url", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.14.0", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", ] +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" + [[package]] name = "wyz" -version = "0.2.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] [[package]] -name = "xattr" -version = "1.0.1" +name = "yoke" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" dependencies = [ - "libc", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", ] [[package]] name = "zeroize" -version = "1.3.0" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zerotrie" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ - "zeroize_derive", + "displaydoc", + "yoke", + "zerofrom", ] [[package]] -name = "zeroize_derive" -version = "1.4.2" +name = "zerovec" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.117", ] [[package]] -name = "zeropool-bn" -version = "0.5.11" +name = "zmij" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e61de68ede9ffdd69c01664f65a178c5188b73f78faa21f0936016a888ff7c" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" dependencies = [ - "borsh 0.9.3", - "byteorder", - "crunchy", - "lazy_static", - "rand 0.8.5", - "rustc-hex", + "zstd-safe", ] [[package]] -name = "zip" -version = "0.5.13" +name = "zstd-safe" +version = "7.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ab48844d61251bb3835145c521d88aa4031d7139e8485990f60ca911fa0815" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" dependencies = [ - "byteorder", - "bzip2", - "crc32fast", - "flate2", - "thiserror", - "time", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.16+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +dependencies = [ + "cc", + "pkg-config", ] diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index eb0b457..86e1e6b 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -4,25 +4,14 @@ version = "1.0.0" publish = false edition = "2021" -[lib] -name = "integration_tests" - [dev-dependencies] -near-workspaces = { workspace = true } -near-sdk = { workspace = true } -near-contract-standards = { workspace = true } -anyhow = { workspace = true } -tokio = { workspace = true } - -near-units = { workspace = true } -borsh = "0.10.3" -maplit = "1.0" -tracing = "0.1.37" -tracing-subscriber = { version = "0.3.11", features = ["env-filter"] } -pkg-config = "0.3.1" - -[dependencies] -async-trait = "0.1.73" +near-workspaces = "0.22.1" +anyhow = "1.0" +tokio = { version = "1", features = ["macros", "rt-multi-thread"] } +serde = { version = "1", features = ["derive"] } +serde_json = "1" +tracing = "0.1" +tracing-subscriber = { version = "0.3", features = ["env-filter"] } +approx = "0.5" -sweat-model = { workspace = true, features = ["integration-test"] } -integration-utils = { workspace = true } +[workspace] diff --git a/integration-tests/data/formula_cases.json b/integration-tests/data/formula_cases.json new file mode 100644 index 0000000..0d9317d --- /dev/null +++ b/integration-tests/data/formula_cases.json @@ -0,0 +1,146 @@ +[ + {"steps_since_tge": "1", "steps": 1, "expected": 0.000999999999999307}, + {"steps_since_tge": "1", "steps": 10, "expected": 0.009999999999972283}, + {"steps_since_tge": "1", "steps": 100, "expected": 0.09999999999764402}, + {"steps_since_tge": "1", "steps": 1000, "expected": 0.9999999997685598}, + {"steps_since_tge": "1", "steps": 10000, "expected": 9.999999976897554}, + {"steps_since_tge": "1", "steps": 100000, "expected": 99.9999976901712}, + {"steps_since_tge": "1", "steps": 1000000, "expected": 999.9997690212772}, + {"steps_since_tge": "1", "steps": 10000000, "expected": 9999.976902169294}, + {"steps_since_tge": "1", "steps": 100000000, "expected": 99997.69021734511}, + {"steps_since_tge": "10", "steps": 1, "expected": 0.0009999999999951495}, + {"steps_since_tge": "10", "steps": 10, "expected": 0.009999999999930707}, + {"steps_since_tge": "10", "steps": 100, "expected": 0.09999999999722826}, + {"steps_since_tge": "10", "steps": 1000, "expected": 0.9999999997644021}, + {"steps_since_tge": "10", "steps": 10000, "expected": 9.999999976855978}, + {"steps_since_tge": "10", "steps": 100000, "expected": 99.99999768975543}, + {"steps_since_tge": "10", "steps": 1000000, "expected": 999.9997690171195}, + {"steps_since_tge": "10", "steps": 10000000, "expected": 9999.976902127717}, + {"steps_since_tge": "10", "steps": 100000000, "expected": 99997.69021692935}, + {"steps_since_tge": "100", "steps": 1, "expected": 0.0009999999999535734}, + {"steps_since_tge": "100", "steps": 10, "expected": 0.009999999999514946}, + {"steps_since_tge": "100", "steps": 100, "expected": 0.09999999999307065}, + {"steps_since_tge": "100", "steps": 1000, "expected": 0.999999999722826}, + {"steps_since_tge": "100", "steps": 10000, "expected": 9.999999976440217}, + {"steps_since_tge": "100", "steps": 100000, "expected": 99.99999768559782}, + {"steps_since_tge": "100", "steps": 1000000, "expected": 999.9997689755435}, + {"steps_since_tge": "100", "steps": 10000000, "expected": 9999.976901711956}, + {"steps_since_tge": "100", "steps": 100000000, "expected": 99997.69021277173}, + {"steps_since_tge": "1000", "steps": 1, "expected": 0.0009999999995378124}, + {"steps_since_tge": "1000", "steps": 10, "expected": 0.009999999995357337}, + {"steps_since_tge": "1000", "steps": 100, "expected": 0.09999999995149457}, + {"steps_since_tge": "1000", "steps": 1000, "expected": 0.9999999993070652}, + {"steps_since_tge": "1000", "steps": 10000, "expected": 9.999999972282609}, + {"steps_since_tge": "1000", "steps": 100000, "expected": 99.99999764402173}, + {"steps_since_tge": "1000", "steps": 1000000, "expected": 999.9997685597826}, + {"steps_since_tge": "1000", "steps": 10000000, "expected": 9999.976897554348}, + {"steps_since_tge": "1000", "steps": 100000000, "expected": 99997.69017119565}, + {"steps_since_tge": "10000", "steps": 1, "expected": 0.0009999999953802037}, + {"steps_since_tge": "10000", "steps": 10, "expected": 0.00999999995378125}, + {"steps_since_tge": "10000", "steps": 100, "expected": 0.0999999995357337}, + {"steps_since_tge": "10000", "steps": 1000, "expected": 0.9999999951494565}, + {"steps_since_tge": "10000", "steps": 10000, "expected": 9.999999930706522}, + {"steps_since_tge": "10000", "steps": 100000, "expected": 99.99999722826087}, + {"steps_since_tge": "10000", "steps": 1000000, "expected": 999.9997644021739}, + {"steps_since_tge": "10000", "steps": 10000000, "expected": 9999.97685597826}, + {"steps_since_tge": "10000", "steps": 100000000, "expected": 99997.68975543478}, + {"steps_since_tge": "100000", "steps": 1, "expected": 0.0009999999538041167}, + {"steps_since_tge": "100000", "steps": 10, "expected": 0.00999999953802038}, + {"steps_since_tge": "100000", "steps": 100, "expected": 0.099999995378125}, + {"steps_since_tge": "100000", "steps": 1000, "expected": 0.9999999535733696}, + {"steps_since_tge": "100000", "steps": 10000, "expected": 9.999999514945651}, + {"steps_since_tge": "100000", "steps": 100000, "expected": 99.99999307065218}, + {"steps_since_tge": "100000", "steps": 1000000, "expected": 999.999722826087}, + {"steps_since_tge": "100000", "steps": 10000000, "expected": 9999.976440217391}, + {"steps_since_tge": "100000", "steps": 100000000, "expected": 99997.68559782609}, + {"steps_since_tge": "1000000", "steps": 1, "expected": 0.0009999995380432472}, + {"steps_since_tge": "1000000", "steps": 10, "expected": 0.009999995380411684}, + {"steps_since_tge": "1000000", "steps": 100, "expected": 0.09999995380203805}, + {"steps_since_tge": "1000000", "steps": 1000, "expected": 0.9999995378125}, + {"steps_since_tge": "1000000", "steps": 10000, "expected": 9.999995357336957}, + {"steps_since_tge": "1000000", "steps": 100000, "expected": 99.99995149456522}, + {"steps_since_tge": "1000000", "steps": 1000000, "expected": 999.9993070652174}, + {"steps_since_tge": "1000000", "steps": 10000000, "expected": 9999.972282608696}, + {"steps_since_tge": "1000000", "steps": 100000000, "expected": 99997.64402173914}, + {"steps_since_tge": "10000000", "steps": 1, "expected": 0.0009999953804345515}, + {"steps_since_tge": "10000000", "steps": 10, "expected": 0.009999953804324729}, + {"steps_since_tge": "10000000", "steps": 100, "expected": 0.09999953804116848}, + {"steps_since_tge": "10000000", "steps": 1000, "expected": 0.9999953802038043}, + {"steps_since_tge": "10000000", "steps": 10000, "expected": 9.99995378125}, + {"steps_since_tge": "10000000", "steps": 100000, "expected": 99.99953573369565}, + {"steps_since_tge": "10000000", "steps": 1000000, "expected": 999.9951494565217}, + {"steps_since_tge": "10000000", "steps": 10000000, "expected": 9999.93070652174}, + {"steps_since_tge": "10000000", "steps": 100000000, "expected": 99997.22826086957}, + {"steps_since_tge": "100000000", "steps": 1, "expected": 0.000999953804347595}, + {"steps_since_tge": "100000000", "steps": 10, "expected": 0.009999538043455164}, + {"steps_since_tge": "100000000", "steps": 100, "expected": 0.09999538043247283}, + {"steps_since_tge": "100000000", "steps": 1000, "expected": 0.9999538041168479}, + {"steps_since_tge": "100000000", "steps": 10000, "expected": 9.999538020380434}, + {"steps_since_tge": "100000000", "steps": 100000, "expected": 99.995378125}, + {"steps_since_tge": "100000000", "steps": 1000000, "expected": 999.9535733695652}, + {"steps_since_tge": "100000000", "steps": 10000000, "expected": 9999.514945652174}, + {"steps_since_tge": "100000000", "steps": 100000000, "expected": 99993.07065217392}, + {"steps_since_tge": "1000000000", "steps": 1, "expected": 0.0009995380434780299}, + {"steps_since_tge": "1000000000", "steps": 10, "expected": 0.009995380434759511}, + {"steps_since_tge": "1000000000", "steps": 100, "expected": 0.0999538043455163}, + {"steps_since_tge": "1000000000", "steps": 1000, "expected": 0.9995380432472826}, + {"steps_since_tge": "1000000000", "steps": 10000, "expected": 9.995380411684783}, + {"steps_since_tge": "1000000000", "steps": 100000, "expected": 99.95380203804348}, + {"steps_since_tge": "1000000000", "steps": 1000000, "expected": 999.5378125}, + {"steps_since_tge": "1000000000", "steps": 10000000, "expected": 9995.357336956522}, + {"steps_since_tge": "1000000000", "steps": 100000000, "expected": 99951.49456521739}, + {"steps_since_tge": "10000000000", "steps": 1, "expected": 0.0009953804347823778}, + {"steps_since_tge": "10000000000", "steps": 10, "expected": 0.00995380434780299}, + {"steps_since_tge": "10000000000", "steps": 100, "expected": 0.09953804347595109}, + {"steps_since_tge": "10000000000", "steps": 1000, "expected": 0.9953804345516304}, + {"steps_since_tge": "10000000000", "steps": 10000, "expected": 9.95380432472826}, + {"steps_since_tge": "10000000000", "steps": 100000, "expected": 99.53804116847826}, + {"steps_since_tge": "10000000000", "steps": 1000000, "expected": 995.3802038043478}, + {"steps_since_tge": "10000000000", "steps": 10000000, "expected": 9953.78125}, + {"steps_since_tge": "10000000000", "steps": 100000000, "expected": 99535.73369565218}, + {"steps_since_tge": "100000000000", "steps": 1, "expected": 0.0009538043478258559}, + {"steps_since_tge": "100000000000", "steps": 10, "expected": 0.009538043478237772}, + {"steps_since_tge": "100000000000", "steps": 100, "expected": 0.09538043478029891}, + {"steps_since_tge": "100000000000", "steps": 1000, "expected": 0.9538043475951087}, + {"steps_since_tge": "100000000000", "steps": 10000, "expected": 9.538043455163043}, + {"steps_since_tge": "100000000000", "steps": 100000, "expected": 95.38043247282609}, + {"steps_since_tge": "100000000000", "steps": 1000000, "expected": 953.8041168478261}, + {"steps_since_tge": "100000000000", "steps": 10000000, "expected": 9538.020380434782}, + {"steps_since_tge": "100000000000", "steps": 100000000, "expected": 95378.125}, + {"steps_since_tge": "1000000000000", "steps": 1, "expected": 0.0005380434782607852}, + {"steps_since_tge": "1000000000000", "steps": 10, "expected": 0.005380434782600264}, + {"steps_since_tge": "1000000000000", "steps": 100, "expected": 0.05380434782524375}, + {"steps_since_tge": "1000000000000", "steps": 1000, "expected": 0.5380434781765493}, + {"steps_since_tge": "1000000000000", "steps": 10000, "expected": 5.380434774176671}, + {"steps_since_tge": "1000000000000", "steps": 100000, "expected": 53.80434698288449}, + {"steps_since_tge": "1000000000000", "steps": 1000000, "expected": 538.043393940623}, + {"steps_since_tge": "1000000000000", "steps": 10000000, "expected": 5380.426350584036}, + {"steps_since_tge": "1000000000000", "steps": 100000000, "expected": 53803.504623621026}, + {"steps_since_tge": "10000000000000", "steps": 1, "expected": 0.00010531914893616589}, + {"steps_since_tge": "10000000000000", "steps": 10, "expected": 0.0010531914893612702}, + {"steps_since_tge": "10000000000000", "steps": 100, "expected": 0.010531914893573824}, + {"steps_since_tge": "10000000000000", "steps": 1000, "expected": 0.10531914893185049}, + {"steps_since_tge": "10000000000000", "steps": 10000, "expected": 1.0531914889297291}, + {"steps_since_tge": "10000000000000", "steps": 100000, "expected": 10.531914850419714}, + {"steps_since_tge": "10000000000000", "steps": 1000000, "expected": 105.31914461643949}, + {"steps_since_tge": "10000000000000", "steps": 10000000, "expected": 1053.1910573886303}, + {"steps_since_tge": "10000000000000", "steps": 100000000, "expected": 10531.87169630984}, + {"steps_since_tge": "100000000000000", "steps": 1, "expected": 1.1647058823529354e-05}, + {"steps_since_tge": "100000000000000", "steps": 10, "expected": 0.00011647058823528842}, + {"steps_since_tge": "100000000000000", "steps": 100, "expected": 0.0011647058823523713}, + {"steps_since_tge": "100000000000000", "steps": 1000, "expected": 0.011647058823472424}, + {"steps_since_tge": "100000000000000", "steps": 10000, "expected": 0.11647058822959541}, + {"steps_since_tge": "100000000000000", "steps": 100000, "expected": 1.164705881783071}, + {"steps_since_tge": "100000000000000", "steps": 1000000, "expected": 11.647058766542404}, + {"steps_since_tge": "100000000000000", "steps": 10000000, "expected": 116.47058253659338}, + {"steps_since_tge": "100000000000000", "steps": 100000000, "expected": 1164.7053124828683}, + {"steps_since_tge": "1000000000000000", "steps": 1, "expected": 1.1895246692412392e-06}, + {"steps_since_tge": "1000000000000000", "steps": 10, "expected": 1.1891116398421971e-05}, + {"steps_since_tge": "1000000000000000", "steps": 100, "expected": 0.00011890600111673168}, + {"steps_since_tge": "1000000000000000", "steps": 1000, "expected": 0.0011890610437408145}, + {"steps_since_tge": "1000000000000000", "steps": 10000, "expected": 0.011890606307114153}, + {"steps_since_tge": "1000000000000000", "steps": 100000, "expected": 0.11890606410371503}, + {"steps_since_tge": "1000000000000000", "steps": 1000000, "expected": 1.1890606420697238}, + {"steps_since_tge": "1000000000000000", "steps": 10000000, "expected": 11.890606361840549}, + {"steps_since_tge": "1000000000000000", "steps": 100000000, "expected": 118.90605827173992} +] diff --git a/integration-tests/rust-toolchain.toml b/integration-tests/rust-toolchain.toml new file mode 100644 index 0000000..d6d3381 --- /dev/null +++ b/integration-tests/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "1.91.1" diff --git a/integration-tests/src/callback_attack.rs b/integration-tests/src/callback_attack.rs deleted file mode 100644 index 71ee0d8..0000000 --- a/integration-tests/src/callback_attack.rs +++ /dev/null @@ -1,92 +0,0 @@ -#![cfg(test)] - -use integration_utils::misc::ToNear; -use near_sdk::{json_types::U128, serde_json::json}; -use sweat_model::FungibleTokenCoreIntegration; - -use crate::{ - common::PanicFinder, - interface::common::ContractAccount, - prepare::{prepare_contract, IntegrationContext}, -}; - -#[tokio::test] -async fn test_call_on_record_in_callback() -> anyhow::Result<()> { - let mut context = prepare_contract().await?; - - let alice = context.alice().await?; - - let alice_balance_before_attack = context.ft_contract().ft_balance_of(alice.to_near()).await?; - let ft_contract_id = context.ft_contract().account(); - - let target_amount = U128(1_000_000); - let result = alice - .call(context.stub_contract().id(), "exploit_on_record") - .args_json(json!({ - "ft_account_id": ft_contract_id, - "amount": target_amount, - })) - .max_gas() - .transact() - .await? - .into_result()?; - - assert!(result.has_panic("Method on_record is private")); - - let alice_balance_after_attack = context.ft_contract().ft_balance_of(alice.to_near()).await?; - assert_eq!(alice_balance_before_attack, alice_balance_after_attack); - - Ok(()) -} - -#[tokio::test] -async fn test_call_on_record_directly() -> anyhow::Result<()> { - let mut context = prepare_contract().await?; - - let alice = context.alice().await?; - - let intruder_id = alice.to_near(); - let result = context - .ft_contract() - .contract - .as_account() - .call(context.ft_contract().contract.id(), "on_record") - .args_json(json!({ - "receiver_id": intruder_id, - "amount": "1000000", - "fee_account_id": intruder_id, - "fee": "2000000", - })) - .max_gas() - .transact() - .await? - .into_result(); - - assert!(result.has_panic("Contract expected a result on the callback")); - - Ok(()) -} - -#[tokio::test] -async fn test_call_ft_resolve_transfer() -> anyhow::Result<()> { - let mut context = prepare_contract().await?; - - let alice = context.alice().await?; - let bob = context.bob().await?; - - let result = alice - .call(context.ft_contract().contract.id(), "ft_resolve_transfer") - .args_json(json!({ - "sender_id": alice.to_near(), - "receiver_id": bob.to_near(), - "amount": "1000000", - })) - .max_gas() - .transact() - .await? - .into_result(); - - assert!(result.has_panic("Method ft_resolve_transfer is private")); - - Ok(()) -} diff --git a/integration-tests/src/defer.rs b/integration-tests/src/defer.rs deleted file mode 100644 index 5a8df3f..0000000 --- a/integration-tests/src/defer.rs +++ /dev/null @@ -1,53 +0,0 @@ -#![cfg(test)] - -use integration_utils::misc::ToNear; -use sweat_model::{FungibleTokenCoreIntegration, IntegrationTestMethodsIntegration, SweatDeferIntegration}; - -use crate::prepare::{prepare_contract, IntegrationContext}; - -#[tokio::test] -async fn test_defer() -> anyhow::Result<()> { - const BATCH_SIZE: u32 = 135; - const CLAIM_AMOUNT: u32 = 10_000; - - let mut context = prepare_contract().await?; - let oracle = context.oracle().await?; - let alice = context.alice().await?; - - let claim_contract_account = context.claim_contract().as_account().to_near(); - - let holder_balance = context - .ft_contract() - .ft_balance_of(claim_contract_account.clone()) - .await?; - - assert_eq!(holder_balance.0, 0); - - let (total_fee, total_for_user) = context - .ft_contract() - .calculate_payout_with_fee_for_batch(BATCH_SIZE, CLAIM_AMOUNT) - .await?; - - let batch: Vec<_> = (0..BATCH_SIZE).map(|_| (alice.to_near(), CLAIM_AMOUNT)).collect(); - - context - .ft_contract() - .defer_batch(batch, claim_contract_account.clone()) - .with_user(&oracle) - .await?; - - let alice_balance = context.ft_contract().ft_balance_of(alice.to_near()).await?; - assert_eq!(0, alice_balance.0); - - let claim_contract_balance = context - .ft_contract() - .ft_balance_of(claim_contract_account.clone()) - .await?; - - let oracle_balance = context.ft_contract().ft_balance_of(oracle.to_near()).await?; - - assert_eq!(oracle_balance, total_fee); - assert_eq!(claim_contract_balance, total_for_user); - - Ok(()) -} diff --git a/integration-tests/src/formula.rs b/integration-tests/src/formula.rs deleted file mode 100644 index f2abed6..0000000 --- a/integration-tests/src/formula.rs +++ /dev/null @@ -1,207 +0,0 @@ -use anyhow::Result; -use near_sdk::json_types::U64; -use sweat_model::SweatApiIntegration; - -use crate::prepare::{prepare_contract, IntegrationContext}; - -const EPS: f64 = 0.00001; - -#[tokio::test] -async fn test_formula() -> Result<()> { - let mut context = prepare_contract().await?; - - let oracle = context.oracle().await?; - - let steps = context.ft_contract().get_steps_since_tge().await?; - - assert_eq!(0, steps.0); - - let steps_to_convert = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000]; - let steps_from_tge = [ - 1, - 10, - 100, - 1000, - 10000, - 100000, - 1000000, - 10000000, - 100000000, - 1000000000, - 10000000000, - 100000000000, - 1000000000000, - 10000000000000, - 100000000000000, - 1000000000000000u64, - ]; - - let mut test_number = 0; - for tge in steps_from_tge { - for steps in steps_to_convert { - let formula_res = context - .ft_contract() - .formula(U64(tge), steps) - .with_user(&oracle) - .await? - .0; - - let formula_res = formula_res as f64 / 1e+18; - - println!("{}. formula ({} {}) = {}", test_number, tge, steps, formula_res); - - let diff = formula_res - TEST_RESULTS[test_number]; - assert!(diff.abs() < EPS); - test_number += 1; - } - } - - Ok(()) -} - -pub const TEST_RESULTS: [f64; 144] = [ - 0.000_999_999_999_999_307, - 0.009_999_999_999_972_283, - 0.099_999_999_997_644_02, - 0.999_999_999_768_559_8, - 9.999_999_976_897_554, - 99.999_997_690_171_2, - 999.999_769_021_277_2, - 9_999.976_902_169_294, - 99_997.690_217_345_11, - 0.000_999_999_999_995_149_5, - 0.009_999_999_999_930_707, - 0.099_999_999_997_228_26, - 0.999_999_999_764_402_1, - 9.999_999_976_855_978, - 99.999_997_689_755_43, - 999.999_769_017_119_5, - 9_999.976_902_127_717, - 99_997.690_216_929_35, - 0.000_999_999_999_953_573_4, - 0.009_999_999_999_514_946, - 0.099_999_999_993_070_65, - 0.999_999_999_722_826, - 9.999_999_976_440_217, - 99.999_997_685_597_82, - 999.999_768_975_543_5, - 9_999.976_901_711_956, - 99_997.690_212_771_73, - 0.000_999_999_999_537_812_4, - 0.009_999_999_995_357_337, - 0.099_999_999_951_494_57, - 0.999_999_999_307_065_2, - 9.999_999_972_282_609, - 99.999_997_644_021_73, - 999.999_768_559_782_6, - 9_999.976_897_554_348, - 99_997.690_171_195_65, - 0.000_999_999_995_380_203_7, - 0.009_999_999_953_781_25, - 0.099_999_999_535_733_7, - 0.999_999_995_149_456_5, - 9.999_999_930_706_522, - 99.999_997_228_260_87, - 999.999_764_402_173_9, - 9_999.976_855_978_26, - 99_997.689_755_434_78, - 0.000_999_999_953_804_116_7, - 0.009_999_999_538_020_38, - 0.099_999_995_378_125, - 0.999_999_953_573_369_6, - 9.999_999_514_945_651, - 99.999_993_070_652_18, - 999.999_722_826_087, - 9_999.976_440_217_391, - 99_997.685_597_826_09, - 0.000_999_999_538_043_247_2, - 0.009_999_995_380_411_684, - 0.099_999_953_802_038_05, - 0.999_999_537_812_5, - 9.999_995_357_336_957, - 99.999_951_494_565_22, - 999.999_307_065_217_4, - 9_999.972_282_608_696, - 99_997.644_021_739_14, - 0.000_999_995_380_434_551_5, - 0.009_999_953_804_324_729, - 0.099_999_538_041_168_48, - 0.999_995_380_203_804_3, - 9.999_953_781_25, - 99.999_535_733_695_65, - 999.995_149_456_521_7, - 9_999.930_706_521_74, - 99_997.228_260_869_57, - 0.000_999_953_804_347_595, - 0.009_999_538_043_455_164, - 0.099_995_380_432_472_83, - 0.999_953_804_116_847_9, - 9.999_538_020_380_434, - 99.995_378_125, - 999.953_573_369_565_2, - 9_999.514_945_652_174, - 99_993.070_652_173_92, - 0.000_999_538_043_478_029_9, - 0.009_995_380_434_759_511, - 0.099_953_804_345_516_3, - 0.999_538_043_247_282_6, - 9.995_380_411_684_783, - 99.953_802_038_043_48, - 999.537_812_5, - 9_995.357_336_956_522, - 99_951.494_565_217_39, - 0.000_995_380_434_782_377_8, - 0.009_953_804_347_802_99, - 0.099_538_043_475_951_09, - 0.995_380_434_551_630_4, - 9.953_804_324_728_26, - 99.538_041_168_478_26, - 995.380_203_804_347_8, - 9953.78125, - 99_535.733_695_652_18, - 0.000_953_804_347_825_855_9, - 0.009_538_043_478_237_772, - 0.095_380_434_780_298_91, - 0.953_804_347_595_108_7, - 9.538_043_455_163_043, - 95.380_432_472_826_09, - 953.804_116_847_826_1, - 9_538.020_380_434_782, - 95378.125, - 0.000_538_043_478_260_785_2, - 0.005_380_434_782_600_264, - 0.053_804_347_825_243_75, - 0.538_043_478_176_549_3, - 5.380_434_774_176_671, - 53.804_346_982_884_49, - 538.043_393_940_623, - 5_380.426_350_584_036, - 53_803.504_623_621_026, - 0.000_105_319_148_936_165_89, - 0.001_053_191_489_361_270_2, - 0.010_531_914_893_573_824, - 0.105_319_148_931_850_49, - 1.053_191_488_929_729_1, - 10.531_914_850_419_714, - 105.319_144_616_439_49, - 1_053.191_057_388_630_3, - 10_531.871_696_309_84, - 1.164_705_882_352_935_4e-5, - 0.000_116_470_588_235_288_42, - 0.001_164_705_882_352_371_3, - 0.011_647_058_823_472_424, - 0.116_470_588_229_595_41, - 1.164_705_881_783_071, - 11.647_058_766_542_404, - 116.470_582_536_593_38, - 1_164.705_312_482_868_3, - 1.189_524_669_241_239_2e-6, - 1.189_111_639_842_197_1e-5, - 0.000_118_906_001_116_731_68, - 0.001_189_061_043_740_814_5, - 0.011_890_606_307_114_153, - 0.118_906_064_103_715_03, - 1.189_060_642_069_723_8, - 11.890_606_361_840_549, - 118.906_058_271_739_92, -]; diff --git a/integration-tests/src/interface/common.rs b/integration-tests/src/interface/common.rs deleted file mode 100644 index 6d5afdb..0000000 --- a/integration-tests/src/interface/common.rs +++ /dev/null @@ -1,12 +0,0 @@ -use near_sdk::AccountId; -use sweat_model::SweatContract; - -pub(crate) trait ContractAccount { - fn account(&self) -> AccountId; -} - -impl ContractAccount for SweatContract<'_> { - fn account(&self) -> AccountId { - AccountId::new_unchecked(self.contract.as_account().id().to_string()) - } -} diff --git a/integration-tests/src/interface/mod.rs b/integration-tests/src/interface/mod.rs deleted file mode 100644 index 34994bf..0000000 --- a/integration-tests/src/interface/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod common; diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs deleted file mode 100644 index e6d078b..0000000 --- a/integration-tests/src/lib.rs +++ /dev/null @@ -1,50 +0,0 @@ -#![cfg(test)] - -use integration_utils::misc::ToNear; -use sweat_model::{FungibleTokenCoreIntegration, SweatApiIntegration, SweatDeferIntegration}; - -use crate::prepare::{prepare_contract, IntegrationContext}; - -mod callback_attack; -mod common; -mod defer; -mod formula; -mod interface; -mod measure; -mod mint; -mod prepare; -mod transfer; - -#[tokio::test] -async fn happy_flow() -> anyhow::Result<()> { - let mut context = prepare_contract().await?; - - let alice = context.alice().await?; - let oracle = context.oracle().await?; - - assert_eq!( - 99999995378125008, - context.ft_contract().formula(100_000.into(), 100).await?.0 - ); - - context - .ft_contract() - .tge_mint(&alice.to_near(), 100_000_000.into()) - .await?; - - assert_eq!( - 100_000_000, - context.ft_contract().ft_balance_of(alice.to_near()).await?.0 - ); - - context - .ft_contract() - .defer_batch( - vec![(alice.to_near(), 1000)], - context.claim_contract().as_account().to_near(), - ) - .with_user(&oracle) - .await?; - - Ok(()) -} diff --git a/integration-tests/src/measure/mod.rs b/integration-tests/src/measure/mod.rs deleted file mode 100644 index d5a8194..0000000 --- a/integration-tests/src/measure/mod.rs +++ /dev/null @@ -1 +0,0 @@ -mod record_batch; diff --git a/integration-tests/src/measure/record_batch.rs b/integration-tests/src/measure/record_batch.rs deleted file mode 100644 index 0f081f7..0000000 --- a/integration-tests/src/measure/record_batch.rs +++ /dev/null @@ -1,38 +0,0 @@ -#![cfg(test)] - -use std::future::IntoFuture; - -use anyhow::Result; -use integration_utils::measure::outcome_storage::OutcomeStorage; -use near_workspaces::types::Gas; -use sweat_model::SweatApiIntegration; - -use crate::{prepare::IntegrationContext, prepare_contract}; - -#[ignore] -#[tokio::test] -async fn single_record_batch() -> anyhow::Result<()> { - let gas = measure_record_batch().await?; - - dbg!(&gas); - - Ok(()) -} - -async fn measure_record_batch() -> Result { - let mut context = prepare_contract().await?; - - let oracle = context.oracle().await?; - - let (gas, _) = OutcomeStorage::measure_total( - &oracle, - context - .ft_contract() - .record_batch(Default::default()) - .with_user(&oracle) - .into_future(), - ) - .await?; - - Ok(gas) -} diff --git a/integration-tests/src/mint.rs b/integration-tests/src/mint.rs deleted file mode 100644 index 512a6d2..0000000 --- a/integration-tests/src/mint.rs +++ /dev/null @@ -1,40 +0,0 @@ -use integration_utils::misc::ToNear; -use near_sdk::json_types::{U128, U64}; -use sweat_model::{FungibleTokenCoreIntegration, Payout, SweatApiIntegration}; - -use crate::prepare::{prepare_contract, IntegrationContext}; - -const TARGET_BALANCE: u128 = 9999999976902174720; -const TARGET_STEPS_SINCE_TGE: u32 = 10_000; - -#[tokio::test] -async fn test_mint() -> anyhow::Result<()> { - let mut context = prepare_contract().await?; - let user = context.alice().await?; - let oracle = context.oracle().await?; - - let result = context.ft_contract().get_steps_since_tge().await?; - assert_eq!(result, U64(0)); - - let result = context.ft_contract().formula(U64(0), TARGET_STEPS_SINCE_TGE).await?; - assert_eq!(result, U128(TARGET_BALANCE)); - - context - .ft_contract() - .record_batch(vec![(user.to_near(), 10_000u32)]) - .with_user(&oracle) - .await?; - - let target_payout = Payout::from(TARGET_BALANCE); - - let result = context.ft_contract().ft_balance_of(oracle.to_near()).await?; - assert_eq!(result, U128(target_payout.fee)); - - let result = context.ft_contract().ft_balance_of(user.to_near()).await?; - assert_eq!(result, U128(target_payout.amount_for_user)); - - let result = context.ft_contract().get_steps_since_tge().await?; - assert_eq!(result, U64(TARGET_STEPS_SINCE_TGE as u64)); - - Ok(()) -} diff --git a/integration-tests/src/prepare.rs b/integration-tests/src/prepare.rs deleted file mode 100644 index 430dccc..0000000 --- a/integration-tests/src/prepare.rs +++ /dev/null @@ -1,126 +0,0 @@ -use anyhow::Result; -use async_trait::async_trait; -use integration_utils::misc::ToNear; -use near_sdk::serde_json::json; -use near_workspaces::{Account, Contract}; -use sweat_model::{StorageManagementIntegration, SweatApiIntegration, SweatContract}; - -const CLAIM_CONTRACT: &str = "sweat_claim"; -const HOLDING_STUB_CONTRACT: &str = "exploit_stub"; -const FT_CONTRACT: &str = "sweat"; - -pub type Context = integration_utils::context::Context; - -#[async_trait] -pub trait IntegrationContext { - async fn oracle(&mut self) -> Result; - async fn alice(&mut self) -> Result; - async fn bob(&mut self) -> Result; - async fn long_account_name(&mut self) -> Result; - - fn ft_contract(&self) -> SweatContract; - fn claim_contract(&self) -> &Contract; - fn stub_contract(&self) -> &Contract; -} - -#[async_trait] -impl IntegrationContext for Context { - async fn oracle(&mut self) -> Result { - self.account("oracle").await - } - - async fn alice(&mut self) -> Result { - self.account("alice").await - } - - async fn bob(&mut self) -> Result { - self.account("bob").await - } - - async fn long_account_name(&mut self) -> Result { - self.account("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").await - } - - fn ft_contract(&self) -> SweatContract { - SweatContract { - contract: &self.contracts[FT_CONTRACT], - } - } - - fn claim_contract(&self) -> &Contract { - &self.contracts[CLAIM_CONTRACT] - } - - fn stub_contract(&self) -> &Contract { - &self.contracts[HOLDING_STUB_CONTRACT] - } -} - -pub async fn prepare_contract() -> Result { - let mut context = Context::new( - &[FT_CONTRACT, CLAIM_CONTRACT, HOLDING_STUB_CONTRACT], - true, - "build-integration".into(), - ) - .await?; - let oracle = context.oracle().await?; - let alice = context.alice().await?; - let long = context.long_account_name().await?; - let token_account_id = context.ft_contract().contract.as_account().to_near(); - - context.ft_contract().new(".u.sweat.testnet".to_string().into()).await?; - - context - .ft_contract() - .storage_deposit(oracle.to_near().into(), None) - .await?; - - context - .ft_contract() - .storage_deposit(alice.to_near().into(), None) - .await?; - - context - .ft_contract() - .storage_deposit(long.to_near().into(), None) - .await?; - - context.ft_contract().add_oracle(&oracle.to_near()).await?; - - let claim_contract_result = context - .claim_contract() - .call("init") - .args_json(json!({ "token_account_id": token_account_id })) - .max_gas() - .transact() - .await? - .into_result()?; - - println!("Initialized claim contract: {:?}", claim_contract_result); - - let exploit_stup_contract_result = context - .stub_contract() - .call("new") - .max_gas() - .transact() - .await? - .into_result()?; - - println!("Initialized exploit stub contract: {:?}", exploit_stup_contract_result); - - context - .claim_contract() - .call("add_oracle") - .args_json(json!({ "account_id": token_account_id })) - .max_gas() - .transact() - .await? - .into_result()?; - - context - .ft_contract() - .storage_deposit(context.claim_contract().as_account().to_near().into(), None) - .await?; - - Ok(context) -} diff --git a/integration-tests/src/transfer.rs b/integration-tests/src/transfer.rs deleted file mode 100644 index 87e9e78..0000000 --- a/integration-tests/src/transfer.rs +++ /dev/null @@ -1,48 +0,0 @@ -use integration_utils::misc::ToNear; -use near_sdk::json_types::U128; -use sweat_model::{FungibleTokenCoreIntegration, StorageManagementIntegration, SweatApiIntegration}; - -use crate::prepare::{prepare_contract, IntegrationContext}; - -#[tokio::test] -async fn test_transfer() -> anyhow::Result<()> { - let mut context = prepare_contract().await?; - let oracle = context.oracle().await?; - let alice = context.alice().await?; - let bob = context.bob().await?; - - context - .ft_contract() - .record_batch(vec![(alice.to_near(), 10_000)]) - .with_user(&oracle) - .await?; - - // This will fail because storage is not registered for this new account - let res = context - .ft_contract() - .ft_transfer(bob.to_near(), U128(9499999991723028480), None) - .with_user(&alice) - .await; - assert!(res.is_err()); - - let res = context.ft_contract().storage_deposit(Some(bob.to_near()), None).await; - assert!(res.is_ok()); - - let alice_balance = context.ft_contract().ft_balance_of(alice.to_near()).await?; - assert_ne!(U128(0), alice_balance); - - // Transfer all tokens from alice to new account - context - .ft_contract() - .ft_transfer(bob.to_near(), alice_balance, None) - .with_user(&alice) - .await?; - - let alice_balance_updated = context.ft_contract().ft_balance_of(alice.to_near()).await?; - assert_eq!(U128(0), alice_balance_updated); - - let bob_balance = context.ft_contract().ft_balance_of(bob.to_near()).await?; - assert_eq!(alice_balance, bob_balance); - - Ok(()) -} diff --git a/integration-tests/tests/access_control.rs b/integration-tests/tests/access_control.rs new file mode 100644 index 0000000..d7f5a7d --- /dev/null +++ b/integration-tests/tests/access_control.rs @@ -0,0 +1,286 @@ +use serde_json::json; +use tracing::info; + +mod common; +use common::{panic::PanicFinder, prepare::Context}; + +#[tokio::test] +#[tracing::instrument] +async fn test_acl_grant_role() -> anyhow::Result<()> { + let context = Context::builder().with_bob().build().await?; + + info!("call acl_grant_role(Oracle, alice) [signer=contract, super-admin]"); + let granted: Option = context + .sweat + .call("acl_grant_role") + .args_json(json!({ + "role": "Oracle", + "account_id": context.alice.id(), + })) + .transact() + .await? + .json()?; + assert_eq!(granted, Some(true)); + info!("acl_grant_role: {granted:?}"); + + info!("view acl_has_role(Oracle, alice)"); + let has_role: bool = context + .sweat + .view("acl_has_role") + .args_json(json!({ + "role": "Oracle", + "account_id": context.alice.id(), + })) + .await? + .json()?; + assert!(has_role); + info!("acl_has_role: {has_role:?}"); + + info!("call acl_grant_role(Oracle, bob) [signer=alice, unauthorized]"); + let granted: Option = context + .alice + .call(context.sweat.id(), "acl_grant_role") + .args_json(json!({ + "role": "Oracle", + "account_id": context.bob().id(), + })) + .transact() + .await? + .json()?; + assert_eq!(granted, None); + info!("acl_grant_role: {granted:?}"); + + info!("view acl_has_role(Oracle, bob)"); + let has_role: bool = context + .sweat + .view("acl_has_role") + .args_json(json!({ + "role": "Oracle", + "account_id": context.bob().id(), + })) + .await? + .json()?; + assert!(!has_role); + info!("acl_has_role: {has_role:?}"); + + Ok(()) +} + +#[tokio::test] +#[tracing::instrument] +async fn test_acl_defer_batch() -> anyhow::Result<()> { + let context = Context::builder().with_claim().build().await?; + + info!("call defer_batch([(alice, 10_000)]) [signer=alice, unauthorized]"); + let result = context + .alice + .call(context.sweat.id(), "defer_batch") + .args_json(json!({ "steps_batch": [[context.alice.id(), 10_000]] })) + .max_gas() + .transact() + .await? + .into_result(); + assert!(result.has_panic("Insufficient permissions for method defer_batch restricted by access control.")); + info!("defer_batch: {result:?}"); + + info!("call acl_grant_role(Oracle, alice) [signer=contract, super-admin]"); + let granted: Option = context + .sweat + .call("acl_grant_role") + .args_json(json!({ + "role": "Oracle", + "account_id": context.alice.id(), + })) + .transact() + .await? + .json()?; + assert_eq!(granted, Some(true)); + info!("acl_grant_role: {granted:?}"); + + info!("call defer_batch([(alice, 10_000)]) [signer=alice, authorized]"); + let result = context + .alice + .call(context.sweat.id(), "defer_batch") + .args_json(json!({ "steps_batch": [[context.alice.id(), 10_000]] })) + .max_gas() + .transact() + .await? + .into_result()?; + assert!(result.outcome().is_success()); + info!("defer_batch: {result:?}"); + + Ok(()) +} + +#[tokio::test] +#[tracing::instrument] +async fn test_acl_set_restricted() -> anyhow::Result<()> { + let context = Context::builder().build().await?; + + info!("call set_restricted(alice, true) [signer=alice, unauthorized]"); + let result = context + .alice + .call(context.sweat.id(), "set_restricted") + .args_json(json!({ + "account_id": context.alice.id(), + "is_restricted": true, + })) + .transact() + .await? + .into_result(); + assert!(result.has_panic("Insufficient permissions for method set_restricted restricted by access control.")); + info!("set_restricted: {result:?}"); + + info!("call acl_grant_role(DenylistManager, alice) [signer=contract, super-admin]"); + let granted: Option = context + .sweat + .call("acl_grant_role") + .args_json(json!({ + "role": "DenylistManager", + "account_id": context.alice.id(), + })) + .transact() + .await? + .json()?; + assert_eq!(granted, Some(true)); + info!("acl_grant_role: {granted:?}"); + + info!("call set_restricted(alice, true) [signer=alice, authorized]"); + let result = context + .alice + .call(context.sweat.id(), "set_restricted") + .args_json(json!({ + "account_id": context.alice.id(), + "is_restricted": true, + })) + .transact() + .await? + .into_result()?; + assert!(result.outcome().is_success()); + info!("set_restricted: {result:?}"); + + info!("view is_restricted(alice)"); + let is_restricted: bool = context + .sweat + .view("is_restricted") + .args_json(json!({ "account_id": context.alice.id() })) + .await? + .json()?; + assert!(is_restricted); + info!("is_restricted: {is_restricted:?}"); + + Ok(()) +} + +#[tokio::test] +#[tracing::instrument] +async fn test_acl_pause_feature() -> anyhow::Result<()> { + let context = Context::builder().build().await?; + + info!("call pause_features(ALL) [signer=alice, unauthorized]"); + let result = context + .alice + .call(context.sweat.id(), "pause_features") + .args_json(json!({ "features": ["token", "minting"] })) + .transact() + .await? + .into_result(); + assert!(result.has_panic("Insufficient permissions for method pause_features restricted by access control.")); + info!("pause_features: {result:?}"); + + info!("call acl_grant_role(PauseManager, alice) [signer=contract, super-admin]"); + let granted: Option = context + .sweat + .call("acl_grant_role") + .args_json(json!({ + "role": "PauseManager", + "account_id": context.alice.id(), + })) + .transact() + .await? + .json()?; + assert_eq!(granted, Some(true)); + info!("acl_grant_role: {granted:?}"); + + info!("call pause_features(ALL) [signer=alice, authorized]"); + let is_paused: bool = context + .alice + .call(context.sweat.id(), "pause_features") + .args_json(json!({ "features": ["token", "minting"] })) + .transact() + .await? + .json()?; + assert!(is_paused); + info!("pause_features: {is_paused:?}"); + + Ok(()) +} + +#[tokio::test] +#[tracing::instrument] +async fn test_acl_unpause_feature() -> anyhow::Result<()> { + let context = Context::builder().build().await?; + + info!("call unpause_features(ALL) [signer=alice, unauthorized]"); + let result = context + .alice + .call(context.sweat.id(), "unpause_features") + .args_json(json!({ "features": ["token", "minting"] })) + .transact() + .await? + .into_result(); + assert!(result.has_panic("Insufficient permissions for method unpause_features restricted by access control.")); + info!("unpause_features: {result:?}"); + + info!("call acl_grant_role(PauseManager, alice) [signer=contract, super-admin]"); + let granted: Option = context + .sweat + .call("acl_grant_role") + .args_json(json!({ + "role": "PauseManager", + "account_id": context.alice.id(), + })) + .transact() + .await? + .json()?; + assert_eq!(granted, Some(true)); + info!("acl_grant_role: {granted:?}"); + + info!("call acl_grant_role(UnpauseManager, alice) [signer=contract, super-admin]"); + let granted: Option = context + .sweat + .call("acl_grant_role") + .args_json(json!({ + "role": "UnpauseManager", + "account_id": context.alice.id(), + })) + .transact() + .await? + .json()?; + assert_eq!(granted, Some(true)); + info!("acl_grant_role: {granted:?}"); + + info!("call pause_features(ALL) [signer=alice, authorized]"); + let is_paused: bool = context + .alice + .call(context.sweat.id(), "pause_features") + .args_json(json!({ "features": ["token", "minting"] })) + .transact() + .await? + .json()?; + assert!(is_paused); + info!("pause_features: {is_paused:?}"); + + info!("call unpause_features(ALL) [signer=alice, authorized]"); + let is_unpaused: bool = context + .alice + .call(context.sweat.id(), "unpause_features") + .args_json(json!({ "features": ["token", "minting"] })) + .transact() + .await? + .json()?; + assert!(is_unpaused); + info!("unpause_features: {is_unpaused:?}"); + + Ok(()) +} diff --git a/integration-tests/tests/callback_attack.rs b/integration-tests/tests/callback_attack.rs new file mode 100644 index 0000000..d3e95dd --- /dev/null +++ b/integration-tests/tests/callback_attack.rs @@ -0,0 +1,114 @@ +use serde_json::json; +use tracing::info; + +mod common; +use common::panic::PanicFinder; +use common::prepare::Context; + +#[tokio::test] +#[tracing::instrument] +async fn test_call_on_record_in_callback() -> anyhow::Result<()> { + let context = Context::builder().with_stub().build().await?; + + info!("view ft_balance_of(alice) [before attack]"); + let balance_before: String = context + .sweat + .view("ft_balance_of") + .args_json(json!({ "account_id": context.alice.id() })) + .await? + .json()?; + info!(value = %balance_before, "alice balance before"); + + info!("alice → stub.exploit_on_record(ft, 1_000_000)"); + let result = context + .alice + .call(context.stub().id(), "exploit_on_record") + .args_json(json!({ + "ft_account_id": context.sweat.id(), + "amount": "1000000", + })) + .max_gas() + .transact() + .await? + .into_result()?; + + assert!( + result.has_panic("Method on_record is private"), + "expected nested panic \"Method on_record is private\" in receipts" + ); + info!("nested panic caught as expected"); + + info!("view ft_balance_of(alice) [after attack]"); + let balance_after: String = context + .sweat + .view("ft_balance_of") + .args_json(json!({ "account_id": context.alice.id() })) + .await? + .json()?; + info!(value = %balance_after, "alice balance after"); + assert_eq!(balance_before, balance_after); + + info!("done"); + Ok(()) +} + +#[tokio::test] +#[tracing::instrument] +async fn test_call_on_record_directly() -> anyhow::Result<()> { + let context = Context::builder().build().await?; + + info!("sweat → sweat.on_record(...) [direct call, no preceding promise]"); + let result = context + .sweat + .as_account() + .call(context.sweat.id(), "on_record") + .args_json(json!({ + "receiver_id": context.alice.id(), + "amount": "1000000", + "fee_account_id": context.alice.id(), + "fee": "2000000", + "steps_increment": 0, + })) + .max_gas() + .transact() + .await? + .into_result(); + + assert!( + result.has_panic("Contract expected a single result on the callback"), + "expected panic \"Contract expected a single result on the callback\"" + ); + info!("panic caught as expected"); + + info!("done"); + Ok(()) +} + +#[tokio::test] +#[tracing::instrument] +async fn test_call_ft_resolve_transfer() -> anyhow::Result<()> { + let context = Context::builder().with_bob().build().await?; + + info!("alice → sweat.ft_resolve_transfer(...) [private callback]"); + let result = context + .alice + .call(context.sweat.id(), "ft_resolve_transfer") + .args_json(json!({ + "sender_id": context.alice.id(), + "receiver_id": context.bob().id(), + "amount": "1000000", + })) + .max_gas() + .transact() + .await? + .into_result(); + + assert!( + result.has_panic("Method ft_resolve_transfer is private"), + "expected panic \"Method ft_resolve_transfer is private\"" + ); + info!("panic caught as expected"); + + info!("done"); + Ok(()) +} diff --git a/integration-tests/tests/common/helpers.rs b/integration-tests/tests/common/helpers.rs new file mode 100644 index 0000000..693d90d --- /dev/null +++ b/integration-tests/tests/common/helpers.rs @@ -0,0 +1,14 @@ +use tracing_subscriber::EnvFilter; + +pub(crate) fn init_tracing() { + let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info,near_workspaces=warn")); + let _ = tracing_subscriber::fmt() + .with_env_filter(filter) + .with_test_writer() + .try_init(); +} + +pub fn payout(value: u128) -> (u128, u128) { + let fee = (value * 5).div_ceil(100); + (value - fee, fee) +} diff --git a/integration-tests/tests/common/mod.rs b/integration-tests/tests/common/mod.rs new file mode 100644 index 0000000..bbdc5a0 --- /dev/null +++ b/integration-tests/tests/common/mod.rs @@ -0,0 +1,6 @@ +#![allow(dead_code)] + +pub mod helpers; +pub mod panic; +pub mod prepare; +pub mod storage; diff --git a/integration-tests/src/common.rs b/integration-tests/tests/common/panic.rs similarity index 56% rename from integration-tests/src/common.rs rename to integration-tests/tests/common/panic.rs index c7c1fe4..5d752be 100644 --- a/integration-tests/src/common.rs +++ b/integration-tests/tests/common/panic.rs @@ -1,6 +1,6 @@ use near_workspaces::result::{ExecutionFailure, ExecutionResult, ExecutionSuccess}; -pub(crate) trait PanicFinder { +pub trait PanicFinder { fn has_panic(&self, message: &str) -> bool; } @@ -15,15 +15,12 @@ impl PanicFinder for Result { impl PanicFinder for ExecutionResult { fn has_panic(&self, message: &str) -> bool { - self.outcomes() - .into_iter() - .map(|item| match item.clone().into_result() { - Ok(_) => None, - Err(err) => Some(err), - }) - .any(|item| match item { - None => false, - Some(err) => format!("{err:?}").contains(message), - }) + self.outcomes().into_iter().any(|outcome| { + outcome + .clone() + .into_result() + .err() + .is_some_and(|err| format!("{err:?}").contains(message)) + }) } } diff --git a/integration-tests/tests/common/prepare.rs b/integration-tests/tests/common/prepare.rs new file mode 100644 index 0000000..d50f607 --- /dev/null +++ b/integration-tests/tests/common/prepare.rs @@ -0,0 +1,271 @@ +use std::path::PathBuf; + +use anyhow::{anyhow, Result}; +use near_workspaces::{network::Sandbox, types::NearToken, Account, AccountId, Contract, Worker}; +use serde_json::json; +use tracing::info; + +use super::helpers::init_tracing; +use super::storage::{storage_balance_min, storage_deposit}; + +const INITIAL_USER_BALANCE: NearToken = NearToken::from_near(10); + +const SWEAT_WASM_ENV: &str = "SWEAT_WASM"; +const CLAIM_WASM_ENV: &str = "CLAIM_WASM"; +const STUB_WASM_ENV: &str = "STUB_WASM"; + +pub struct Context { + #[allow(dead_code)] // held to keep the sandbox alive for the test's lifetime + pub worker: Worker, + pub sweat: Contract, + pub alice: Account, + oracle: Option, + bob: Option, + claim: Option, + stub: Option, +} + +impl Context { + pub fn builder() -> ContextBuilder { + ContextBuilder::new() + } + + pub fn oracle(&self) -> &Account { + self.oracle + .as_ref() + .expect("oracle missing — add .with_oracle() to the Context::builder() chain") + } + + pub fn bob(&self) -> &Account { + self.bob + .as_ref() + .expect("bob missing — add .with_bob() to the Context::builder() chain") + } + + pub fn claim(&self) -> &Contract { + self.claim + .as_ref() + .expect("claim missing — add .with_claim() to the Context::builder() chain") + } + + pub fn stub(&self) -> &Contract { + self.stub + .as_ref() + .expect("stub missing — add .with_stub() to the Context::builder() chain") + } +} + +pub struct ContextBuilder { + oracle: bool, + bob: bool, + claim: bool, + stub: bool, +} + +impl ContextBuilder { + fn new() -> Self { + init_tracing(); + Self { + oracle: false, + bob: false, + claim: false, + stub: false, + } + } + + pub fn with_oracle(mut self) -> Self { + self.oracle = true; + self + } + + pub fn with_bob(mut self) -> Self { + self.bob = true; + self + } + + pub fn with_claim(mut self) -> Self { + self.claim = true; + self + } + + pub fn with_stub(mut self) -> Self { + self.stub = true; + self + } + + #[tracing::instrument(name = "prepare", skip(self))] + pub async fn build(self) -> Result { + info!("booting sandbox"); + let worker = near_workspaces::sandbox().await?; + let root = worker.root_account()?; + + info!("deploying sweat"); + let sweat = deploy(&worker, sweat_wasm_path(), "sweat", SWEAT_WASM_ENV).await?; + info!(id = %sweat.id(), "sweat deployed"); + + // Deploy the claim contract before initializing sweat so its account id + // can be baked in as the fixed deferred-minting holding account. + let claim = if self.claim { + info!("deploying claim"); + let claim = deploy(&worker, claim_wasm_path(), "claim", CLAIM_WASM_ENV).await?; + info!(id = %claim.id(), "claim deployed"); + Some(claim) + } else { + None + }; + + // Initializing sweat requires a holding account id. When the test + // doesn't deploy the claim contract, fall back to the sandbox root + // account — tests that don't exercise defer_batch don't care which + // account holds the role. + let holding_account_id = claim.as_ref().map(Contract::id).unwrap_or_else(|| root.id()); + + info!("initializing sweat (new)"); + sweat + .call("new") + .args_json(json!({ + "holding_account_id": holding_account_id, + "super_admin_account_id": sweat.id(), + "oracle_account_ids": [], + "denylist_manager_account_ids": [], + "pause_manager_account_ids": [], + "unpause_manager_account_ids": [], + })) + .transact() + .await? + .into_result()?; + + info!("creating alice"); + let alice = create_user(&root, "alice").await?; + + let min = storage_balance_min(&sweat).await?; + storage_deposit(&sweat, alice.id(), min).await?; + + let oracle = if self.oracle { + info!("creating oracle + sweat.acl_grant_role(Oracle)"); + let oracle = create_user(&root, "oracle").await?; + sweat + .call("acl_grant_role") + .args_json(json!({ + "role": "Oracle", + "account_id": oracle.id(), + })) + .transact() + .await? + .into_result()?; + storage_deposit(&sweat, oracle.id(), min).await?; + Some(oracle) + } else { + None + }; + + let bob = if self.bob { + info!("creating bob (FT-unregistered)"); + Some(create_user(&root, "bob").await?) + } else { + None + }; + + // Finish claim setup now that sweat is initialized. + if let Some(claim) = &claim { + info!("initializing claim"); + init_claim(claim, sweat.id()).await?; + storage_deposit(&sweat, claim.id(), min).await?; + } + + let stub = if self.stub { + info!("deploying + initializing stub"); + let stub = deploy(&worker, stub_wasm_path(), "stub", STUB_WASM_ENV).await?; + info!(id = %stub.id(), "stub deployed"); + stub.call("new").transact().await?.into_result()?; + Some(stub) + } else { + None + }; + + info!("ready"); + Ok(Context { + worker, + sweat, + alice, + oracle, + bob, + claim, + stub, + }) + } +} + +fn wasm_path(env_var: &str, default: PathBuf) -> PathBuf { + std::env::var_os(env_var).map(PathBuf::from).unwrap_or(default) +} + +fn sweat_wasm_path() -> PathBuf { + wasm_path( + SWEAT_WASM_ENV, + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("target") + .join("integration-wasm") + .join("contract.wasm"), + ) +} + +fn claim_wasm_path() -> PathBuf { + wasm_path( + CLAIM_WASM_ENV, + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("..") + .join("res") + .join("sweat_claim.wasm"), + ) +} + +fn stub_wasm_path() -> PathBuf { + wasm_path( + STUB_WASM_ENV, + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("..") + .join("res") + .join("exploit_stub.wasm"), + ) +} + +async fn deploy(worker: &Worker, path: PathBuf, label: &str, env_var: &str) -> Result { + let bytes = std::fs::read(&path).map_err(|e| { + anyhow!( + "failed to read {label} WASM at {} — did you run `make build-integration`? \ + Override the path with the {env_var} env var. ({e})", + path.display() + ) + })?; + Ok(worker.dev_deploy(&bytes).await?) +} + +async fn create_user(root: &Account, name: &str) -> Result { + Ok(root + .create_subaccount(name) + .initial_balance(INITIAL_USER_BALANCE) + .transact() + .await? + .into_result()?) +} + +async fn init_claim(claim: &Contract, token_account_id: &AccountId) -> Result<()> { + claim + .call("init") + .args_json(json!({ "token_account_id": token_account_id })) + .max_gas() + .transact() + .await? + .into_result()?; + + claim + .call("add_oracle") + .args_json(json!({ "account_id": token_account_id })) + .max_gas() + .transact() + .await? + .into_result()?; + + Ok(()) +} diff --git a/integration-tests/tests/common/storage.rs b/integration-tests/tests/common/storage.rs new file mode 100644 index 0000000..8e1514f --- /dev/null +++ b/integration-tests/tests/common/storage.rs @@ -0,0 +1,27 @@ +use anyhow::{anyhow, Result}; +use near_workspaces::{types::NearToken, AccountId, Contract}; +use serde_json::{json, Value}; + +pub async fn storage_balance_min(ft: &Contract) -> Result { + let bounds: Value = ft.view("storage_balance_bounds").await?.json()?; + let min_str = bounds + .get("min") + .and_then(Value::as_str) + .ok_or_else(|| anyhow!("storage_balance_bounds.min missing"))?; + Ok(NearToken::from_yoctonear(min_str.parse()?)) +} + +pub async fn storage_deposit(ft: &Contract, account_id: &AccountId, deposit: NearToken) -> Result<()> { + ft.call("storage_deposit") + .args_json(json!({ "account_id": account_id })) + .deposit(deposit) + .transact() + .await? + .into_result()?; + Ok(()) +} + +pub async fn register_for_storage(ft: &Contract, account_id: &AccountId) -> Result<()> { + let min = storage_balance_min(ft).await?; + storage_deposit(ft, account_id, min).await +} diff --git a/integration-tests/tests/defer.rs b/integration-tests/tests/defer.rs new file mode 100644 index 0000000..fb885a6 --- /dev/null +++ b/integration-tests/tests/defer.rs @@ -0,0 +1,427 @@ +use serde_json::json; +use tracing::info; + +mod common; +use common::{panic::PanicFinder, prepare::Context}; + +const BATCH_SIZE: u32 = 135; +const CLAIM_AMOUNT: u32 = 10_000; + +#[tokio::test] +#[tracing::instrument] +async fn test_defer() -> anyhow::Result<()> { + let context = Context::builder().with_oracle().with_claim().build().await?; + + info!("view ft_balance_of(claim)"); + let claim_balance_before: String = context + .sweat + .view("ft_balance_of") + .args_json(json!({ "account_id": context.claim().id() })) + .await? + .json()?; + info!(value = %claim_balance_before, "claim balance before"); + assert_eq!(0_u128, claim_balance_before.parse::()?); + + info!( + batch_size = BATCH_SIZE, + claim_amount = CLAIM_AMOUNT, + "view calculate_payout_with_fee_for_batch" + ); + let (total_fee, total_for_user): (String, String) = context + .sweat + .view("calculate_payout_with_fee_for_batch") + .args_json(json!({ + "batch_size": BATCH_SIZE, + "claim_amount": CLAIM_AMOUNT, + })) + .await? + .json()?; + info!(%total_fee, %total_for_user, "payout breakdown"); + + let batch: Vec<_> = (0..BATCH_SIZE).map(|_| (context.alice.id(), CLAIM_AMOUNT)).collect(); + + info!( + batch_size = BATCH_SIZE, + claim_amount = CLAIM_AMOUNT, + "call defer_batch [signer=oracle]" + ); + context + .oracle() + .call(context.sweat.id(), "defer_batch") + .args_json(json!({ "steps_batch": batch })) + .max_gas() + .transact() + .await? + .into_result()?; + + info!("view ft_balance_of(alice)"); + let alice_balance: String = context + .sweat + .view("ft_balance_of") + .args_json(json!({ "account_id": context.alice.id() })) + .await? + .json()?; + info!(value = %alice_balance, "alice balance"); + assert_eq!(0_u128, alice_balance.parse::()?); + + info!("view ft_balance_of(claim)"); + let claim_balance: String = context + .sweat + .view("ft_balance_of") + .args_json(json!({ "account_id": context.claim().id() })) + .await? + .json()?; + info!(value = %claim_balance, "claim balance"); + assert_eq!(total_for_user, claim_balance); + + info!("view ft_balance_of(oracle)"); + let oracle_balance: String = context + .sweat + .view("ft_balance_of") + .args_json(json!({ "account_id": context.oracle().id() })) + .await? + .json()?; + info!(value = %oracle_balance, "oracle balance"); + assert_eq!(total_fee, oracle_balance); + + info!("done"); + Ok(()) +} + +#[tokio::test] +#[tracing::instrument] +async fn test_defer_batch_skips_denylisted_users() -> anyhow::Result<()> { + // alice is denylisted, bob is not. A single defer_batch records both. The + // loop in defer_batch must skip alice (nothing recorded for her to claim) + // while still recording bob. bob is the positive control proving the batch + // isn't simply rejected wholesale. + let context = Context::builder().with_oracle().with_claim().with_bob().build().await?; + + info!("call acl_grant_role(DenylistManager, sweat) [signer=contract, super-admin]"); + context + .sweat + .call("acl_grant_role") + .args_json(json!({ + "role": "DenylistManager", + "account_id": context.sweat.id(), + })) + .transact() + .await? + .into_result()?; + + info!("call set_restricted(alice, true) [signer=contract, DenylistManager]"); + context + .sweat + .call("set_restricted") + .args_json(json!({ + "account_id": context.alice.id(), + "is_restricted": true, + })) + .transact() + .await? + .into_result()?; + + info!("call defer_batch([(alice, {CLAIM_AMOUNT}), (bob, {CLAIM_AMOUNT})]) [signer=oracle]"); + context + .oracle() + .call(context.sweat.id(), "defer_batch") + .args_json(json!({ + "steps_batch": [ + [context.alice.id(), CLAIM_AMOUNT], + [context.bob().id(), CLAIM_AMOUNT], + ], + })) + .max_gas() + .transact() + .await? + .into_result()?; + + info!("view get_claimable_balance_for_account(alice) [denylisted — expect nothing]"); + let alice_claimable: String = context + .claim() + .view("get_claimable_balance_for_account") + .args_json(json!({ "account_id": context.alice.id() })) + .await? + .json()?; + info!(value = %alice_claimable, "alice claimable"); + assert_eq!( + alice_claimable.parse::()?, + 0, + "denylisted user must have nothing recorded to claim" + ); + + info!("view get_claimable_balance_for_account(bob) [not denylisted — expect a balance]"); + let bob_claimable: String = context + .claim() + .view("get_claimable_balance_for_account") + .args_json(json!({ "account_id": context.bob().id() })) + .await? + .json()?; + info!(value = %bob_claimable, "bob claimable"); + assert!( + bob_claimable.parse::()? > 0, + "non-denylisted user must have a claimable balance recorded" + ); + + info!("done"); + Ok(()) +} + +#[tokio::test] +#[tracing::instrument] +async fn test_set_holding_account_id_updates_defer_target() -> anyhow::Result<()> { + let context = Context::builder() + .with_oracle() + .with_claim() + .with_stub() + .build() + .await?; + + info!("view get_holding_account_id [baked in at init]"); + let holding: String = context.sweat.view("get_holding_account_id").await?.json()?; + assert_eq!(holding, context.claim().id().to_string()); + info!(%holding, "holding account starts as claim"); + + info!("call set_holding_account_id(stub) [signer=contract, super-admin]"); + context + .sweat + .call("set_holding_account_id") + .args_json(json!({ "account_id": context.stub().id() })) + .transact() + .await? + .into_result()?; + + info!("view get_holding_account_id [after update]"); + let holding: String = context.sweat.view("get_holding_account_id").await?.json()?; + assert_eq!(holding, context.stub().id().to_string()); + info!(%holding, "holding account updated to stub"); + + info!("view formula(0, {CLAIM_AMOUNT}) — raw deferred amount"); + let minted_raw: String = context + .sweat + .view("formula") + .args_json(json!({ + "steps_since_tge": "0", + "steps": CLAIM_AMOUNT, + })) + .await? + .json()?; + + let minted: u128 = minted_raw.parse()?; + let total_fee = (minted * 5).div_ceil(100); + let total_for_user = minted - total_fee; + info!(%minted_raw, total_fee, total_for_user, "expected payout breakdown"); + + info!("call defer_batch([(alice, {CLAIM_AMOUNT})]) [signer=oracle]"); + context + .oracle() + .call(context.sweat.id(), "defer_batch") + .args_json(json!({ "steps_batch": [[context.alice.id(), CLAIM_AMOUNT]] })) + .max_gas() + .transact() + .await? + .into_result()?; + + info!("view ft_balance_of(stub) [updated holding account]"); + let stub_balance: String = context + .sweat + .view("ft_balance_of") + .args_json(json!({ "account_id": context.stub().id() })) + .await? + .json()?; + assert_eq!( + stub_balance.parse::()?, + total_for_user, + "deferred mint must follow the updated holding account" + ); + info!(value = %stub_balance, "stub received the deferred amount"); + + info!("view ft_balance_of(claim) [former holding account]"); + let claim_balance: String = context + .sweat + .view("ft_balance_of") + .args_json(json!({ "account_id": context.claim().id() })) + .await? + .json()?; + assert_eq!(claim_balance, "0", "former holding account must receive nothing"); + info!(value = %claim_balance, "claim received nothing"); + + info!("done"); + Ok(()) +} + +#[tokio::test] +#[tracing::instrument] +async fn test_set_holding_account_id_rejects_non_admin() -> anyhow::Result<()> { + let context = Context::builder().with_claim().build().await?; + + info!("call set_holding_account_id(alice) [signer=alice, unauthorized]"); + let result = context + .alice + .call(context.sweat.id(), "set_holding_account_id") + .args_json(json!({ "account_id": context.alice.id() })) + .transact() + .await? + .into_result(); + assert!(result.has_panic("Method set_holding_account_id is private")); + info!("set_holding_account_id: {result:?}"); + + info!("view get_holding_account_id [unchanged]"); + let holding: String = context.sweat.view("get_holding_account_id").await?.json()?; + assert_eq!(holding, context.claim().id().to_string()); + info!(%holding, "holding account unchanged"); + + Ok(()) +} + +#[tokio::test] +#[tracing::instrument] +async fn test_defer_batch_rejects_empty_batch() -> anyhow::Result<()> { + let context = Context::builder().with_oracle().with_claim().build().await?; + + info!("call defer_batch([]) [signer=oracle] — empty batch must be rejected"); + let result = context + .oracle() + .call(context.sweat.id(), "defer_batch") + .args_json(json!({ "steps_batch": [] })) + .max_gas() + .transact() + .await? + .into_result(); + assert!(result.has_panic("Empty steps batch")); + info!("defer_batch: {result:?}"); + + info!("done"); + Ok(()) +} + +#[tokio::test] +#[tracing::instrument] +async fn test_defer_batch_rejects_zero_step_count() -> anyhow::Result<()> { + let context = Context::builder().with_oracle().with_claim().build().await?; + + info!("call defer_batch([(alice, 0)]) [signer=oracle] — zero step count must be rejected"); + let result = context + .oracle() + .call(context.sweat.id(), "defer_batch") + .args_json(json!({ "steps_batch": [[context.alice.id(), 0]] })) + .max_gas() + .transact() + .await? + .into_result(); + assert!(result.has_panic("Step count must not be zero")); + info!("defer_batch: {result:?}"); + + info!("view get_steps_since_tge [unchanged after rejected batch]"); + let steps: String = context.sweat.view("get_steps_since_tge").await?.json()?; + assert_eq!( + steps.parse::()?, + 0, + "a rejected batch must not advance the steps counter" + ); + info!(value = %steps, "steps unchanged"); + + info!("done"); + Ok(()) +} + +#[tokio::test] +#[tracing::instrument] +async fn test_defer_batch_advances_steps_on_success() -> anyhow::Result<()> { + let context = Context::builder().with_oracle().with_claim().build().await?; + + info!("view get_steps_since_tge [before]"); + let steps_before: String = context.sweat.view("get_steps_since_tge").await?.json()?; + assert_eq!(steps_before.parse::()?, 0); + info!(value = %steps_before, "steps before"); + + info!("call defer_batch([(alice, {CLAIM_AMOUNT})]) [signer=oracle]"); + context + .oracle() + .call(context.sweat.id(), "defer_batch") + .args_json(json!({ "steps_batch": [[context.alice.id(), CLAIM_AMOUNT]] })) + .max_gas() + .transact() + .await? + .into_result()?; + + info!("view get_steps_since_tge [after]"); + let steps_after: String = context.sweat.view("get_steps_since_tge").await?.json()?; + assert_eq!( + steps_after.parse::()?, + u64::from(CLAIM_AMOUNT), + "steps_since_tge must advance by the batch step count on success" + ); + info!(value = %steps_after, "steps after"); + + info!("done"); + Ok(()) +} + +#[tokio::test] +#[tracing::instrument] +async fn test_defer_batch_rolls_back_steps_on_failed_record() -> anyhow::Result<()> { + let context = Context::builder().with_oracle().with_claim().build().await?; + + info!("view get_steps_since_tge [before]"); + let steps_before: String = context.sweat.view("get_steps_since_tge").await?.json()?; + assert_eq!(steps_before.parse::()?, 0); + info!(value = %steps_before, "steps before"); + + info!("call set_holding_account_id(alice) — a contractless account [signer=contract]"); + context + .sweat + .call("set_holding_account_id") + .args_json(json!({ "account_id": context.alice.id() })) + .transact() + .await? + .into_result()?; + + info!("call defer_batch([(alice, {CLAIM_AMOUNT})]) [signer=oracle] — record XCC will fail"); + let outcome = context + .oracle() + .call(context.sweat.id(), "defer_batch") + .args_json(json!({ "steps_batch": [[context.alice.id(), CLAIM_AMOUNT]] })) + .max_gas() + .transact() + .await?; + + outcome.clone().into_result()?; + + info!("assert the failure branch ran"); + assert!( + outcome + .logs() + .iter() + .any(|log| log.contains("rolled back steps counter")), + "expected the on_record failure branch to log the rollback" + ); + + info!("view get_steps_since_tge [after failed defer]"); + let steps_after: String = context.sweat.view("get_steps_since_tge").await?.json()?; + assert_eq!( + steps_after.parse::()?, + 0, + "steps_since_tge must be rolled back after a failed record XCC" + ); + info!(value = %steps_after, "steps after"); + + info!("view ft_balance_of(alice) + ft_balance_of(oracle)"); + let alice_balance: String = context + .sweat + .view("ft_balance_of") + .args_json(json!({ "account_id": context.alice.id() })) + .await? + .json()?; + let oracle_balance: String = context + .sweat + .view("ft_balance_of") + .args_json(json!({ "account_id": context.oracle().id() })) + .await? + .json()?; + assert_eq!(alice_balance, "0", "no tokens may be minted on a failed defer"); + assert_eq!(oracle_balance, "0", "no fee may be minted on a failed defer"); + + info!("done"); + Ok(()) +} diff --git a/integration-tests/tests/formula.rs b/integration-tests/tests/formula.rs new file mode 100644 index 0000000..dce4c26 --- /dev/null +++ b/integration-tests/tests/formula.rs @@ -0,0 +1,53 @@ +use approx::abs_diff_eq; +use serde::Deserialize; +use serde_json::json; +use tracing::info; + +mod common; +use common::prepare::Context; + +const EPS: f64 = 0.00001; +const CASES_JSON: &str = include_str!("../data/formula_cases.json"); + +#[derive(Deserialize)] +struct Case { + steps_since_tge: String, + steps: u32, + expected: f64, +} + +#[tokio::test] +#[tracing::instrument] +async fn test_formula() -> anyhow::Result<()> { + let context = Context::builder().build().await?; + + info!("view get_steps_since_tge"); + let steps_since_tge: String = context.sweat.view("get_steps_since_tge").await?.json()?; + info!(value = %steps_since_tge, "steps_since_tge"); + assert_eq!(0_u64, steps_since_tge.parse::()?); + + let cases: Vec = serde_json::from_str(CASES_JSON)?; + info!(cases = cases.len(), "iterating formula cases"); + + for (i, case) in cases.iter().enumerate() { + let raw: String = context + .sweat + .view("formula") + .args_json(json!({ "steps_since_tge": case.steps_since_tge, "steps": case.steps })) + .await? + .json()?; + let value = raw.parse::()? as f64 / 1e18; + assert!( + abs_diff_eq!(value, case.expected, epsilon = EPS), + "case #{i} (tge={}, steps={}): expected {}, got {} (diff {})", + case.steps_since_tge, + case.steps, + case.expected, + value, + value - case.expected, + ); + } + + info!(passed = cases.len(), "all cases passed"); + Ok(()) +} diff --git a/integration-tests/tests/migration.rs b/integration-tests/tests/migration.rs new file mode 100644 index 0000000..5cb4fb4 --- /dev/null +++ b/integration-tests/tests/migration.rs @@ -0,0 +1,200 @@ +use std::path::PathBuf; + +use near_workspaces::{types::NearToken, Account}; +use serde_json::json; +use tracing::info; + +mod common; +use common::helpers::init_tracing; + +const FT_POSTFIX: &str = ".u.sweat.testnet"; +const INITIAL_USER_BALANCE: NearToken = NearToken::from_near(10); + +fn old_wasm_path() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("..") + .join("res") + .join("sweat_old.wasm") +} + +fn new_wasm_path() -> PathBuf { + std::env::var_os("SWEAT_WASM").map(PathBuf::from).unwrap_or_else(|| { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("target") + .join("integration-wasm") + .join("contract.wasm") + }) +} + +async fn create_user(root: &Account, name: &str) -> anyhow::Result { + Ok(root + .create_subaccount(name) + .initial_balance(INITIAL_USER_BALANCE) + .transact() + .await? + .into_result()?) +} + +#[tokio::test] +#[tracing::instrument] +async fn migration_from_deployed_release() -> anyhow::Result<()> { + init_tracing(); + + info!("booting sandbox"); + let worker = near_workspaces::sandbox().await?; + let root = worker.root_account()?; + + info!("deploying old contract"); + let old_wasm = std::fs::read(old_wasm_path())?; + let contract = worker.dev_deploy(&old_wasm).await?; + + contract + .call("new") + .args_json(json!({ "postfix": FT_POSTFIX })) + .transact() + .await? + .into_result()?; + + let oracle1 = create_user(&root, "oracle1").await?; + let oracle2 = create_user(&root, "oracle2").await?; + let alice = create_user(&root, "alice").await?; + let denied = create_user(&root, "denied").await?; + let admin = create_user(&root, "admin").await?; + let denylist_manager = create_user(&root, "denylist-manager").await?; + let pause_manager = create_user(&root, "pause-manager").await?; + let unpause_manager = create_user(&root, "unpause-manager").await?; + + info!("registering oracles on the old contract"); + for oracle in [&oracle1, &oracle2] { + contract + .call("add_oracle") + .args_json(json!({ "account_id": oracle.id() })) + .transact() + .await? + .into_result()?; + } + + info!("denylisting an account on the old contract"); + contract + .call("set_restricted") + .args_json(json!({ "account_id": denied.id(), "is_restricted": true })) + .transact() + .await? + .into_result()?; + + info!("recording a batch on the old contract"); + oracle1 + .call(contract.id(), "record_batch") + .args_json(json!({ "steps_batch": [[alice.id(), 10_000]] })) + .max_gas() + .transact() + .await? + .into_result()?; + + let oracles_before: Vec = contract.view("get_oracles").await?.json()?; + assert_eq!(oracles_before.len(), 2, "old contract should have 2 oracles"); + let denied_restricted_before: bool = contract + .view("is_restricted") + .args_json(json!({ "account_id": denied.id() })) + .await? + .json()?; + assert!(denied_restricted_before, "denied account should be restricted before migration"); + let steps_before: String = contract.view("get_steps_since_tge").await?.json()?; + let alice_balance_before: String = contract + .view("ft_balance_of") + .args_json(json!({ "account_id": alice.id() })) + .await? + .json()?; + assert_ne!( + alice_balance_before, "0", + "alice should have a balance before migration" + ); + info!(steps = %steps_before, balance = %alice_balance_before, "pre-migration snapshot"); + + info!("deploying new contract over the same account"); + let new_wasm = std::fs::read(new_wasm_path())?; + contract.as_account().deploy(&new_wasm).await?.into_result()?; + + info!("calling migrate [signer=contract account]"); + contract + .call("migrate") + .args_json(json!({ + "holding_account_id": root.id(), + "super_admin_account_id": admin.id(), + "denylist_manager_account_ids": [denylist_manager.id()], + "pause_manager_account_ids": [pause_manager.id()], + "unpause_manager_account_ids": [unpause_manager.id()], + })) + .max_gas() + .transact() + .await? + .into_result()?; + + info!("verifying super admin"); + let is_super_admin: bool = contract + .view("acl_is_super_admin") + .args_json(json!({ "account_id": admin.id() })) + .await? + .json()?; + assert!(is_super_admin, "admin account should be the ACL super admin"); + + info!("verifying role managers migrated to their ACL roles"); + for (role, manager) in [ + ("DenylistManager", &denylist_manager), + ("PauseManager", &pause_manager), + ("UnpauseManager", &unpause_manager), + ] { + let has_role: bool = contract + .view("acl_has_role") + .args_json(json!({ "role": role, "account_id": manager.id() })) + .await? + .json()?; + assert!(has_role, "{} should hold the {} role", manager.id(), role); + } + + info!("verifying oracles migrated to the ACL Oracle role"); + let grantees: Vec = contract + .view("acl_get_grantees") + .args_json(json!({ "role": "Oracle", "skip": 0, "limit": 100 })) + .await? + .json()?; + assert_eq!(grantees.len(), 2, "both oracles should hold the Oracle role"); + for oracle in [&oracle1, &oracle2] { + let has_role: bool = contract + .view("acl_has_role") + .args_json(json!({ "role": "Oracle", "account_id": oracle.id() })) + .await? + .json()?; + assert!(has_role, "{} should hold the Oracle role", oracle.id()); + } + + info!("verifying the denylist survived the migration"); + let denied_restricted_after: bool = contract + .view("is_restricted") + .args_json(json!({ "account_id": denied.id() })) + .await? + .json()?; + assert!( + denied_restricted_after, + "denylisted account must stay restricted after migration" + ); + + info!("verifying token state survived"); + let steps_after: String = contract.view("get_steps_since_tge").await?.json()?; + assert_eq!(steps_after, steps_before, "steps counter must be preserved"); + let alice_balance_after: String = contract + .view("ft_balance_of") + .args_json(json!({ "account_id": alice.id() })) + .await? + .json()?; + assert_eq!(alice_balance_after, alice_balance_before, "balance must be preserved"); + + info!("verifying the legacy get_oracles view is gone"); + assert!( + contract.view("get_oracles").await.is_err(), + "get_oracles should be removed from the new contract" + ); + + info!("done"); + Ok(()) +} diff --git a/integration-tests/tests/pause.rs b/integration-tests/tests/pause.rs new file mode 100644 index 0000000..ebd8d68 --- /dev/null +++ b/integration-tests/tests/pause.rs @@ -0,0 +1,337 @@ +use near_workspaces::types::NearToken; +use serde_json::json; +use tracing::info; + +mod common; +use common::{panic::PanicFinder, prepare::Context}; + +#[tokio::test] +#[tracing::instrument] +async fn test_pause_all() -> anyhow::Result<()> { + let context = Context::builder().with_oracle().with_claim().with_bob().build().await?; + + info!("call pause_features(ALL) [signer=alice, unauthorized]"); + let result = context + .alice + .call(context.sweat.id(), "pause_features") + .args_json(json!({ "features": ["token", "minting"] })) + .transact() + .await? + .into_result(); + assert!(result.has_panic("Insufficient permissions for method pause_features restricted by access control.")); + info!("pause_features: {result:?}"); + + info!("call acl_grant_role(PauseManager, alice) [signer=contract]"); + let role_is_granted: bool = context + .sweat + .call("acl_grant_role") + .args_json(json!({ + "role": "PauseManager", + "account_id": context.alice.id(), + })) + .transact() + .await? + .json()?; + assert!(role_is_granted); + info!("acl_grant_role: {role_is_granted:?}"); + + info!("call acl_grant_role(PauseManager, alice) [signer=contract] — idempotent"); + let role_is_granted: bool = context + .sweat + .call("acl_grant_role") + .args_json(json!({ + "role": "PauseManager", + "account_id": context.alice.id(), + })) + .transact() + .await? + .json()?; + assert!(!role_is_granted); + info!("acl_grant_role: {role_is_granted:?}"); + + info!("call pause_features(ALL) [signer=alice]"); + let is_paused: bool = context + .alice + .call(context.sweat.id(), "pause_features") + .args_json(json!({ "features": ["token", "minting"] })) + .transact() + .await? + .json()?; + assert!(is_paused); + info!("pause_features: {is_paused:?}"); + + info!("call pause_features(ALL) [signer=alice] — idempotent"); + let is_paused: bool = context + .alice + .call(context.sweat.id(), "pause_features") + .args_json(json!({ "features": ["token", "minting"] })) + .transact() + .await? + .json()?; + assert!(!is_paused); + info!("pause_features: {is_paused:?}"); + + info!("call ft_transfer(bob, 1000000000000000000) [signer=alice] — pause check fires before balance check"); + let result = context + .alice + .call(context.sweat.id(), "ft_transfer") + .args_json(json!({ + "receiver_id": context.bob().id(), + "amount": "1000000000000000000", + })) + .deposit(NearToken::from_yoctonear(1)) + .transact() + .await? + .into_result(); + assert!(result.has_panic("Feature 'token' is paused")); + info!("ft_transfer: {result:?}"); + + info!("call defer_batch([(alice, 10_000)]) [signer=oracle]"); + let result = context + .oracle() + .call(context.sweat.id(), "defer_batch") + .args_json(json!({ "steps_batch": [[context.alice.id(), 10_000]] })) + .max_gas() + .transact() + .await? + .into_result(); + assert!(result.has_panic("Feature 'minting' is paused")); + info!("defer_batch: {result:?}"); + + info!("call unpause_features(ALL) [signer=alice, unauthorized]"); + let result = context + .alice + .call(context.sweat.id(), "unpause_features") + .args_json(json!({ "features": ["token", "minting"] })) + .transact() + .await? + .into_result(); + assert!(result.has_panic("Insufficient permissions for method unpause_features restricted by access control.")); + info!("unpause_features: {result:?}"); + + info!("call acl_grant_role(UnpauseManager, alice) [signer=contract]"); + let role_is_granted: bool = context + .sweat + .call("acl_grant_role") + .args_json(json!({ + "role": "UnpauseManager", + "account_id": context.alice.id(), + })) + .transact() + .await? + .json()?; + assert!(role_is_granted); + info!("acl_grant_role: {role_is_granted:?}"); + + info!("call unpause_features(ALL) [signer=alice]"); + let is_unpaused: bool = context + .alice + .call(context.sweat.id(), "unpause_features") + .args_json(json!({ "features": ["token", "minting"] })) + .transact() + .await? + .json()?; + assert!(is_unpaused); + info!("unpause_features: {is_unpaused:?}"); + + info!("call unpause_features(ALL) [signer=alice] — idempotent"); + let is_unpaused: bool = context + .alice + .call(context.sweat.id(), "unpause_features") + .args_json(json!({ "features": ["token", "minting"] })) + .transact() + .await? + .json()?; + assert!(!is_unpaused); + info!("unpause_features: {is_unpaused:?}"); + + info!("call defer_batch([(alice, 10_000)]) [signer=oracle] — minting works after unpause"); + context + .oracle() + .call(context.sweat.id(), "defer_batch") + .args_json(json!({ "steps_batch": [[context.alice.id(), 10_000]] })) + .max_gas() + .transact() + .await? + .into_result()?; + + Ok(()) +} + +#[tokio::test] +#[tracing::instrument] +async fn test_pause_minting() -> anyhow::Result<()> { + let context = Context::builder().with_oracle().with_claim().build().await?; + + info!("call acl_grant_role(PauseManager, alice) [signer=contract]"); + let role_is_granted: bool = context + .sweat + .call("acl_grant_role") + .args_json(json!({ + "role": "PauseManager", + "account_id": context.alice.id(), + })) + .transact() + .await? + .json()?; + assert!(role_is_granted); + info!("acl_grant_role: {role_is_granted:?}"); + + info!("call pause_features(minting) [signer=alice]"); + let is_paused: bool = context + .alice + .call(context.sweat.id(), "pause_features") + .args_json(json!({ "features": ["minting"] })) + .transact() + .await? + .json()?; + assert!(is_paused); + info!("pause_features: {is_paused:?}"); + + info!("call defer_batch([(alice, 10_000)]) [signer=oracle]"); + let result = context + .oracle() + .call(context.sweat.id(), "defer_batch") + .args_json(json!({ "steps_batch": [[context.alice.id(), 10_000]] })) + .max_gas() + .transact() + .await? + .into_result(); + assert!(result.has_panic("Feature 'minting' is paused")); + info!("defer_batch: {result:?}"); + + info!("call acl_grant_role(UnpauseManager, alice) [signer=contract]"); + let role_is_granted: bool = context + .sweat + .call("acl_grant_role") + .args_json(json!({ + "role": "UnpauseManager", + "account_id": context.alice.id(), + })) + .transact() + .await? + .json()?; + assert!(role_is_granted); + info!("acl_grant_role: {role_is_granted:?}"); + + info!("call unpause_features(minting) [signer=alice]"); + let is_unpaused: bool = context + .alice + .call(context.sweat.id(), "unpause_features") + .args_json(json!({ "features": ["minting"] })) + .transact() + .await? + .json()?; + assert!(is_unpaused); + info!("unpause_features: {is_unpaused:?}"); + + info!("call defer_batch([(alice, 10_000)]) [signer=oracle] — minting works after unpause"); + context + .oracle() + .call(context.sweat.id(), "defer_batch") + .args_json(json!({ "steps_batch": [[context.alice.id(), 10_000]] })) + .max_gas() + .transact() + .await? + .into_result()?; + + Ok(()) +} + +#[tokio::test] +#[tracing::instrument] +async fn test_pause_token() -> anyhow::Result<()> { + let context = Context::builder().with_oracle().with_claim().with_bob().build().await?; + + info!("call acl_grant_role(PauseManager, alice) [signer=contract]"); + let role_is_granted: bool = context + .sweat + .call("acl_grant_role") + .args_json(json!({ + "role": "PauseManager", + "account_id": context.alice.id(), + })) + .transact() + .await? + .json()?; + assert!(role_is_granted); + info!("acl_grant_role: {role_is_granted:?}"); + + info!("call pause_features(token) [signer=alice]"); + let is_paused: bool = context + .alice + .call(context.sweat.id(), "pause_features") + .args_json(json!({ "features": ["token"] })) + .transact() + .await? + .json()?; + assert!(is_paused); + info!("pause_features: {is_paused:?}"); + + info!("call ft_transfer(bob, 1000000000000000000) [signer=alice] — pause check fires before balance check"); + let result = context + .alice + .call(context.sweat.id(), "ft_transfer") + .args_json(json!({ + "receiver_id": context.bob().id(), + "amount": "1000000000000000000", + })) + .deposit(NearToken::from_yoctonear(1)) + .transact() + .await? + .into_result(); + assert!(result.has_panic("Feature 'token' is paused")); + info!("ft_transfer: {result:?}"); + + info!("call ft_transfer_call(bob, 1000000000000000000) [signer=alice]"); + let result = context + .alice + .call(context.sweat.id(), "ft_transfer_call") + .args_json(json!({ + "receiver_id": context.bob().id(), + "amount": "1000000000000000000", + "msg": "", + })) + .deposit(NearToken::from_yoctonear(1)) + .max_gas() + .transact() + .await? + .into_result(); + assert!(result.has_panic("Feature 'token' is paused")); + info!("ft_transfer_call: {result:?}"); + + info!("call burn(1000000000000000000) [signer=alice]"); + let result = context + .alice + .call(context.sweat.id(), "burn") + .args_json(json!({ "amount": "1000000000000000000" })) + .transact() + .await? + .into_result(); + assert!(result.has_panic("Feature 'token' is paused")); + info!("burn: {result:?}"); + + info!("call storage_unregister(force=true) [signer=alice] — pause check fires before denylist check"); + let result = context + .alice + .call(context.sweat.id(), "storage_unregister") + .args_json(json!({ "force": true })) + .deposit(NearToken::from_yoctonear(1)) + .transact() + .await? + .into_result(); + assert!(result.has_panic("Feature 'token' is paused")); + info!("storage_unregister: {result:?}"); + + info!("call defer_batch([(alice, 10_000)]) [signer=oracle] — minting feature not paused, should succeed"); + context + .oracle() + .call(context.sweat.id(), "defer_batch") + .args_json(json!({ "steps_batch": [[context.alice.id(), 10_000]] })) + .max_gas() + .transact() + .await? + .into_result()?; + + Ok(()) +} diff --git a/integration-tests/tests/payout.rs b/integration-tests/tests/payout.rs new file mode 100644 index 0000000..0b46cbb --- /dev/null +++ b/integration-tests/tests/payout.rs @@ -0,0 +1,59 @@ +//! Drift guard for `helpers::payout()`. +//! +//! `helpers::payout()` mirrors `Payout::from(u128)` in `contract/src/api.rs`. +//! Nothing forces them to stay in sync. This test asks the deployed contract +//! to compute a single-row payout via `calculate_payout_with_fee_for_batch` +//! (with batch_size=1, internally `Payout::from(formula(0, STEPS))`) and +//! compares to the locally-computed split. Divergence — a fee-percentage +//! change, a rounding-rule change, a swapped tuple order — fails here first. + +use serde_json::json; +use tracing::info; + +mod common; +use common::helpers::payout; +use common::prepare::Context; + +const STEPS: u32 = 10_000; + +#[tokio::test] +#[tracing::instrument] +async fn payout_helper_matches_contract() -> anyhow::Result<()> { + let context = Context::builder().build().await?; + + info!(steps = STEPS, "view formula(0, STEPS)"); + let minted: String = context + .sweat + .view("formula") + .args_json(json!({ "steps_since_tge": "0", "steps": STEPS })) + .await? + .json()?; + let value: u128 = minted.parse()?; + info!(value, "minted amount for one row"); + + info!("view calculate_payout_with_fee_for_batch(batch_size=1, claim_amount=STEPS)"); + let (contract_fee, contract_for_user): (String, String) = context + .sweat + .view("calculate_payout_with_fee_for_batch") + .args_json(json!({ "batch_size": 1, "claim_amount": STEPS })) + .await? + .json()?; + let contract_fee: u128 = contract_fee.parse()?; + let contract_for_user: u128 = contract_for_user.parse()?; + info!(contract_fee, contract_for_user, "contract payout split"); + + let (local_for_user, local_fee) = payout(value); + info!(local_fee, local_for_user, "helper payout split"); + + assert_eq!( + local_fee, contract_fee, + "fee diverged: helper says {local_fee}, contract says {contract_fee} (value={value})" + ); + assert_eq!( + local_for_user, contract_for_user, + "amount_for_user diverged: helper says {local_for_user}, contract says {contract_for_user} (value={value})" + ); + + info!("payout helper matches contract Payout::from"); + Ok(()) +} diff --git a/integration-tests/tests/restriction.rs b/integration-tests/tests/restriction.rs new file mode 100644 index 0000000..29023ee --- /dev/null +++ b/integration-tests/tests/restriction.rs @@ -0,0 +1,123 @@ +use near_workspaces::types::NearToken; +use serde_json::json; +use tracing::info; + +mod common; +use common::{panic::PanicFinder, prepare::Context, storage::register_for_storage}; + +async fn restrict_alice(context: &Context) -> anyhow::Result<()> { + info!("call acl_grant_role(DenylistManager, sweat) [signer=contract, super-admin]"); + context + .sweat + .call("acl_grant_role") + .args_json(json!({ + "role": "DenylistManager", + "account_id": context.sweat.id(), + })) + .transact() + .await? + .into_result()?; + + info!("call set_restricted(alice, true) [signer=contract, DenylistManager]"); + context + .sweat + .call("set_restricted") + .args_json(json!({ + "account_id": context.alice.id(), + "is_restricted": true, + })) + .transact() + .await? + .into_result()?; + + let is_restricted: bool = context + .sweat + .view("is_restricted") + .args_json(json!({ "account_id": context.alice.id() })) + .await? + .json()?; + assert!(is_restricted); + info!("alice is restricted"); + + Ok(()) +} + +#[tokio::test] +#[tracing::instrument] +async fn test_restricted_cannot_ft_transfer() -> anyhow::Result<()> { + let context = Context::builder().with_bob().build().await?; + + info!("register bob for FT storage"); + register_for_storage(&context.sweat, context.bob().id()).await?; + + restrict_alice(&context).await?; + + info!("call ft_transfer(bob, 1000000000000000000) [signer=alice, restricted]"); + let result = context + .alice + .call(context.sweat.id(), "ft_transfer") + .args_json(json!({ + "receiver_id": context.bob().id(), + "amount": "1000000000000000000", + })) + .deposit(NearToken::from_yoctonear(1)) + .transact() + .await? + .into_result(); + assert!(result.has_panic(&format!("The account {} is restricted", context.alice.id()))); + info!("ft_transfer: {result:?}"); + + Ok(()) +} + +#[tokio::test] +#[tracing::instrument] +async fn test_restricted_cannot_ft_transfer_call() -> anyhow::Result<()> { + let context = Context::builder().with_bob().build().await?; + + info!("register bob for FT storage"); + register_for_storage(&context.sweat, context.bob().id()).await?; + + restrict_alice(&context).await?; + + info!("call ft_transfer_call(bob, 1000000000000000000) [signer=alice, restricted]"); + let result = context + .alice + .call(context.sweat.id(), "ft_transfer_call") + .args_json(json!({ + "receiver_id": context.bob().id(), + "amount": "1000000000000000000", + "msg": "", + })) + .deposit(NearToken::from_yoctonear(1)) + .max_gas() + .transact() + .await? + .into_result(); + assert!(result.has_panic(&format!("The account {} is restricted", context.alice.id()))); + info!("ft_transfer_call: {result:?}"); + + Ok(()) +} + +#[tokio::test] +#[tracing::instrument] +async fn test_restricted_cannot_burn() -> anyhow::Result<()> { + let context = Context::builder().build().await?; + + restrict_alice(&context).await?; + + info!("call burn(1000000000000000000) [signer=alice, restricted]"); + let result = context + .alice + .call(context.sweat.id(), "burn") + .args_json(json!({ "amount": "1000000000000000000" })) + .deposit(NearToken::from_yoctonear(1)) + .transact() + .await? + .into_result(); + assert!(result.has_panic(&format!("The account {} is restricted", context.alice.id()))); + info!("burn: {result:?}"); + + Ok(()) +} diff --git a/model/Cargo.toml b/model/Cargo.toml deleted file mode 100644 index 8435611..0000000 --- a/model/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "sweat-model" -version = "0.1.0" -edition = "2021" - -[features] -default = [] -integration-test = ["dep:integration-utils", "dep:near-workspaces"] - -[dependencies] -anyhow = { workspace = true } -async-trait = { workspace = true } -integration-trait = { workspace = true } - -near-sdk = { workspace = true } -near-contract-standards = { workspace = true } - -integration-utils = { workspace = true, optional = true } -near-workspaces = { workspace = true, optional = true } diff --git a/model/src/lib.rs b/model/src/lib.rs deleted file mode 100644 index 4b6f14b..0000000 --- a/model/src/lib.rs +++ /dev/null @@ -1,116 +0,0 @@ -#![allow(clippy::new_ret_no_self, clippy::wrong_self_convention)] - -use integration_trait::make_integration_version; -use near_contract_standards::storage_management::{StorageBalance, StorageBalanceBounds}; -use near_sdk::{ - json_types::{U128, U64}, - AccountId, PromiseOrValue, -}; - -#[cfg(feature = "integration-test")] -pub struct SweatContract<'a> { - pub contract: &'a near_workspaces::Contract, -} - -#[make_integration_version] -pub trait SweatApi { - fn new(postfix: Option) -> Self; - fn add_oracle(&mut self, account_id: &AccountId); - fn remove_oracle(&mut self, account_id: &AccountId); - fn get_oracles(&self) -> Vec; - fn tge_mint(&mut self, account_id: &AccountId, amount: U128); - fn tge_mint_batch(&mut self, batch: Vec<(AccountId, U128)>); - fn burn(&mut self, amount: &U128); - fn get_steps_since_tge(&self) -> U64; - fn record_batch(&mut self, steps_batch: Vec<(AccountId, u32)>); - fn formula(&self, steps_since_tge: U64, steps: u32) -> U128; -} - -pub trait RestrictionApi { - fn is_restricted(&self, account_id: &AccountId) -> bool; - fn set_restricted(&mut self, account_id: &AccountId, is_restricted: bool); -} - -#[make_integration_version] -pub trait SweatDefer { - fn defer_batch(&mut self, steps_batch: Vec<(AccountId, u32)>, holding_account_id: AccountId) -> PromiseOrValue<()>; -} - -/// Copy of near_sdk trait to use in integration tests -#[make_integration_version] -pub trait FungibleTokenCore { - #[deposit_one_yocto] - fn ft_transfer(&mut self, receiver_id: AccountId, amount: U128, memo: Option); - fn ft_transfer_call( - &mut self, - receiver_id: AccountId, - amount: U128, - memo: Option, - msg: String, - ) -> PromiseOrValue; - fn ft_total_supply(&self) -> U128; - fn ft_balance_of(&self, account_id: AccountId) -> U128; -} - -/// Copy of near_sdk trait to use in integration tests -#[make_integration_version] -pub trait StorageManagement { - // if `registration_only=true` MUST refund above the minimum balance if the account didn't exist and - // refund full deposit if the account exists. - #[deposit_yocto = near_sdk::env::storage_byte_cost() * 125] - fn storage_deposit(&mut self, account_id: Option, registration_only: Option) -> StorageBalance; - - /// Withdraw specified amount of available Ⓝ for predecessor account. - /// - /// This method is safe to call. It MUST NOT remove data. - /// - /// `amount` is sent as a string representing an unsigned 128-bit integer. If - /// omitted, contract MUST refund full `available` balance. If `amount` exceeds - /// predecessor account's available balance, contract MUST panic. - /// - /// If predecessor account not registered, contract MUST panic. - /// - /// MUST require exactly 1 yoctoNEAR attached balance to prevent restricted - /// function-call access-key call (UX wallet security) - /// - /// Returns the StorageBalance structure showing updated balances. - fn storage_withdraw(&mut self, amount: Option) -> StorageBalance; - - /// Unregisters the predecessor account and returns the storage NEAR deposit back. - /// - /// If the predecessor account is not registered, the function MUST return `false` without panic. - /// - /// If `force=true` the function SHOULD ignore account balances (burn them) and close the account. - /// Otherwise, MUST panic if caller has a positive registered balance (eg token holdings) or - /// the contract doesn't support force unregistration. - /// MUST require exactly 1 yoctoNEAR attached balance to prevent restricted function-call access-key call - /// (UX wallet security) - /// Returns `true` iff the account was unregistered. - /// Returns `false` iff account was not registered before. - fn storage_unregister(&mut self, force: Option) -> bool; - - fn storage_balance_bounds(&self) -> StorageBalanceBounds; - - fn storage_balance_of(&self, account_id: AccountId) -> Option; -} - -#[make_integration_version] -pub trait IntegrationTestMethods { - fn calculate_payout_with_fee_for_batch(&self, batch_size: u32, claim_amount: u32) -> (U128, U128); -} - -pub struct Payout { - pub amount_for_user: u128, - pub fee: u128, -} - -impl From for Payout { - fn from(value: u128) -> Self { - let fee = (value * 5).div_ceil(100); - - Self { - fee, - amount_for_user: value - fee, - } - } -} diff --git a/res/contract.wasm b/res/contract.wasm new file mode 100644 index 0000000..f7f5328 Binary files /dev/null and b/res/contract.wasm differ diff --git a/res/contract_abi.json b/res/contract_abi.json new file mode 100644 index 0000000..304215a --- /dev/null +++ b/res/contract_abi.json @@ -0,0 +1,1430 @@ +{ + "schema_version": "0.4.0", + "metadata": { + "name": "contract", + "version": "1.3.0", + "build": { + "compiler": "rustc 1.86.0", + "builder": "cargo-near cargo-near-build 0.11.0" + }, + "wasm_hash": "8qN5Q5wxyzZ7ik1SkANXnPKk1AXb9MzoXDzhkD3tvXzW" + }, + "body": { + "functions": [ + { + "name": "acl_add_admin", + "kind": "call", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "role", + "type_schema": { + "type": "string" + } + }, + { + "name": "account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": [ + "boolean", + "null" + ] + } + } + }, + { + "name": "acl_add_super_admin", + "kind": "call", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": [ + "boolean", + "null" + ] + } + } + }, + { + "name": "acl_get_admins", + "kind": "view", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "role", + "type_schema": { + "type": "string" + } + }, + { + "name": "skip", + "type_schema": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + { + "name": "limit", + "type_schema": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": "array", + "items": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + } + }, + { + "name": "acl_get_grantees", + "kind": "view", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "role", + "type_schema": { + "type": "string" + } + }, + { + "name": "skip", + "type_schema": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + { + "name": "limit", + "type_schema": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": "array", + "items": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + } + }, + { + "name": "acl_get_permissioned_accounts", + "kind": "view", + "result": { + "serialization_type": "json", + "type_schema": { + "$ref": "#/definitions/PermissionedAccounts" + } + } + }, + { + "name": "acl_get_super_admins", + "kind": "view", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "skip", + "type_schema": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + { + "name": "limit", + "type_schema": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": "array", + "items": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + } + }, + { + "name": "acl_grant_role", + "kind": "call", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "role", + "type_schema": { + "type": "string" + } + }, + { + "name": "account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": [ + "boolean", + "null" + ] + } + } + }, + { + "name": "acl_has_any_role", + "kind": "view", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "roles", + "type_schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": "boolean" + } + } + }, + { + "name": "acl_has_role", + "kind": "view", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "role", + "type_schema": { + "type": "string" + } + }, + { + "name": "account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": "boolean" + } + } + }, + { + "name": "acl_init_super_admin", + "kind": "call", + "modifiers": [ + "private" + ], + "params": { + "serialization_type": "json", + "args": [ + { + "name": "account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": "boolean" + } + } + }, + { + "name": "acl_is_admin", + "kind": "view", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "role", + "type_schema": { + "type": "string" + } + }, + { + "name": "account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": "boolean" + } + } + }, + { + "name": "acl_is_super_admin", + "kind": "view", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": "boolean" + } + } + }, + { + "name": "acl_renounce_admin", + "kind": "call", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "role", + "type_schema": { + "type": "string" + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": "boolean" + } + } + }, + { + "name": "acl_renounce_role", + "kind": "call", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "role", + "type_schema": { + "type": "string" + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": "boolean" + } + } + }, + { + "name": "acl_revoke_admin", + "kind": "call", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "role", + "type_schema": { + "type": "string" + } + }, + { + "name": "account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": [ + "boolean", + "null" + ] + } + } + }, + { + "name": "acl_revoke_role", + "kind": "call", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "role", + "type_schema": { + "type": "string" + } + }, + { + "name": "account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": [ + "boolean", + "null" + ] + } + } + }, + { + "name": "acl_revoke_super_admin", + "kind": "call", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": [ + "boolean", + "null" + ] + } + } + }, + { + "name": "acl_role_variants", + "kind": "view", + "result": { + "serialization_type": "json", + "type_schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + { + "name": "acl_storage_prefix", + "kind": "view", + "result": { + "serialization_type": "json", + "type_schema": { + "type": "array", + "items": { + "type": "integer", + "format": "uint8", + "minimum": 0.0 + } + } + } + }, + { + "name": "acl_transfer_super_admin", + "kind": "call", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": [ + "boolean", + "null" + ] + } + } + }, + { + "name": "burn", + "kind": "call", + "modifiers": [ + "payable" + ], + "params": { + "serialization_type": "json", + "args": [ + { + "name": "amount", + "type_schema": { + "type": "string" + } + } + ] + } + }, + { + "name": "contract_source_metadata", + "kind": "view" + }, + { + "name": "defer_batch", + "kind": "call", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "steps_batch", + "type_schema": { + "type": "array", + "items": { + "type": "array", + "items": [ + { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + }, + { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + ], + "maxItems": 2, + "minItems": 2 + } + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "$ref": "#/definitions/PromiseOrValueNull" + } + } + }, + { + "name": "formula", + "kind": "view", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "steps_since_tge", + "type_schema": { + "type": "string" + } + }, + { + "name": "steps", + "type_schema": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": "string" + } + } + }, + { + "name": "ft_balance_of", + "kind": "view", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": "string" + } + } + }, + { + "name": "ft_metadata", + "kind": "view", + "result": { + "serialization_type": "json", + "type_schema": { + "$ref": "#/definitions/FungibleTokenMetadata" + } + } + }, + { + "name": "ft_resolve_transfer", + "kind": "call", + "modifiers": [ + "private" + ], + "params": { + "serialization_type": "json", + "args": [ + { + "name": "sender_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + }, + { + "name": "receiver_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + }, + { + "name": "amount", + "type_schema": { + "type": "string" + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": "string" + } + } + }, + { + "name": "ft_total_supply", + "kind": "view", + "result": { + "serialization_type": "json", + "type_schema": { + "type": "string" + } + } + }, + { + "name": "ft_transfer", + "kind": "call", + "modifiers": [ + "payable" + ], + "params": { + "serialization_type": "json", + "args": [ + { + "name": "receiver_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + }, + { + "name": "amount", + "type_schema": { + "type": "string" + } + }, + { + "name": "memo", + "type_schema": { + "type": [ + "string", + "null" + ] + } + } + ] + } + }, + { + "name": "ft_transfer_call", + "kind": "call", + "modifiers": [ + "payable" + ], + "params": { + "serialization_type": "json", + "args": [ + { + "name": "receiver_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + }, + { + "name": "amount", + "type_schema": { + "type": "string" + } + }, + { + "name": "memo", + "type_schema": { + "type": [ + "string", + "null" + ] + } + }, + { + "name": "msg", + "type_schema": { + "type": "string" + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "$ref": "#/definitions/PromiseOrValueString" + } + } + }, + { + "name": "get_holding_account_id", + "kind": "view", + "result": { + "serialization_type": "json", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + }, + { + "name": "get_paused_features", + "kind": "view", + "result": { + "serialization_type": "json", + "type_schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Feature" + } + } + } + }, + { + "name": "get_steps_since_tge", + "kind": "view", + "result": { + "serialization_type": "json", + "type_schema": { + "type": "string" + } + } + }, + { + "name": "is_feature_paused", + "kind": "view", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "feature", + "type_schema": { + "$ref": "#/definitions/Feature" + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": "boolean" + } + } + }, + { + "name": "is_restricted", + "kind": "view", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": "boolean" + } + } + }, + { + "name": "migrate", + "kind": "call", + "modifiers": [ + "init", + "private" + ], + "params": { + "serialization_type": "json", + "args": [ + { + "name": "holding_account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + }, + { + "name": "super_admin_account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + }, + { + "name": "denylist_manager_account_ids", + "type_schema": { + "type": "array", + "items": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + }, + { + "name": "pause_manager_account_ids", + "type_schema": { + "type": "array", + "items": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + }, + { + "name": "unpause_manager_account_ids", + "type_schema": { + "type": "array", + "items": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + } + ] + } + }, + { + "name": "new", + "kind": "call", + "modifiers": [ + "init" + ], + "params": { + "serialization_type": "json", + "args": [ + { + "name": "holding_account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + }, + { + "name": "super_admin_account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + }, + { + "name": "oracle_account_ids", + "type_schema": { + "type": "array", + "items": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + }, + { + "name": "denylist_manager_account_ids", + "type_schema": { + "type": "array", + "items": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + }, + { + "name": "pause_manager_account_ids", + "type_schema": { + "type": "array", + "items": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + }, + { + "name": "unpause_manager_account_ids", + "type_schema": { + "type": "array", + "items": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + } + ] + } + }, + { + "name": "on_record", + "kind": "call", + "modifiers": [ + "private" + ], + "params": { + "serialization_type": "json", + "args": [ + { + "name": "receiver_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + }, + { + "name": "amount", + "type_schema": { + "type": "string" + } + }, + { + "name": "fee_account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + }, + { + "name": "fee", + "type_schema": { + "type": "string" + } + }, + { + "name": "steps_increment", + "type_schema": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } + ] + } + }, + { + "name": "pause_features", + "kind": "call", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "features", + "type_schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Feature" + } + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": "boolean" + } + } + }, + { + "name": "set_holding_account_id", + "kind": "call", + "modifiers": [ + "private" + ], + "params": { + "serialization_type": "json", + "args": [ + { + "name": "account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + ] + } + }, + { + "name": "set_restricted", + "kind": "call", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + }, + { + "name": "is_restricted", + "type_schema": { + "type": "boolean" + } + } + ] + } + }, + { + "name": "storage_balance_bounds", + "kind": "view", + "result": { + "serialization_type": "json", + "type_schema": { + "$ref": "#/definitions/StorageBalanceBounds" + } + } + }, + { + "name": "storage_balance_of", + "kind": "view", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "anyOf": [ + { + "$ref": "#/definitions/StorageBalance" + }, + { + "type": "null" + } + ] + } + } + }, + { + "name": "storage_deposit", + "kind": "call", + "modifiers": [ + "payable" + ], + "params": { + "serialization_type": "json", + "args": [ + { + "name": "account_id", + "type_schema": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": [ + "string", + "null" + ] + } + }, + { + "name": "registration_only", + "type_schema": { + "type": [ + "boolean", + "null" + ] + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "$ref": "#/definitions/StorageBalance" + } + } + }, + { + "name": "storage_unregister", + "kind": "call", + "modifiers": [ + "payable" + ], + "params": { + "serialization_type": "json", + "args": [ + { + "name": "force", + "type_schema": { + "type": [ + "boolean", + "null" + ] + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": "boolean" + } + } + }, + { + "name": "storage_withdraw", + "kind": "call", + "modifiers": [ + "payable" + ], + "params": { + "serialization_type": "json", + "args": [ + { + "name": "amount", + "type_schema": { + "type": [ + "string", + "null" + ] + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "$ref": "#/definitions/StorageBalance" + } + } + }, + { + "name": "unpause_features", + "kind": "call", + "params": { + "serialization_type": "json", + "args": [ + { + "name": "features", + "type_schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Feature" + } + } + } + ] + }, + "result": { + "serialization_type": "json", + "type_schema": { + "type": "boolean" + } + } + } + ], + "root_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "String", + "type": "string", + "definitions": { + "Base64VecU8": { + "description": "Helper class to serialize/deserialize `Vec` to base64 string.\n\n# Example ```rust use near_sdk::{json_types::Base64VecU8, near};\n\n#[near(serializers=[json])] struct NewStruct { field: Base64VecU8, } ```", + "type": "array", + "items": { + "type": "integer", + "format": "uint8", + "minimum": 0.0 + } + }, + "Feature": { + "description": "A contract feature that can be independently paused.\n\nSerialized in snake_case so call args read e.g. `{\"features\": [\"token\", \"minting\"]}`.", + "oneOf": [ + { + "description": "Token movement: `ft_transfer`, `ft_transfer_call`, `burn`, `storage_unregister`.", + "type": "string", + "enum": [ + "token" + ] + }, + { + "description": "Reward minting: `defer_batch`.", + "type": "string", + "enum": [ + "minting" + ] + } + ] + }, + "FungibleTokenMetadata": { + "type": "object", + "required": [ + "decimals", + "name", + "spec", + "symbol" + ], + "properties": { + "decimals": { + "type": "integer", + "format": "uint8", + "minimum": 0.0 + }, + "icon": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": "string" + }, + "reference": { + "type": [ + "string", + "null" + ] + }, + "reference_hash": { + "anyOf": [ + { + "$ref": "#/definitions/Base64VecU8" + }, + { + "type": "null" + } + ] + }, + "spec": { + "type": "string" + }, + "symbol": { + "type": "string" + } + } + }, + "PermissionedAccounts": { + "description": "Collects super admin accounts and accounts that have been granted permissions defined by `AccessControlRole`.\n\n# Data structure\n\nAssume `AccessControlRole` is derived for the following enum, which is then passed as `role` attribute to `AccessControllable`.\n\n```rust pub enum Role { PauseManager, UnpauseManager, } ```\n\nThen the returned data has the following structure:\n\n```ignore PermissionedAccounts { super_admins: vec![\"acc1.near\", \"acc2.near\"], roles: HashMap::from([ (\"PauseManager\", PermissionedAccountsPerRole { admins: vec![\"acc3.near\", \"acc4.near\"], grantees: vec![\"acc5.near\", \"acc6.near\"], }), (\"UnpauseManager\", PermissionedAccountsPerRole { admins: vec![\"acc7.near\", \"acc8.near\"], grantees: vec![\"acc9.near\", \"acc10.near\"], }), ]) } ```\n\n# Uniqueness and ordering\n\nAccount ids returned in vectors are unique but not ordered.", + "type": "object", + "required": [ + "roles", + "super_admins" + ], + "properties": { + "roles": { + "description": "The admins and grantees of all roles.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/PermissionedAccountsPerRole" + } + }, + "super_admins": { + "description": "The accounts that have super admin permissions.", + "type": "array", + "items": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + } + }, + "PermissionedAccountsPerRole": { + "description": "Collects all admins and grantees of a role.\n\n# Uniqueness and ordering\n\nAccount ids returned in vectors are unique but not ordered.", + "type": "object", + "required": [ + "admins", + "grantees" + ], + "properties": { + "admins": { + "description": "The accounts that have admin permissions for the role.", + "type": "array", + "items": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + }, + "grantees": { + "description": "The accounts that have been granted the role.", + "type": "array", + "items": { + "description": "NEAR Account Identifier.\n\nThis is a unique, syntactically valid, human-readable account identifier on the NEAR network.\n\n[See the crate-level docs for information about validation.](index.html#account-id-rules)\n\nAlso see [Error kind precedence](AccountId#error-kind-precedence).\n\n## Examples\n\n``` use near_account_id::AccountId;\n\nlet alice: AccountId = \"alice.near\".parse().unwrap();\n\nassert!(\"ƒelicia.near\".parse::().is_err()); // (ƒ is not f) ```", + "type": "string" + } + } + } + }, + "PromiseOrValueNull": { + "type": "null" + }, + "PromiseOrValueString": { + "type": "string" + }, + "StorageBalance": { + "type": "object", + "required": [ + "available", + "total" + ], + "properties": { + "available": { + "type": "string" + }, + "total": { + "type": "string" + } + } + }, + "StorageBalanceBounds": { + "type": "object", + "required": [ + "min" + ], + "properties": { + "max": { + "type": [ + "string", + "null" + ] + }, + "min": { + "type": "string" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/res/contract_abi.zst b/res/contract_abi.zst new file mode 100644 index 0000000..d3e0b16 Binary files /dev/null and b/res/contract_abi.zst differ diff --git a/res/sweat.wasm b/res/sweat_old.wasm old mode 100755 new mode 100644 similarity index 100% rename from res/sweat.wasm rename to res/sweat_old.wasm diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 6d833ff..e8528c4 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,3 @@ [toolchain] -channel = "1.75" +channel = "1.86" +targets = ["wasm32-unknown-unknown"] diff --git a/scripts/build-integration.sh b/scripts/build-integration.sh index 685de31..636feca 100755 --- a/scripts/build-integration.sh +++ b/scripts/build-integration.sh @@ -1,9 +1,12 @@ #!/bin/bash set -eox pipefail -echo ">> Building contract" +echo ">> Building contract (integration-test feature)" -rustup target add wasm32-unknown-unknown -cargo build -p sweat --target wasm32-unknown-unknown --profile=contract --features integration-test +OUT_DIR="integration-tests/target/integration-wasm" +mkdir -p "$OUT_DIR" -cp ./target/wasm32-unknown-unknown/contract/sweat.wasm res/sweat.wasm +cargo near build non-reproducible-wasm \ + --manifest-path contract/Cargo.toml \ + --features integration-test \ + --out-dir "$OUT_DIR" diff --git a/scripts/build.sh b/scripts/build.sh index 937a1f5..8208c77 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -3,7 +3,6 @@ set -eox pipefail echo ">> Building contract" -rustup target add wasm32-unknown-unknown -cargo build -p sweat --target wasm32-unknown-unknown --profile=contract - -cp ./target/wasm32-unknown-unknown/contract/sweat.wasm res/sweat.wasm +cargo near build non-reproducible-wasm \ + --manifest-path contract/Cargo.toml \ + --out-dir res diff --git a/scripts/lint.sh b/scripts/lint.sh index d6e3e78..beec0cf 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -3,14 +3,6 @@ set -eox pipefail rustup component add clippy -cargo clippy --all \ +cargo clippy --all --target wasm32-unknown-unknown \ -- \ - \ - -W clippy::all \ - -W clippy::pedantic \ - \ - -A clippy::module_name_repetitions \ - -A clippy::needless-pass-by-value \ - -A clippy::must-use-candidate \ - \ -D warnings diff --git a/scripts/sync_vendor.sh b/scripts/sync_vendor.sh new file mode 100755 index 0000000..87fad00 --- /dev/null +++ b/scripts/sync_vendor.sh @@ -0,0 +1,101 @@ +#!/bin/bash +# Re-vendor near-contract-standards from upstream, preserving local modifications. +# +# Source of truth is the vendor directory itself (`vendors/near-contract-standards/`). +# Local modifications are derived on the fly by diffing the live vendor against the +# pristine upstream tarball at the version it was based on. After the target upstream +# version is dropped in, that diff is re-applied. +# +# Workflow: +# 1. Read CURRENT version from vendor's Cargo.toml. +# 2. Download pristine CURRENT from crates.io and diff against live vendor — this +# captures every local modification, regardless of who made it or when. +# 3. Read TARGET version from workspace [workspace.dependencies] near-sdk. +# 4. Download TARGET from crates.io and replace the vendor directory. +# 5. Re-apply the captured diff. +# +# If a hunk fails (upstream changed near our modification site), `patch` writes .rej +# files and aborts. Inspect, resolve manually, and commit the resolved state. +# The next `make sync` will re-derive a fresh diff from your resolved vendor. + +set -e + +# Run from the workspace root regardless of invocation directory. +cd "$(dirname "$0")/.." + +CARGO_TOML="Cargo.toml" +TARGET_DIR="vendors/near-contract-standards" +CRATE="near-contract-standards" + +# Target version: what we want to migrate TO (read from workspace deps). +TARGET_VERSION=$(grep -E '^near-sdk\s*=\s*' "$CARGO_TOML" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n 1) +if [ -z "$TARGET_VERSION" ]; then + echo "❌ Could not find near-sdk version in $CARGO_TOML" + exit 1 +fi + +TMP_DIR=$(mktemp -d) +trap 'rm -rf "$TMP_DIR"' EXIT + +download_crate() { + # Extracts `-/` into the given directory. + local version="$1" + local into="$2" + mkdir -p "$into" + curl -fsSL "https://crates.io/api/v1/crates/$CRATE/$version/download" \ + | tar -xz -C "$into" +} + +# 1. Capture local modifications as the diff between live vendor and pristine upstream. +LOCAL_PATCH="" +if [ -d "$TARGET_DIR" ]; then + CURRENT_VERSION=$(grep -E '^version\s*=\s*"[0-9]+\.[0-9]+\.[0-9]+"' "$TARGET_DIR/Cargo.toml" \ + | head -n 1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+') + if [ -z "$CURRENT_VERSION" ]; then + echo "❌ Could not determine current vendored version from $TARGET_DIR/Cargo.toml" + exit 1 + fi + echo "📦 Currently vendored: $CRATE@$CURRENT_VERSION" + + echo "⬇️ Downloading pristine $CURRENT_VERSION for diff baseline..." + download_crate "$CURRENT_VERSION" "$TMP_DIR/stage" + + # Stage both trees under the same relative path so diff output has clean prefixes + # (`base/$TARGET_DIR` and `head/$TARGET_DIR`) without regex-escaping concerns. + mkdir -p "$TMP_DIR/base/$(dirname "$TARGET_DIR")" + mv "$TMP_DIR/stage/$CRATE-$CURRENT_VERSION" "$TMP_DIR/base/$TARGET_DIR" + mkdir -p "$TMP_DIR/head/$(dirname "$TARGET_DIR")" + cp -r "$TARGET_DIR" "$TMP_DIR/head/$TARGET_DIR" + + echo "📝 Computing local modifications..." + LOCAL_PATCH="$TMP_DIR/local.patch" + # diff returns 1 when files differ — expected and not an error. + ( cd "$TMP_DIR" && diff -ruN "base/$TARGET_DIR" "head/$TARGET_DIR" ) \ + | sed -e "s|^--- base/|--- a/|" -e "s|^+++ head/|+++ b/|" \ + > "$LOCAL_PATCH" || true + + if [ -s "$LOCAL_PATCH" ]; then + echo " captured $(grep -c '^@@' "$LOCAL_PATCH") hunk(s) of local mods" + else + echo " no local modifications detected" + LOCAL_PATCH="" + fi +fi + +# 2. Download the target upstream version. +echo "⬇️ Downloading $CRATE@$TARGET_VERSION from crates.io..." +download_crate "$TARGET_VERSION" "$TMP_DIR/target" + +# 3. Replace the vendor directory. +echo "🔄 Replacing $TARGET_DIR with $TARGET_VERSION..." +mkdir -p "$(dirname "$TARGET_DIR")" +rm -rf "$TARGET_DIR" +mv "$TMP_DIR/target/$CRATE-$TARGET_VERSION" "$TARGET_DIR" + +# 4. Re-apply local modifications. +if [ -n "$LOCAL_PATCH" ]; then + echo "🛠️ Re-applying local modifications..." + patch -p1 < "$LOCAL_PATCH" +fi + +echo "🎉 Vendor sync complete!" diff --git a/sweat/Cargo.toml b/sweat/Cargo.toml deleted file mode 100644 index 4adafd3..0000000 --- a/sweat/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "sweat" -version = "1.2.1" -authors = [] -edition = "2021" -publish = false - -[lib] -crate-type = ["cdylib"] - -[features] -default = [] -integration-test = [] - -[dependencies] -sweat-model = { workspace = true } - -static_assertions = "1.1.0" -near-sdk = { workspace = true } -near-contract-standards = { workspace = true } diff --git a/sweat/src/core.rs b/sweat/src/core.rs deleted file mode 100644 index d477a88..0000000 --- a/sweat/src/core.rs +++ /dev/null @@ -1,73 +0,0 @@ -use near_contract_standards::{ - fungible_token::{core::FungibleTokenCore, resolver::FungibleTokenResolver}, - storage_management::{StorageBalance, StorageBalanceBounds, StorageManagement}, -}; -use near_sdk::{env, json_types::U128, near_bindgen, AccountId, PromiseOrValue}; - -use crate::{Contract, ContractExt}; - -#[near_bindgen] -impl FungibleTokenCore for Contract { - #[payable] - fn ft_transfer(&mut self, receiver_id: AccountId, amount: U128, memo: Option) { - self.assert_not_in_denylist(vec![&env::predecessor_account_id(), &receiver_id]); - - self.token.ft_transfer(receiver_id, amount, memo); - } - - #[payable] - fn ft_transfer_call( - &mut self, - receiver_id: AccountId, - amount: U128, - memo: Option, - msg: String, - ) -> PromiseOrValue { - self.assert_not_in_denylist(vec![&env::predecessor_account_id(), &receiver_id]); - - self.token.ft_transfer_call(receiver_id, amount, memo, msg) - } - - fn ft_total_supply(&self) -> U128 { - self.token.ft_total_supply() - } - - fn ft_balance_of(&self, account_id: AccountId) -> U128 { - self.token.ft_balance_of(account_id) - } -} - -#[near_bindgen] -impl StorageManagement for Contract { - #[payable] - fn storage_deposit(&mut self, account_id: Option, registration_only: Option) -> StorageBalance { - self.token.storage_deposit(account_id, registration_only) - } - - #[payable] - fn storage_withdraw(&mut self, amount: Option) -> StorageBalance { - self.token.storage_withdraw(amount) - } - - #[payable] - fn storage_unregister(&mut self, force: Option) -> bool { - self.token.internal_storage_unregister(force).is_some() - } - - fn storage_balance_bounds(&self) -> StorageBalanceBounds { - self.token.storage_balance_bounds() - } - - fn storage_balance_of(&self, account_id: AccountId) -> Option { - self.token.storage_balance_of(account_id) - } -} - -#[near_bindgen] -impl FungibleTokenResolver for Contract { - #[private] - fn ft_resolve_transfer(&mut self, sender_id: AccountId, receiver_id: AccountId, amount: U128) -> U128 { - let (used_amount, _) = self.token.internal_ft_resolve_transfer(&sender_id, receiver_id, amount); - used_amount.into() - } -} diff --git a/sweat/src/defer.rs b/sweat/src/defer.rs deleted file mode 100644 index 8b848d4..0000000 --- a/sweat/src/defer.rs +++ /dev/null @@ -1,100 +0,0 @@ -use near_contract_standards::fungible_token::events::FtMint; -use near_sdk::{ - env, env::panic_str, ext_contract, is_promise_success, json_types::U128, near_bindgen, require, serde_json::json, - AccountId, Gas, Promise, PromiseOrValue, -}; -use sweat_model::SweatDefer; - -use crate::{internal_deposit, Contract, ContractExt}; - -const GAS_FOR_DEFER_CALLBACK: Gas = Gas(5 * Gas::ONE_TERA.0); -const GAS_FOR_DEFER: Gas = Gas(30 * Gas::ONE_TERA.0); - -#[near_bindgen] -impl SweatDefer for Contract { - fn defer_batch(&mut self, steps_batch: Vec<(AccountId, u32)>, holding_account_id: AccountId) -> PromiseOrValue<()> { - require!( - env::prepaid_gas() > GAS_FOR_DEFER, - "Not enough gas to complete the operation" - ); - - require!( - self.oracles.contains(&env::predecessor_account_id()), - "Unauthorized access! Only oracle can call that!" - ); - - let mut accounts_tokens: Vec<(AccountId, U128)> = Vec::new(); - let mut total_effective: U128 = U128(0); - let mut total_fee: U128 = U128(0); - - for (account_id, step_count) in steps_batch { - let (amount, fee) = self.calculate_tokens_amount(step_count); - self.steps_since_tge.0 += u64::from(step_count); - - accounts_tokens.push((account_id, U128(amount))); - total_effective.0 += amount; - total_fee.0 += fee; - } - - let hold_arguments = json!({ - "amounts": accounts_tokens, - }); - - let record_batch_for_hold_gas = Gas(env::prepaid_gas() - .0 - .checked_sub(GAS_FOR_DEFER.0) - .unwrap_or_else(|| panic_str("Prepaid gas overflow"))); - - Promise::new(holding_account_id.clone()) - .function_call( - "record_batch_for_hold".to_string(), - hold_arguments.to_string().into_bytes(), - 0, - record_batch_for_hold_gas, - ) - .then( - ext_ft_transfer_callback::ext(env::current_account_id()) - .with_static_gas(GAS_FOR_DEFER_CALLBACK) - .on_record( - holding_account_id, - total_effective, - env::predecessor_account_id(), - total_fee, - ), - ) - .into() - } -} - -#[ext_contract(ext_ft_transfer_callback)] -pub trait FungibleTokenTransferCallback { - fn on_record(&mut self, receiver_id: AccountId, amount: U128, fee_account_id: AccountId, fee: U128); -} - -#[near_bindgen] -impl FungibleTokenTransferCallback for Contract { - #[private] - fn on_record(&mut self, receiver_id: AccountId, amount: U128, fee_account_id: AccountId, fee: U128) { - if !is_promise_success() { - panic_str("Failed to record data in holding account"); - } - - let mut events: Vec = Vec::with_capacity(2); - - internal_deposit(&mut self.token, &fee_account_id, fee.0); - events.push(FtMint { - owner_id: &fee_account_id, - amount: &fee, - memo: None, - }); - - internal_deposit(&mut self.token, &receiver_id, amount.0); - events.push(FtMint { - owner_id: &receiver_id, - amount: &amount, - memo: None, - }); - - FtMint::emit_many(&events); - } -} diff --git a/sweat/src/lib.rs b/sweat/src/lib.rs deleted file mode 100644 index 4068448..0000000 --- a/sweat/src/lib.rs +++ /dev/null @@ -1,519 +0,0 @@ -#[macro_use] -extern crate static_assertions; - -use near_contract_standards::fungible_token::{ - events::{FtBurn, FtMint}, - metadata::{FungibleTokenMetadata, FungibleTokenMetadataProvider}, - FungibleToken, -}; -use near_sdk::{ - borsh::{self, BorshDeserialize, BorshSerialize}, - collections::UnorderedSet, - env, - json_types::{U128, U64}, - near_bindgen, require, AccountId, Balance, PanicOnDefault, -}; -use sweat_model::{Payout, RestrictionApi, SweatApi}; - -mod core; -mod defer; -mod integration; -mod math; - -#[near_bindgen] -#[derive(BorshSerialize, BorshDeserialize, PanicOnDefault)] -pub struct Contract { - oracles: UnorderedSet, - token: FungibleToken, - steps_since_tge: U64, - denylist: UnorderedSet, -} - -#[near_bindgen] -impl SweatApi for Contract { - #[init] - fn new(postfix: Option) -> Self { - Self { - oracles: UnorderedSet::new(b"s"), - token: FungibleToken::new(b"t", postfix), - steps_since_tge: U64::from(0), - denylist: UnorderedSet::new(b"d"), - } - } - fn add_oracle(&mut self, account_id: &AccountId) { - require!( - env::predecessor_account_id() == env::current_account_id(), - "Unauthorized access! Only token owner can add oracles!" - ); - require!(self.oracles.insert(account_id), "Already exists!"); - env::log_str(&format!("Oracle {account_id} was added")); - } - - fn remove_oracle(&mut self, account_id: &AccountId) { - require!( - env::predecessor_account_id() == env::current_account_id(), - "Unauthorized access! Only token owner can remove oracles!" - ); - require!(self.oracles.remove(account_id), "No such oracle was found!"); - env::log_str(&format!("Oracle {account_id} was removed")); - } - - fn get_oracles(&self) -> Vec { - self.oracles.to_vec() - } - - fn tge_mint(&mut self, account_id: &AccountId, amount: U128) { - require!( - env::predecessor_account_id() == env::current_account_id(), - "Unauthorized access! Only token owner can do TGE!" - ); - internal_deposit(&mut self.token, account_id, amount.0); - FtMint { - owner_id: account_id, - amount: &amount, - memo: None, - } - .emit(); - } - - fn tge_mint_batch(&mut self, batch: Vec<(AccountId, U128)>) { - require!( - env::predecessor_account_id() == env::current_account_id(), - "Unauthorized access! Only token owner can do TGE!" - ); - let mut events = Vec::with_capacity(batch.len()); - for (account_id, steps_count) in &batch { - // let steps_count = steps_count.0; - internal_deposit(&mut self.token, account_id, steps_count.0); - - let event = FtMint { - owner_id: account_id, - amount: steps_count, - memo: None, - }; - events.push(event); - } - if !events.is_empty() { - FtMint::emit_many(events.as_slice()); - } - } - - fn burn(&mut self, amount: &U128) { - self.token.internal_withdraw(&env::predecessor_account_id(), amount.0); - FtBurn { - amount, - owner_id: &env::predecessor_account_id(), - memo: None, - } - .emit(); - } - - fn get_steps_since_tge(&self) -> U64 { - self.steps_since_tge - } - - fn record_batch(&mut self, steps_batch: Vec<(AccountId, u32)>) { - require!( - self.oracles.contains(&env::predecessor_account_id()), - "Unauthorized access! Only oracle can call that!" - ); - let mut oracle_fee: U128 = U128(0); - let mut sweats: Vec = Vec::with_capacity(steps_batch.len() + 1); - let mut events = Vec::with_capacity(steps_batch.len() + 1); - - for (account_id, steps_count) in &steps_batch { - let (minted_to_user, trx_oracle_fee) = self.calculate_tokens_amount(*steps_count); - oracle_fee.0 += trx_oracle_fee; - internal_deposit(&mut self.token, account_id, minted_to_user); - - sweats.push(U128(minted_to_user)); - self.steps_since_tge.0 += u64::from(*steps_count); - } - for i in 0..steps_batch.len() { - events.push(FtMint { - owner_id: &steps_batch[i].0, - amount: &sweats[i], - memo: None, - }); - } - - internal_deposit(&mut self.token, &env::predecessor_account_id(), oracle_fee.0); - let oracle_event = FtMint { - owner_id: &env::predecessor_account_id(), - amount: &oracle_fee, - memo: None, - }; - events.push(oracle_event); - FtMint::emit_many(events.as_slice()); - } - - #[allow(clippy::cast_precision_loss)] - fn formula(&self, steps_since_tge: U64, steps: u32) -> U128 { - U128(math::formula(steps_since_tge.0 as f64, f64::from(steps))) - } -} - -#[near_bindgen] -impl RestrictionApi for Contract { - fn is_restricted(&self, account_id: &AccountId) -> bool { - self.denylist.contains(account_id) - } - - fn set_restricted(&mut self, account_id: &AccountId, is_restricted: bool) { - require!( - env::predecessor_account_id() == env::current_account_id(), - "Unauthorized access! Only token owner can do restrict accounts!" - ); - - if is_restricted { - self.denylist.insert(account_id); - } else { - self.denylist.remove(account_id); - } - } -} - -impl Contract { - pub(crate) fn calculate_tokens_amount(&self, steps: u32) -> (u128, u128) { - let sweat_to_mint: u128 = self.formula(self.steps_since_tge, steps).0; - let payout = Payout::from(sweat_to_mint); - - (payout.amount_for_user, payout.fee) - } - - pub(crate) fn assert_not_in_denylist(&self, account_ids: Vec<&AccountId>) { - for account_id in account_ids { - require!( - !self.is_restricted(account_id), - format!("The account {account_id} is restricted") - ); - } - } -} - -/// Taken from contract standards but modified to default if account isn't initialized -/// rather than panicking: -/// -fn internal_deposit(token: &mut FungibleToken, account_id: &AccountId, amount: Balance) { - let balance = token.accounts.get(account_id).unwrap_or_default(); - let new_balance = balance - .checked_add(amount) - .unwrap_or_else(|| env::panic_str("Balance overflow")); - token.accounts.insert(account_id, &new_balance); - token.total_supply = token - .total_supply - .checked_add(amount) - .unwrap_or_else(|| env::panic_str("Total supply overflow")); -} - -pub const ICON: &str = "data:image/svg+xml,%3Csvg viewBox='0 0 100 100' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='100' height='100' rx='50' fill='%23FF0D75'/%3E%3Cg clip-path='url(%23clip0_283_2788)'%3E%3Cpath d='M39.4653 77.5455L19.0089 40.02L35.5411 22.2805L55.9975 59.806L39.4653 77.5455Z' stroke='white' stroke-width='10'/%3E%3Cpath d='M66.0253 77.8531L45.569 40.3276L62.1012 22.5882L82.5576 60.1136L66.0253 77.8531Z' stroke='white' stroke-width='10'/%3E%3C/g%3E%3Cdefs%3E%3CclipPath id='clip0_283_2788'%3E%3Crect width='100' height='56' fill='white' transform='translate(0 22)'/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E%0A"; - -#[near_bindgen] -impl FungibleTokenMetadataProvider for Contract { - fn ft_metadata(&self) -> FungibleTokenMetadata { - FungibleTokenMetadata { - spec: "ft-1.0".to_string(), - name: "SWEAT".to_string(), - symbol: "SWEAT".to_string(), - icon: Some(String::from(ICON)), - reference: None, - reference_hash: None, - decimals: 18, - } - } -} - -#[cfg(test)] -mod tests { - use near_contract_standards::fungible_token::core::FungibleTokenCore; - use near_sdk::{ - json_types::{U128, U64}, - test_utils::VMContextBuilder, - testing_env, AccountId, - }; - use sweat_model::{RestrictionApi, SweatApi}; - - use crate::Contract; - - const EPS: f64 = 0.00001; - - fn sweat_the_token() -> AccountId { - AccountId::new_unchecked("sweat_the_token".to_string()) - } - fn sweat_oracle() -> AccountId { - AccountId::new_unchecked("sweat_the_oracle".to_string()) - } - fn user1() -> AccountId { - AccountId::new_unchecked("sweat_user1".to_string()) - } - fn user2() -> AccountId { - AccountId::new_unchecked("sweat_user2".to_string()) - } - - fn get_context(owner: AccountId, sender: AccountId) -> VMContextBuilder { - let mut builder = VMContextBuilder::new(); - builder - .current_account_id(owner.clone()) - .signer_account_id(sender.clone()) - .predecessor_account_id(sender) - .attached_deposit(1); - builder - } - - #[test] - #[should_panic(expected = r#"Unauthorized access! Only token owner can add oracles!"#)] - fn add_oracle_access() { - testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); - let mut token = Contract::new(Some(".u.sweat".to_string())); - assert!(token.get_oracles().is_empty()); - testing_env!(get_context(sweat_the_token(), sweat_oracle()).build()); - token.add_oracle(&sweat_oracle()); - } - - #[test] - #[should_panic(expected = r#"Unauthorized access! Only token owner can remove oracles!"#)] - fn remove_oracle_access() { - testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); - let mut token = Contract::new(Some(".u.sweat".to_string())); - assert!(token.get_oracles().is_empty()); - token.add_oracle(&sweat_oracle()); - assert_eq!(vec![sweat_oracle()], token.get_oracles()); - testing_env!(get_context(sweat_the_token(), sweat_oracle()).build()); - token.remove_oracle(&sweat_oracle()); - } - - #[test] - #[should_panic(expected = r#"Already exists!"#)] - fn add_same_oracle() { - testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); - let mut token = Contract::new(Some(".u.sweat".to_string())); - assert!(token.get_oracles().is_empty()); - token.add_oracle(&sweat_oracle()); - token.add_oracle(&sweat_oracle()); - } - - #[test] - #[should_panic(expected = r#"No such oracle was found!"#)] - fn remove_fake_oracle() { - testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); - let mut token = Contract::new(Some(".u.sweat".to_string())); - assert!(token.get_oracles().is_empty()); - token.add_oracle(&sweat_oracle()); - assert_eq!(vec![sweat_oracle()], token.get_oracles()); - token.remove_oracle(&user1()); - } - - #[test] - fn add_remove_oracle() { - testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); - let mut token = Contract::new(Some(".u.sweat".to_string())); - assert!(token.get_oracles().is_empty()); - token.add_oracle(&sweat_oracle()); - assert_eq!(vec![sweat_oracle()], token.get_oracles()); - token.remove_oracle(&sweat_oracle()); - assert!(token.get_oracles().is_empty()); - } - - #[test] - #[should_panic(expected = r#"Unauthorized access! Only oracle can call that!"#)] - fn mint_steps_access_1() { - testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); - let mut token = Contract::new(Some(".u.sweat".to_string())); - assert!(token.get_oracles().is_empty()); - token.add_oracle(&sweat_oracle()); - assert_eq!(vec![sweat_oracle()], token.get_oracles()); - token.record_batch(vec![(user1(), 10_000), (user2(), 10_000)]); - } - - #[test] - #[should_panic(expected = r#"Unauthorized access! Only oracle can call that!"#)] - fn minting_steps_access_2() { - testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); - let mut token = Contract::new(Some(".u.sweat".to_string())); - assert!(token.get_oracles().is_empty()); - token.add_oracle(&sweat_oracle()); - assert_eq!(vec![sweat_oracle()], token.get_oracles()); - testing_env!(get_context(sweat_the_token(), user1()).build()); - token.record_batch(vec![(user1(), 10_000), (user2(), 10_000)]); - } - - #[test] - fn oracle_fee_test() { - testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); - let mut token = Contract::new(Some(".u.sweat".to_string())); - assert_eq!(U64(0), token.get_steps_since_tge()); - assert!(token.get_oracles().is_empty()); - token.add_oracle(&sweat_oracle()); - assert_eq!(vec![sweat_oracle()], token.get_oracles()); - testing_env!(get_context(sweat_the_token(), sweat_oracle()).build()); - token.record_batch(vec![(user1(), 10_000), (user2(), 10_000)]); - assert!((9.499_999_991_723_028 - token.token.ft_balance_of(user1()).0 as f64 / 1e+18).abs() < EPS); - assert!((9.499_999_975_169_082 - token.token.ft_balance_of(user2()).0 as f64 / 1e+18).abs() < EPS); - assert!((0.999_999_998_257_479_4 - token.token.ft_balance_of(sweat_oracle()).0 as f64 / 1e+18).abs() < EPS); - assert_eq!(U64(2 * 10_000), token.get_steps_since_tge()); - } - - #[test] - #[should_panic(expected = r#"Unauthorized access! Only token owner can do TGE!"#)] - fn tge_access_1() { - testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); - let mut token = Contract::new(Some(".u.sweat".to_string())); - assert!(token.get_oracles().is_empty()); - token.add_oracle(&sweat_oracle()); - testing_env!(get_context(sweat_the_token(), sweat_oracle()).build()); - token.tge_mint(&user1(), U128(9499999991723028480)); - } - - #[test] - #[should_panic(expected = r#"Unauthorized access! Only token owner can do TGE!"#)] - fn tge_access_2() { - testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); - let mut token = Contract::new(Some(".u.sweat".to_string())); - token.add_oracle(&sweat_oracle()); - testing_env!(get_context(sweat_the_token(), user1()).build()); - token.tge_mint_batch(vec![ - (user1(), U128(9499999991723028480)), - (user2(), U128(9499999991723028480)), - ]); - } - - #[test] - fn tge_liquid() { - testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); - let mut token = Contract::new(Some(".u.sweat".to_string())); - assert!(token.get_oracles().is_empty()); - token.add_oracle(&sweat_oracle()); - token.tge_mint(&user1(), U128(9499999991723028480)); - assert!((9.499_999_991_723_028 - token.token.ft_balance_of(user1()).0 as f64 / 1e+18).abs() < EPS); - } - - #[test] - fn tge_liquid_batch() { - testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); - let mut token = Contract::new(Some(".u.sweat".to_string())); - assert!(token.get_oracles().is_empty()); - token.add_oracle(&sweat_oracle()); - token.tge_mint_batch(vec![ - (user1(), U128(9499999991723028480)), - (user2(), U128(9499999991723028480)), - ]); - assert!((9.499_999_991_723_028 - token.token.ft_balance_of(user1()).0 as f64 / 1e+18).abs() < EPS); - assert!((9.499_999_975_169_082 - token.token.ft_balance_of(user2()).0 as f64 / 1e+18).abs() < EPS); - } - - #[test] - fn burn() { - testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); - let mut token = Contract::new(Some(".u.sweat".to_string())); - assert!(token.get_oracles().is_empty()); - token.add_oracle(&sweat_oracle()); - token.tge_mint(&user1(), U128(9499999991723028480)); - testing_env!(get_context(sweat_the_token(), user1()).build()); - token.burn(&U128(9499999991723028480)); - assert!((0.0 - token.token.ft_balance_of(user1()).0 as f64 / 1e+18).abs() < EPS); - } - - #[test] - #[should_panic(expected = r#"The account sweat_user2 is not registered"#)] - fn transfer_to_unregistered() { - testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); - let mut token = Contract::new(Some(".u.sweat".to_string())); - assert!(token.get_oracles().is_empty()); - token.add_oracle(&sweat_oracle()); - token.tge_mint(&user1(), U128(9499999991723028480)); - testing_env!(get_context(sweat_the_token(), user1()).build()); - - token.token.ft_transfer(user2(), U128(9499999991723028480), None); - - assert!((0.0 - token.token.ft_balance_of(user1()).0 as f64 / 1e+18).abs() < EPS); - - assert!((9.499_999_991_723_028 - token.token.ft_balance_of(user2()).0 as f64 / 1e+18).abs() < EPS); - } - - #[test] - fn transfer_to_registered() { - testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); - let mut token = Contract::new(Some(".u.sweat".to_string())); - assert!(token.get_oracles().is_empty()); - token.add_oracle(&sweat_oracle()); - token.tge_mint_batch(vec![ - (user1(), U128(9499999991723028480)), - (user2(), U128(9499999991723028480)), - ]); - testing_env!(get_context(sweat_the_token(), user1()).build()); - - token.token.ft_transfer(user2(), U128(9499999991723028480), None); - - assert!((0.0 - token.token.ft_balance_of(user1()).0 as f64 / 1e+18).abs() < EPS); - - assert!((9.499_999_991_723_028 * 2.0 - token.token.ft_balance_of(user2()).0 as f64 / 1e+18).abs() < EPS); - } - - #[test] - #[should_panic(expected = r#"The account sweat_user1 is restricted"#)] - fn transfer_from_denied_account() { - testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); - let mut token = Contract::new(Some(".u.sweat".to_string())); - assert!(token.get_oracles().is_empty()); - token.add_oracle(&sweat_oracle()); - token.tge_mint_batch(vec![ - (user1(), U128(9499999991723028480)), - (user2(), U128(9499999991723028480)), - ]); - token.set_restricted(&user1(), true); - - testing_env!(get_context(sweat_the_token(), user1()).build()); - token.ft_transfer(user2(), U128(9499999991723028480), None); - } - - #[test] - #[should_panic(expected = r#"The account sweat_user2 is restricted"#)] - fn transfer_to_denied_account() { - testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); - let mut token = Contract::new(Some(".u.sweat".to_string())); - assert!(token.get_oracles().is_empty()); - token.add_oracle(&sweat_oracle()); - token.tge_mint_batch(vec![ - (user1(), U128(9499999991723028480)), - (user2(), U128(9499999991723028480)), - ]); - token.set_restricted(&user2(), true); - - testing_env!(get_context(sweat_the_token(), user1()).build()); - token.ft_transfer(user2(), U128(9499999991723028480), None); - } - - #[test] - #[should_panic(expected = r#"The account sweat_user1 is restricted"#)] - fn ft_transfer_call_from_denied_account() { - testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); - let mut token = Contract::new(Some(".u.sweat".to_string())); - assert!(token.get_oracles().is_empty()); - token.add_oracle(&sweat_oracle()); - token.tge_mint_batch(vec![ - (user1(), U128(9499999991723028480)), - (user2(), U128(9499999991723028480)), - ]); - token.set_restricted(&user1(), true); - - testing_env!(get_context(sweat_the_token(), user1()).build()); - token.ft_transfer_call(user2(), U128(9499999991723028480), None, String::from("test")); - } - - #[test] - #[should_panic(expected = r#"The account sweat_user2 is restricted"#)] - fn ft_transfer_call_to_denied_account() { - testing_env!(get_context(sweat_the_token(), sweat_the_token()).build()); - let mut token = Contract::new(Some(".u.sweat".to_string())); - assert!(token.get_oracles().is_empty()); - token.add_oracle(&sweat_oracle()); - token.tge_mint_batch(vec![ - (user1(), U128(9499999991723028480)), - (user2(), U128(9499999991723028480)), - ]); - token.set_restricted(&user2(), true); - - testing_env!(get_context(sweat_the_token(), user1()).build()); - token.ft_transfer_call(user2(), U128(9499999991723028480), None, String::from("test")); - } -} diff --git a/vendors/near-contract-standards/.cargo_vcs_info.json b/vendors/near-contract-standards/.cargo_vcs_info.json new file mode 100644 index 0000000..3a255ba --- /dev/null +++ b/vendors/near-contract-standards/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "dfd22bc5939d2d725f8842654fb605b5abdea0a8" + }, + "path_in_vcs": "near-contract-standards" +} \ No newline at end of file diff --git a/vendors/near-contract-standards/CHANGELOG.md b/vendors/near-contract-standards/CHANGELOG.md new file mode 100644 index 0000000..4ab7edc --- /dev/null +++ b/vendors/near-contract-standards/CHANGELOG.md @@ -0,0 +1,155 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [5.25.0](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.24.1...near-contract-standards-v5.25.0) - 2026-03-26 + +### Added + +- add `ext_self()` and document cross-contract call patterns ([#1504](https://github.com/near/near-sdk-rs/pull/1504)) + +### Other + +- update to Rust edition 2024 ([#1480](https://github.com/near/near-sdk-rs/pull/1480)) + +## [5.24.1](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.24.0...near-contract-standards-v5.24.1) - 2026-02-05 + +### Other + +- *(contract-standards)* added msrv ([#1472](https://github.com/near/near-sdk-rs/pull/1472)) + +## [5.24.0](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.23.0...near-contract-standards-v5.24.0) - 2025-12-26 + +### Added + +- *(env)* `promise_result_checked()` ([#1456](https://github.com/near/near-sdk-rs/pull/1456)) + +### Other + +- reuse shared TokenId alias in enumeration_impl ([#1445](https://github.com/near/near-sdk-rs/pull/1445)) + +## [5.20.1](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.20.0...near-contract-standards-v5.20.1) - 2025-12-05 + +### Fixed + +- Corrected deploy_code time gate in upgradability standard implementation ([#1429](https://github.com/near/near-sdk-rs/pull/1429)) + +## [5.19.0](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.18.1...near-contract-standards-v5.19.0) - 2025-12-01 + +### Other + +- avoid String allocation in approvals lookup ([#1422](https://github.com/near/near-sdk-rs/pull/1422)) + +## [5.18.1](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.18.0...near-contract-standards-v5.18.1) - 2025-11-28 + +### Fixed + +- Fixed docs.rs compilation error ([#1415](https://github.com/near/near-sdk-rs/pull/1415)) + +## [5.18.0](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.17.2...near-contract-standards-v5.18.0) - 2025-11-27 + +### Added + +- be explicit about detached `Promise`s ([#1400](https://github.com/near/near-sdk-rs/pull/1400)) + +### Fixed + +- *(near-contract-standards)* do not distribute remaining gas for ft/nft_resolve_transfer() callback ([#1391](https://github.com/near/near-sdk-rs/pull/1391)) + +## [5.14.0](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.13.0...near-contract-standards-v5.14.0) - 2025-05-14 + +### Other + +- updates near-* dependencies to 0.30 release ([#1356](https://github.com/near/near-sdk-rs/pull/1356)) + +## [5.13.0](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.12.0...near-contract-standards-v5.13.0) - 2025-05-05 + +### Other + +- resolves https://github.com/near/NEPs/pull/606/files#r2045175915 ([#1348](https://github.com/near/near-sdk-rs/pull/1348)) + +## [5.12.0](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.11.0...near-contract-standards-v5.12.0) - 2025-04-10 + +### Added + +- nep330 result wasm path field ([#1344](https://github.com/near/near-sdk-rs/pull/1344)) + +## [5.8.0](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.7.1...near-contract-standards-v5.8.0) - 2025-02-07 + +### Other + +- *(near-contract-standards)* add `build_info` field (#1297) + +## [5.7.1](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.7.0...near-contract-standards-v5.7.1) - 2025-01-30 + +### Other + +- `__abi-generate` feature in docs.rs (#1286) + +## [5.7.0](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.6.0...near-contract-standards-v5.7.0) - 2024-12-13 + +### Other + +- add a `cargo doc` job (#1269) +- allow clippy::needless_lifetimes (1.83 more suggestions) (#1267) + +## [5.5.0](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.4.0...near-contract-standards-v5.5.0) - 2024-09-11 + +### Other + +- Updated near-* dependendencies to v0.26.0. Migrated testing blockchain mock to C-unwind ([#1244](https://github.com/near/near-sdk-rs/pull/1244)) + +## [5.3.0](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.2.1...near-contract-standards-v5.3.0) - 2024-08-13 + +### Fixed +- Fix storage management error message with proper amount ([#1222](https://github.com/near/near-sdk-rs/pull/1222)) + +## [5.2.0](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.1.0...near-contract-standards-v5.2.0) - 2024-07-04 + +### Added +- Exported `ext_storage_management` Promise shortcuts, so Storage Management interfaces can be used in contracts to call external contracts using the high-level cross-contract call interfaces ([#1208](https://github.com/near/near-sdk-rs/pull/1208)) +- Exported `ext_nft_*` Promise shortcuts, so NFT interfaces can be re-used in contracts to call external NFT contracts using the high-level cross-contract call interfaces ([#1206](https://github.com/near/near-sdk-rs/pull/1206)) + +## [5.1.0](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.0.0...near-contract-standards-v5.1.0) - 2024-03-28 + +### Added +- Finalize `#[near]` attribute-macro implementation with the support for custom parameters passing to serializer attributes `#[near(serializers = [borsh(...)])]` ([#1158](https://github.com/near/near-sdk-rs/pull/1158)) +- Introduce `#[near]` macro to further streamline contracts development reducing the boilerplate! ([#1142](https://github.com/near/near-sdk-rs/pull/1142)) + +## [5.0.0-alpha.3](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.0.0-alpha.2...near-contract-standards-v5.0.0-alpha.3) - 2024-02-19 + +### Fixed +- Fixed a typo in the storage_deposit refund computation (introduced in 5.0.0-alpha.1 release) ([#1146](https://github.com/near/near-sdk-rs/pull/1146)) + +## [5.0.0-alpha.2](https://github.com/near/near-sdk-rs/compare/near-contract-standards-v5.0.0-alpha.1...near-contract-standards-v5.0.0-alpha.2) - 2024-01-16 + +### Other +- fix new 1.75 warnings ([#1128](https://github.com/near/near-sdk-rs/pull/1128)) +- Re-exported packages cleanup ([#1114](https://github.com/near/near-sdk-rs/pull/1114)) + +## [5.0.0-alpha.1](https://github.com/near/near-sdk-rs/compare/4.1.1...near-contract-standards-v5.0.0-alpha.1) - 2023-11-18 + +### Added +- adding `nep-0330` contract source metadata info ([#1106](https://github.com/near/near-sdk-rs/pull/1106)) + +### Fixed +- remove receiver approval ([#1020](https://github.com/near/near-sdk-rs/pull/1020)) +- rename param `approvals` to `approved_account_ids` ([#1019](https://github.com/near/near-sdk-rs/pull/1019)) +- Properly report an error when Approval Extension is not enabled vs when account is not approved ([#1021](https://github.com/near/near-sdk-rs/pull/1021)) + +### Other +- [**breaking**] Use type-safe NearToken instead of u128/U128 ([#1104](https://github.com/near/near-sdk-rs/pull/1104)) +- migrate to a external near-account-id crate for reusable AccountId type ([#1108](https://github.com/near/near-sdk-rs/pull/1108)) +- Update borsh to 1.0.0 ([#1075](https://github.com/near/near-sdk-rs/pull/1075)) +- Move from Gas to NearGas from near-gas crate ([#1082](https://github.com/near/near-sdk-rs/pull/1082)) +- Deprecate Fungible Token declarative macros. ([#1054](https://github.com/near/near-sdk-rs/pull/1054)) +- Add release-plz to automate releases ([#1069](https://github.com/near/near-sdk-rs/pull/1069)) +- *(contract-standards)* deprecate declarative macros in NFT helpers, promote explicit trait implementations instead ([#1042](https://github.com/near/near-sdk-rs/pull/1042)) +- Added a default method for TokenMetadata ([#978](https://github.com/near/near-sdk-rs/pull/978)) +- Removed the not ready enum type ([#977](https://github.com/near/near-sdk-rs/pull/977)) +- Fix empty owner tokens `start_index` error ([#962](https://github.com/near/near-sdk-rs/pull/962)) diff --git a/vendors/near-contract-standards/Cargo.lock b/vendors/near-contract-standards/Cargo.lock new file mode 100644 index 0000000..7918e4a --- /dev/null +++ b/vendors/near-contract-standards/Cargo.lock @@ -0,0 +1,890 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "borsh" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" +dependencies = [ + "borsh-derive", + "bytes", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" +dependencies = [ + "once_cell", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "cc" +version = "1.2.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chrono" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +dependencies = [ + "iana-time-zone", + "num-traits", + "serde", + "windows-link", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core 0.21.3", + "darling_macro 0.21.3", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core 0.20.11", + "quote", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core 0.21.3", + "quote", + "syn", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", + "serde_core", +] + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "js-sys" +version = "0.3.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.184" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "near-abi" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fe0c8cdaf8369d8c78f2577d95673007c7f256c85752a66672be5244e2681a6" +dependencies = [ + "borsh", + "schemars 0.8.22", + "semver", + "serde", +] + +[[package]] +name = "near-account-id" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702dbca982e748975658812c7be2ca53211f454137486f98f6cf768934e2cb29" +dependencies = [ + "borsh", + "schemars 0.8.22", + "serde", +] + +[[package]] +name = "near-contract-standards" +version = "5.26.1" +dependencies = [ + "near-sdk", +] + +[[package]] +name = "near-gas" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6fbc2f97dea1fad4289ce70604955fc3421fb7c95c7300aba1d6a3466590f60" +dependencies = [ + "borsh", + "schemars 0.8.22", + "serde", +] + +[[package]] +name = "near-sdk" +version = "5.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f78c9d9392f3a0c5acba9e1dd3ea89554804a2c1b533170cc5cce00e483a4e" +dependencies = [ + "base64", + "borsh", + "bs58", + "near-abi", + "near-account-id", + "near-gas", + "near-sdk-macros", + "near-sys", + "near-token", + "once_cell", + "schemars 0.8.22", + "serde", + "serde_json", + "serde_with", +] + +[[package]] +name = "near-sdk-macros" +version = "5.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b0bdc1666723a140e41ec8a14cf0b11b5e3ecf8ab55ed7e66d995c962fbac77" +dependencies = [ + "Inflector", + "darling 0.20.11", + "proc-macro2", + "quote", + "serde", + "serde_json", + "strum", + "strum_macros", + "syn", +] + +[[package]] +name = "near-sys" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c212278351251aa342eab33a9d64f99294bc5784cda10107867a72dda699bb" + +[[package]] +name = "near-token" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34de6b54d82d0790b2a56b677e7b4ecb7f021a7e8559f8611065c890d56cfcda" +dependencies = [ + "borsh", + "schemars 0.8.22", + "serde", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "schemars" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "indexmap 2.13.1", + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_with" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "381b283ce7bc6b476d903296fb59d0d36633652b633b27f64db4fb46dcbfc3b9" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.13.1", + "schemars 0.8.22", + "schemars 0.9.0", + "schemars 1.2.1", + "serde_core", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6d4e30573c8cb306ed6ab1dca8423eec9a463ea0e155f45399455e0368b27e0" +dependencies = [ + "darling 0.21.3", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "time" +version = "0.3.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9e442fc33d7fdb45aa9bfeb312c095964abdf596f7567261062b2a7107aaabd" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b36ee98fd31ec7426d599183e8fe26932a8dc1fb76ddb6214d05493377d34ca" + +[[package]] +name = "time-macros" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e552d1249bf61ac2a52db88179fd0673def1e1ad8243a00d9ec9ed71fee3dd" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.25.11+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" +dependencies = [ + "indexmap 2.13.1", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "wasm-bindgen" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "winnow" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" +dependencies = [ + "memchr", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/vendors/near-contract-standards/Cargo.toml b/vendors/near-contract-standards/Cargo.toml new file mode 100644 index 0000000..b9282b0 --- /dev/null +++ b/vendors/near-contract-standards/Cargo.toml @@ -0,0 +1,50 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2024" +rust-version = "1.86" +name = "near-contract-standards" +version = "5.26.1" +authors = ["Near Inc "] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = """ +NEAR smart contracts standard library. +""" +homepage = "https://docs.near.org/" +documentation = "https://docs.rs/near-contract-standards" +readme = "README.md" +categories = ["wasm"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/near/near-sdk-rs" + +[package.metadata.docs.rs] +features = ["abi"] + +[features] +abi = ["near-sdk/__abi-generate"] +default = [] + +[lib] +name = "near_contract_standards" +path = "src/lib.rs" + +[dependencies.near-sdk] +version = "~5.26.1" +features = ["legacy"] +default-features = false + +[dev-dependencies] diff --git a/vendors/near-contract-standards/Cargo.toml.orig b/vendors/near-contract-standards/Cargo.toml.orig new file mode 100644 index 0000000..fa0a036 --- /dev/null +++ b/vendors/near-contract-standards/Cargo.toml.orig @@ -0,0 +1,31 @@ +[package] +name = "near-contract-standards" +version.workspace = true +authors = ["Near Inc "] +edition.workspace = true +license.workspace = true +categories.workspace = true +repository.workspace = true +homepage.workspace = true +rust-version.workspace = true +documentation = "https://docs.rs/near-contract-standards" +description = """ +NEAR smart contracts standard library. +""" + +[dependencies] +near-sdk = { path = "../near-sdk", version = "~5.26.1", default-features = false, features = [ + "legacy", +] } + +[dev-dependencies] +near-sdk = { path = "../near-sdk", default-features = false, features = [ + "unit-testing", +] } + +[features] +default = [] +abi = ["near-sdk/__abi-generate"] + +[package.metadata.docs.rs] +features = ["abi"] diff --git a/vendors/near-contract-standards/README.md b/vendors/near-contract-standards/README.md new file mode 100644 index 0000000..6e4eb44 --- /dev/null +++ b/vendors/near-contract-standards/README.md @@ -0,0 +1,10 @@ +# NEAR library for Rust contract standards + +This cargo provides a set of interfaces and implementations for NEAR's contract standards: + - Upgradability + - Fungible Token (NEP-141). See [example usage](../examples/fungible-token) + +## Changelog + +### `3.1.1` +- Fixed FT macro compilation for Rust `1.51.0` diff --git a/vendors/near-contract-standards/src/contract_metadata.rs b/vendors/near-contract-standards/src/contract_metadata.rs new file mode 100644 index 0000000..1b0ee4c --- /dev/null +++ b/vendors/near-contract-standards/src/contract_metadata.rs @@ -0,0 +1,186 @@ +pub use build_info::BuildInfo; +use near_sdk::serde::{Deserialize, Serialize}; + +/// The struct provides information about deployed contract's source code and supported standards. +/// +/// Contract source metadata follows [**NEP-330 standard**](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) for smart contracts +/// +/// See documentation of [`near_api::types::contract::ContractSourceMetadata`](https://docs.rs/near-api/latest/near_api/types/contract/struct.ContractSourceMetadata.html) +/// and [`near_api::Contract::contract_source_metadata`](https://docs.rs/near-api/latest/near_api/struct.Contract.html#method.contract_source_metadata) +/// on how to query this piece of data from a contract via `near_api` crate +#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)] +#[serde(crate = "near_sdk::serde")] +pub struct ContractSourceMetadata { + /// Optional version identifier, typically a semantic version + /// + /// ## Examples: + /// + /// ```rust,no_run + /// # let version: Option = + /// // Semantic version + /// Some("1.0.0".into()) + /// # ; + /// ``` + /// ```rust,no_run + /// # let version: Option = + /// // Git commit + /// Some("39f2d2646f2f60e18ab53337501370dc02a5661c".into()) + /// # ; + /// ``` + pub version: Option, + /// Optional URL to source code repository/tree + /// + /// ## Examples: + /// + /// ```rust,no_run + /// # let link: Option = + /// // GitHub URL + /// Some("https://github.com/org/repo/tree/8d8a8a0fe86a1d8eb3bce45f04ab1a65fecf5a1b".into()) + /// # ; + /// ``` + /// ```rust,no_run + /// # let link: Option = + /// // GitHub URL + /// Some("https://github.com/near-examples/nft-tutorial".into()) + /// # ; + /// ``` + /// ```rust,no_run + /// # let link: Option = + /// // IPFS CID + /// Some("bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq".into()) + /// # ; + /// ``` + pub link: Option, + /// List of supported NEAR standards (NEPs) with their versions + /// + /// This field is an addition of **1.1.0** **NEP-330** revision + /// + /// ## Examples: + /// + /// This field will always include NEP-330 itself: + /// ```rust,no_run + /// # use near_contract_standards::contract_metadata::Standard; + /// # let link: Vec = + /// // this is always at least 1.1.0 + /// vec![Standard { standard: "nep330".into(), version: "1.1.0".into() }] + /// # ; + /// ``` + /// ```rust,no_run + /// # use near_contract_standards::contract_metadata::Standard; + /// # let link: Vec = + /// vec![Standard { standard: "nep330".into(), version: "1.3.0".into() }] + /// # ; + /// ``` + // it's a guess it was added as 1.1.0 of nep330, [nep330 1.1.0 standard recording](https://www.youtube.com/watch?v=pBLN9UyE6AA) actually discusses nep351 + #[serde(default)] + pub standards: Vec, + /// Optional details that are required for formal contract WASM build reproducibility verification + /// + /// This field is an addition of **1.2.0** **NEP-330** revision + pub build_info: Option, +} + +/// NEAR Standard implementation descriptor following [NEP-330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) +#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)] +#[serde(crate = "near_sdk::serde")] +pub struct Standard { + /// Standard name in lowercase NEP format + /// + /// ## Examples: + /// + /// ```rust,no_run + /// # let standard: String = + /// // for fungible tokens + /// "nep141".into() + /// # ; + /// ``` + pub standard: String, + /// Implemented standard version using semantic versioning + /// + /// ## Examples: + /// + /// ```rust,no_run + /// # let version: String = + /// // for initial release + /// "1.0.0".into() + /// # ; + /// ``` + pub version: String, +} + +mod build_info { + use near_sdk::serde::{Deserialize, Serialize}; + + /// Defines all required details for formal WASM build reproducibility verification + /// according to [**NEP-330 standard 1.3.0 revision**](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) + #[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)] + #[serde(crate = "near_sdk::serde")] + pub struct BuildInfo { + /// Reference to a reproducible build environment docker image + /// + /// ## Examples: + /// + /// ```rust,no_run + /// # let build_environment: String = + /// "sourcescan/cargo-near:0.13.3-rust-1.84.0@sha256:722198ddb92d1b82cbfcd3a4a9f7fba6fd8715f4d0b5fb236d8725c4883f97de".into() + /// # ; + /// ``` + pub build_environment: String, + /// The exact command that was used to build the contract, with all the flags + /// + /// ## Examples: + /// + /// ```rust,no_run + /// # let build_command: Vec = + /// vec![ + /// "cargo".into(), + /// "near".into(), + /// "build".into(), + /// "non-reproducible-wasm".into(), + /// "--locked".into() + /// ] + /// # ; + /// ``` + pub build_command: Vec, + /// Relative path to contract crate within the source code + /// + /// ## Examples: + /// + /// ```rust,no_run + /// # let contract_path: String = + /// "near/omni-prover/wormhole-omni-prover-proxy".into() + /// # ; + /// ``` + /// ```rust,no_run + /// # let contract_path: String = + /// // root of a repo + /// "".into() + /// # ; + /// ``` + pub contract_path: String, + /// Reference to the source code snapshot that was used to build the contract + /// + /// ## Examples: + /// + /// ```rust,no_run + /// # let source_code_snapshot: String = + /// "git+https://github.com/org/repo?rev=8d8a8a0fe86a1d8eb3bce45f04ab1a65fecf5a1b".into() + /// # ; + /// ``` + pub source_code_snapshot: String, + /// A path within the build environment, where the result WASM binary has been put + /// during build. + /// This should be a subpath of `/home/near/code` + /// + /// This field is an addition of **1.3.0** **NEP-330** revision + /// + /// ## Examples: + /// + /// ```rust,no_run + /// # let output_wasm_path: Option = + /// Some("/home/near/code/target/near/simple_package.wasm".into()) + /// # ; + /// ``` + pub output_wasm_path: Option, + } +} diff --git a/vendors/near-contract-standards/src/event.rs b/vendors/near-contract-standards/src/event.rs new file mode 100644 index 0000000..6179578 --- /dev/null +++ b/vendors/near-contract-standards/src/event.rs @@ -0,0 +1,31 @@ +use near_sdk::env; +use near_sdk::serde::Serialize; +use near_sdk::serde_json; + +#[derive(Serialize, Debug)] +#[serde(crate = "near_sdk::serde")] +#[serde(tag = "standard")] +#[must_use = "don't forget to `.emit()` this event"] +#[serde(rename_all = "snake_case")] +pub(crate) enum NearEvent<'a> { + Nep171(crate::non_fungible_token::events::Nep171Event<'a>), + Nep141(crate::fungible_token::events::Nep141Event<'a>), +} + +impl<'a> NearEvent<'a> { + fn to_json_string(&self) -> String { + // Events cannot fail to serialize so fine to panic on error + #[allow(clippy::redundant_closure)] + serde_json::to_string(self).ok().unwrap_or_else(|| env::abort()) + } + + fn to_json_event_string(&self) -> String { + format!("EVENT_JSON:{}", self.to_json_string()) + } + + /// Logs the event to the host. This is required to ensure that the event is triggered + /// and to consume the event. + pub(crate) fn emit(self) { + near_sdk::env::log_str(&self.to_json_event_string()); + } +} diff --git a/vendors/near-contract-standards/src/fungible_token/core.rs b/vendors/near-contract-standards/src/fungible_token/core.rs new file mode 100644 index 0000000..31d4614 --- /dev/null +++ b/vendors/near-contract-standards/src/fungible_token/core.rs @@ -0,0 +1,132 @@ +use near_sdk::AccountId; +use near_sdk::PromiseOrValue; +use near_sdk::ext_contract; +use near_sdk::json_types::U128; +/// The core methods for a basic fungible token. Extension standards may be +/// added in addition to this trait. +/// +/// # Examples +/// +/// ## Implementing the trait +/// +/// ``` +/// use near_sdk::{near, PanicOnDefault, AccountId, PromiseOrValue}; +/// use near_sdk::collections::LazyOption; +/// use near_sdk::json_types::U128; +/// use near_contract_standards::fungible_token::{FungibleToken, FungibleTokenCore}; +/// use near_contract_standards::fungible_token::metadata::FungibleTokenMetadata; +/// +/// #[near(contract_state)] +/// #[derive(PanicOnDefault)] +/// pub struct Contract { +/// token: FungibleToken, +/// metadata: LazyOption, +/// } +/// +/// #[near] +/// impl FungibleTokenCore for Contract { +/// #[payable] +/// fn ft_transfer(&mut self, receiver_id: AccountId, amount: U128, memo: Option) { +/// self.token.ft_transfer(receiver_id, amount, memo) +/// } +/// +/// #[payable] +/// fn ft_transfer_call( +/// &mut self, +/// receiver_id: AccountId, +/// amount: U128, +/// memo: Option, +/// msg: String, +/// ) -> PromiseOrValue { +/// self.token.ft_transfer_call(receiver_id, amount, memo, msg) +/// } +/// +/// fn ft_total_supply(&self) -> U128 { +/// self.token.ft_total_supply() +/// } +/// +/// fn ft_balance_of(&self, account_id: AccountId) -> U128 { +/// self.token.ft_balance_of(account_id) +/// } +/// } +/// ``` +/// +/// ## Cross-contract calls +/// +/// The `#[ext_contract]` annotation on this trait also generates the [`ext_ft_core`] module, +/// which can be used to make type-safe cross-contract calls to **any** contract that +/// implements this interface (e.g. `wrap.near`): +/// +/// ```ignore +/// use near_contract_standards::fungible_token::core::ext_ft_core; +/// use near_sdk::{Gas, NearToken}; +/// +/// // Transfer tokens on an external FT contract +/// ext_ft_core::ext("wrap.near".parse().unwrap()) +/// .with_attached_deposit(NearToken::from_yoctonear(1)) +/// .with_static_gas(Gas::from_tgas(5)) +/// .ft_transfer(receiver_id, amount, memo); +/// +/// // Chain with a callback to the current contract +/// ext_ft_core::ext("wrap.near".parse().unwrap()) +/// .with_attached_deposit(NearToken::from_yoctonear(1)) +/// .with_static_gas(Gas::from_tgas(10)) +/// .ft_transfer(receiver_id, amount, memo) +/// .then( +/// Self::ext_self() +/// .with_static_gas(Gas::from_tgas(5)) +/// .on_ft_transfer_complete() +/// ); +/// ``` +/// +#[ext_contract(ext_ft_core)] +pub trait FungibleTokenCore { + /// Transfers positive `amount` of tokens from the `env::predecessor_account_id` to `receiver_id`. + /// Both accounts must be registered with the contract for transfer to succeed. (See [NEP-145](https://github.com/near/NEPs/discussions/145)) + /// This method must to be able to accept attached deposits, and must not panic on attached deposit. + /// Exactly 1 yoctoNEAR must be attached. + /// See [the Security section](https://github.com/near/NEPs/issues/141#user-content-security) of the standard. + /// + /// Arguments: + /// - `receiver_id` - the account ID of the receiver. + /// - `amount` - the amount of tokens to transfer. Must be a positive number in decimal string representation. + /// - `memo` - an optional string field in a free form to associate a memo with this transfer. + fn ft_transfer(&mut self, receiver_id: AccountId, amount: U128, memo: Option); + + /// Transfers positive `amount` of tokens from the `env::predecessor_account_id` to `receiver_id` account. Then + /// calls `ft_on_transfer` method on `receiver_id` contract and attaches a callback to resolve this transfer. + /// `ft_on_transfer` method must return the amount of tokens unused by the receiver contract, the remaining tokens + /// must be refunded to the `predecessor_account_id` at the resolve transfer callback. + /// + /// Token contract must pass all the remaining unused gas to the `ft_on_transfer` call. + /// + /// Malicious or invalid behavior by the receiver's contract: + /// - If the receiver contract promise fails or returns invalid value, the full transfer amount must be refunded. + /// - If the receiver contract overspent the tokens, and the `receiver_id` balance is lower than the required refund + /// amount, the remaining balance must be refunded. See [the Security section](https://github.com/near/NEPs/issues/141#user-content-security) of the standard. + /// + /// Both accounts must be registered with the contract for transfer to succeed. (See #145) + /// This method must to be able to accept attached deposits, and must not panic on attached deposit. Exactly 1 yoctoNEAR must be attached. See [the Security + /// section](https://github.com/near/NEPs/issues/141#user-content-security) of the standard. + /// + /// Arguments: + /// - `receiver_id` - the account ID of the receiver contract. This contract will be called. + /// - `amount` - the amount of tokens to transfer. Must be a positive number in a decimal string representation. + /// - `memo` - an optional string field in a free form to associate a memo with this transfer. + /// - `msg` - a string message that will be passed to `ft_on_transfer` contract call. + /// + /// Returns a promise which will result in the amount of tokens withdrawn from sender's account. + fn ft_transfer_call( + &mut self, + receiver_id: AccountId, + amount: U128, + memo: Option, + msg: String, + ) -> PromiseOrValue; + + /// Returns the total supply of the token in a decimal string representation. + fn ft_total_supply(&self) -> U128; + + /// Returns the balance of the account. If the account doesn't exist must returns `"0"`. + fn ft_balance_of(&self, account_id: AccountId) -> U128; +} diff --git a/vendors/near-contract-standards/src/fungible_token/core_impl.rs b/vendors/near-contract-standards/src/fungible_token/core_impl.rs new file mode 100644 index 0000000..ee8279c --- /dev/null +++ b/vendors/near-contract-standards/src/fungible_token/core_impl.rs @@ -0,0 +1,311 @@ +use near_sdk::{ + AccountId, Gas, IntoStorageKey, PromiseOrValue, StorageUsage, assert_one_yocto, + collections::LookupMap, env, json_types::U128, log, near, require, serde_json, +}; + +use crate::fungible_token::{ + core::FungibleTokenCore, + events::{FtBurn, FtTransfer}, + receiver::ext_ft_receiver, + resolver::{FungibleTokenResolver, ext_ft_resolver}, +}; + +const GAS_FOR_RESOLVE_TRANSFER: Gas = Gas::from_tgas(5); + +const ERR_TOTAL_SUPPLY_OVERFLOW: &str = "Total supply overflow"; + +pub type Balance = u128; + +/// Implementation of a FungibleToken standard. +/// Allows to include NEP-141 compatible token to any contract. +/// There are next traits that any contract may implement: +/// - FungibleTokenCore -- interface with ft_transfer methods. FungibleToken provides methods for it. +/// - FungibleTokenMetaData -- return metadata for the token in NEP-148, up to contract to implement. +/// - StorageManager -- interface for NEP-145 for allocating storage per account. FungibleToken provides methods for it. +/// - AccountRegistrar -- interface for an account to register and unregister +/// +/// For example usage, see examples/fungible-token/src/lib.rs. +#[near] +pub struct FungibleToken { + /// sha256(AccountId) -> Account balance + pub accounts: LookupMapAdapter, + + /// Total supply of the all token. + pub total_supply: Balance, + + /// The storage size in bytes for one account. + pub account_storage_usage: StorageUsage, +} + +/// Storage key wrapper for an account balance. +/// +/// Kept as an enum so the stored key retains its leading borsh discriminant +/// byte (`Hash` => `0x00`). Existing balances are keyed by `0x00 ‖ sha256` on +/// the trie; collapsing this into a bare `[u8; 32]` would drop that byte and +/// orphan every entry, which can't be re-keyed cheaply (the map isn't +/// enumerable). The historical `AccountId` variant has been removed — no +/// account was ever stored unhashed — and removing it leaves `Hash` at +/// discriminant `0`, so the encoding is unchanged. +#[near] +pub enum LookupMapKey { + Hash([u8; 32]), +} + +#[near] +pub struct LookupMapAdapter { + inner: LookupMap, +} + +impl FungibleToken { + pub fn new(prefix: S) -> Self + where + S: IntoStorageKey, + { + let mut this = Self { + accounts: LookupMapAdapter::new(prefix), + total_supply: 0, + account_storage_usage: 0, + }; + this.measure_account_storage_usage(); + this + } + + /// Reconstructs the token over already-populated `accounts` storage during a + /// state migration. Unlike [`FungibleToken::new`], it adopts `prefix` + /// without re-measuring per-account storage — measurement transiently writes + /// a probe key and would clobber a live account on a populated map — so the + /// recorded `total_supply` and `account_storage_usage` are carried over from + /// the previous state instead. + pub fn from_prefix( + prefix: S, + total_supply: Balance, + account_storage_usage: StorageUsage, + ) -> Self + where + S: IntoStorageKey, + { + Self { accounts: LookupMapAdapter::new(prefix), total_supply, account_storage_usage } + } + + fn measure_account_storage_usage(&mut self) { + let initial_storage_usage = env::storage_usage(); + let tmp_account_id = "a".repeat(64).parse().unwrap(); + self.accounts.insert(&tmp_account_id, &0u128); + self.account_storage_usage = env::storage_usage() - initial_storage_usage; + self.accounts.remove(&tmp_account_id); + } + + pub fn internal_unwrap_balance_of(&self, account_id: &AccountId) -> Balance { + match self.accounts.get(account_id) { + Some(balance) => balance, + None => { + env::panic_str(format!("The account {} is not registered", &account_id).as_str()) + } + } + } + + pub fn internal_deposit(&mut self, account_id: &AccountId, amount: Balance) { + let balance = self.internal_unwrap_balance_of(account_id); + if let Some(new_balance) = balance.checked_add(amount) { + self.accounts.insert(account_id, &new_balance); + self.total_supply = self + .total_supply + .checked_add(amount) + .unwrap_or_else(|| env::panic_str(ERR_TOTAL_SUPPLY_OVERFLOW)); + } else { + env::panic_str("Balance overflow"); + } + } + + pub fn internal_withdraw(&mut self, account_id: &AccountId, amount: Balance) { + let balance = self.internal_unwrap_balance_of(account_id); + if let Some(new_balance) = balance.checked_sub(amount) { + self.accounts.insert(account_id, &new_balance); + self.total_supply = self + .total_supply + .checked_sub(amount) + .unwrap_or_else(|| env::panic_str(ERR_TOTAL_SUPPLY_OVERFLOW)); + } else { + env::panic_str("The account doesn't have enough balance"); + } + } + + pub fn internal_transfer( + &mut self, + sender_id: &AccountId, + receiver_id: &AccountId, + amount: Balance, + memo: Option, + ) { + require!(sender_id != receiver_id, "Sender and receiver should be different"); + require!(amount > 0, "The amount should be a positive number"); + self.internal_withdraw(sender_id, amount); + self.internal_deposit(receiver_id, amount); + FtTransfer { + old_owner_id: sender_id, + new_owner_id: receiver_id, + amount: U128(amount), + memo: memo.as_deref(), + } + .emit(); + } + + pub fn internal_register_account(&mut self, account_id: &AccountId) { + if self.accounts.insert(account_id, &0).is_some() { + env::panic_str("The account is already registered"); + } + } +} + +impl FungibleTokenCore for FungibleToken { + fn ft_transfer(&mut self, receiver_id: AccountId, amount: U128, memo: Option) { + assert_one_yocto(); + let sender_id = env::predecessor_account_id(); + let amount: Balance = amount.into(); + self.internal_transfer(&sender_id, &receiver_id, amount, memo); + } + + fn ft_transfer_call( + &mut self, + receiver_id: AccountId, + amount: U128, + memo: Option, + msg: String, + ) -> PromiseOrValue { + assert_one_yocto(); + + let sender_id = env::predecessor_account_id(); + let amount: Balance = amount.into(); + self.internal_transfer(&sender_id, &receiver_id, amount, memo); + // Initiating receiver's call and the callback + ext_ft_receiver::ext(receiver_id.clone()) + // forward all remaining gas to `ft_on_transfer` + .with_unused_gas_weight(1) + .ft_on_transfer(sender_id.clone(), amount.into(), msg) + .then( + ext_ft_resolver::ext(env::current_account_id()) + .with_static_gas(GAS_FOR_RESOLVE_TRANSFER) + // do not distribute remaining gas for `ft_resolve_transfer` + .with_unused_gas_weight(0) + .ft_resolve_transfer(sender_id, receiver_id, amount.into()), + ) + .into() + } + + fn ft_total_supply(&self) -> U128 { + self.total_supply.into() + } + + fn ft_balance_of(&self, account_id: AccountId) -> U128 { + self.accounts.get(&account_id).unwrap_or(0).into() + } +} + +impl FungibleToken { + /// Internal method that returns the amount of burned tokens in a corner case when the sender + /// has deleted (unregistered) their account while the `ft_transfer_call` was still in flight. + /// Returns (Used token amount, Burned token amount) + pub fn internal_ft_resolve_transfer( + &mut self, + sender_id: &AccountId, + receiver_id: AccountId, + amount: U128, + ) -> (u128, u128) { + const MAX_RESULT_LENGTH: usize = "\"+340282366920938463463374607431768211455\"".len(); // u128::MAX + + // Get the unused amount from the `ft_on_transfer` call result. + let unused_amount = env::promise_result_checked(0, MAX_RESULT_LENGTH) + .ok() + .and_then(|value| serde_json::from_slice::(&value).ok()) + .unwrap_or(amount) + .0 + .min(amount.0); + + let amount: Balance = amount.into(); + + if unused_amount > 0 { + let receiver_balance = self.accounts.get(&receiver_id).unwrap_or(0); + if receiver_balance > 0 { + let refund_amount = std::cmp::min(receiver_balance, unused_amount); + if let Some(new_receiver_balance) = receiver_balance.checked_sub(refund_amount) { + self.accounts.insert(&receiver_id, &new_receiver_balance); + } else { + env::panic_str("The receiver account doesn't have enough balance"); + } + + if let Some(sender_balance) = self.accounts.get(sender_id) { + if let Some(new_sender_balance) = sender_balance.checked_add(refund_amount) { + self.accounts.insert(sender_id, &new_sender_balance); + } else { + env::panic_str("Sender balance overflow"); + } + + FtTransfer { + old_owner_id: &receiver_id, + new_owner_id: sender_id, + amount: U128(refund_amount), + memo: Some("refund"), + } + .emit(); + let used_amount = amount + .checked_sub(refund_amount) + .unwrap_or_else(|| env::panic_str(ERR_TOTAL_SUPPLY_OVERFLOW)); + return (used_amount, 0); + } else { + // Sender's account was deleted, so we need to burn tokens. + self.total_supply = self + .total_supply + .checked_sub(refund_amount) + .unwrap_or_else(|| env::panic_str(ERR_TOTAL_SUPPLY_OVERFLOW)); + log!("The account of the sender was deleted"); + FtBurn { + owner_id: &receiver_id, + amount: U128(refund_amount), + memo: Some("refund"), + } + .emit(); + return (amount, refund_amount); + } + } + } + (amount, 0) + } +} + +impl FungibleTokenResolver for FungibleToken { + fn ft_resolve_transfer( + &mut self, + sender_id: AccountId, + receiver_id: AccountId, + amount: U128, + ) -> U128 { + self.internal_ft_resolve_transfer(&sender_id, receiver_id, amount).0.into() + } +} + +impl LookupMapAdapter { + fn new(prefix: S) -> LookupMapAdapter { + Self { inner: LookupMap::new(prefix) } + } + + fn hash_key(account: &AccountId) -> LookupMapKey { + LookupMapKey::Hash(env::sha256_array(account.as_bytes())) + } + + pub fn get(&self, key: &AccountId) -> Option { + self.inner.get(&Self::hash_key(key)) + } + + pub fn remove(&mut self, key: &AccountId) -> Option { + self.inner.remove(&Self::hash_key(key)) + } + + pub fn insert(&mut self, key: &AccountId, value: &Balance) -> Option { + self.inner.insert(&Self::hash_key(key), value) + } + + /// Returns true if the map contains a given key. + pub fn contains_key(&self, key: &AccountId) -> bool { + self.inner.contains_key(&Self::hash_key(key)) + } +} diff --git a/vendors/near-contract-standards/src/fungible_token/events.rs b/vendors/near-contract-standards/src/fungible_token/events.rs new file mode 100644 index 0000000..d5487cf --- /dev/null +++ b/vendors/near-contract-standards/src/fungible_token/events.rs @@ -0,0 +1,220 @@ +//! Standard for nep141 (Fungible Token) events. +//! +//! These events will be picked up by the NEAR indexer. +//! +//! +//! +//! This is an extension of the events format (nep-297): +//! +//! +//! The three events in this standard are [`FtMint`], [`FtTransfer`], and [`FtBurn`]. +//! +//! These events can be logged by calling `.emit()` on them if a single event, or calling +//! [`FtMint::emit_many`], [`FtTransfer::emit_many`], +//! or [`FtBurn::emit_many`] respectively. + +use crate::event::NearEvent; +use near_sdk::AccountIdRef; +use near_sdk::json_types::U128; +use near_sdk::serde::Serialize; + +/// Data to log for an FT mint event. To log this event, call [`.emit()`](FtMint::emit). +#[must_use] +#[derive(Serialize, Debug, Clone)] +#[serde(crate = "near_sdk::serde")] +pub struct FtMint<'a> { + pub owner_id: &'a AccountIdRef, + pub amount: U128, + #[serde(skip_serializing_if = "Option::is_none")] + pub memo: Option<&'a str>, +} + +impl FtMint<'_> { + /// Logs the event to the host. This is required to ensure that the event is triggered + /// and to consume the event. + pub fn emit(self) { + Self::emit_many(&[self]) + } + + /// Emits an FT mint event, through [`env::log_str`](near_sdk::env::log_str), + /// where each [`FtMint`] represents the data of each mint. + pub fn emit_many(data: &[FtMint<'_>]) { + new_141_v1(Nep141EventKind::FtMint(data)).emit() + } +} + +/// Data to log for an FT transfer event. To log this event, +/// call [`.emit()`](FtTransfer::emit). +#[must_use] +#[derive(Serialize, Debug, Clone)] +#[serde(crate = "near_sdk::serde")] +pub struct FtTransfer<'a> { + pub old_owner_id: &'a AccountIdRef, + pub new_owner_id: &'a AccountIdRef, + pub amount: U128, + #[serde(skip_serializing_if = "Option::is_none")] + pub memo: Option<&'a str>, +} + +impl FtTransfer<'_> { + /// Logs the event to the host. This is required to ensure that the event is triggered + /// and to consume the event. + pub fn emit(self) { + Self::emit_many(&[self]) + } + + /// Emits an FT transfer event, through [`env::log_str`](near_sdk::env::log_str), + /// where each [`FtTransfer`] represents the data of each transfer. + pub fn emit_many(data: &[FtTransfer<'_>]) { + new_141_v1(Nep141EventKind::FtTransfer(data)).emit() + } +} + +/// Data to log for an FT burn event. To log this event, call [`.emit()`](FtBurn::emit). +#[must_use] +#[derive(Serialize, Debug, Clone)] +#[serde(crate = "near_sdk::serde")] +pub struct FtBurn<'a> { + pub owner_id: &'a AccountIdRef, + pub amount: U128, + #[serde(skip_serializing_if = "Option::is_none")] + pub memo: Option<&'a str>, +} + +impl FtBurn<'_> { + /// Logs the event to the host. This is required to ensure that the event is triggered + /// and to consume the event. + pub fn emit(self) { + Self::emit_many(&[self]) + } + + /// Emits an FT burn event, through [`env::log_str`](near_sdk::env::log_str), + /// where each [`FtBurn`] represents the data of each burn. + pub fn emit_many<'a>(data: &'a [FtBurn<'a>]) { + new_141_v1(Nep141EventKind::FtBurn(data)).emit() + } +} + +#[derive(Serialize, Debug)] +#[serde(crate = "near_sdk::serde")] +pub(crate) struct Nep141Event<'a> { + version: &'static str, + #[serde(flatten)] + event_kind: Nep141EventKind<'a>, +} + +#[derive(Serialize, Debug)] +#[serde(crate = "near_sdk::serde")] +#[serde(tag = "event", content = "data")] +#[serde(rename_all = "snake_case")] +#[allow(clippy::enum_variant_names)] +enum Nep141EventKind<'a> { + FtMint(&'a [FtMint<'a>]), + FtTransfer(&'a [FtTransfer<'a>]), + FtBurn(&'a [FtBurn<'a>]), +} + +fn new_141<'a>(version: &'static str, event_kind: Nep141EventKind<'a>) -> NearEvent<'a> { + NearEvent::Nep141(Nep141Event { version, event_kind }) +} + +fn new_141_v1(event_kind: Nep141EventKind) -> NearEvent { + new_141("1.0.0", event_kind) +} + +#[cfg(test)] +mod tests { + use super::*; + use near_sdk::{AccountIdRef, test_utils}; + + #[test] + fn ft_mint() { + let owner_id = AccountIdRef::new_or_panic("bob"); + let amount = U128(100); + FtMint { owner_id, amount, memo: None }.emit(); + assert_eq!( + test_utils::get_logs()[0], + r#"EVENT_JSON:{"standard":"nep141","version":"1.0.0","event":"ft_mint","data":[{"owner_id":"bob","amount":"100"}]}"# + ); + } + + #[test] + fn ft_mints() { + let owner_id = AccountIdRef::new_or_panic("bob"); + let amount = U128(100); + let mint_log = FtMint { owner_id, amount, memo: None }; + FtMint::emit_many(&[ + mint_log, + FtMint { + owner_id: AccountIdRef::new_or_panic("alice"), + amount: U128(200), + memo: Some("has memo"), + }, + ]); + assert_eq!( + test_utils::get_logs()[0], + r#"EVENT_JSON:{"standard":"nep141","version":"1.0.0","event":"ft_mint","data":[{"owner_id":"bob","amount":"100"},{"owner_id":"alice","amount":"200","memo":"has memo"}]}"# + ); + } + + #[test] + fn ft_burn() { + let owner_id = AccountIdRef::new_or_panic("bob"); + let amount = U128(100); + FtBurn { owner_id, amount, memo: None }.emit(); + assert_eq!( + test_utils::get_logs()[0], + r#"EVENT_JSON:{"standard":"nep141","version":"1.0.0","event":"ft_burn","data":[{"owner_id":"bob","amount":"100"}]}"# + ); + } + + #[test] + fn ft_burns() { + let owner_id = AccountIdRef::new_or_panic("bob"); + let amount = U128(100); + FtBurn::emit_many(&[ + FtBurn { + owner_id: AccountIdRef::new_or_panic("alice"), + amount: U128(200), + memo: Some("has memo"), + }, + FtBurn { owner_id, amount, memo: None }, + ]); + assert_eq!( + test_utils::get_logs()[0], + r#"EVENT_JSON:{"standard":"nep141","version":"1.0.0","event":"ft_burn","data":[{"owner_id":"alice","amount":"200","memo":"has memo"},{"owner_id":"bob","amount":"100"}]}"# + ); + } + + #[test] + fn ft_transfer() { + let old_owner_id = AccountIdRef::new_or_panic("bob"); + let new_owner_id = AccountIdRef::new_or_panic("alice"); + let amount = U128(100); + FtTransfer { old_owner_id, new_owner_id, amount, memo: None }.emit(); + assert_eq!( + test_utils::get_logs()[0], + r#"EVENT_JSON:{"standard":"nep141","version":"1.0.0","event":"ft_transfer","data":[{"old_owner_id":"bob","new_owner_id":"alice","amount":"100"}]}"# + ); + } + + #[test] + fn ft_transfers() { + let old_owner_id = AccountIdRef::new_or_panic("bob"); + let new_owner_id = AccountIdRef::new_or_panic("alice"); + let amount = U128(100); + FtTransfer::emit_many(&[ + FtTransfer { + old_owner_id: AccountIdRef::new_or_panic("alice"), + new_owner_id: AccountIdRef::new_or_panic("bob"), + amount: U128(200), + memo: Some("has memo"), + }, + FtTransfer { old_owner_id, new_owner_id, amount, memo: None }, + ]); + assert_eq!( + test_utils::get_logs()[0], + r#"EVENT_JSON:{"standard":"nep141","version":"1.0.0","event":"ft_transfer","data":[{"old_owner_id":"alice","new_owner_id":"bob","amount":"200","memo":"has memo"},{"old_owner_id":"bob","new_owner_id":"alice","amount":"100"}]}"# + ); + } +} diff --git a/vendors/near-contract-standards/src/fungible_token/macros.rs b/vendors/near-contract-standards/src/fungible_token/macros.rs new file mode 100644 index 0000000..12d210f --- /dev/null +++ b/vendors/near-contract-standards/src/fungible_token/macros.rs @@ -0,0 +1,115 @@ +/// The core methods for a basic fungible token. Extension standards may be +/// added in addition to this macro. +#[macro_export] +#[deprecated( + note = "implement the near_contract_standards::fungible_token::{FungibleTokenCore, FungibleTokenResolver} traits manually instead." +)] +macro_rules! impl_fungible_token_core { + ($contract: ident, $token: ident $(, $on_tokens_burned_fn:ident)?) => { + use $crate::fungible_token::core::FungibleTokenCore; + use $crate::fungible_token::resolver::FungibleTokenResolver; + + #[near] + impl FungibleTokenCore for $contract { + #[payable] + fn ft_transfer( + &mut self, + receiver_id: AccountId, + amount: U128, + memo: Option, + ) { + self.$token.ft_transfer(receiver_id, amount, memo) + } + + #[payable] + fn ft_transfer_call( + &mut self, + receiver_id: AccountId, + amount: U128, + memo: Option, + msg: String, + ) -> PromiseOrValue { + self.$token.ft_transfer_call(receiver_id, amount, memo, msg) + } + + fn ft_total_supply(&self) -> U128 { + self.$token.ft_total_supply() + } + + fn ft_balance_of(&self, account_id: AccountId) -> U128 { + self.$token.ft_balance_of(account_id) + } + } + + #[near] + impl FungibleTokenResolver for $contract { + #[private] + fn ft_resolve_transfer( + &mut self, + sender_id: AccountId, + receiver_id: AccountId, + amount: U128, + ) -> U128 { + let (used_amount, burned_amount) = + self.$token.internal_ft_resolve_transfer(&sender_id, receiver_id, amount); + if burned_amount > 0 { + $(self.$on_tokens_burned_fn(sender_id, burned_amount);)? + } + used_amount.into() + } + } + }; +} + +/// Ensures that when fungible token storage grows by collections adding entries, +/// the storage is be paid by the caller. This ensures that storage cannot grow to a point +/// that the FT contract runs out of Ⓝ. +/// Takes name of the Contract struct, the inner field for the token and optional method name to +/// call when the account was closed. +#[macro_export] +#[deprecated( + note = "implement the near_contract_standards::fungible_token::StorageManagement trait manually instead." +)] +macro_rules! impl_fungible_token_storage { + ($contract: ident, $token: ident $(, $on_account_closed_fn:ident)?) => { + use $crate::storage_management::{ + StorageManagement, StorageBalance, StorageBalanceBounds + }; + + #[near] + impl StorageManagement for $contract { + #[payable] + fn storage_deposit( + &mut self, + account_id: Option, + registration_only: Option, + ) -> StorageBalance { + self.$token.storage_deposit(account_id, registration_only) + } + + #[payable] + fn storage_withdraw(&mut self, amount: Option) -> StorageBalance { + self.$token.storage_withdraw(amount) + } + + #[payable] + fn storage_unregister(&mut self, force: Option) -> bool { + #[allow(unused_variables)] + if let Some((account_id, balance)) = self.$token.internal_storage_unregister(force) { + $(self.$on_account_closed_fn(account_id, balance);)? + true + } else { + false + } + } + + fn storage_balance_bounds(&self) -> StorageBalanceBounds { + self.$token.storage_balance_bounds() + } + + fn storage_balance_of(&self, account_id: AccountId) -> Option { + self.$token.storage_balance_of(account_id) + } + } + }; +} diff --git a/vendors/near-contract-standards/src/fungible_token/metadata.rs b/vendors/near-contract-standards/src/fungible_token/metadata.rs new file mode 100644 index 0000000..1eecbbb --- /dev/null +++ b/vendors/near-contract-standards/src/fungible_token/metadata.rs @@ -0,0 +1,31 @@ +use near_sdk::json_types::Base64VecU8; +use near_sdk::{ext_contract, near, require}; + +pub const FT_METADATA_SPEC: &str = "ft-1.0.0"; + +#[derive(Clone)] +#[near(serializers=[borsh, json])] +pub struct FungibleTokenMetadata { + pub spec: String, + pub name: String, + pub symbol: String, + pub icon: Option, + pub reference: Option, + pub reference_hash: Option, + pub decimals: u8, +} + +#[ext_contract(ext_ft_metadata)] +pub trait FungibleTokenMetadataProvider { + fn ft_metadata(&self) -> FungibleTokenMetadata; +} + +impl FungibleTokenMetadata { + pub fn assert_valid(&self) { + require!(self.spec == FT_METADATA_SPEC); + require!(self.reference.is_some() == self.reference_hash.is_some()); + if let Some(reference_hash) = &self.reference_hash { + require!(reference_hash.0.len() == 32, "Hash has to be 32 bytes"); + } + } +} diff --git a/vendors/near-contract-standards/src/fungible_token/mod.rs b/vendors/near-contract-standards/src/fungible_token/mod.rs new file mode 100644 index 0000000..902c89b --- /dev/null +++ b/vendors/near-contract-standards/src/fungible_token/mod.rs @@ -0,0 +1,25 @@ +//! Fungible tokens as described in [by the spec](https://nomicon.io/Standards/Tokens/FungibleToken). +//! +//! This module represents a Fungible Token standard. +//! +//! # Examples +//! See [`FungibleTokenCore`] and [`FungibleTokenResolver`] for example usage and [`FungibleToken`] +//! for core standard implementation. +//! +//! # Cross-contract calls +//! The traits in this module are annotated with `#[ext_contract]`, which means they can also be +//! used for type-safe cross-contract calls to external contracts that implement these interfaces. +//! See the documentation on [`FungibleTokenCore`] for examples. + +pub mod core; +pub mod core_impl; +pub mod events; +pub mod macros; +pub mod metadata; +pub mod receiver; +pub mod resolver; +pub mod storage_impl; + +pub use crate::fungible_token::core::FungibleTokenCore; +pub use core_impl::{Balance, FungibleToken}; +pub use resolver::FungibleTokenResolver; diff --git a/vendors/near-contract-standards/src/fungible_token/receiver.rs b/vendors/near-contract-standards/src/fungible_token/receiver.rs new file mode 100644 index 0000000..1fbcd5a --- /dev/null +++ b/vendors/near-contract-standards/src/fungible_token/receiver.rs @@ -0,0 +1,30 @@ +use near_sdk::json_types::U128; +use near_sdk::{AccountId, PromiseOrValue, ext_contract}; + +#[ext_contract(ext_ft_receiver)] +pub trait FungibleTokenReceiver { + /// Called by fungible token contract after `ft_transfer_call` was initiated by + /// `sender_id` of the given `amount` with the transfer message given in `msg` field. + /// The `amount` of tokens were already transferred to this contract account and ready to be used. + /// + /// The method must return the amount of tokens that are *not* used/accepted by this contract from the transferred + /// amount. Examples: + /// - The transferred amount was `500`, the contract completely takes it and must return `0`. + /// - The transferred amount was `500`, but this transfer call only needs `450` for the action passed in the `msg` + /// field, then the method must return `50`. + /// - The transferred amount was `500`, but the action in `msg` field has expired and the transfer must be + /// cancelled. The method must return `500` or panic. + /// + /// Arguments: + /// - `sender_id` - the account ID that initiated the transfer. + /// - `amount` - the amount of tokens that were transferred to this account in a decimal string representation. + /// - `msg` - a string message that was passed with this transfer call. + /// + /// Returns the amount of unused tokens that should be returned to sender, in a decimal string representation. + fn ft_on_transfer( + &mut self, + sender_id: AccountId, + amount: U128, + msg: String, + ) -> PromiseOrValue; +} diff --git a/vendors/near-contract-standards/src/fungible_token/resolver.rs b/vendors/near-contract-standards/src/fungible_token/resolver.rs new file mode 100644 index 0000000..6ebe784 --- /dev/null +++ b/vendors/near-contract-standards/src/fungible_token/resolver.rs @@ -0,0 +1,48 @@ +use near_sdk::{AccountId, ext_contract, json_types::U128}; + +/// [`FungibleTokenResolver`] provides token transfer resolve functionality. +/// +/// # Examples +/// +/// ``` +/// use near_sdk::{near, PanicOnDefault, AccountId, log}; +/// use near_sdk::collections::LazyOption; +/// use near_sdk::json_types::U128; +/// use near_contract_standards::fungible_token::{FungibleToken, FungibleTokenResolver}; +/// use near_contract_standards::fungible_token::metadata::FungibleTokenMetadata; +/// +/// #[near(contract_state)] +/// #[derive(PanicOnDefault)] +/// pub struct Contract { +/// token: FungibleToken, +/// metadata: LazyOption, +/// } +/// +///#[near] +/// impl FungibleTokenResolver for Contract { +/// #[private] +/// fn ft_resolve_transfer( +/// &mut self, +/// sender_id: AccountId, +/// receiver_id: AccountId, +/// amount: U128, +/// ) -> U128 { +/// let (used_amount, burned_amount) = +/// self.token.internal_ft_resolve_transfer(&sender_id, receiver_id, amount); +/// if burned_amount > 0 { +/// log!("Account @{} burned {}", sender_id, burned_amount); +/// } +/// used_amount.into() +/// } +/// } +/// ``` +/// +#[ext_contract(ext_ft_resolver)] +pub trait FungibleTokenResolver { + fn ft_resolve_transfer( + &mut self, + sender_id: AccountId, + receiver_id: AccountId, + amount: U128, + ) -> U128; +} diff --git a/vendors/near-contract-standards/src/fungible_token/storage_impl.rs b/vendors/near-contract-standards/src/fungible_token/storage_impl.rs new file mode 100644 index 0000000..190dfba --- /dev/null +++ b/vendors/near-contract-standards/src/fungible_token/storage_impl.rs @@ -0,0 +1,116 @@ +use crate::fungible_token::{Balance, FungibleToken}; +use crate::storage_management::{StorageBalance, StorageBalanceBounds, StorageManagement}; +use near_sdk::{AccountId, NearToken, Promise, assert_one_yocto, env, log}; + +impl FungibleToken { + /// Internal method that returns the Account ID and the balance in case the account was + /// unregistered. + pub fn internal_storage_unregister( + &mut self, + force: Option, + ) -> Option<(AccountId, Balance)> { + assert_one_yocto(); + let account_id = env::predecessor_account_id(); + let force = force.unwrap_or(false); + if let Some(balance) = self.accounts.get(&account_id) { + if balance == 0 || force { + self.accounts.remove(&account_id); + self.total_supply -= balance; + Promise::new(account_id.clone()) + .transfer( + self.storage_balance_bounds() + .min + .saturating_add(NearToken::from_yoctonear(1)), + ) + .detach(); + Some((account_id, balance)) + } else { + env::panic_str( + "Can't unregister the account with the positive balance without force", + ) + } + } else { + log!("The account {} is not registered", &account_id); + None + } + } + + fn internal_storage_balance_of(&self, account_id: &AccountId) -> Option { + if self.accounts.contains_key(account_id) { + Some(StorageBalance { + total: self.storage_balance_bounds().min, + available: NearToken::from_near(0), + }) + } else { + None + } + } +} + +impl StorageManagement for FungibleToken { + // `registration_only` doesn't affect the implementation for vanilla fungible token. + #[allow(unused_variables)] + fn storage_deposit( + &mut self, + account_id: Option, + registration_only: Option, + ) -> StorageBalance { + let amount = env::attached_deposit(); + let account_id = account_id.unwrap_or_else(env::predecessor_account_id); + if self.accounts.contains_key(&account_id) { + log!("The account is already registered, refunding the deposit"); + if amount > NearToken::from_near(0) { + Promise::new(env::predecessor_account_id()).transfer(amount).detach(); + } + } else { + let min_balance = self.storage_balance_bounds().min; + if amount < min_balance { + env::panic_str("The attached deposit is less than the minimum storage balance"); + } + + self.internal_register_account(&account_id); + let refund = amount.saturating_sub(min_balance); + if refund > NearToken::from_near(0) { + Promise::new(env::predecessor_account_id()).transfer(refund).detach(); + } + } + self.internal_storage_balance_of(&account_id).unwrap() + } + + /// While storage_withdraw normally allows the caller to retrieve `available` balance, the basic + /// Fungible Token implementation sets storage_balance_bounds.min == storage_balance_bounds.max, + /// which means available balance will always be 0. So this implementation: + /// * panics if `amount > 0` + /// * never transfers Ⓝ to caller + /// * returns a `storage_balance` struct if `amount` is 0 + fn storage_withdraw(&mut self, amount: Option) -> StorageBalance { + assert_one_yocto(); + let predecessor_account_id = env::predecessor_account_id(); + if let Some(storage_balance) = self.internal_storage_balance_of(&predecessor_account_id) { + match amount { + Some(amount) if amount > NearToken::from_near(0) => { + env::panic_str("The amount is greater than the available storage balance"); + } + _ => storage_balance, + } + } else { + env::panic_str( + format!("The account {} is not registered", &predecessor_account_id).as_str(), + ); + } + } + + fn storage_unregister(&mut self, force: Option) -> bool { + self.internal_storage_unregister(force).is_some() + } + + fn storage_balance_bounds(&self) -> StorageBalanceBounds { + let required_storage_balance = + env::storage_byte_cost().saturating_mul(self.account_storage_usage.into()); + StorageBalanceBounds { min: required_storage_balance, max: Some(required_storage_balance) } + } + + fn storage_balance_of(&self, account_id: AccountId) -> Option { + self.internal_storage_balance_of(&account_id) + } +} diff --git a/vendors/near-contract-standards/src/lib.rs b/vendors/near-contract-standards/src/lib.rs new file mode 100644 index 0000000..edd387d --- /dev/null +++ b/vendors/near-contract-standards/src/lib.rs @@ -0,0 +1,23 @@ +// We want to enable all clippy lints, but some of them generate false positives. +#![allow(clippy::missing_const_for_fn, clippy::redundant_pub_crate)] +#![allow(clippy::needless_lifetimes)] + +pub mod fungible_token; + +/// Non-fungible tokens as described in [by the spec](https://nomicon.io/Standards/Tokens/NonFungibleToken). +pub mod non_fungible_token; + +/// Storage management deals with handling [state storage](https://docs.near.org/docs/concepts/storage-staking) on NEAR. This follows the [storage management standard](https://nomicon.io/Standards/StorageManagement.html). +pub mod storage_management; + +/// This upgrade standard is a use case where a staging area exists for a WASM +/// blob, allowing it to be stored for a period of time before deployed. +#[deprecated( + since = "4.1.0", + note = "This was removed because there is no standard (NEP) for upgradable contracts." +)] +pub mod upgrade; + +pub(crate) mod event; + +pub mod contract_metadata; diff --git a/vendors/near-contract-standards/src/non_fungible_token/approval/approval_impl.rs b/vendors/near-contract-standards/src/non_fungible_token/approval/approval_impl.rs new file mode 100644 index 0000000..5417fbf --- /dev/null +++ b/vendors/near-contract-standards/src/non_fungible_token/approval/approval_impl.rs @@ -0,0 +1,154 @@ +use crate::non_fungible_token::NonFungibleToken; +/// Common implementation of the [approval management standard](https://nomicon.io/Standards/NonFungibleToken/ApprovalManagement.html) for NFTs. +/// on the contract/account that has just been approved. This is not required to implement. +use crate::non_fungible_token::approval::NonFungibleTokenApproval; +use crate::non_fungible_token::approval::ext_nft_approval_receiver; +use crate::non_fungible_token::token::TokenId; +use crate::non_fungible_token::utils::{ + assert_at_least_one_yocto, bytes_for_approved_account_id, refund_approved_account_ids, + refund_approved_account_ids_iter, refund_deposit, +}; +use near_sdk::{AccountId, Gas, Promise, assert_one_yocto, env, require}; + +const GAS_FOR_NFT_APPROVE: Gas = Gas::from_tgas(10); + +fn expect_token_found(option: Option) -> T { + option.unwrap_or_else(|| env::panic_str("Token not found")) +} + +fn expect_approval(option: Option) -> T { + option.unwrap_or_else(|| env::panic_str("next_approval_by_id must be set for approval ext")) +} + +impl NonFungibleTokenApproval for NonFungibleToken { + fn nft_approve( + &mut self, + token_id: TokenId, + account_id: AccountId, + msg: Option, + ) -> Option { + assert_at_least_one_yocto(); + let approvals_by_id = self + .approvals_by_id + .as_mut() + .unwrap_or_else(|| env::panic_str("NFT does not support Approval Management")); + + let owner_id = expect_token_found(self.owner_by_id.get(&token_id)); + + require!(env::predecessor_account_id() == owner_id, "Predecessor must be token owner."); + + let next_approval_id_by_id = expect_approval(self.next_approval_id_by_id.as_mut()); + // update HashMap of approvals for this token + let approved_account_ids = &mut approvals_by_id.get(&token_id).unwrap_or_default(); + let approval_id: u64 = next_approval_id_by_id.get(&token_id).unwrap_or(1u64); + let old_approval_id = approved_account_ids.insert(account_id.clone(), approval_id); + + // save updated approvals HashMap to contract's LookupMap + approvals_by_id.insert(&token_id, approved_account_ids); + + // increment next_approval_id for this token + next_approval_id_by_id.insert(&token_id, &(approval_id + 1)); + + // If this approval replaced existing for same account, no storage was used. + // Otherwise, require that enough deposit was attached to pay for storage, and refund + // excess. + let storage_used = + if old_approval_id.is_none() { bytes_for_approved_account_id(&account_id) } else { 0 }; + refund_deposit(storage_used); + + // if given `msg`, schedule call to `nft_on_approve` and return it. Else, return None. + msg.map(|msg| { + ext_nft_approval_receiver::ext(account_id) + .with_static_gas(env::prepaid_gas().saturating_sub(GAS_FOR_NFT_APPROVE)) + .nft_on_approve(token_id, owner_id, approval_id, msg) + }) + } + + fn nft_revoke(&mut self, token_id: TokenId, account_id: AccountId) { + assert_one_yocto(); + let approvals_by_id = self.approvals_by_id.as_mut().unwrap_or_else(|| { + env::panic_str("NFT does not support Approval Management"); + }); + + let owner_id = expect_token_found(self.owner_by_id.get(&token_id)); + let predecessor_account_id = env::predecessor_account_id(); + + require!(predecessor_account_id == owner_id, "Predecessor must be token owner."); + + // if token has no approvals, do nothing + if let Some(approved_account_ids) = &mut approvals_by_id.get(&token_id) { + // if account_id was already not approved, do nothing + if approved_account_ids.remove(&account_id).is_some() { + refund_approved_account_ids_iter( + predecessor_account_id, + core::iter::once(&account_id), + ) + .detach(); + // if this was the last approval, remove the whole HashMap to save space. + if approved_account_ids.is_empty() { + approvals_by_id.remove(&token_id); + } else { + // otherwise, update approvals_by_id with updated HashMap + approvals_by_id.insert(&token_id, approved_account_ids); + } + } + } + } + + fn nft_revoke_all(&mut self, token_id: TokenId) { + assert_one_yocto(); + let approvals_by_id = self.approvals_by_id.as_mut().unwrap_or_else(|| { + env::panic_str("NFT does not support Approval Management"); + }); + + let owner_id = expect_token_found(self.owner_by_id.get(&token_id)); + let predecessor_account_id = env::predecessor_account_id(); + + require!(predecessor_account_id == owner_id, "Predecessor must be token owner."); + + // if token has no approvals, do nothing + if let Some(approved_account_ids) = &mut approvals_by_id.get(&token_id) { + // otherwise, refund owner for storage costs of all approvals... + refund_approved_account_ids(predecessor_account_id, approved_account_ids).detach(); + // ...and remove whole HashMap of approvals + approvals_by_id.remove(&token_id); + } + } + + fn nft_is_approved( + &self, + token_id: TokenId, + approved_account_id: AccountId, + approval_id: Option, + ) -> bool { + expect_token_found(self.owner_by_id.get(&token_id)); + + let approvals_by_id = if let Some(a) = self.approvals_by_id.as_ref() { + a + } else { + // contract does not support approval management + return false; + }; + + let approved_account_ids = if let Some(ids) = approvals_by_id.get(&token_id) { + ids + } else { + // token has no approvals + return false; + }; + + let actual_approval_id = if let Some(id) = approved_account_ids.get(&approved_account_id) { + id + } else { + // account not in approvals HashMap + return false; + }; + + if let Some(given_approval_id) = approval_id { + &given_approval_id == actual_approval_id + } else { + // account approved, no approval_id given + true + } + } +} diff --git a/vendors/near-contract-standards/src/non_fungible_token/approval/approval_receiver.rs b/vendors/near-contract-standards/src/non_fungible_token/approval/approval_receiver.rs new file mode 100644 index 0000000..af7b367 --- /dev/null +++ b/vendors/near-contract-standards/src/non_fungible_token/approval/approval_receiver.rs @@ -0,0 +1,27 @@ +use crate::non_fungible_token::token::TokenId; +use near_sdk::{AccountId, ext_contract}; + +/// Approval receiver is the trait for the method called (or attempted to be called) when an NFT contract adds an approval for an account. +#[ext_contract(ext_nft_approval_receiver)] +pub trait NonFungibleTokenApprovalReceiver { + /// Respond to notification that contract has been granted approval for a token. + /// + /// Notes + /// * Contract knows the token contract ID from `predecessor_account_id` + /// + /// Arguments: + /// * `token_id`: the token to which this contract has been granted approval + /// * `owner_id`: the owner of the token + /// * `approval_id`: the approval ID stored by NFT contract for this approval. + /// Expected to be a number within the 2^53 limit representable by JSON. + /// * `msg`: specifies information needed by the approved contract in order to + /// handle the approval. Can indicate both a function to call and the + /// parameters to pass to that function. + fn nft_on_approve( + &mut self, + token_id: TokenId, + owner_id: AccountId, + approval_id: u64, + msg: String, + ) -> near_sdk::PromiseOrValue; // TODO: how to make "any"? +} diff --git a/vendors/near-contract-standards/src/non_fungible_token/approval/mod.rs b/vendors/near-contract-standards/src/non_fungible_token/approval/mod.rs new file mode 100644 index 0000000..7a2d874 --- /dev/null +++ b/vendors/near-contract-standards/src/non_fungible_token/approval/mod.rs @@ -0,0 +1,133 @@ +mod approval_impl; +mod approval_receiver; + +pub use approval_receiver::*; +use near_sdk::ext_contract; + +use crate::non_fungible_token::token::TokenId; +use near_sdk::AccountId; +use near_sdk::Promise; + +/// Trait used when it's desired to have a non-fungible token that has a +/// traditional escrow or approval system. This allows Alice to allow Bob +/// to take only the token with the unique identifier "19" but not others. +/// It should be noted that in the [core non-fungible token standard] there +/// is a method to do "transfer and call" which may be preferred over using +/// an approval management standard in certain use cases. +/// +/// [approval management standard]: https://nomicon.io/Standards/NonFungibleToken/ApprovalManagement.html +/// [core non-fungible token standard]: https://nomicon.io/Standards/NonFungibleToken/Core.html +/// +/// # Examples +/// +/// ``` +/// use std::collections::HashMap; +/// use near_sdk::{PanicOnDefault, AccountId, PromiseOrValue, near, Promise}; +/// use near_contract_standards::non_fungible_token::{TokenId, NonFungibleToken, NonFungibleTokenApproval}; +/// +/// #[near(contract_state)] +/// #[derive(PanicOnDefault)] +/// pub struct Contract { +/// tokens: NonFungibleToken, +///} +/// +/// #[near] +/// impl NonFungibleTokenApproval for Contract { +/// #[payable] +/// fn nft_approve(&mut self, token_id: TokenId, account_id: AccountId, msg: Option) -> Option { +/// self.tokens.nft_approve(token_id, account_id, msg) +/// } +/// +/// #[payable] +/// fn nft_revoke(&mut self, token_id: TokenId, account_id: AccountId) { +/// self.tokens.nft_revoke(token_id, account_id); +/// } +/// +/// #[payable] +/// fn nft_revoke_all(&mut self, token_id: TokenId) { +/// self.tokens.nft_revoke_all(token_id); +/// +/// } +/// +/// fn nft_is_approved(&self, token_id: TokenId, approved_account_id: AccountId, approval_id: Option) -> bool { +/// self.tokens.nft_is_approved(token_id, approved_account_id, approval_id) +/// } +/// } +/// ``` +/// +#[ext_contract(ext_nft_approval)] +pub trait NonFungibleTokenApproval { + /// Add an approved account for a specific token. + /// + /// Requirements + /// * Caller of the method must attach a deposit of at least 1 yoctoⓃ for + /// security purposes + /// * Contract MAY require caller to attach larger deposit, to cover cost of + /// storing approver data + /// * Contract MUST panic if called by someone other than token owner + /// * Contract MUST panic if addition would cause `nft_revoke_all` to exceed + /// single-block gas limit + /// * Contract MUST increment approval ID even if re-approving an account + /// * If successfully approved or if had already been approved, and if `msg` is + /// present, contract MUST call `nft_on_approve` on `account_id`. See + /// `nft_on_approve` description below for details. + /// + /// Arguments: + /// * `token_id`: the token for which to add an approval + /// * `account_id`: the account to add to `approvals` + /// * `msg`: optional string to be passed to `nft_on_approve` + /// + /// Returns void, if no `msg` given. Otherwise, returns promise call to + /// `nft_on_approve`, which can resolve with whatever it wants. + fn nft_approve( + &mut self, + token_id: TokenId, + account_id: AccountId, + msg: Option, + ) -> Option; + + /// Revoke an approved account for a specific token. + /// + /// Requirements + /// * Caller of the method must attach a deposit of 1 yoctoⓃ for security + /// purposes + /// * If contract requires >1yN deposit on `nft_approve`, contract + /// MUST refund associated storage deposit when owner revokes approval + /// * Contract MUST panic if called by someone other than token owner + /// + /// Arguments: + /// * `token_id`: the token for which to revoke an approval + /// * `account_id`: the account to remove from `approvals` + fn nft_revoke(&mut self, token_id: TokenId, account_id: AccountId); + + /// Revoke all approved accounts for a specific token. + /// + /// Requirements + /// * Caller of the method must attach a deposit of 1 yoctoⓃ for security + /// purposes + /// * If contract requires >1yN deposit on `nft_approve`, contract + /// MUST refund all associated storage deposit when owner revokes approvals + /// * Contract MUST panic if called by someone other than token owner + /// + /// Arguments: + /// * `token_id`: the token with approvals to revoke + fn nft_revoke_all(&mut self, token_id: TokenId); + + /// Check if a token is approved for transfer by a given account, optionally + /// checking an approval_id + /// + /// Arguments: + /// * `token_id`: the token for which to revoke an approval + /// * `approved_account_id`: the account to check the existence of in `approvals` + /// * `approval_id`: an optional approval ID to check against current approval ID for given account + /// + /// Returns: + /// if `approval_id` given, `true` if `approved_account_id` is approved with given `approval_id` + /// otherwise, `true` if `approved_account_id` is in list of approved accounts + fn nft_is_approved( + &self, + token_id: TokenId, + approved_account_id: AccountId, + approval_id: Option, + ) -> bool; +} diff --git a/vendors/near-contract-standards/src/non_fungible_token/core/core_impl.rs b/vendors/near-contract-standards/src/non_fungible_token/core/core_impl.rs new file mode 100644 index 0000000..34dcfd7 --- /dev/null +++ b/vendors/near-contract-standards/src/non_fungible_token/core/core_impl.rs @@ -0,0 +1,483 @@ +use std::{collections::HashMap, ops::Deref}; + +use near_sdk::{ + AccountId, BorshStorageKey, Gas, IntoStorageKey, PromiseOrValue, StorageUsage, + assert_one_yocto, + borsh::BorshSerialize, + collections::{LookupMap, TreeMap, UnorderedSet}, + env, + json_types::Base64VecU8, + near, require, serde_json, +}; + +use crate::non_fungible_token::{ + core::{NonFungibleTokenCore, receiver::ext_nft_receiver, resolver::ext_nft_resolver}, + events::{NftMint, NftTransfer}, + metadata::TokenMetadata, + token::{Token, TokenId}, + utils::{refund_approved_account_ids, refund_deposit_to_account}, +}; + +use super::resolver::NonFungibleTokenResolver; + +const GAS_FOR_RESOLVE_TRANSFER: Gas = Gas::from_tgas(5); + +/// Implementation of the non-fungible token standard. +/// Allows to include NEP-171 compatible token to any contract. +/// There are next traits that any contract may implement: +/// - NonFungibleTokenCore -- interface with nft_transfer methods. NonFungibleToken provides methods for it. +/// - NonFungibleTokenApproval -- interface with nft_approve methods. NonFungibleToken provides methods for it. +/// - NonFungibleTokenEnumeration -- interface for getting lists of tokens. NonFungibleToken provides methods for it. +/// - NonFungibleTokenMetadata -- return metadata for the token in NEP-177, up to contract to implement. +/// +/// For example usage, see examples/non-fungible-token/src/lib.rs. +#[near] +pub struct NonFungibleToken { + // owner of contract + pub owner_id: AccountId, + + // The storage size in bytes for each new token + pub extra_storage_in_bytes_per_token: StorageUsage, + + // always required + pub owner_by_id: TreeMap, + + // required by metadata extension + pub token_metadata_by_id: Option>, + + // required by enumeration extension + pub tokens_per_owner: Option>>, + + // required by approval extension + pub approvals_by_id: Option>>, + pub next_approval_id_by_id: Option>, +} + +#[derive(BorshStorageKey, BorshSerialize)] +#[borsh(crate = "near_sdk::borsh")] +pub enum StorageKey { + TokensPerOwner { account_hash: Vec }, +} + +impl NonFungibleToken { + pub fn new( + owner_by_id_prefix: Q, + owner_id: AccountId, + token_metadata_prefix: Option, + enumeration_prefix: Option, + approval_prefix: Option, + ) -> Self + where + Q: IntoStorageKey, + R: IntoStorageKey, + S: IntoStorageKey, + T: IntoStorageKey, + { + let (approvals_by_id, next_approval_id_by_id) = if let Some(prefix) = approval_prefix { + let prefix: Vec = prefix.into_storage_key(); + ( + Some(LookupMap::new(prefix.clone())), + Some(LookupMap::new([prefix, "n".into()].concat())), + ) + } else { + (None, None) + }; + + let mut this = Self { + owner_id, + extra_storage_in_bytes_per_token: 0, + owner_by_id: TreeMap::new(owner_by_id_prefix), + token_metadata_by_id: token_metadata_prefix.map(LookupMap::new), + tokens_per_owner: enumeration_prefix.map(LookupMap::new), + approvals_by_id, + next_approval_id_by_id, + }; + this.measure_min_token_storage_cost(); + this + } + + // TODO: does this seem reasonable? + fn measure_min_token_storage_cost(&mut self) { + let initial_storage_usage = env::storage_usage(); + // 64 Length because this is the max account id length + let tmp_token_id = "a".repeat(64); + let tmp_owner_id = "a".repeat(64).parse().unwrap(); + + // 1. set some dummy data + self.owner_by_id.insert(&tmp_token_id, &tmp_owner_id); + if let Some(token_metadata_by_id) = &mut self.token_metadata_by_id { + token_metadata_by_id.insert( + &tmp_token_id, + &TokenMetadata { + title: Some("a".repeat(64)), + description: Some("a".repeat(64)), + media: Some("a".repeat(64)), + media_hash: Some(Base64VecU8::from("a".repeat(64).as_bytes().to_vec())), + copies: Some(1), + issued_at: None, + expires_at: None, + starts_at: None, + updated_at: None, + extra: None, + reference: None, + reference_hash: None, + }, + ); + } + if let Some(tokens_per_owner) = &mut self.tokens_per_owner { + let u = &mut UnorderedSet::new(StorageKey::TokensPerOwner { + account_hash: env::sha256(tmp_owner_id.as_bytes()), + }); + u.insert(&tmp_token_id); + tokens_per_owner.insert(&tmp_owner_id, u); + } + if let Some(approvals_by_id) = &mut self.approvals_by_id { + let mut approvals = HashMap::new(); + approvals.insert(tmp_owner_id.clone(), 1u64); + approvals_by_id.insert(&tmp_token_id, &approvals); + } + if let Some(next_approval_id_by_id) = &mut self.next_approval_id_by_id { + next_approval_id_by_id.insert(&tmp_token_id, &1u64); + } + + // 2. see how much space it took + self.extra_storage_in_bytes_per_token = env::storage_usage() - initial_storage_usage; + + // 3. roll it all back + if let Some(next_approval_id_by_id) = &mut self.next_approval_id_by_id { + next_approval_id_by_id.remove(&tmp_token_id); + } + if let Some(approvals_by_id) = &mut self.approvals_by_id { + approvals_by_id.remove(&tmp_token_id); + } + if let Some(tokens_per_owner) = &mut self.tokens_per_owner { + let mut u = tokens_per_owner.remove(&tmp_owner_id).unwrap(); + u.remove(&tmp_token_id); + } + if let Some(token_metadata_by_id) = &mut self.token_metadata_by_id { + token_metadata_by_id.remove(&tmp_token_id); + } + self.owner_by_id.remove(&tmp_token_id); + } + + /// Transfer token_id from `from` to `to` + /// + /// Do not perform any safety checks or do any logging + pub fn internal_transfer_unguarded( + &mut self, + #[allow(clippy::ptr_arg)] token_id: &TokenId, + from: &AccountId, + to: &AccountId, + ) { + // update owner + self.owner_by_id.insert(token_id, to); + + // if using Enumeration standard, update old & new owner's token lists + if let Some(tokens_per_owner) = &mut self.tokens_per_owner { + // owner_tokens should always exist, so call `unwrap` without guard + let mut owner_tokens = tokens_per_owner.get(from).unwrap_or_else(|| { + env::panic_str("Unable to access tokens per owner in unguarded call.") + }); + owner_tokens.remove(token_id); + if owner_tokens.is_empty() { + tokens_per_owner.remove(from); + } else { + tokens_per_owner.insert(from, &owner_tokens); + } + + let mut receiver_tokens = tokens_per_owner.get(to).unwrap_or_else(|| { + UnorderedSet::new(StorageKey::TokensPerOwner { + account_hash: env::sha256(to.as_bytes()), + }) + }); + receiver_tokens.insert(token_id); + tokens_per_owner.insert(to, &receiver_tokens); + } + } + + /// Transfer from current owner to receiver_id, checking that sender is allowed to transfer. + /// Clear approvals, if approval extension being used. + /// Return previous owner and approvals. + pub fn internal_transfer( + &mut self, + sender_id: &AccountId, + receiver_id: &AccountId, + #[allow(clippy::ptr_arg)] token_id: &TokenId, + approval_id: Option, + memo: Option, + ) -> (AccountId, Option>) { + let owner_id = + self.owner_by_id.get(token_id).unwrap_or_else(|| env::panic_str("Token not found")); + + // clear approvals, if using Approval Management extension + // this will be rolled back by a panic if sending fails + let approved_account_ids = + self.approvals_by_id.as_mut().map(|by_id| by_id.remove(token_id).unwrap_or_default()); + + // check if authorized + let sender_id = if sender_id != &owner_id { + // Panic if approval extension is NOT being used + let app_acc_ids = approved_account_ids + .as_ref() + .unwrap_or_else(|| env::panic_str("Approval extension is disabled")); + + // Approval extension is being used; get approval_id for sender. + let actual_approval_id = app_acc_ids.get(sender_id); + + // Panic if sender not approved at all + if actual_approval_id.is_none() { + env::panic_str("Sender not approved"); + } + + // If approval_id included, check that it matches + require!( + approval_id.is_none() || actual_approval_id == approval_id.as_ref(), + format!( + "The actual approval_id {:?} is different from the given approval_id {:?}", + actual_approval_id, approval_id + ) + ); + Some(sender_id) + } else { + None + }; + + require!(&owner_id != receiver_id, "Current and next owner must differ"); + + self.internal_transfer_unguarded(token_id, &owner_id, receiver_id); + + NonFungibleToken::emit_transfer(&owner_id, receiver_id, token_id, sender_id, memo); + + // return previous owner & approvals + (owner_id, approved_account_ids) + } + + fn emit_transfer( + owner_id: &AccountId, + receiver_id: &AccountId, + token_id: &str, + sender_id: Option<&AccountId>, + memo: Option, + ) { + NftTransfer { + old_owner_id: owner_id, + new_owner_id: receiver_id, + token_ids: &[token_id], + authorized_id: sender_id.filter(|sender_id| *sender_id == owner_id).map(|f| f.deref()), + memo: memo.as_deref(), + } + .emit(); + } + + /// Mint a new token. Not part of official standard, but needed in most situations. + /// Consuming contract expected to wrap this with an `nft_mint` function. + /// + /// Requirements: + /// * Caller must be the `owner_id` set during contract initialization. + /// * Caller of the method must attach a deposit of 1 yoctoⓃ for security purposes. + /// * If contract is using Metadata extension (by having provided `metadata_prefix` during + /// contract initialization), `token_metadata` must be given. + /// * token_id must be unique + /// + /// Returns the newly minted token + #[deprecated(since = "4.0.0", note = "mint is deprecated, please use internal_mint instead.")] + pub fn mint( + &mut self, + token_id: TokenId, + token_owner_id: AccountId, + token_metadata: Option, + ) -> Token { + assert_eq!(env::predecessor_account_id(), self.owner_id, "Unauthorized"); + + self.internal_mint(token_id, token_owner_id, token_metadata) + } + + /// Mint a new token without checking: + /// * Whether the caller id is equal to the `owner_id` + /// * Assumes there will be a refund to the predecessor after covering the storage costs + /// + /// Returns the newly minted token and emits the mint event + pub fn internal_mint( + &mut self, + token_id: TokenId, + token_owner_id: AccountId, + token_metadata: Option, + ) -> Token { + let token = self.internal_mint_with_refund( + token_id, + token_owner_id, + token_metadata, + Some(env::predecessor_account_id()), + ); + NftMint { owner_id: &token.owner_id, token_ids: &[&token.token_id], memo: None }.emit(); + token + } + + /// Mint a new token without checking: + /// * Whether the caller id is equal to the `owner_id` + /// * `refund_id` will transfer the left over balance after storage costs are calculated to the provided account. + /// Typically the account will be the owner. If `None`, will not refund. This is useful for delaying refunding + /// until multiple tokens have been minted. + /// + /// Returns the newly minted token and does not emit the mint event. This allows minting multiple before emitting. + pub fn internal_mint_with_refund( + &mut self, + token_id: TokenId, + token_owner_id: AccountId, + token_metadata: Option, + refund_id: Option, + ) -> Token { + // Remember current storage usage if refund_id is Some + let initial_storage_usage = refund_id.map(|account_id| (account_id, env::storage_usage())); + + if self.token_metadata_by_id.is_some() && token_metadata.is_none() { + env::panic_str("Must provide metadata"); + } + if self.owner_by_id.get(&token_id).is_some() { + env::panic_str("token_id must be unique"); + } + + let owner_id: AccountId = token_owner_id; + + // Core behavior: every token must have an owner + self.owner_by_id.insert(&token_id, &owner_id); + + // Metadata extension: Save metadata, keep variable around to return later. + // Note that check above already panicked if metadata extension in use but no metadata + // provided to call. + self.token_metadata_by_id + .as_mut() + .and_then(|by_id| by_id.insert(&token_id, token_metadata.as_ref().unwrap())); + + // Enumeration extension: Record tokens_per_owner for use with enumeration view methods. + if let Some(tokens_per_owner) = &mut self.tokens_per_owner { + let mut token_ids = tokens_per_owner.get(&owner_id).unwrap_or_else(|| { + UnorderedSet::new(StorageKey::TokensPerOwner { + account_hash: env::sha256(owner_id.as_bytes()), + }) + }); + token_ids.insert(&token_id); + tokens_per_owner.insert(&owner_id, &token_ids); + } + + // Approval Management extension: return empty HashMap as part of Token + let approved_account_ids = + if self.approvals_by_id.is_some() { Some(HashMap::new()) } else { None }; + + if let Some((id, storage_usage)) = initial_storage_usage { + refund_deposit_to_account(env::storage_usage() - storage_usage, id) + } + + // Return any extra attached deposit not used for storage + + Token { token_id, owner_id, metadata: token_metadata, approved_account_ids } + } +} + +impl NonFungibleTokenCore for NonFungibleToken { + fn nft_transfer( + &mut self, + receiver_id: AccountId, + token_id: TokenId, + approval_id: Option, + memo: Option, + ) { + assert_one_yocto(); + let sender_id = env::predecessor_account_id(); + self.internal_transfer(&sender_id, &receiver_id, &token_id, approval_id, memo); + } + + fn nft_transfer_call( + &mut self, + receiver_id: AccountId, + token_id: TokenId, + approval_id: Option, + memo: Option, + msg: String, + ) -> PromiseOrValue { + assert_one_yocto(); + let sender_id = env::predecessor_account_id(); + let (old_owner, old_approvals) = + self.internal_transfer(&sender_id, &receiver_id, &token_id, approval_id, memo); + // Initiating receiver's call and the callback + ext_nft_receiver::ext(receiver_id.clone()) + // forward all remaining gas to `nft_on_transfer` + .with_unused_gas_weight(1) + .nft_on_transfer(sender_id, old_owner.clone(), token_id.clone(), msg) + .then( + ext_nft_resolver::ext(env::current_account_id()) + .with_static_gas(GAS_FOR_RESOLVE_TRANSFER) + // do not distribute remaining gas for `nft_resolve_transfer` + .with_unused_gas_weight(0) + .nft_resolve_transfer(old_owner, receiver_id, token_id, old_approvals), + ) + .into() + } + + fn nft_token(&self, token_id: TokenId) -> Option { + let owner_id = self.owner_by_id.get(&token_id)?; + let metadata = self.token_metadata_by_id.as_ref().and_then(|by_id| by_id.get(&token_id)); + let approved_account_ids = self + .approvals_by_id + .as_ref() + .and_then(|by_id| by_id.get(&token_id).or_else(|| Some(HashMap::new()))); + Some(Token { token_id, owner_id, metadata, approved_account_ids }) + } +} + +impl NonFungibleTokenResolver for NonFungibleToken { + /// Returns true if token was successfully transferred to `receiver_id`. + fn nft_resolve_transfer( + &mut self, + previous_owner_id: AccountId, + receiver_id: AccountId, + token_id: TokenId, + approved_account_ids: Option>, + ) -> bool { + const MAX_RESULT_LENGTH: usize = "false".len(); + + // Get whether token should be returned + let must_revert = env::promise_result_checked(0, MAX_RESULT_LENGTH) + .ok() + .and_then(|value| serde_json::from_slice(&value).ok()) + .unwrap_or(true); + + // if call succeeded, return early + if !must_revert { + return true; + } + + // OTHERWISE, try to set owner back to previous_owner_id and restore approved_account_ids + + // Check that receiver didn't already transfer it away or burn it. + if let Some(current_owner) = self.owner_by_id.get(&token_id) { + if current_owner != receiver_id { + // The token is not owned by the receiver anymore. Can't return it. + return true; + } + } else { + // The token was burned and doesn't exist anymore. + // Refund storage cost for storing approvals to original owner and return early. + if let Some(approved_account_ids) = approved_account_ids { + refund_approved_account_ids(previous_owner_id, &approved_account_ids).detach(); + } + return true; + }; + + self.internal_transfer_unguarded(&token_id, &receiver_id, &previous_owner_id); + + // If using Approval Management extension, + // 1. revert any approvals receiver already set, refunding storage costs + // 2. reset approvals to what previous owner had set before call to nft_transfer_call + if let Some(by_id) = &mut self.approvals_by_id { + if let Some(receiver_approvals) = by_id.remove(&token_id) { + refund_approved_account_ids(receiver_id.clone(), &receiver_approvals).detach(); + } + if let Some(previous_owner_approvals) = approved_account_ids { + by_id.insert(&token_id, &previous_owner_approvals); + } + } + NonFungibleToken::emit_transfer(&receiver_id, &previous_owner_id, &token_id, None, None); + false + } +} diff --git a/vendors/near-contract-standards/src/non_fungible_token/core/mod.rs b/vendors/near-contract-standards/src/non_fungible_token/core/mod.rs new file mode 100644 index 0000000..3dc7946 --- /dev/null +++ b/vendors/near-contract-standards/src/non_fungible_token/core/mod.rs @@ -0,0 +1,148 @@ +mod core_impl; + +mod receiver; +mod resolver; + +pub use self::core_impl::*; + +pub use self::receiver::{NonFungibleTokenReceiver, ext_nft_receiver}; +pub use self::resolver::{NonFungibleTokenResolver, ext_nft_resolver}; + +use crate::non_fungible_token::token::{Token, TokenId}; +use near_sdk::AccountId; +use near_sdk::PromiseOrValue; +use near_sdk::ext_contract; + +/// Used for all non-fungible tokens. The specification for the +/// [core non-fungible token standard] lays out the reasoning for each method. +/// It's important to check out [NonFungibleTokenReceiver](crate::non_fungible_token::core::NonFungibleTokenReceiver) +/// and [NonFungibleTokenResolver](crate::non_fungible_token::core::NonFungibleTokenResolver) to +/// understand how the cross-contract call work. +/// +/// [core non-fungible token standard]: +/// +/// # Examples +/// +/// ## Implementing the trait +/// +/// ``` +/// use near_sdk::{PanicOnDefault, AccountId, PromiseOrValue, near}; +/// use near_contract_standards::non_fungible_token::{core::NonFungibleTokenCore, NonFungibleToken, TokenId, Token}; +/// +/// #[near(contract_state)] +/// #[derive(PanicOnDefault)] +/// pub struct Contract { +/// tokens: NonFungibleToken, +///} +/// #[near] +/// impl NonFungibleTokenCore for Contract { +/// #[payable] +/// fn nft_transfer(&mut self, receiver_id: AccountId, token_id: TokenId, approval_id: Option, memo: Option) { +/// self.tokens.nft_transfer(receiver_id, token_id, approval_id, memo); +/// } +/// +/// #[payable] +/// fn nft_transfer_call(&mut self, receiver_id: AccountId, token_id: TokenId, approval_id: Option, memo: Option, msg: String) -> PromiseOrValue { +/// self.tokens.nft_transfer_call(receiver_id, token_id, approval_id, memo, msg) +/// } +/// +/// fn nft_token(&self, token_id: TokenId) -> Option { +/// self.tokens.nft_token(token_id) +/// } +///} +/// ``` +/// +/// ## Cross-contract calls +/// +/// The `#[ext_contract]` annotation on this trait also generates the [`ext_nft_core`] module, +/// which can be used to make type-safe cross-contract calls to **any** contract that +/// implements this interface: +/// +/// ```ignore +/// use near_contract_standards::non_fungible_token::core::ext_nft_core; +/// use near_sdk::{Gas, NearToken}; +/// +/// // Transfer an NFT on an external contract +/// ext_nft_core::ext(nft_contract_id) +/// .with_attached_deposit(NearToken::from_yoctonear(1)) +/// .with_static_gas(Gas::from_tgas(5)) +/// .nft_transfer(receiver_id, token_id, None, None); +/// ``` +/// +#[ext_contract(ext_nft_core)] +pub trait NonFungibleTokenCore { + /// Simple transfer. Transfer a given `token_id` from current owner to + /// `receiver_id`. + /// + /// Requirements + /// * Caller of the method must attach a deposit of 1 yoctoⓃ for security purposes + /// * Contract MUST panic if called by someone other than token owner or, + /// if using Approval Management, one of the approved accounts + /// * `approval_id` is for use with Approval Management, + /// see + /// * If using Approval Management, contract MUST nullify approved accounts on + /// successful transfer. + /// * TODO: needed? Both accounts must be registered with the contract for transfer to + /// succeed. See see + /// + /// Arguments: + /// * `receiver_id`: the valid NEAR account receiving the token + /// * `token_id`: the token to transfer + /// * `approval_id`: expected approval ID. A number smaller than + /// 2^53, and therefore representable as JSON. See Approval Management + /// standard for full explanation. + /// * `memo` (optional): for use cases that may benefit from indexing or + /// providing information for a transfer + fn nft_transfer( + &mut self, + receiver_id: AccountId, + token_id: TokenId, + approval_id: Option, + memo: Option, + ); + + /// Transfer token and call a method on a receiver contract. A successful + /// workflow will end in a success execution outcome to the callback on the NFT + /// contract at the method `nft_resolve_transfer`. + /// + /// You can think of this as being similar to attaching native NEAR tokens to a + /// function call. It allows you to attach any Non-Fungible Token in a call to a + /// receiver contract. + /// + /// Requirements: + /// * Caller of the method must attach a deposit of 1 yoctoⓃ for security + /// purposes + /// * Contract MUST panic if called by someone other than token owner or, + /// if using Approval Management, one of the approved accounts + /// * The receiving contract must implement `ft_on_transfer` according to the + /// standard. If it does not, FT contract's `ft_resolve_transfer` MUST deal + /// with the resulting failed cross-contract call and roll back the transfer. + /// * Contract MUST implement the behavior described in `ft_resolve_transfer` + /// * `approval_id` is for use with Approval Management extension, see + /// that document for full explanation. + /// * If using Approval Management, contract MUST nullify approved accounts on + /// successful transfer. + /// + /// Arguments: + /// * `receiver_id`: the valid NEAR account receiving the token. + /// * `token_id`: the token to send. + /// * `approval_id`: expected approval ID. A number smaller than + /// 2^53, and therefore representable as JSON. See Approval Management + /// standard for full explanation. + /// * `memo` (optional): for use cases that may benefit from indexing or + /// providing information for a transfer. + /// * `msg`: specifies information needed by the receiving contract in + /// order to properly handle the transfer. Can indicate both a function to + /// call and the parameters to pass to that function. + fn nft_transfer_call( + &mut self, + receiver_id: AccountId, + token_id: TokenId, + approval_id: Option, + memo: Option, + msg: String, + ) -> PromiseOrValue; + + /// Returns the token with the given `token_id` or `null` if no such token. + fn nft_token(&self, token_id: TokenId) -> Option; +} diff --git a/vendors/near-contract-standards/src/non_fungible_token/core/receiver.rs b/vendors/near-contract-standards/src/non_fungible_token/core/receiver.rs new file mode 100644 index 0000000..348be11 --- /dev/null +++ b/vendors/near-contract-standards/src/non_fungible_token/core/receiver.rs @@ -0,0 +1,30 @@ +use crate::non_fungible_token::token::TokenId; +use near_sdk::{AccountId, PromiseOrValue, ext_contract}; + +/// Used when an NFT is transferred using `nft_transfer_call`. This trait is implemented on the receiving contract, not on the NFT contract. +#[ext_contract(ext_nft_receiver)] +pub trait NonFungibleTokenReceiver { + /// Take some action after receiving a non-fungible token + /// + /// Requirements: + /// * Contract MUST restrict calls to this function to a set of whitelisted NFT + /// contracts + /// + /// Arguments: + /// * `sender_id`: the sender of `nft_transfer_call` + /// * `previous_owner_id`: the account that owned the NFT prior to it being + /// transferred to this contract, which can differ from `sender_id` if using + /// Approval Management extension + /// * `token_id`: the `token_id` argument given to `nft_transfer_call` + /// * `msg`: information necessary for this contract to know how to process the + /// request. This may include method names and/or arguments. + /// + /// Returns true if token should be returned to `sender_id` + fn nft_on_transfer( + &mut self, + sender_id: AccountId, + previous_owner_id: AccountId, + token_id: TokenId, + msg: String, + ) -> PromiseOrValue; +} diff --git a/vendors/near-contract-standards/src/non_fungible_token/core/resolver.rs b/vendors/near-contract-standards/src/non_fungible_token/core/resolver.rs new file mode 100644 index 0000000..565bfb2 --- /dev/null +++ b/vendors/near-contract-standards/src/non_fungible_token/core/resolver.rs @@ -0,0 +1,63 @@ +use crate::non_fungible_token::token::TokenId; +use near_sdk::{AccountId, ext_contract}; +use std::collections::HashMap; + +/// Used when an NFT is transferred using `nft_transfer_call`. This is the method that's called after `nft_on_transfer`. This trait is implemented on the NFT contract. +/// +/// # Examples +/// +/// ``` +/// use std::collections::HashMap; +/// use near_sdk::{PanicOnDefault, AccountId, PromiseOrValue, near}; +/// use near_contract_standards::non_fungible_token::{NonFungibleToken, NonFungibleTokenResolver, TokenId}; +/// +/// #[near(contract_state)] +/// #[derive(PanicOnDefault)] +/// pub struct Contract { +/// tokens: NonFungibleToken, +///} +/// #[near] +/// impl NonFungibleTokenResolver for Contract { +/// #[private] +/// fn nft_resolve_transfer(&mut self, previous_owner_id: AccountId, receiver_id: AccountId, token_id: TokenId, approved_account_ids: Option>) -> bool { +/// self.tokens.nft_resolve_transfer(previous_owner_id, receiver_id, token_id, approved_account_ids) +/// } +/// } +/// ``` +/// +#[ext_contract(ext_nft_resolver)] +pub trait NonFungibleTokenResolver { + /// Finalize an `nft_transfer_call` chain of cross-contract calls. + /// + /// The `nft_transfer_call` process: + /// + /// 1. Sender calls `nft_transfer_call` on FT contract + /// 2. NFT contract transfers token from sender to receiver + /// 3. NFT contract calls `nft_on_transfer` on receiver contract + /// 4+. [receiver contract may make other cross-contract calls] + /// N. NFT contract resolves promise chain with `nft_resolve_transfer`, and may + /// transfer token back to sender + /// + /// Requirements: + /// * Contract MUST forbid calls to this function by any account except self + /// * If promise chain failed, contract MUST revert token transfer + /// * If promise chain resolves with `true`, contract MUST return token to + /// `sender_id` + /// + /// Arguments: + /// * `previous_owner_id`: the owner prior to the call to `nft_transfer_call` + /// * `receiver_id`: the `receiver_id` argument given to `nft_transfer_call` + /// * `token_id`: the `token_id` argument given to `ft_transfer_call` + /// * `approved_account_ids`: if using Approval Management, contract MUST provide + /// set of original approved accounts in this argument, and restore these + /// approved accounts in case of revert. + /// + /// Returns true if token was successfully transferred to `receiver_id`. + fn nft_resolve_transfer( + &mut self, + previous_owner_id: AccountId, + receiver_id: AccountId, + token_id: TokenId, + approved_account_ids: Option>, + ) -> bool; +} diff --git a/vendors/near-contract-standards/src/non_fungible_token/enumeration/enumeration_impl.rs b/vendors/near-contract-standards/src/non_fungible_token/enumeration/enumeration_impl.rs new file mode 100644 index 0000000..e2d6679 --- /dev/null +++ b/vendors/near-contract-standards/src/non_fungible_token/enumeration/enumeration_impl.rs @@ -0,0 +1,95 @@ +use super::NonFungibleTokenEnumeration; +use crate::non_fungible_token::NonFungibleToken; +use crate::non_fungible_token::token::{Token, TokenId}; +use near_sdk::json_types::U128; +use near_sdk::{AccountId, env, require}; + +impl NonFungibleToken { + /// Helper function used by a enumerations methods + /// Note: this method is not exposed publicly to end users + fn enum_get_token(&self, owner_id: AccountId, token_id: TokenId) -> Token { + let metadata = self.token_metadata_by_id.as_ref().and_then(|m| m.get(&token_id)); + let approved_account_ids = self + .approvals_by_id + .as_ref() + .map(|approvals_by_id| approvals_by_id.get(&token_id).unwrap_or_default()); + + Token { token_id, owner_id, metadata, approved_account_ids } + } +} + +impl NonFungibleTokenEnumeration for NonFungibleToken { + fn nft_total_supply(&self) -> U128 { + // An unfortunate cast from the max of TreeMap to the spec + (self.owner_by_id.len() as u128).into() + } + + fn nft_tokens(&self, from_index: Option, limit: Option) -> Vec { + // Get starting index, whether or not it was explicitly given. + // Defaults to 0 based on the spec: + // https://nomicon.io/Standards/NonFungibleToken/Enumeration.html#interface + let start_index: u128 = from_index.map(From::from).unwrap_or_default(); + require!( + (self.owner_by_id.len() as u128) >= start_index, + "Out of bounds, please use a smaller from_index." + ); + let limit = limit.map(|v| v as usize).unwrap_or(usize::MAX); + require!(limit != 0, "Cannot provide limit of 0."); + self.owner_by_id + .iter() + .skip(start_index as usize) + .take(limit) + .map(|(token_id, owner_id)| self.enum_get_token(owner_id, token_id)) + .collect() + } + + fn nft_supply_for_owner(&self, account_id: AccountId) -> U128 { + let tokens_per_owner = self.tokens_per_owner.as_ref().unwrap_or_else(|| { + env::panic_str( + "Could not find tokens_per_owner when calling a method on the \ + enumeration standard.", + ) + }); + tokens_per_owner + .get(&account_id) + .map(|account_tokens| U128::from(account_tokens.len() as u128)) + .unwrap_or(U128(0)) + } + + fn nft_tokens_for_owner( + &self, + account_id: AccountId, + from_index: Option, + limit: Option, + ) -> Vec { + let tokens_per_owner = self.tokens_per_owner.as_ref().unwrap_or_else(|| { + env::panic_str( + "Could not find tokens_per_owner when calling a method on the \ + enumeration standard.", + ) + }); + let token_set = if let Some(token_set) = tokens_per_owner.get(&account_id) { + token_set + } else { + return vec![]; + }; + + if token_set.is_empty() { + return vec![]; + } + + let limit = limit.map(|v| v as usize).unwrap_or(usize::MAX); + require!(limit != 0, "Cannot provide limit of 0."); + let start_index: u128 = from_index.map(From::from).unwrap_or_default(); + require!( + token_set.len() as u128 > start_index, + "Out of bounds, please use a smaller from_index." + ); + token_set + .iter() + .skip(start_index as usize) + .take(limit) + .map(|token_id| self.enum_get_token(account_id.clone(), token_id)) + .collect() + } +} diff --git a/vendors/near-contract-standards/src/non_fungible_token/enumeration/mod.rs b/vendors/near-contract-standards/src/non_fungible_token/enumeration/mod.rs new file mode 100644 index 0000000..eb5d3a0 --- /dev/null +++ b/vendors/near-contract-standards/src/non_fungible_token/enumeration/mod.rs @@ -0,0 +1,88 @@ +mod enumeration_impl; + +use crate::non_fungible_token::token::Token; +use near_sdk::json_types::U128; +use near_sdk::{AccountId, ext_contract}; + +/// Offers methods helpful in determining account ownership of NFTs and provides a way to page through NFTs per owner, determine total supply, etc. +/// +/// # Examples +/// +/// ``` +/// use std::collections::HashMap; +/// use near_sdk::{PanicOnDefault, AccountId, PromiseOrValue, near, Promise}; +/// use near_contract_standards::non_fungible_token::{NonFungibleToken, NonFungibleTokenEnumeration, TokenId, Token}; +/// use near_sdk::json_types::U128; +/// +/// #[near(contract_state)] +/// #[derive(PanicOnDefault)] +/// pub struct Contract { +/// tokens: NonFungibleToken, +///} +/// +/// #[near] +/// impl NonFungibleTokenEnumeration for Contract { +/// fn nft_total_supply(&self) -> U128 { +/// self.tokens.nft_total_supply() +/// } +/// +/// fn nft_tokens(&self, from_index: Option, limit: Option) -> Vec { +/// self.tokens.nft_tokens(from_index, limit) +/// } +/// +/// fn nft_supply_for_owner(&self, account_id: AccountId) -> U128 { +/// self.tokens.nft_supply_for_owner(account_id) +/// } +/// +/// fn nft_tokens_for_owner(&self, account_id: AccountId, from_index: Option, limit: Option) -> Vec { +/// self.tokens.nft_tokens_for_owner(account_id, from_index, limit) +/// } +/// } +/// ``` +/// +#[ext_contract(ext_nft_enumeration)] +pub trait NonFungibleTokenEnumeration { + /// Returns the total supply of non-fungible tokens as a string representing an + /// unsigned 128-bit integer to avoid JSON number limit of 2^53. + fn nft_total_supply(&self) -> U128; + + /// Get a list of all tokens + /// + /// Arguments: + /// * `from_index`: a string representing an unsigned 128-bit integer, + /// representing the starting index of tokens to return + /// * `limit`: the maximum number of tokens to return + /// + /// Returns an array of Token objects, as described in Core standard + fn nft_tokens( + &self, + from_index: Option, // default: "0" + limit: Option, // default: unlimited (could fail due to gas limit) + ) -> Vec; + + /// Get number of tokens owned by a given account + /// + /// Arguments: + /// * `account_id`: a valid NEAR account + /// + /// Returns the number of non-fungible tokens owned by given `account_id` as + /// a string representing the value as an unsigned 128-bit integer to avoid JSON + /// number limit of 2^53. + fn nft_supply_for_owner(&self, account_id: AccountId) -> U128; + + /// Get list of all tokens owned by a given account + /// + /// Arguments: + /// * `account_id`: a valid NEAR account + /// * `from_index`: a string representing an unsigned 128-bit integer, + /// representing the starting index of tokens to return + /// * `limit`: the maximum number of tokens to return + /// + /// Returns a paginated list of all tokens owned by this account + fn nft_tokens_for_owner( + &self, + account_id: AccountId, + from_index: Option, // default: "0" + limit: Option, // default: unlimited (could fail due to gas limit) + ) -> Vec; +} diff --git a/vendors/near-contract-standards/src/non_fungible_token/events.rs b/vendors/near-contract-standards/src/non_fungible_token/events.rs new file mode 100644 index 0000000..bf4417c --- /dev/null +++ b/vendors/near-contract-standards/src/non_fungible_token/events.rs @@ -0,0 +1,226 @@ +//! Standard for nep171 (Non-Fungible Token) events. +//! +//! These events will be picked up by the NEAR indexer. +//! +//! +//! +//! This is an extension of the events format (nep-297): +//! +//! +//! The three events in this standard are [`NftMint`], [`NftTransfer`], and [`NftBurn`]. +//! +//! These events can be logged by calling `.emit()` on them if a single event, or calling +//! [`NftMint::emit_many`], [`NftTransfer::emit_many`], +//! or [`NftBurn::emit_many`] respectively. + +use crate::event::NearEvent; +use near_sdk::AccountIdRef; +use near_sdk::serde::Serialize; + +/// Data to log for an NFT mint event. To log this event, call [`.emit()`](NftMint::emit). +#[must_use] +#[derive(Serialize, Debug, Clone)] +#[serde(crate = "near_sdk::serde")] +pub struct NftMint<'a> { + pub owner_id: &'a AccountIdRef, + pub token_ids: &'a [&'a str], + #[serde(skip_serializing_if = "Option::is_none")] + pub memo: Option<&'a str>, +} + +impl NftMint<'_> { + /// Logs the event to the host. This is required to ensure that the event is triggered + /// and to consume the event. + pub fn emit(self) { + Self::emit_many(&[self]) + } + + /// Emits an nft mint event, through [`env::log_str`](near_sdk::env::log_str), + /// where each [`NftMint`] represents the data of each mint. + pub fn emit_many(data: &[NftMint<'_>]) { + new_171_v1(Nep171EventKind::NftMint(data)).emit() + } +} + +/// Data to log for an NFT transfer event. To log this event, +/// call [`.emit()`](NftTransfer::emit). +#[must_use] +#[derive(Serialize, Debug, Clone)] +#[serde(crate = "near_sdk::serde")] +pub struct NftTransfer<'a> { + pub old_owner_id: &'a AccountIdRef, + pub new_owner_id: &'a AccountIdRef, + pub token_ids: &'a [&'a str], + #[serde(skip_serializing_if = "Option::is_none")] + pub authorized_id: Option<&'a AccountIdRef>, + #[serde(skip_serializing_if = "Option::is_none")] + pub memo: Option<&'a str>, +} + +impl NftTransfer<'_> { + /// Logs the event to the host. This is required to ensure that the event is triggered + /// and to consume the event. + pub fn emit(self) { + Self::emit_many(&[self]) + } + + /// Emits an nft transfer event, through [`env::log_str`](near_sdk::env::log_str), + /// where each [`NftTransfer`] represents the data of each transfer. + pub fn emit_many(data: &[NftTransfer<'_>]) { + new_171_v1(Nep171EventKind::NftTransfer(data)).emit() + } +} + +/// Data to log for an NFT burn event. To log this event, call [`.emit()`](NftBurn::emit). +#[must_use] +#[derive(Serialize, Debug, Clone)] +#[serde(crate = "near_sdk::serde")] +pub struct NftBurn<'a> { + pub owner_id: &'a AccountIdRef, + pub token_ids: &'a [&'a str], + #[serde(skip_serializing_if = "Option::is_none")] + pub authorized_id: Option<&'a AccountIdRef>, + #[serde(skip_serializing_if = "Option::is_none")] + pub memo: Option<&'a str>, +} + +impl NftBurn<'_> { + /// Logs the event to the host. This is required to ensure that the event is triggered + /// and to consume the event. + pub fn emit(self) { + Self::emit_many(&[self]) + } + + /// Emits an nft burn event, through [`env::log_str`](near_sdk::env::log_str), + /// where each [`NftBurn`] represents the data of each burn. + pub fn emit_many<'a>(data: &'a [NftBurn<'a>]) { + new_171_v1(Nep171EventKind::NftBurn(data)).emit() + } +} + +#[derive(Serialize, Debug)] +#[serde(crate = "near_sdk::serde")] +pub(crate) struct Nep171Event<'a> { + version: &'static str, + #[serde(flatten)] + event_kind: Nep171EventKind<'a>, +} + +#[derive(Serialize, Debug)] +#[serde(crate = "near_sdk::serde")] +#[serde(tag = "event", content = "data")] +#[serde(rename_all = "snake_case")] +#[allow(clippy::enum_variant_names)] +enum Nep171EventKind<'a> { + NftMint(&'a [NftMint<'a>]), + NftTransfer(&'a [NftTransfer<'a>]), + NftBurn(&'a [NftBurn<'a>]), +} + +fn new_171<'a>(version: &'static str, event_kind: Nep171EventKind<'a>) -> NearEvent<'a> { + NearEvent::Nep171(Nep171Event { version, event_kind }) +} + +fn new_171_v1(event_kind: Nep171EventKind) -> NearEvent { + new_171("1.0.0", event_kind) +} + +#[cfg(test)] +mod tests { + use super::*; + use near_sdk::test_utils; + + #[test] + fn nft_mint() { + let owner_id = AccountIdRef::new_or_panic("bob"); + let token_ids = &["0", "1"]; + NftMint { owner_id, token_ids, memo: None }.emit(); + assert_eq!( + test_utils::get_logs()[0], + r#"EVENT_JSON:{"standard":"nep171","version":"1.0.0","event":"nft_mint","data":[{"owner_id":"bob","token_ids":["0","1"]}]}"# + ); + } + + #[test] + fn nft_mints() { + let owner_id = AccountIdRef::new_or_panic("bob"); + let token_ids = &["0", "1"]; + let mint_log = NftMint { owner_id, token_ids, memo: None }; + NftMint::emit_many(&[ + mint_log, + NftMint { + owner_id: AccountIdRef::new_or_panic("alice"), + token_ids: &["2", "3"], + memo: Some("has memo"), + }, + ]); + assert_eq!( + test_utils::get_logs()[0], + r#"EVENT_JSON:{"standard":"nep171","version":"1.0.0","event":"nft_mint","data":[{"owner_id":"bob","token_ids":["0","1"]},{"owner_id":"alice","token_ids":["2","3"],"memo":"has memo"}]}"# + ); + } + + #[test] + fn nft_burn() { + let owner_id = AccountIdRef::new_or_panic("bob"); + let token_ids = &["0", "1"]; + NftBurn { owner_id, token_ids, authorized_id: None, memo: None }.emit(); + assert_eq!( + test_utils::get_logs()[0], + r#"EVENT_JSON:{"standard":"nep171","version":"1.0.0","event":"nft_burn","data":[{"owner_id":"bob","token_ids":["0","1"]}]}"# + ); + } + + #[test] + fn nft_burns() { + let owner_id = AccountIdRef::new_or_panic("bob"); + let token_ids = &["0", "1"]; + NftBurn::emit_many(&[ + NftBurn { + owner_id: AccountIdRef::new_or_panic("alice"), + token_ids: &["2", "3"], + authorized_id: Some(AccountIdRef::new_or_panic("bob")), + memo: Some("has memo"), + }, + NftBurn { owner_id, token_ids, authorized_id: None, memo: None }, + ]); + assert_eq!( + test_utils::get_logs()[0], + r#"EVENT_JSON:{"standard":"nep171","version":"1.0.0","event":"nft_burn","data":[{"owner_id":"alice","token_ids":["2","3"],"authorized_id":"bob","memo":"has memo"},{"owner_id":"bob","token_ids":["0","1"]}]}"# + ); + } + + #[test] + fn nft_transfer() { + let old_owner_id = AccountIdRef::new_or_panic("bob"); + let new_owner_id = AccountIdRef::new_or_panic("alice"); + let token_ids = &["0", "1"]; + NftTransfer { old_owner_id, new_owner_id, token_ids, authorized_id: None, memo: None } + .emit(); + assert_eq!( + test_utils::get_logs()[0], + r#"EVENT_JSON:{"standard":"nep171","version":"1.0.0","event":"nft_transfer","data":[{"old_owner_id":"bob","new_owner_id":"alice","token_ids":["0","1"]}]}"# + ); + } + + #[test] + fn nft_transfers() { + let old_owner_id = AccountIdRef::new_or_panic("bob"); + let new_owner_id = AccountIdRef::new_or_panic("alice"); + let token_ids = &["0", "1"]; + NftTransfer::emit_many(&[ + NftTransfer { + old_owner_id: AccountIdRef::new_or_panic("alice"), + new_owner_id: AccountIdRef::new_or_panic("bob"), + token_ids: &["2", "3"], + authorized_id: Some(AccountIdRef::new_or_panic("bob")), + memo: Some("has memo"), + }, + NftTransfer { old_owner_id, new_owner_id, token_ids, authorized_id: None, memo: None }, + ]); + assert_eq!( + test_utils::get_logs()[0], + r#"EVENT_JSON:{"standard":"nep171","version":"1.0.0","event":"nft_transfer","data":[{"old_owner_id":"alice","new_owner_id":"bob","token_ids":["2","3"],"authorized_id":"bob","memo":"has memo"},{"old_owner_id":"bob","new_owner_id":"alice","token_ids":["0","1"]}]}"# + ); + } +} diff --git a/vendors/near-contract-standards/src/non_fungible_token/macros.rs b/vendors/near-contract-standards/src/non_fungible_token/macros.rs new file mode 100644 index 0000000..e16b8b3 --- /dev/null +++ b/vendors/near-contract-standards/src/non_fungible_token/macros.rs @@ -0,0 +1,145 @@ +/// The core methods for a basic non-fungible token. Extension standards may be +/// added in addition to this macro. +#[macro_export] +#[deprecated( + note = "implement the near_contract_standards::non_fungible_token::NonFungibleTokenCore and near_contract_standards::non_fungible_token::NonFungibleTokenResolver traits manually instead." +)] +macro_rules! impl_non_fungible_token_core { + ($contract: ident, $token: ident) => { + use $crate::non_fungible_token::core::NonFungibleTokenCore; + use $crate::non_fungible_token::core::NonFungibleTokenResolver; + + #[near] + impl NonFungibleTokenCore for $contract { + #[payable] + fn nft_transfer( + &mut self, + receiver_id: AccountId, + token_id: TokenId, + approval_id: Option, + memo: Option, + ) { + self.$token.nft_transfer(receiver_id, token_id, approval_id, memo) + } + + #[payable] + fn nft_transfer_call( + &mut self, + receiver_id: AccountId, + token_id: TokenId, + approval_id: Option, + memo: Option, + msg: String, + ) -> PromiseOrValue { + self.$token.nft_transfer_call(receiver_id, token_id, approval_id, memo, msg) + } + + fn nft_token(&self, token_id: TokenId) -> Option { + self.$token.nft_token(token_id) + } + } + + #[near] + impl NonFungibleTokenResolver for $contract { + #[private] + fn nft_resolve_transfer( + &mut self, + previous_owner_id: AccountId, + receiver_id: AccountId, + token_id: TokenId, + approved_account_ids: Option>, + ) -> bool { + self.$token.nft_resolve_transfer( + previous_owner_id, + receiver_id, + token_id, + approved_account_ids, + ) + } + } + }; +} + +/// Non-fungible token approval management allows for an escrow system where +/// multiple approvals per token exist. +#[macro_export] +#[deprecated( + note = "implement the near_contract_standards::non_fungible_token::NonFungibleTokenApproval trait manually instead." +)] +macro_rules! impl_non_fungible_token_approval { + ($contract: ident, $token: ident) => { + use $crate::non_fungible_token::approval::NonFungibleTokenApproval; + + #[near] + impl NonFungibleTokenApproval for $contract { + #[payable] + fn nft_approve( + &mut self, + token_id: TokenId, + account_id: AccountId, + msg: Option, + ) -> Option { + self.$token.nft_approve(token_id, account_id, msg) + } + + #[payable] + fn nft_revoke(&mut self, token_id: TokenId, account_id: AccountId) { + self.$token.nft_revoke(token_id, account_id) + } + + #[payable] + fn nft_revoke_all(&mut self, token_id: TokenId) { + self.$token.nft_revoke_all(token_id) + } + + fn nft_is_approved( + &self, + token_id: TokenId, + approved_account_id: AccountId, + approval_id: Option, + ) -> bool { + self.$token.nft_is_approved(token_id, approved_account_id, approval_id) + } + } + }; +} + +/// Non-fungible enumeration adds the extension standard offering several +/// view-only methods to get token supply, tokens per owner, etc. +#[macro_export] +#[deprecated( + note = "implement the near_contract_standards::non_fungible_token::NonFungibleTokenEnumeration trait manually instead." +)] +macro_rules! impl_non_fungible_token_enumeration { + ($contract: ident, $token: ident) => { + use $crate::non_fungible_token::enumeration::NonFungibleTokenEnumeration; + + #[near] + impl NonFungibleTokenEnumeration for $contract { + fn nft_total_supply(&self) -> near_sdk::json_types::U128 { + self.$token.nft_total_supply() + } + + fn nft_tokens( + &self, + from_index: Option, + limit: Option, + ) -> Vec { + self.$token.nft_tokens(from_index, limit) + } + + fn nft_supply_for_owner(&self, account_id: AccountId) -> near_sdk::json_types::U128 { + self.$token.nft_supply_for_owner(account_id) + } + + fn nft_tokens_for_owner( + &self, + account_id: AccountId, + from_index: Option, + limit: Option, + ) -> Vec { + self.$token.nft_tokens_for_owner(account_id, from_index, limit) + } + } + }; +} diff --git a/vendors/near-contract-standards/src/non_fungible_token/metadata.rs b/vendors/near-contract-standards/src/non_fungible_token/metadata.rs new file mode 100644 index 0000000..b82babe --- /dev/null +++ b/vendors/near-contract-standards/src/non_fungible_token/metadata.rs @@ -0,0 +1,68 @@ +use near_sdk::json_types::Base64VecU8; +use near_sdk::{ext_contract, near, require}; + +/// This spec can be treated like a version of the standard. +pub const NFT_METADATA_SPEC: &str = "nft-1.0.0"; + +/// Metadata for the NFT contract itself. +#[derive(Clone, Debug, PartialEq, Eq)] +#[near(serializers=[borsh, json])] +pub struct NFTContractMetadata { + pub spec: String, // required, essentially a version like "nft-1.0.0" + pub name: String, // required, ex. "Mosaics" + pub symbol: String, // required, ex. "MOSIAC" + pub icon: Option, // Data URL + pub base_uri: Option, // Centralized gateway known to have reliable access to decentralized storage assets referenced by `reference` or `media` URLs + pub reference: Option, // URL to a JSON file with more info + pub reference_hash: Option, // Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included. +} + +#[near(serializers=[borsh, json])] +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub struct TokenMetadata { + pub title: Option, // ex. "Arch Nemesis: Mail Carrier" or "Parcel #5055" + pub description: Option, // free-form description + pub media: Option, // URL to associated media, preferably to decentralized, content-addressed storage + pub media_hash: Option, // Base64-encoded sha256 hash of content referenced by the `media` field. Required if `media` is included. + pub copies: Option, // number of copies of this set of metadata in existence when token was minted. + pub issued_at: Option, // ISO 8601 datetime when token was issued or minted + pub expires_at: Option, // ISO 8601 datetime when token expires + pub starts_at: Option, // ISO 8601 datetime when token starts being valid + pub updated_at: Option, // ISO 8601 datetime when token was last updated + pub extra: Option, // anything extra the NFT wants to store on-chain. Can be stringified JSON. + pub reference: Option, // URL to an off-chain JSON file with more info. + pub reference_hash: Option, // Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included. +} + +/// Offers details on the contract-level metadata. +#[ext_contract(ext_nft_metadata_provider)] +pub trait NonFungibleTokenMetadataProvider { + fn nft_metadata(&self) -> NFTContractMetadata; +} + +impl NFTContractMetadata { + pub fn assert_valid(&self) { + require!(self.spec == NFT_METADATA_SPEC, "Spec is not NFT metadata"); + require!( + self.reference.is_some() == self.reference_hash.is_some(), + "Reference and reference hash must be present" + ); + if let Some(reference_hash) = &self.reference_hash { + require!(reference_hash.0.len() == 32, "Hash has to be 32 bytes"); + } + } +} + +impl TokenMetadata { + pub fn assert_valid(&self) { + require!(self.media.is_some() == self.media_hash.is_some()); + if let Some(media_hash) = &self.media_hash { + require!(media_hash.0.len() == 32, "Media hash has to be 32 bytes"); + } + + require!(self.reference.is_some() == self.reference_hash.is_some()); + if let Some(reference_hash) = &self.reference_hash { + require!(reference_hash.0.len() == 32, "Reference hash has to be 32 bytes"); + } + } +} diff --git a/vendors/near-contract-standards/src/non_fungible_token/mod.rs b/vendors/near-contract-standards/src/non_fungible_token/mod.rs new file mode 100644 index 0000000..d8ee105 --- /dev/null +++ b/vendors/near-contract-standards/src/non_fungible_token/mod.rs @@ -0,0 +1,28 @@ +/// The [approval management standard](https://nomicon.io/Standards/NonFungibleToken/ApprovalManagement.html) for NFTs. +pub mod approval; +/// The [core non-fungible token standard](https://nomicon.io/Standards/NonFungibleToken/Core.html). This can be though of as the base standard, with the others being extension standards. +pub mod core; +/// Common implementation of the [core non-fungible token standard](https://nomicon.io/Standards/NonFungibleToken/Core.html). +/// Trait for the [NFT enumeration standard](https://nomicon.io/Standards/NonFungibleToken/Enumeration.html). +/// This provides useful view-only methods returning token supply, tokens by owner, etc. +pub mod enumeration; +/// Macros typically used by a contract wanting to take advantage of the non-fungible +/// token NEAR contract standard approach. +mod macros; +/// Metadata traits and implementation according to the [NFT enumeration standard](https://nomicon.io/Standards/NonFungibleToken/Metadata.html). +/// This covers both the contract metadata and the individual token metadata. +pub mod metadata; +/// The Token struct for the non-fungible token. +mod token; +pub use self::token::{Token, TokenId}; + +/// NFT utility functions +mod utils; +pub use utils::*; + +pub use self::approval::NonFungibleTokenApproval; +pub use self::core::NonFungibleToken; +pub use self::core::NonFungibleTokenResolver; +pub use self::enumeration::NonFungibleTokenEnumeration; + +pub mod events; diff --git a/vendors/near-contract-standards/src/non_fungible_token/token.rs b/vendors/near-contract-standards/src/non_fungible_token/token.rs new file mode 100644 index 0000000..b043ba8 --- /dev/null +++ b/vendors/near-contract-standards/src/non_fungible_token/token.rs @@ -0,0 +1,18 @@ +use crate::non_fungible_token::metadata::TokenMetadata; +use near_sdk::{ + AccountId, NearSchema, + serde::{Deserialize, Serialize}, +}; +use std::collections::HashMap; +/// Note that token IDs for NFTs are strings on NEAR. It's still fine to use autoincrementing numbers as unique IDs if desired, but they should be stringified. This is to make IDs more future-proof as chain-agnostic conventions and standards arise, and allows for more flexibility with considerations like bridging NFTs across chains, etc. +pub type TokenId = String; + +/// In this implementation, the Token struct takes two extensions standards (metadata and approval) as optional fields, as they are frequently used in modern NFTs. +#[derive(NearSchema, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +#[serde(crate = "near_sdk::serde")] +pub struct Token { + pub token_id: TokenId, + pub owner_id: AccountId, + pub metadata: Option, + pub approved_account_ids: Option>, +} diff --git a/vendors/near-contract-standards/src/non_fungible_token/utils.rs b/vendors/near-contract-standards/src/non_fungible_token/utils.rs new file mode 100644 index 0000000..5095d28 --- /dev/null +++ b/vendors/near-contract-standards/src/non_fungible_token/utils.rs @@ -0,0 +1,56 @@ +use near_sdk::{AccountId, NearToken, Promise, env, require}; +use std::collections::HashMap; +use std::mem::size_of; + +// TODO: need a way for end users to determine how much an approval will cost. +pub fn bytes_for_approved_account_id(account_id: &AccountId) -> u64 { + // The extra 4 bytes are coming from Borsh serialization to store the length of the string. + account_id.as_str().len() as u64 + 4 + size_of::() as u64 +} + +pub fn refund_approved_account_ids_iter<'a, I>( + account_id: AccountId, + approved_account_ids: I, +) -> Promise +where + I: Iterator, +{ + let storage_released: u64 = approved_account_ids.map(bytes_for_approved_account_id).sum(); + Promise::new(account_id) + .transfer(env::storage_byte_cost().saturating_mul(storage_released.into())) +} + +pub fn refund_approved_account_ids( + account_id: AccountId, + approved_account_ids: &HashMap, +) -> Promise { + refund_approved_account_ids_iter(account_id, approved_account_ids.keys()) +} + +pub fn refund_deposit_to_account(storage_used: u64, account_id: AccountId) { + let required_cost = env::storage_byte_cost().saturating_mul(storage_used.into()); + let attached_deposit = env::attached_deposit(); + + require!( + required_cost <= attached_deposit, + format!("Must attach {} to cover storage", required_cost.exact_amount_display()) + ); + + let refund = attached_deposit.saturating_sub(required_cost); + if refund.as_yoctonear() > 1 { + Promise::new(account_id).transfer(refund).detach(); + } +} + +/// Assumes that the precedecessor will be refunded +pub fn refund_deposit(storage_used: u64) { + refund_deposit_to_account(storage_used, env::predecessor_account_id()) +} + +/// Assert that at least 1 yoctoNEAR was attached. +pub(crate) fn assert_at_least_one_yocto() { + require!( + env::attached_deposit() >= NearToken::from_yoctonear(1), + "Requires attached deposit of at least 1 yoctoNEAR" + ) +} diff --git a/vendors/near-contract-standards/src/storage_management/mod.rs b/vendors/near-contract-standards/src/storage_management/mod.rs new file mode 100644 index 0000000..cbd404d --- /dev/null +++ b/vendors/near-contract-standards/src/storage_management/mod.rs @@ -0,0 +1,120 @@ +use near_sdk::{AccountId, NearToken, ext_contract, near}; + +#[near(serializers=[borsh, json])] +pub struct StorageBalance { + pub total: NearToken, + pub available: NearToken, +} + +#[near(serializers=[borsh, json])] +pub struct StorageBalanceBounds { + pub min: NearToken, + pub max: Option, +} + +/// Ensures that when fungible token storage grows by collections adding entries, +/// the storage is be paid by the caller. This ensures that storage cannot grow to a point +/// that the FT contract runs out of Ⓝ. +/// Takes name of the Contract struct, the inner field for the token and optional method name to +/// call when the account was closed. +/// +/// # Examples +/// +/// ``` +/// use near_sdk::{near, PanicOnDefault, AccountId, NearToken, log}; +/// use near_sdk::collections::LazyOption; +/// use near_sdk::json_types::U128; +/// use near_contract_standards::fungible_token::FungibleToken; +/// use near_contract_standards::storage_management::{ +/// StorageBalance, StorageBalanceBounds, StorageManagement, +/// }; +/// use near_contract_standards::fungible_token::metadata::FungibleTokenMetadata; +/// +/// #[near(contract_state)] +/// #[derive(PanicOnDefault)] +/// pub struct Contract { +/// token: FungibleToken, +/// metadata: LazyOption, +/// } +/// +/// #[near] +/// impl StorageManagement for Contract { +/// #[payable] +/// fn storage_deposit( +/// &mut self, +/// account_id: Option, +/// registration_only: Option, +/// ) -> StorageBalance { +/// self.token.storage_deposit(account_id, registration_only) +/// } +/// +/// #[payable] +/// fn storage_withdraw(&mut self, amount: Option) -> StorageBalance { +/// self.token.storage_withdraw(amount) +/// } +/// +/// #[payable] +/// fn storage_unregister(&mut self, force: Option) -> bool { +/// #[allow(unused_variables)] +/// if let Some((account_id, balance)) = self.token.internal_storage_unregister(force) { +/// log!("Closed @{} with {}", account_id, balance); +/// true +/// } else { +/// false +/// } +/// } +/// +/// fn storage_balance_bounds(&self) -> StorageBalanceBounds { +/// self.token.storage_balance_bounds() +/// } +/// +/// fn storage_balance_of(&self, account_id: AccountId) -> Option { +/// self.token.storage_balance_of(account_id) +/// } +/// } +/// +/// ``` +/// +#[ext_contract(ext_storage_management)] +pub trait StorageManagement { + // if `registration_only=true` MUST refund above the minimum balance if the account didn't exist and + // refund full deposit if the account exists. + fn storage_deposit( + &mut self, + account_id: Option, + registration_only: Option, + ) -> StorageBalance; + + /// Withdraw specified amount of available Ⓝ for predecessor account. + /// + /// This method is safe to call. It MUST NOT remove data. + /// + /// `amount` is sent as a string representing an unsigned 128-bit integer. If + /// omitted, contract MUST refund full `available` balance. If `amount` exceeds + /// predecessor account's available balance, contract MUST panic. + /// + /// If predecessor account not registered, contract MUST panic. + /// + /// MUST require exactly 1 yoctoNEAR attached balance to prevent restricted + /// function-call access-key call (UX wallet security) + /// + /// Returns the StorageBalance structure showing updated balances. + fn storage_withdraw(&mut self, amount: Option) -> StorageBalance; + + /// Unregisters the predecessor account and returns the storage NEAR deposit back. + /// + /// If the predecessor account is not registered, the function MUST return `false` without panic. + /// + /// If `force=true` the function SHOULD ignore account balances (burn them) and close the account. + /// Otherwise, MUST panic if caller has a positive registered balance (eg token holdings) or + /// the contract doesn't support force deregistration. + /// MUST require exactly 1 yoctoNEAR attached balance to prevent restricted function-call access-key call + /// (UX wallet security) + /// Returns `true` iff the account was unregistered. + /// Returns `false` iff account was not registered before. + fn storage_unregister(&mut self, force: Option) -> bool; + + fn storage_balance_bounds(&self) -> StorageBalanceBounds; + + fn storage_balance_of(&self, account_id: AccountId) -> Option; +} diff --git a/vendors/near-contract-standards/src/upgrade/mod.rs b/vendors/near-contract-standards/src/upgrade/mod.rs new file mode 100644 index 0000000..d313950 --- /dev/null +++ b/vendors/near-contract-standards/src/upgrade/mod.rs @@ -0,0 +1,79 @@ +use near_sdk::json_types::U64; +use near_sdk::{AccountId, Duration, Promise, Timestamp, env, near, require}; + +type WrappedDuration = U64; + +pub trait Ownable { + fn assert_owner(&self) { + require!(env::predecessor_account_id() == self.get_owner(), "Owner must be predecessor"); + } + fn get_owner(&self) -> AccountId; + fn set_owner(&mut self, owner: AccountId); +} + +pub trait Upgradable { + fn get_staging_duration(&self) -> WrappedDuration; + fn stage_code(&mut self, code: Vec, timestamp: Timestamp); + fn deploy_code(&mut self) -> Promise; + + /// Implement migration for the next version. + /// Should be `unimplemented` for a new contract. + /// TODO: consider adding version of the contract stored in the storage? + fn migrate(&mut self) { + unimplemented!(); + } +} + +#[near] +pub struct Upgrade { + pub owner: AccountId, + pub staging_duration: Duration, + pub staging_timestamp: Timestamp, +} + +impl Upgrade { + pub fn new(owner: AccountId, staging_duration: Duration) -> Self { + Self { owner, staging_duration, staging_timestamp: 0 } + } +} + +impl Ownable for Upgrade { + fn get_owner(&self) -> AccountId { + self.owner.clone() + } + + fn set_owner(&mut self, owner: AccountId) { + self.assert_owner(); + self.owner = owner; + } +} + +impl Upgradable for Upgrade { + fn get_staging_duration(&self) -> WrappedDuration { + self.staging_duration.into() + } + + fn stage_code(&mut self, code: Vec, timestamp: Timestamp) { + self.assert_owner(); + require!( + env::block_timestamp() + self.staging_duration < timestamp, + "Timestamp must be later than staging duration" + ); + // Writes directly into storage to avoid serialization penalty by using default struct. + env::storage_write(b"upgrade", &code); + self.staging_timestamp = timestamp; + } + + fn deploy_code(&mut self) -> Promise { + if env::block_timestamp() < self.staging_timestamp { + env::panic_str( + format!("Deploy code too early: staging ends on {}", self.staging_timestamp) + .as_str(), + ); + } + let code = env::storage_read(b"upgrade") + .unwrap_or_else(|| env::panic_str("No upgrade code available")); + env::storage_remove(b"upgrade"); + Promise::new(env::current_account_id()).deploy_contract(code) + } +}