diff --git a/Cargo.lock b/Cargo.lock index 0ffd4ef..dfc7919 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "ahash" version = "0.7.6" @@ -24,9 +39,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" [[package]] name = "assert_matches" @@ -53,18 +68,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.28", ] [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.28", ] [[package]] @@ -86,9 +101,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "axum" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8175979259124331c1d7bf6586ee7e0da434155e4b2d48ec2c8386281d8df39" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" dependencies = [ "async-trait", "axum-core", @@ -129,6 +144,21 @@ dependencies = [ "tower-service", ] +[[package]] +name = "backtrace" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base16ct" version = "0.1.1" @@ -160,7 +190,7 @@ dependencies = [ "pbkdf2", "rand_core 0.6.4", "ripemd", - "sha2 0.10.6", + "sha2 0.10.7", "subtle", "zeroize", ] @@ -227,9 +257,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -258,9 +291,9 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.2" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" +checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" [[package]] name = "core-foundation" @@ -404,7 +437,7 @@ dependencies = [ "schemars", "serde", "serde-json-wasm", - "sha2 0.10.6", + "sha2 0.10.7", "thiserror", ] @@ -420,9 +453,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] @@ -471,6 +504,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "cw-address-like" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451a4691083a88a3c0630a8a88799e9d4cd6679b7ce8ff22b8da2873ff31d380" +dependencies = [ + "cosmwasm-std", +] + [[package]] name = "cw-multi-test" version = "0.16.5" @@ -479,8 +521,8 @@ checksum = "127c7bb95853b8e828bdab97065c81cb5ddc20f7339180b61b2300565aaa99d1" dependencies = [ "anyhow", "cosmwasm-std", - "cw-storage-plus", - "cw-utils", + "cw-storage-plus 1.1.0", + "cw-utils 1.0.1", "derivative", "itertools", "k256", @@ -490,6 +532,43 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cw-ownable" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093dfb4520c48b5848274dd88ea99e280a04bc08729603341c7fb0d758c74321" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-address-like", + "cw-ownable-derive", + "cw-storage-plus 1.1.0", + "cw-utils 1.0.1", + "thiserror", +] + +[[package]] +name = "cw-ownable-derive" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d3bf2e0f341bb6cc100d7d441d31cf713fbd3ce0c511f91e79f14b40a889af" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cw-storage-plus" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b6f91c0b94481a3e9ef1ceb183c37d00764f8751e39b45fc09f4d9b970d469" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + [[package]] name = "cw-storage-plus" version = "1.1.0" @@ -501,6 +580,21 @@ dependencies = [ "serde", ] +[[package]] +name = "cw-utils" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6a84c6c1c0acc3616398eba50783934bd6c964bad6974241eaee3460c8f5b26" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw2 0.16.0", + "schemars", + "semver", + "serde", + "thiserror", +] + [[package]] name = "cw-utils" version = "1.0.1" @@ -509,13 +603,26 @@ checksum = "c80e93d1deccb8588db03945016a292c3c631e6325d349ebb35d2db6f4f946f7" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw2", + "cw2 1.1.0", "schemars", "semver", "serde", "thiserror", ] +[[package]] +name = "cw2" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91398113b806f4d2a8d5f8d05684704a20ffd5968bf87e3473e1973710b884ad" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 0.16.0", + "schemars", + "serde", +] + [[package]] name = "cw2" version = "1.1.0" @@ -524,12 +631,25 @@ checksum = "29ac2dc7a55ad64173ca1e0a46697c31b7a5c51342f55a1e84a724da4eb99908" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus", + "cw-storage-plus 1.1.0", "schemars", "serde", "thiserror", ] +[[package]] +name = "cw721" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94a1ea6e6277bdd6dfc043a9b1380697fe29d6e24b072597439523658d21d791" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils 0.16.0", + "schemars", + "serde", +] + [[package]] name = "cw721" version = "0.18.0" @@ -538,9 +658,45 @@ checksum = "e3c4d286625ccadc957fe480dd3bdc54ada19e0e6b5b9325379db3130569e914" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-utils", + "cw-utils 1.0.1", + "schemars", + "serde", +] + +[[package]] +name = "cw721-base" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77518e27431d43214cff4cdfbd788a7508f68d9b1f32389e6fce513e7eaccbef" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 0.16.0", + "cw-utils 0.16.0", + "cw2 0.16.0", + "cw721 0.16.0", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw721-base" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da518d9f68bfda7d972cbaca2e8fcf04651d0edc3de72b04ae2bcd9289c81614" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-ownable", + "cw-storage-plus 1.1.0", + "cw-utils 1.0.1", + "cw2 1.1.0", + "cw721 0.18.0", + "cw721-base 0.16.0", "schemars", "serde", + "thiserror", ] [[package]] @@ -553,6 +709,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "deranged" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7684a49fb1af197853ef7b2ee694bc1f5b4179556f1e5710e1760c5db6f5e929" + [[package]] name = "derivative" version = "2.2.0" @@ -592,9 +754,9 @@ checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" [[package]] name = "dyn-clone" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" +checksum = "304e6508efa593091e97a9abbc10f90aa7ca635b6d2784feff3c89d41dd12272" [[package]] name = "e2e-tests" @@ -604,7 +766,7 @@ dependencies = [ "cosm-orc", "cosm-tome", "cosmwasm-std", - "cw-utils", + "cw-utils 1.0.1", "env_logger", "itertools", "once_cell", @@ -665,9 +827,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "elliptic-curve" @@ -704,9 +866,9 @@ dependencies = [ [[package]] name = "erased-serde" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2b0c2380453a92ea8b6c8e5f64ecaafccddde8ceab55ff7a8ac1029f894569" +checksum = "da96524cc884f6558f1769b6c46686af2fe8e8b4cd253bd5a3cdba8181b8e070" dependencies = [ "serde", ] @@ -818,7 +980,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.28", ] [[package]] @@ -863,9 +1025,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "js-sys", @@ -874,6 +1036,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" + [[package]] name = "group" version = "0.12.1" @@ -887,9 +1055,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.19" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" +checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" dependencies = [ "bytes", "fnv", @@ -949,12 +1117,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "hex" @@ -1013,9 +1178,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.26" +version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ "bytes", "futures-channel", @@ -1121,9 +1286,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "js-sys" @@ -1154,7 +1319,7 @@ dependencies = [ "cfg-if", "ecdsa", "elliptic-curve", - "sha2 0.10.6", + "sha2 0.10.7", "sha3", ] @@ -1175,9 +1340,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.144" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "linked-hash-map" @@ -1193,9 +1358,9 @@ checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "matchit" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" +checksum = "ed1202b2a6f884ae56f04cff409ab315c5ce26b5e58d7412e484f01fd52f52ef" [[package]] name = "memchr" @@ -1215,6 +1380,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + [[package]] name = "mio" version = "0.8.8" @@ -1223,7 +1397,7 @@ checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1249,28 +1423,37 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi 0.3.2", "libc", ] +[[package]] +name = "object" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "opaque-debug" @@ -1296,9 +1479,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "pathdiff" @@ -1350,9 +1533,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" -version = "2.6.0" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e68e84bfb01f0507134eac1e9b410a12ba379d064eab48c50ba4ce329a527b70" +checksum = "1acb4a4365a13f749a93f1a094a7805e5cfa0955373a9de860d962eaa3a5fe5a" dependencies = [ "thiserror", "ucd-trie", @@ -1360,9 +1543,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.6.0" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b79d4c71c865a25a4322296122e3924d30bc8ee0834c8bfc8b95f7f054afbfb" +checksum = "666d00490d4ac815001da55838c500eafb0320019bbaa44444137c48b443a853" dependencies = [ "pest", "pest_generator", @@ -1370,53 +1553,53 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.6.0" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c435bf1076437b851ebc8edc3a18442796b30f1728ffea6262d59bbe28b077e" +checksum = "68ca01446f50dbda87c1786af8770d535423fa8a53aec03b8f4e3d7eb10e0929" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.28", ] [[package]] name = "pest_meta" -version = "2.6.0" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "745a452f8eb71e39ffd8ee32b3c5f51d03845f99786fa9b68db6ff509c505411" +checksum = "56af0a30af74d0445c0bf6d9d051c979b516a1a5af790d251daee76005420a48" dependencies = [ "once_cell", "pest", - "sha2 0.10.6", + "sha2 0.10.7", ] [[package]] name = "pin-project" -version = "1.1.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.28", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "2c516611246607d0c04186886dbb3a754368ef82c79e9827a802c6d836dd111c" [[package]] name = "pin-utils" @@ -1442,9 +1625,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.59" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] @@ -1506,9 +1689,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.28" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] @@ -1551,9 +1734,21 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.4" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" dependencies = [ "aho-corasick", "memchr", @@ -1562,9 +1757,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "rfc6979" @@ -1633,6 +1828,12 @@ dependencies = [ "ordered-multimap", ] +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "rustls" version = "0.19.1" @@ -1660,15 +1861,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "same-file" @@ -1681,11 +1882,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" dependencies = [ - "windows-sys 0.42.0", + "windows-sys", ] [[package]] @@ -1738,9 +1939,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ "bitflags", "core-foundation", @@ -1751,9 +1952,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -1761,15 +1962,15 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" [[package]] name = "serde" -version = "1.0.163" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" dependencies = [ "serde_derive", ] @@ -1785,22 +1986,22 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.9" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416bda436f9aab92e02c8e10d49a15ddd339cea90b6e340fe51ed97abb548294" +checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.163" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.28", ] [[package]] @@ -1816,9 +2017,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" dependencies = [ "itoa", "ryu", @@ -1827,13 +2028,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.12" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" +checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.28", ] [[package]] @@ -1848,14 +2049,26 @@ dependencies = [ "sg-std", ] +[[package]] +name = "sg-name" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba179e312060ca767f809353a3181a9f7a94932f2498d9b0f337229063a6b93" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "schemars", + "serde", +] + [[package]] name = "sg-std" version = "3.1.0" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-utils", - "cw721", + "cw-utils 1.0.1", + "cw721 0.18.0", "schemars", "serde", "thiserror", @@ -1887,9 +2100,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" dependencies = [ "cfg-if", "cpufeatures", @@ -1959,9 +2172,9 @@ dependencies = [ "cosmwasm-std", "cosmwasm-storage", "cw-multi-test", - "cw-storage-plus", - "cw-utils", - "cw2", + "cw-storage-plus 1.1.0", + "cw-utils 1.0.1", + "cw2 1.1.0", "schemars", "serde", "sg-multi-test", @@ -1969,6 +2182,61 @@ dependencies = [ "thiserror", ] +[[package]] +name = "stargaze-vip-collection" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cosmwasm-storage", + "cw-multi-test", + "cw-storage-plus 1.1.0", + "cw2 1.1.0", + "cw721 0.18.0", + "cw721-base 0.18.0", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "stargaze-vip-minter" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cosmwasm-storage", + "cw-multi-test", + "cw-storage-plus 1.1.0", + "cw2 1.1.0", + "cw721 0.18.0", + "cw721-base 0.18.0", + "schemars", + "serde", + "sg-name", + "stargaze-vip-collection", + "thiserror", +] + +[[package]] +name = "stargaze-vip-program" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cosmwasm-storage", + "cw-multi-test", + "cw-storage-plus 1.1.0", + "cw2 1.1.0", + "cw721 0.18.0", + "cw721-base 0.18.0", + "schemars", + "serde", + "sg-name", + "stargaze-vip-collection", + "thiserror", +] + [[package]] name = "subtle" version = "2.5.0" @@ -1997,9 +2265,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.17" +version = "2.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45b6ddbb36c5b969c182aec3c4a0bce7df3fbad4b77114706a49aacc80567388" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" dependencies = [ "proc-macro2", "quote", @@ -2141,30 +2409,31 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.28", ] [[package]] name = "time" -version = "0.3.22" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" +checksum = "b0fdd63d58b18d663fbdf70e049f00a22c8e42be082203be7f26589213cd75ea" dependencies = [ + "deranged", "serde", "time-core", "time-macros", @@ -2178,9 +2447,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "time-macros" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd" dependencies = [ "time-core", ] @@ -2202,11 +2471,12 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.28.2" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg", + "backtrace", "bytes", "libc", "mio", @@ -2214,7 +2484,7 @@ dependencies = [ "pin-project-lite", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -2235,7 +2505,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.28", ] [[package]] @@ -2361,13 +2631,13 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.28", ] [[package]] @@ -2403,9 +2673,9 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "ucd-trie" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] name = "unicode-bidi" @@ -2415,9 +2685,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-normalization" @@ -2503,7 +2773,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.28", "wasm-bindgen-shared", ] @@ -2525,7 +2795,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.28", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2596,21 +2866,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -2622,97 +2877,55 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.0" @@ -2745,5 +2958,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.28", ] diff --git a/Cargo.toml b/Cargo.toml index 4cffeac..44978c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,12 @@ [workspace] -members = ["packages/*", "contracts/fair-burn", "test/*"] +members = [ + "packages/*", + "contracts/fair-burn", + "contracts/vip/collection", + "contracts/vip/minter", + "contracts/vip/program", + "test/*", +] resolver = "2" [workspace.package] @@ -19,7 +26,7 @@ cw-storage-plus = "1.1.0" cw-controllers = "1.1.0" cw2 = "1.1.0" cw721 = "0.18.0" -cw721-base = "0.18.0" +cw721-base = { version = "0.18.0", feature = ["library"] } cw-utils = "1.0.1" schemars = "0.8.11" semver = "1.0.16" diff --git a/contracts/vip/README.md b/contracts/vip/README.md new file mode 100644 index 0000000..4eb9243 --- /dev/null +++ b/contracts/vip/README.md @@ -0,0 +1,37 @@ +# Stargaze VIP Program (SVP) + +The Stargaze VIP Program is a program that rewards users for staking STARS in the form of reduced fees. The program is implemented as a set of NFT smart contracts. Users are assigned to a tier based on the amount of STARS they have staked. The tier determines the amount of fees they pay. + +A user mints a Stargaze VIP NFT (vNFT) to join the Stargaze VIP Program. It contains metadata that includes the amount of STARS they have staked that is periodically updated via end blocker. vNFTs are non-transferrable. + +A Stargaze Name is required to mint a vNFT. + +## VIP Collection (sg721-vip) + +The VIP Collection is a contract that stores all the vNFTs, and periodically updates the metadata of each vNFT. + +vNFTs are indexed by Stargaze Names, using the name for the `token_id`. If a name is transferred or burned, the associated vNFT is burned. This happens via a hook in the Stargaze Name collection contract. + +The stake weight metadata can only be updated at specific intervals. The `updated_at` field is used to determine when the metadata can be updated. The `updated_at` field is set to the current block time when the vNFT is minted. The metadata can be updated when the current block time is greater than the `updated_at` field plus the `update_period` field in the config. + + +### Queries + +```rs +pub enum QueryMsg { + Config {}, + Metadata { address: String }, + TotalStakedAmount { name: String }, +} +``` + +Note that a user may have multiple wallets that stake. For example they may have a cold wallet that does the majority of staking, and a hot wallet for use for minting on Stargaze. To determine the tier of a user, we need to sum up the amount of STARS staked across all wallets. To associate wallets, a user can link their accounts in their Stargaze Name. The `TotalStakedAmount` query returns the total amount of STARS staked by a user across all wallets. + +#### TODO + +- [ ] Come up with a consistent way to link multiple accounts to one name (Version 2) + +## vNFT Minter (vip-minter) + +The vNFT Minter is a contract that allows users to mint vNFTs. + diff --git a/contracts/vip/collection/.cargo/config b/contracts/vip/collection/.cargo/config new file mode 100644 index 0000000..af5698e --- /dev/null +++ b/contracts/vip/collection/.cargo/config @@ -0,0 +1,4 @@ +[alias] +wasm = "build --release --lib --target wasm32-unknown-unknown" +unit-test = "test --lib" +schema = "run --bin schema" diff --git a/contracts/vip/collection/Cargo.toml b/contracts/vip/collection/Cargo.toml new file mode 100644 index 0000000..43cd74d --- /dev/null +++ b/contracts/vip/collection/Cargo.toml @@ -0,0 +1,47 @@ +[package] +name = "stargaze-vip-collection" +authors = ["Shane Vitarana "] +description = "Stargaze VIP Collection" +version = { workspace = true } +edition = { workspace = true } +homepage = { workspace = true } +repository = { workspace = true } +license = { workspace = true } + +exclude = [ + # Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication. + "contract.wasm", + "hash.txt", +] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[[bin]] +name = "schema" +path = "src/bin/schema.rs" +doc = false + +[features] +# for more explicit tests, cargo test --features=backtraces +backtraces = ["cosmwasm-std/backtraces"] +# use library feature to disable all instantiate/execute/query exports +library = [] + + +[dependencies] +cosmwasm-schema = { workspace = true } +cosmwasm-std = { workspace = true, features = ["cosmwasm_1_2"] } +cosmwasm-storage = { workspace = true } +cw-storage-plus = { workspace = true } +cw2 = { workspace = true } +cw721 = { workspace = true } +cw721-base = { workspace = true } +schemars = { workspace = true } +serde = { workspace = true } +thiserror = { workspace = true } + +[dev-dependencies] +cw-multi-test = { workspace = true } diff --git a/contracts/vip/collection/README.md b/contracts/vip/collection/README.md new file mode 100644 index 0000000..d39ba23 --- /dev/null +++ b/contracts/vip/collection/README.md @@ -0,0 +1,3 @@ +# Stargaze VIP Collection + +This contract wraps the `cw721_base::Cw721Contract` struct to represent a collection that stores vNFTs (Stargaze VIP NFTs) with onchain metadata. The stake weight is stored as onchain metadata. diff --git a/contracts/vip/collection/schema/stargaze-vip-collection.json b/contracts/vip/collection/schema/stargaze-vip-collection.json new file mode 100644 index 0000000..d7dd839 --- /dev/null +++ b/contracts/vip/collection/schema/stargaze-vip-collection.json @@ -0,0 +1,556 @@ +{ + "contract_name": "stargaze-vip-collection", + "contract_version": "0.1.0", + "idl_version": "1.0.0", + "instantiate": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "type": "object", + "required": [ + "minter", + "name", + "symbol" + ], + "properties": { + "minter": { + "description": "The minter is the only one who can create new NFTs. This is designed for a base NFT that is controlled by an external program or contract. You will likely replace this with custom logic in custom NFTs", + "type": "string" + }, + "name": { + "description": "Name of the NFT contract", + "type": "string" + }, + "symbol": { + "description": "Symbol of the NFT contract", + "type": "string" + } + }, + "additionalProperties": false + }, + "execute": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "description": "This is like Cw721ExecuteMsg but we add a Mint command for an owner to make this stand-alone. You will likely want to remove mint and use other control logic in any contract that inherits this.", + "oneOf": [ + { + "description": "Transfer is a base message to move a token to another account without triggering actions", + "type": "object", + "required": [ + "transfer_nft" + ], + "properties": { + "transfer_nft": { + "type": "object", + "required": [ + "recipient", + "token_id" + ], + "properties": { + "recipient": { + "type": "string" + }, + "token_id": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Send is a base message to transfer a token to a contract and trigger an action on the receiving contract.", + "type": "object", + "required": [ + "send_nft" + ], + "properties": { + "send_nft": { + "type": "object", + "required": [ + "contract", + "msg", + "token_id" + ], + "properties": { + "contract": { + "type": "string" + }, + "msg": { + "$ref": "#/definitions/Binary" + }, + "token_id": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Allows operator to transfer / send the token from the owner's account. If expiration is set, then this allowance has a time/height limit", + "type": "object", + "required": [ + "approve" + ], + "properties": { + "approve": { + "type": "object", + "required": [ + "spender", + "token_id" + ], + "properties": { + "expires": { + "anyOf": [ + { + "$ref": "#/definitions/Expiration" + }, + { + "type": "null" + } + ] + }, + "spender": { + "type": "string" + }, + "token_id": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Remove previously granted Approval", + "type": "object", + "required": [ + "revoke" + ], + "properties": { + "revoke": { + "type": "object", + "required": [ + "spender", + "token_id" + ], + "properties": { + "spender": { + "type": "string" + }, + "token_id": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Allows operator to transfer / send any token from the owner's account. If expiration is set, then this allowance has a time/height limit", + "type": "object", + "required": [ + "approve_all" + ], + "properties": { + "approve_all": { + "type": "object", + "required": [ + "operator" + ], + "properties": { + "expires": { + "anyOf": [ + { + "$ref": "#/definitions/Expiration" + }, + { + "type": "null" + } + ] + }, + "operator": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Remove previously granted ApproveAll permission", + "type": "object", + "required": [ + "revoke_all" + ], + "properties": { + "revoke_all": { + "type": "object", + "required": [ + "operator" + ], + "properties": { + "operator": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Mint a new NFT, can only be called by the contract minter", + "type": "object", + "required": [ + "mint" + ], + "properties": { + "mint": { + "type": "object", + "required": [ + "extension", + "owner", + "token_id" + ], + "properties": { + "extension": { + "description": "Any custom extension used by this contract", + "allOf": [ + { + "$ref": "#/definitions/Metadata" + } + ] + }, + "owner": { + "description": "The owner of the newly minter NFT", + "type": "string" + }, + "token_id": { + "description": "Unique ID of the NFT", + "type": "string" + }, + "token_uri": { + "description": "Universal resource identifier for this NFT Should point to a JSON file that conforms to the ERC721 Metadata JSON Schema", + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Burn an NFT the sender has access to", + "type": "object", + "required": [ + "burn" + ], + "properties": { + "burn": { + "type": "object", + "required": [ + "token_id" + ], + "properties": { + "token_id": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Extension msg", + "type": "object", + "required": [ + "extension" + ], + "properties": { + "extension": { + "type": "object", + "required": [ + "msg" + ], + "properties": { + "msg": { + "$ref": "#/definitions/Empty" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Update the contract's ownership. The `action` to be provided can be either to propose transferring ownership to an account, accept a pending ownership transfer, or renounce the ownership permanently.", + "type": "object", + "required": [ + "update_ownership" + ], + "properties": { + "update_ownership": { + "$ref": "#/definitions/Action" + } + }, + "additionalProperties": false + } + ], + "definitions": { + "Action": { + "description": "Actions that can be taken to alter the contract's ownership", + "oneOf": [ + { + "description": "Propose to transfer the contract's ownership to another account, optionally with an expiry time.\n\nCan only be called by the contract's current owner.\n\nAny existing pending ownership transfer is overwritten.", + "type": "object", + "required": [ + "transfer_ownership" + ], + "properties": { + "transfer_ownership": { + "type": "object", + "required": [ + "new_owner" + ], + "properties": { + "expiry": { + "anyOf": [ + { + "$ref": "#/definitions/Expiration" + }, + { + "type": "null" + } + ] + }, + "new_owner": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Accept the pending ownership transfer.\n\nCan only be called by the pending owner.", + "type": "string", + "enum": [ + "accept_ownership" + ] + }, + { + "description": "Give up the contract's ownership and the possibility of appointing a new owner.\n\nCan only be invoked by the contract's current owner.\n\nAny existing pending ownership transfer is canceled.", + "type": "string", + "enum": [ + "renounce_ownership" + ] + } + ] + }, + "Binary": { + "description": "Binary is a wrapper around Vec to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec. See also .", + "type": "string" + }, + "Empty": { + "description": "An empty struct that serves as a placeholder in different places, such as contracts that don't set a custom message.\n\nIt is designed to be expressable in correct JSON and JSON Schema but contains no meaningful data. Previously we used enums without cases, but those cannot represented as valid JSON Schema (https://github.com/CosmWasm/cosmwasm/issues/451)", + "type": "object" + }, + "Expiration": { + "description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)", + "oneOf": [ + { + "description": "AtHeight will expire when `env.block.height` >= height", + "type": "object", + "required": [ + "at_height" + ], + "properties": { + "at_height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + { + "description": "AtTime will expire when `env.block.time` >= time", + "type": "object", + "required": [ + "at_time" + ], + "properties": { + "at_time": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + { + "description": "Never will never expire. Used to express the empty variant", + "type": "object", + "required": [ + "never" + ], + "properties": { + "never": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Metadata": { + "type": "object", + "required": [ + "staked_amount", + "updated_at" + ], + "properties": { + "data": { + "type": [ + "string", + "null" + ] + }, + "staked_amount": { + "$ref": "#/definitions/Uint128" + }, + "updated_at": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint128": { + "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", + "type": "string" + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } + }, + "query": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "metadata" + ], + "properties": { + "metadata": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "total_staked" + ], + "properties": { + "total_staked": { + "type": "object", + "required": [ + "owner" + ], + "properties": { + "owner": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "migrate": null, + "sudo": null, + "responses": { + "metadata": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Metadata", + "type": "object", + "required": [ + "staked_amount", + "updated_at" + ], + "properties": { + "data": { + "type": [ + "string", + "null" + ] + }, + "staked_amount": { + "$ref": "#/definitions/Uint128" + }, + "updated_at": { + "$ref": "#/definitions/Timestamp" + } + }, + "additionalProperties": false, + "definitions": { + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint128": { + "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", + "type": "string" + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } + }, + "total_staked": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Uint128", + "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", + "type": "string" + } + } +} diff --git a/contracts/vip/collection/src/bin/schema.rs b/contracts/vip/collection/src/bin/schema.rs new file mode 100644 index 0000000..cbd2a58 --- /dev/null +++ b/contracts/vip/collection/src/bin/schema.rs @@ -0,0 +1,12 @@ +use cosmwasm_schema::write_api; + +use cw721_base::InstantiateMsg; +use stargaze_vip_collection::{msg::QueryMsg, ExecuteMsg}; + +fn main() { + write_api! { + instantiate: InstantiateMsg, + execute: ExecuteMsg, + query: QueryMsg, + } +} diff --git a/contracts/vip/collection/src/contract.rs b/contracts/vip/collection/src/contract.rs new file mode 100644 index 0000000..7972f2b --- /dev/null +++ b/contracts/vip/collection/src/contract.rs @@ -0,0 +1,104 @@ +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; +use cosmwasm_std::{to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; +use cw2::set_contract_version; +use cw721_base::InstantiateMsg; + +use crate::error::ContractError; +use crate::msg::QueryMsg; +use crate::{ExecuteMsg, VipCollection}; + +const CONTRACT_NAME: &str = "crates.io:stargaze-vip-collection"; +const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + mut deps: DepsMut, + env: Env, + info: MessageInfo, + msg: InstantiateMsg, +) -> StdResult { + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + + // This configures the collection with the minter as the owner, the only one that can mint + VipCollection::default().instantiate(deps.branch(), env, info, msg) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: ExecuteMsg, +) -> Result { + match msg { + cw721_base::ExecuteMsg::TransferNft { + recipient, + token_id, + } => Err(ContractError::Unauthorized {}), + cw721_base::ExecuteMsg::SendNft { + contract, + token_id, + msg, + } => Err(ContractError::Unauthorized {}), + cw721_base::ExecuteMsg::Approve { + spender, + token_id, + expires, + } => Err(ContractError::Unauthorized {}), + cw721_base::ExecuteMsg::Revoke { spender, token_id } => Err(ContractError::Unauthorized {}), + cw721_base::ExecuteMsg::ApproveAll { operator, expires } => { + Err(ContractError::Unauthorized {}) + } + cw721_base::ExecuteMsg::RevokeAll { operator } => Err(ContractError::Unauthorized {}), + // cw721_base::ExecuteMsg::Mint { + // token_id, + // owner, + // token_uri, + // extension, + // } => todo!(), + // cw721_base::ExecuteMsg::Burn { token_id } => todo!(), + // cw721_base::ExecuteMsg::Extension { msg } => todo!(), + // cw721_base::ExecuteMsg::UpdateOwnership(_) => todo!(), + _ => VipCollection::default() + .execute(deps, env, info, msg) + .map_err(Into::into), + } +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { + match msg { + QueryMsg::Metadata { address } => to_binary(&query_metadata(deps, address)?), + QueryMsg::TotalStaked { owner } => to_binary(&query_total_staked(deps, owner)?), + } +} + +pub fn query_metadata(deps: Deps, address: String) -> StdResult { + // TODO: get metadata by address (token_id) + + todo!() +} + +/// Total staked is the sum of all staked amounts for a given owner. If +/// an owner has multiple items, it will iterate through all of them and +/// sum the staked amounts. +pub fn query_total_staked(deps: Deps, owner: String) -> StdResult { + // TODO: get all tokens by owner of `address` (token_id) + // TODO: iterate through metdata to get total stake weight + + todo!() +} + +// pub fn query_stake_weight(deps: Deps, env: Env, name: String) -> StdResult { +// let res: NftInfoResponse = VipCollection::default().query( +// deps, +// env, +// cw721_base::msg::QueryMsg::NftInfo { token_id: name }, +// ); + +// res.extension.staked_amount +// } + +#[cfg(test)] +mod tests {} diff --git a/contracts/vip/collection/src/error.rs b/contracts/vip/collection/src/error.rs new file mode 100644 index 0000000..12744d7 --- /dev/null +++ b/contracts/vip/collection/src/error.rs @@ -0,0 +1,14 @@ +use cosmwasm_std::StdError; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum ContractError { + #[error("{0}")] + Std(#[from] StdError), + + #[error("{0}")] + Cw721Base(#[from] cw721_base::ContractError), + + #[error("Unauthorized")] + Unauthorized {}, +} diff --git a/contracts/vip/collection/src/lib.rs b/contracts/vip/collection/src/lib.rs new file mode 100644 index 0000000..4033b34 --- /dev/null +++ b/contracts/vip/collection/src/lib.rs @@ -0,0 +1,12 @@ +pub mod contract; +mod error; +pub mod msg; +pub mod state; +use cosmwasm_std::Empty; +use state::Metadata; + +pub use crate::error::ContractError; + +pub type VipCollection<'a> = cw721_base::Cw721Contract<'a, Metadata, Empty, Empty, Empty>; + +pub type ExecuteMsg = cw721_base::ExecuteMsg; diff --git a/contracts/vip/collection/src/msg.rs b/contracts/vip/collection/src/msg.rs new file mode 100644 index 0000000..24fdc1d --- /dev/null +++ b/contracts/vip/collection/src/msg.rs @@ -0,0 +1,13 @@ +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::Uint128; + +use crate::state::Metadata; + +#[cw_serde] +#[derive(QueryResponses)] +pub enum QueryMsg { + #[returns(Metadata)] + Metadata { address: String }, + #[returns(Uint128)] + TotalStaked { owner: String }, +} diff --git a/contracts/vip/collection/src/state.rs b/contracts/vip/collection/src/state.rs new file mode 100644 index 0000000..3e8f0ec --- /dev/null +++ b/contracts/vip/collection/src/state.rs @@ -0,0 +1,9 @@ +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{Timestamp, Uint128}; + +#[cw_serde] +pub struct Metadata { + pub staked_amount: Uint128, + pub data: Option, + pub updated_at: Timestamp, +} diff --git a/contracts/vip/minter/.cargo/config b/contracts/vip/minter/.cargo/config new file mode 100644 index 0000000..af5698e --- /dev/null +++ b/contracts/vip/minter/.cargo/config @@ -0,0 +1,4 @@ +[alias] +wasm = "build --release --lib --target wasm32-unknown-unknown" +unit-test = "test --lib" +schema = "run --bin schema" diff --git a/contracts/vip/minter/Cargo.toml b/contracts/vip/minter/Cargo.toml new file mode 100644 index 0000000..fa4f844 --- /dev/null +++ b/contracts/vip/minter/Cargo.toml @@ -0,0 +1,49 @@ +[package] +name = "stargaze-vip-minter" +authors = ["Shane Vitarana "] +description = "Stargaze vNFT Minter" +version = { workspace = true } +edition = { workspace = true } +homepage = { workspace = true } +repository = { workspace = true } +license = { workspace = true } + +exclude = [ + # Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication. + "contract.wasm", + "hash.txt", +] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[[bin]] +name = "schema" +path = "src/bin/schema.rs" +doc = false + +[features] +# for more explicit tests, cargo test --features=backtraces +backtraces = ["cosmwasm-std/backtraces"] +# use library feature to disable all instantiate/execute/query exports +library = [] + + +[dependencies] +cosmwasm-schema = { workspace = true } +cosmwasm-std = { workspace = true, features = ["staking"] } +cosmwasm-storage = { workspace = true } +cw-storage-plus = { workspace = true } +cw2 = { workspace = true } +cw721 = { workspace = true } +cw721-base = { workspace = true } +schemars = { workspace = true } +serde = { workspace = true } +thiserror = { workspace = true } +sg-name = "1.2.5" +stargaze-vip-collection = { path = "../collection", features = ["library"] } + +[dev-dependencies] +cw-multi-test = { workspace = true } diff --git a/contracts/vip/minter/README.md b/contracts/vip/minter/README.md new file mode 100644 index 0000000..c4f983e --- /dev/null +++ b/contracts/vip/minter/README.md @@ -0,0 +1,5 @@ +# Stargaze VIP Minter + +This contract is responsible for writing to the Stargaze VIP Collection contract. + +Upon instantiation, a collection contract is also instantiated via `instantiate2`. The collection address is derived from the minter contract address, the collection contract code hash, and a salt. It is outputted as an attribute when the contract is instantiated and saved in `Config`. diff --git a/contracts/vip/minter/schema/stargaze-vip-minter.json b/contracts/vip/minter/schema/stargaze-vip-minter.json new file mode 100644 index 0000000..06b1b78 --- /dev/null +++ b/contracts/vip/minter/schema/stargaze-vip-minter.json @@ -0,0 +1,96 @@ +{ + "contract_name": "stargaze-vip-minter", + "contract_version": "0.1.0", + "idl_version": "1.0.0", + "instantiate": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "type": "object", + "required": [ + "name_collection", + "vip_collection" + ], + "properties": { + "name_collection": { + "type": "string" + }, + "vip_collection": { + "type": "string" + } + }, + "additionalProperties": false + }, + "execute": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "oneOf": [ + { + "description": "Mint a loyalty token for the given name", + "type": "object", + "required": [ + "mint" + ], + "properties": { + "mint": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Update the stake amount for the given name", + "type": "object", + "required": [ + "update" + ], + "properties": { + "update": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "So we can pause before migrating names, etc.", + "type": "object", + "required": [ + "pause" + ], + "properties": { + "pause": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "query": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "type": "string", + "enum": [] + }, + "migrate": null, + "sudo": null, + "responses": {} +} diff --git a/contracts/vip/minter/src/bin/schema.rs b/contracts/vip/minter/src/bin/schema.rs new file mode 100644 index 0000000..f160419 --- /dev/null +++ b/contracts/vip/minter/src/bin/schema.rs @@ -0,0 +1,11 @@ +use cosmwasm_schema::write_api; + +use stargaze_vip_minter::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; + +fn main() { + write_api! { + instantiate: InstantiateMsg, + execute: ExecuteMsg, + query: QueryMsg, + } +} diff --git a/contracts/vip/minter/src/contract.rs b/contracts/vip/minter/src/contract.rs new file mode 100644 index 0000000..ebd65c9 --- /dev/null +++ b/contracts/vip/minter/src/contract.rs @@ -0,0 +1,195 @@ +use std::env; + +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; +use cosmwasm_std::{ + ensure, instantiate2_address, to_binary, Addr, Binary, CodeInfoResponse, ContractInfoResponse, + Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, Timestamp, Uint128, WasmMsg, +}; +use cw2::set_contract_version; + +use crate::error::ContractError; +use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; +use crate::state::{Config, CONFIG, NAME_QUEUE}; + +const CONTRACT_NAME: &str = "crates.io:stargaze-vip-minter"; +const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + deps: DepsMut, + env: Env, + _info: MessageInfo, + msg: InstantiateMsg, +) -> Result { + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + + let minter = env.contract.address; + + let canonical_creator = deps.api.addr_canonicalize(minter.as_str())?; + let CodeInfoResponse { checksum, .. } = + deps.querier.query_wasm_code_info(msg.collection_code_id)?; + let salt = b"vip_collection1"; + + // create collection address with instantiate2 + let canonical_addr = instantiate2_address(&checksum, &canonical_creator, salt) + .map_err(|_| StdError::generic_err("Could not calculate addr"))?; + let collection = deps.api.addr_humanize(&canonical_addr)?; + + let ContractInfoResponse { admin, .. } = + deps.querier.query_wasm_contract_info(minter.clone())?; + + CONFIG.save( + deps.storage, + &Config { + vip_collection: deps.api.addr_validate(collection.as_str())?, + name_collection: deps.api.addr_validate(&msg.name_collection)?, + update_interval: msg.update_interval, + }, + )?; + + let collection_init_msg = WasmMsg::Instantiate2 { + admin, + code_id: msg.collection_code_id, + label: String::from("vip-collection"), + msg: to_binary(&cw721_base::InstantiateMsg { + name: "Stargaze VIP Collection".to_string(), + symbol: "SGVIP".to_string(), + minter: minter.to_string(), + })?, + funds: vec![], + salt: Binary::from(salt.to_vec()), + }; + + Ok(Response::new() + .add_message(collection_init_msg) + .add_attribute("collection", collection)) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: ExecuteMsg, +) -> Result { + match msg { + ExecuteMsg::Mint { name } => execute_mint(deps, env, info, name), + ExecuteMsg::Update { name } => execute_update(deps, env, info, name), + ExecuteMsg::Pause {} => todo!(), + } +} + +pub fn execute_mint( + deps: DepsMut, + env: Env, + info: MessageInfo, + name: String, +) -> Result { + ensure!( + info.sender == associated_address(deps.as_ref(), name.clone())?, + ContractError::Unauthorized {} + ); + + let Config { + vip_collection, + update_interval, + .. + } = CONFIG.load(deps.storage)?; + + let mint_msg = mint( + deps.as_ref(), + info.sender, + env.block.time, + name.clone(), + vip_collection, + )?; + + NAME_QUEUE.update( + deps.storage, + env.block.height + update_interval, + |names| -> StdResult<_> { + let mut names = names.unwrap_or_default(); + names.push(name); + Ok(names) + }, + )?; + + Ok(Response::new().add_message(mint_msg)) +} + +pub fn execute_update( + deps: DepsMut, + env: Env, + info: MessageInfo, + name: String, +) -> Result { + ensure!( + info.sender == associated_address(deps.as_ref(), name.clone())?, + ContractError::Unauthorized {} + ); + + let Config { vip_collection, .. } = CONFIG.load(deps.storage)?; + + let mint_msg = mint( + deps.as_ref(), + info.sender, + env.block.time, + name, + vip_collection, + )?; + + Ok(Response::new().add_message(mint_msg)) +} + +pub fn mint( + deps: Deps, + sender: Addr, + block_time: Timestamp, + name: String, + vip_collection: Addr, +) -> Result { + let msg = stargaze_vip_collection::ExecuteMsg::Mint { + token_id: name, + owner: sender.to_string(), + token_uri: None, + extension: stargaze_vip_collection::state::Metadata { + staked_amount: total_staked(deps, sender)?, + data: None, + updated_at: block_time, + }, + }; + + Ok(WasmMsg::Execute { + contract_addr: vip_collection.to_string(), + msg: to_binary(&msg)?, + funds: vec![], + }) +} + +pub fn associated_address(deps: Deps, name: String) -> Result { + let associated_addr: Addr = deps.querier.query_wasm_smart( + CONFIG.load(deps.storage)?.name_collection, + &sg_name::SgNameQueryMsg::AssociatedAddress { name }, + )?; + + Ok(associated_addr) +} + +fn total_staked(deps: Deps, address: Addr) -> StdResult { + let total = deps + .querier + .query_all_delegations(address)? + .iter() + .fold(0, |acc, d| acc + d.amount.amount.u128()); + + Ok(Uint128::from(total)) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(_deps: Deps, _env: Env, _msg: QueryMsg) -> StdResult { + unimplemented!() +} + +#[cfg(test)] +mod tests {} diff --git a/contracts/vip/minter/src/error.rs b/contracts/vip/minter/src/error.rs new file mode 100644 index 0000000..4a69d8f --- /dev/null +++ b/contracts/vip/minter/src/error.rs @@ -0,0 +1,13 @@ +use cosmwasm_std::StdError; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum ContractError { + #[error("{0}")] + Std(#[from] StdError), + + #[error("Unauthorized")] + Unauthorized {}, + // Add any other custom errors you like here. + // Look at https://docs.rs/thiserror/1.0.21/thiserror/ for details. +} diff --git a/contracts/vip/minter/src/lib.rs b/contracts/vip/minter/src/lib.rs new file mode 100644 index 0000000..e455cce --- /dev/null +++ b/contracts/vip/minter/src/lib.rs @@ -0,0 +1,7 @@ +pub mod contract; +mod error; +pub mod msg; +pub mod state; +pub mod sudo; + +pub use crate::error::ContractError; diff --git a/contracts/vip/minter/src/msg.rs b/contracts/vip/minter/src/msg.rs new file mode 100644 index 0000000..89899d1 --- /dev/null +++ b/contracts/vip/minter/src/msg.rs @@ -0,0 +1,34 @@ +use cosmwasm_schema::{cw_serde, QueryResponses}; + +#[cw_serde] +pub struct InstantiateMsg { + pub collection_code_id: u64, + pub name_collection: String, + pub update_interval: u64, // in blocks +} + +#[cw_serde] +pub enum ExecuteMsg { + /// Mint a loyalty token for the given name + Mint { name: String }, + /// Update the stake amount for the given name + Update { name: String }, + /// So we can pause before migrating names, etc. + Pause {}, +} + +// #[allow(clippy::large_enum_variant)] +#[cw_serde] +pub enum SudoMsg { + BeginBlock {}, // Is called by x/cron module BeginBlocker + EndBlock {}, // Is called by x/cron module EndBlocker + // UpdateParams { + // // fair_burn: Option, + // // trading_fee_percent: Option, + // // min_bid_increment_percent: Option, + // }, +} + +#[cw_serde] +#[derive(QueryResponses)] +pub enum QueryMsg {} diff --git a/contracts/vip/minter/src/state.rs b/contracts/vip/minter/src/state.rs new file mode 100644 index 0000000..01ea6e7 --- /dev/null +++ b/contracts/vip/minter/src/state.rs @@ -0,0 +1,17 @@ +use cosmwasm_schema::cw_serde; +use cosmwasm_std::Addr; +use cw_storage_plus::{Item, Map}; + +#[cw_serde] +pub struct Config { + pub vip_collection: Addr, + pub name_collection: Addr, + pub update_interval: u64, // in blocks +} + +pub const CONFIG: Item = Item::new("config"); + +/// (block_height, [name1, name2, ...]) +pub const NAME_QUEUE: Map> = Map::new("nq"); + +// TODO: need secondary queue for name <> height mapping diff --git a/contracts/vip/minter/src/sudo.rs b/contracts/vip/minter/src/sudo.rs new file mode 100644 index 0000000..cc29fb7 --- /dev/null +++ b/contracts/vip/minter/src/sudo.rs @@ -0,0 +1,63 @@ +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; +use cosmwasm_std::{DepsMut, Env, Response}; + +use crate::{ + contract::{associated_address, mint}, + msg::SudoMsg, + state::{Config, CONFIG, NAME_QUEUE}, + ContractError, +}; + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn sudo(deps: DepsMut, env: Env, msg: SudoMsg) -> Result { + match msg { + SudoMsg::BeginBlock {} => sudo_begin_block(deps, env), + SudoMsg::EndBlock {} => sudo_end_block(deps, env), + // SudoMsg::UpdateParams { + // fair_burn, + // trading_fee_percent, + // min_bid_increment_percent, + // } => sudo_update_params( + // deps, + // env, + // fair_burn, + // trading_fee_percent, + // min_bid_increment_percent, + // ), + } +} + +pub fn sudo_begin_block(deps: DepsMut, env: Env) -> Result { + Ok(Response::new()) +} + +pub fn sudo_end_block(deps: DepsMut, env: Env) -> Result { + let Config { + vip_collection, + update_interval, + .. + } = CONFIG.load(deps.storage)?; + let names = NAME_QUEUE.load(deps.storage, env.block.height)?; + + let mint_msgs = names + .iter() + .map(|name| { + let name = name.clone(); + let owner = associated_address(deps.as_ref(), name.clone())?; + let mint_msg = mint( + deps.as_ref(), + owner, + env.block.time, + name, + vip_collection.clone(), + )?; + Ok(mint_msg) + }) + .collect::, ContractError>>()?; + + NAME_QUEUE.remove(deps.storage, env.block.height); + NAME_QUEUE.save(deps.storage, env.block.height + update_interval, &names)?; + + Ok(Response::new().add_messages(mint_msgs)) +} diff --git a/contracts/vip/program/.cargo/config b/contracts/vip/program/.cargo/config new file mode 100644 index 0000000..af5698e --- /dev/null +++ b/contracts/vip/program/.cargo/config @@ -0,0 +1,4 @@ +[alias] +wasm = "build --release --lib --target wasm32-unknown-unknown" +unit-test = "test --lib" +schema = "run --bin schema" diff --git a/contracts/vip/program/Cargo.toml b/contracts/vip/program/Cargo.toml new file mode 100644 index 0000000..4ff8ffe --- /dev/null +++ b/contracts/vip/program/Cargo.toml @@ -0,0 +1,49 @@ +[package] +name = "stargaze-vip-program" +authors = ["Shane Vitarana "] +description = "Stargaze vNFT Minter" +version = { workspace = true } +edition = { workspace = true } +homepage = { workspace = true } +repository = { workspace = true } +license = { workspace = true } + +exclude = [ + # Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication. + "contract.wasm", + "hash.txt", +] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[[bin]] +name = "schema" +path = "src/bin/schema.rs" +doc = false + +[features] +# for more explicit tests, cargo test --features=backtraces +backtraces = ["cosmwasm-std/backtraces"] +# use library feature to disable all instantiate/execute/query exports +library = [] + + +[dependencies] +cosmwasm-schema = { workspace = true } +cosmwasm-std = { workspace = true, features = ["staking"] } +cosmwasm-storage = { workspace = true } +cw-storage-plus = { workspace = true } +cw2 = { workspace = true } +cw721 = { workspace = true } +cw721-base = { workspace = true } +schemars = { workspace = true } +serde = { workspace = true } +thiserror = { workspace = true } +sg-name = "1.2.5" +stargaze-vip-collection = { path = "../collection", features = ["library"] } + +[dev-dependencies] +cw-multi-test = { workspace = true } diff --git a/contracts/vip/program/README.md b/contracts/vip/program/README.md new file mode 100644 index 0000000..2430f1d --- /dev/null +++ b/contracts/vip/program/README.md @@ -0,0 +1,4 @@ +# Stargaze VIP Program + +This contract implements the logic of the Stargaze VIP Program. It queries the VIP collection and determines which tier the account is in. It also manages tier limits. + diff --git a/contracts/vip/program/schema/stargaze-vip-program.json b/contracts/vip/program/schema/stargaze-vip-program.json new file mode 100644 index 0000000..dfba3ae --- /dev/null +++ b/contracts/vip/program/schema/stargaze-vip-program.json @@ -0,0 +1,76 @@ +{ + "contract_name": "stargaze-vip-program", + "contract_version": "0.1.0", + "idl_version": "1.0.0", + "instantiate": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "type": "object", + "required": [ + "collection", + "tiers" + ], + "properties": { + "collection": { + "type": "string" + }, + "tiers": { + "type": "array", + "items": { + "$ref": "#/definitions/Uint128" + } + } + }, + "additionalProperties": false, + "definitions": { + "Uint128": { + "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```", + "type": "string" + } + } + }, + "execute": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "type": "string", + "enum": [] + }, + "query": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "tier" + ], + "properties": { + "tier": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "migrate": null, + "sudo": null, + "responses": { + "tier": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "uint64", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } +} diff --git a/contracts/vip/program/src/bin/schema.rs b/contracts/vip/program/src/bin/schema.rs new file mode 100644 index 0000000..b1561be --- /dev/null +++ b/contracts/vip/program/src/bin/schema.rs @@ -0,0 +1,11 @@ +use cosmwasm_schema::write_api; + +use stargaze_vip_program::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; + +fn main() { + write_api! { + instantiate: InstantiateMsg, + execute: ExecuteMsg, + query: QueryMsg, + } +} diff --git a/contracts/vip/program/src/contract.rs b/contracts/vip/program/src/contract.rs new file mode 100644 index 0000000..bed29f9 --- /dev/null +++ b/contracts/vip/program/src/contract.rs @@ -0,0 +1,65 @@ +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; +use cosmwasm_std::{to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; +use cw2::set_contract_version; +use stargaze_vip_collection::state::Metadata; + +use crate::error::ContractError; +use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; +use crate::state::{COLLECTION, TIERS}; + +// version info for migration info +const CONTRACT_NAME: &str = "crates.io:stargaze-vip-program"; +const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + deps: DepsMut, + _env: Env, + _info: MessageInfo, + msg: InstantiateMsg, +) -> Result { + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + + // TODO: add cw_ownable so an admin can update tier limits + + COLLECTION.save(deps.storage, &deps.api.addr_validate(&msg.collection)?)?; + + TIERS.save(deps.storage, &msg.tiers)?; + + Ok(Response::new()) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + _deps: DepsMut, + _env: Env, + _info: MessageInfo, + _msg: ExecuteMsg, +) -> Result { + unimplemented!() +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { + match msg { + QueryMsg::Tier { name } => { + let token_info: cw721::NftInfoResponse = deps.querier.query_wasm_smart( + COLLECTION.load(deps.storage)?, + &cw721::Cw721QueryMsg::NftInfo { token_id: name }, + )?; + let staked_amount = token_info.extension.staked_amount; + + let tiers = TIERS.load(deps.storage)?; + let index = tiers + .iter() + .position(|&x| x >= staked_amount) + .unwrap_or(tiers.len()); + + Ok(to_binary(&index)?) + } + } +} + +#[cfg(test)] +mod tests {} diff --git a/contracts/vip/program/src/error.rs b/contracts/vip/program/src/error.rs new file mode 100644 index 0000000..4a69d8f --- /dev/null +++ b/contracts/vip/program/src/error.rs @@ -0,0 +1,13 @@ +use cosmwasm_std::StdError; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum ContractError { + #[error("{0}")] + Std(#[from] StdError), + + #[error("Unauthorized")] + Unauthorized {}, + // Add any other custom errors you like here. + // Look at https://docs.rs/thiserror/1.0.21/thiserror/ for details. +} diff --git a/contracts/vip/program/src/lib.rs b/contracts/vip/program/src/lib.rs new file mode 100644 index 0000000..dfedc9d --- /dev/null +++ b/contracts/vip/program/src/lib.rs @@ -0,0 +1,6 @@ +pub mod contract; +mod error; +pub mod msg; +pub mod state; + +pub use crate::error::ContractError; diff --git a/contracts/vip/program/src/msg.rs b/contracts/vip/program/src/msg.rs new file mode 100644 index 0000000..644bc6f --- /dev/null +++ b/contracts/vip/program/src/msg.rs @@ -0,0 +1,18 @@ +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::Uint128; + +#[cw_serde] +pub struct InstantiateMsg { + pub collection: String, + pub tiers: Vec, +} + +#[cw_serde] +pub enum ExecuteMsg {} + +#[cw_serde] +#[derive(QueryResponses)] +pub enum QueryMsg { + #[returns(u64)] + Tier { name: String }, +} diff --git a/contracts/vip/program/src/state.rs b/contracts/vip/program/src/state.rs new file mode 100644 index 0000000..33cd571 --- /dev/null +++ b/contracts/vip/program/src/state.rs @@ -0,0 +1,6 @@ +use cosmwasm_std::{Addr, Uint128}; +use cw_storage_plus::Item; + +pub const COLLECTION: Item = Item::new("collection"); + +pub const TIERS: Item> = Item::new("tiers"); diff --git a/scripts/schema.sh b/scripts/schema.sh index 4fd87ff..49641d8 100755 --- a/scripts/schema.sh +++ b/scripts/schema.sh @@ -1,13 +1,14 @@ -# for d in contracts/*; do -# if [ -d "$d" ]; then -# cd $d -# cargo schema -# rm -rf schema/raw -# cd ../.. -# fi -# done - cd contracts/fair-burn cargo schema rm -rf schema/raw -cd ../.. \ No newline at end of file +cd ../.. + +for d in contracts/vip/*; do + if [ -d "$d" ]; then + cd $d + cargo schema + rm -rf schema/raw + cd ../../.. + fi +done +