diff --git a/Cargo.lock b/Cargo.lock index e1863ae8..322d89cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" dependencies = [ "getrandom", "once_cell", @@ -15,9 +15,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "astroport" @@ -25,8 +25,8 @@ version = "2.0.0" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus 1.1.0", - "cw20 1.1.1", + "cw-storage-plus 1.2.0", + "cw20 1.1.2", "itertools 0.11.0", "uint", ] @@ -34,7 +34,7 @@ dependencies = [ [[package]] name = "astroport" version = "2.5.0" -source = "git+https://github.com/astroport-fi/astroport-core.git?tag=v2.5.0#65ce7d1879cc5d95b09fa14202f0423bba52ae0e" +source = "git+https://github.com/astroport-fi/astroport-core.git?rev=65ce7d1879cc5d95b09fa14202f0423bba52ae0e#65ce7d1879cc5d95b09fa14202f0423bba52ae0e" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -47,24 +47,38 @@ dependencies = [ [[package]] name = "astroport" -version = "2.5.0" -source = "git+https://github.com/astroport-fi/astroport-core.git?rev=65ce7d1879cc5d95b09fa14202f0423bba52ae0e#65ce7d1879cc5d95b09fa14202f0423bba52ae0e" +version = "3.11.0" +source = "git+https://github.com/astroport-fi/astroport-core.git?tag=v3.11.0#d6adad9bcbf5df75ea503601115de7a1aed501db" dependencies = [ + "astroport-circular-buffer", "cosmwasm-schema", "cosmwasm-std", + "cw-asset", "cw-storage-plus 0.15.1", - "cw-utils 0.15.1", + "cw-utils 1.0.3", "cw20 0.15.1", + "cw3", "itertools 0.10.5", "uint", ] +[[package]] +name = "astroport-circular-buffer" +version = "0.1.0" +source = "git+https://github.com/astroport-fi/astroport-core.git?tag=v3.11.0#d6adad9bcbf5df75ea503601115de7a1aed501db" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 0.15.1", + "thiserror", +] + [[package]] name = "astroport-factory" version = "1.5.0" source = "git+https://github.com/astroport-fi/astroport-core.git?rev=65ce7d1879cc5d95b09fa14202f0423bba52ae0e#65ce7d1879cc5d95b09fa14202f0423bba52ae0e" dependencies = [ - "astroport 2.5.0 (git+https://github.com/astroport-fi/astroport-core.git?rev=65ce7d1879cc5d95b09fa14202f0423bba52ae0e)", + "astroport 2.5.0", "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus 0.15.1", @@ -79,7 +93,7 @@ name = "astroport-native-coin-registry" version = "1.0.1" source = "git+https://github.com/astroport-fi/astroport-core.git?rev=65ce7d1879cc5d95b09fa14202f0423bba52ae0e#65ce7d1879cc5d95b09fa14202f0423bba52ae0e" dependencies = [ - "astroport 2.5.0 (git+https://github.com/astroport-fi/astroport-core.git?rev=65ce7d1879cc5d95b09fa14202f0423bba52ae0e)", + "astroport 2.5.0", "cosmwasm-schema", "cosmwasm-std", "cosmwasm-storage", @@ -101,10 +115,10 @@ dependencies = [ "astroport-token", "cosmwasm-schema", "cosmwasm-std", - "cw-multi-test", - "cw-storage-plus 1.1.0", - "cw2 1.1.1", - "cw20 1.1.1", + "cw-multi-test 0.16.5", + "cw-storage-plus 1.2.0", + "cw2 1.1.2", + "cw20 1.1.2", "itertools 0.11.0", "thiserror", ] @@ -114,7 +128,7 @@ name = "astroport-pair" version = "1.2.0" source = "git+https://github.com/astroport-fi/astroport-core.git?rev=65ce7d1879cc5d95b09fa14202f0423bba52ae0e#65ce7d1879cc5d95b09fa14202f0423bba52ae0e" dependencies = [ - "astroport 2.5.0 (git+https://github.com/astroport-fi/astroport-core.git?rev=65ce7d1879cc5d95b09fa14202f0423bba52ae0e)", + "astroport 2.5.0", "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus 0.15.1", @@ -130,11 +144,11 @@ name = "astroport-pair-stable" version = "2.1.1" source = "git+https://github.com/astroport-fi/astroport-core.git?rev=65ce7d1879cc5d95b09fa14202f0423bba52ae0e#65ce7d1879cc5d95b09fa14202f0423bba52ae0e" dependencies = [ - "astroport 2.5.0 (git+https://github.com/astroport-fi/astroport-core.git?rev=65ce7d1879cc5d95b09fa14202f0423bba52ae0e)", + "astroport 2.5.0", "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus 0.15.1", - "cw-utils 1.0.2", + "cw-utils 1.0.3", "cw2 0.15.1", "cw20 0.15.1", "itertools 0.10.5", @@ -145,11 +159,11 @@ dependencies = [ name = "astroport-periphery" version = "1.1.0" dependencies = [ - "astroport 2.5.0 (git+https://github.com/astroport-fi/astroport-core.git?tag=v2.5.0)", + "astroport 3.11.0", "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus 0.15.1", - "cw20 1.1.1", + "cw20 1.1.2", "schemars", "serde", ] @@ -159,7 +173,7 @@ name = "astroport-token" version = "1.1.1" source = "git+https://github.com/astroport-fi/astroport-core.git?rev=65ce7d1879cc5d95b09fa14202f0423bba52ae0e#65ce7d1879cc5d95b09fa14202f0423bba52ae0e" dependencies = [ - "astroport 2.5.0 (git+https://github.com/astroport-fi/astroport-core.git?rev=65ce7d1879cc5d95b09fa14202f0423bba52ae0e)", + "astroport 2.5.0", "cosmwasm-schema", "cosmwasm-std", "cw2 0.15.1", @@ -188,9 +202,9 @@ checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" [[package]] name = "base64" -version = "0.21.4" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64ct" @@ -224,9 +238,9 @@ dependencies = [ [[package]] name = "bnum" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128a44527fc0d6abf05f9eda748b9027536e12dff93f5acc8449f51583309350" +checksum = "56953345e39537a3e18bdaeba4cb0c58a78c1f61f361dc0fa7c5c7340ae87c5f" [[package]] name = "byteorder" @@ -248,17 +262,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "const-oid" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "cosmwasm-crypto" -version = "1.4.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6fb22494cf7d23d0c348740e06e5c742070b2991fd41db77bba0bcfbae1a723" +checksum = "9934c79e58d9676edfd592557dee765d2a6ef54c09d5aa2edb06156b00148966" dependencies = [ "digest 0.10.7", + "ecdsa 0.16.9", "ed25519-zebra", "k256 0.13.1", "rand_core 0.6.4", @@ -267,18 +282,18 @@ dependencies = [ [[package]] name = "cosmwasm-derive" -version = "1.4.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e199424486ea97d6b211db6387fd72e26b4a439d40cc23140b2d8305728055b" +checksum = "bc5e72e330bd3bdab11c52b5ecbdeb6a8697a004c57964caeb5d876f0b088b3c" dependencies = [ "syn 1.0.109", ] [[package]] name = "cosmwasm-schema" -version = "1.4.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fef683a9c1c4eabd6d31515719d0d2cc66952c4c87f7eb192bfc90384517dc34" +checksum = "ac3e3a2136e2a60e8b6582f5dffca5d1a683ed77bf38537d330bc1dfccd69010" dependencies = [ "cosmwasm-schema-derive", "schemars", @@ -289,22 +304,23 @@ dependencies = [ [[package]] name = "cosmwasm-schema-derive" -version = "1.4.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9567025acbb4c0c008178393eb53b3ac3c2e492c25949d3bf415b9cbe80772d8" +checksum = "f5d803bea6bd9ed61bd1ee0b4a2eb09ee20dbb539cc6e0b8795614d20952ebb1" dependencies = [ "proc-macro2", - "quote 1.0.33", + "quote 1.0.35", "syn 1.0.109", ] [[package]] name = "cosmwasm-std" -version = "1.4.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d89d680fb60439b7c5947b15f9c84b961b88d1f8a3b20c4bd178a3f87db8bae" +checksum = "ef8666e572a3a2519010dde88c04d16e9339ae751b56b2bb35081fe3f7d6be74" dependencies = [ "base64", + "bech32", "bnum", "cosmwasm-crypto", "cosmwasm-derive", @@ -315,14 +331,15 @@ dependencies = [ "serde", "serde-json-wasm", "sha2 0.10.8", + "static_assertions", "thiserror", ] [[package]] name = "cosmwasm-storage" -version = "1.4.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a1c574d30feffe4b8121e61e839c231a5ce21901221d2fb4d5c945968a4f00" +checksum = "66de2ab9db04757bcedef2b5984fbe536903ada4a8a9766717a4a71197ef34f6" dependencies = [ "cosmwasm-std", "serde", @@ -330,9 +347,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -343,9 +360,9 @@ version = "0.1.0" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus 1.1.0", - "cw2 1.1.1", - "cw20 1.1.1", + "cw-storage-plus 1.2.0", + "cw2 1.1.2", + "cw20 1.1.2", "cw20-base 0.13.4", "schemars", "serde", @@ -372,9 +389,9 @@ dependencies = [ [[package]] name = "crypto-bigint" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740fe28e594155f10cfc383984cbefd529d7396050557148f79cb0f621204124" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", "rand_core 0.6.4", @@ -405,6 +422,29 @@ 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-asset" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "431e57314dceabd29a682c78bb3ff7c641f8bdc8b915400bb9956cb911e8e571" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-address-like", + "cw-storage-plus 1.2.0", + "cw20 1.1.2", + "thiserror", +] + [[package]] name = "cw-band" version = "0.1.1" @@ -416,6 +456,25 @@ dependencies = [ "obi", ] +[[package]] +name = "cw-multi-test" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8e81b4a7821d5eeba0d23f737c16027b39a600742ca8c32eb980895ffd270f4" +dependencies = [ + "anyhow", + "cosmwasm-std", + "cosmwasm-storage", + "cw-storage-plus 0.15.1", + "cw-utils 0.15.1", + "derivative", + "itertools 0.10.5", + "prost", + "schemars", + "serde", + "thiserror", +] + [[package]] name = "cw-multi-test" version = "0.16.5" @@ -424,8 +483,8 @@ checksum = "127c7bb95853b8e828bdab97065c81cb5ddc20f7339180b61b2300565aaa99d1" dependencies = [ "anyhow", "cosmwasm-std", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.2", + "cw-storage-plus 1.2.0", + "cw-utils 1.0.3", "derivative", "itertools 0.10.5", "k256 0.11.6", @@ -458,9 +517,9 @@ dependencies = [ [[package]] name = "cw-storage-plus" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f0e92a069d62067f3472c62e30adedb4cab1754725c0f2a682b3128d2bf3c79" +checksum = "d5ff29294ee99373e2cd5fd21786a3c0ced99a52fec2ca347d565489c61b723c" dependencies = [ "cosmwasm-std", "schemars", @@ -495,13 +554,13 @@ dependencies = [ [[package]] name = "cw-utils" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9f351a4e4d81ef7c890e44d903f8c0bdcdc00f094fd3a181eaf70c0eec7a3a" +checksum = "1c4a657e5caacc3a0d00ee96ca8618745d050b8f757c709babafb81208d4239c" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw2 1.1.1", + "cw2 1.1.2", "schemars", "semver", "serde", @@ -534,14 +593,15 @@ dependencies = [ [[package]] name = "cw2" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9431d14f64f49e41c6ef5561ed11a5391c417d0cb16455dea8cdcb9037a8d197" +checksum = "c6c120b24fbbf5c3bedebb97f2cc85fbfa1c3287e09223428e7e597b5293c1fa" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus 1.1.0", + "cw-storage-plus 1.2.0", "schemars", + "semver", "serde", "thiserror", ] @@ -572,13 +632,13 @@ dependencies = [ [[package]] name = "cw20" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "786e9da5e937f473cecd2463e81384c1af65d0f6398bbd851be7655487c55492" +checksum = "526e39bb20534e25a1cd0386727f0038f4da294e5e535729ba3ef54055246abd" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-utils 1.0.2", + "cw-utils 1.0.3", "schemars", "serde", ] @@ -618,16 +678,15 @@ dependencies = [ [[package]] name = "cw20-base" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09558f87fd3d5e4a479761051b3f98ee2fa723d9e484b5679b6058ad0eadf8f1" +checksum = "17ad79e86ea3707229bf78df94e08732e8f713207b4a77b2699755596725e7d9" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus 1.1.0", - "cw-utils 1.0.2", - "cw2 1.1.1", - "cw20 1.1.1", + "cw-storage-plus 1.2.0", + "cw2 1.1.2", + "cw20 1.1.2", "schemars", "semver", "serde", @@ -642,11 +701,11 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "credits", - "cw-multi-test", - "cw-storage-plus 1.1.0", - "cw2 1.1.1", - "cw20 1.1.1", - "cw20-base 1.1.1", + "cw-multi-test 0.16.5", + "cw-storage-plus 1.2.0", + "cw2 1.1.2", + "cw20 1.1.2", + "cw20-base 1.1.2", "hex", "ripemd", "schemars", @@ -656,6 +715,21 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cw3" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2967fbd073d4b626dd9e7148e05a84a3bebd9794e71342e12351110ffbb12395" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils 1.0.3", + "cw20 1.1.2", + "schemars", + "serde", + "thiserror", +] + [[package]] name = "der" version = "0.6.1" @@ -683,7 +757,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2", - "quote 1.0.33", + "quote 1.0.35", "syn 1.0.109", ] @@ -716,9 +790,9 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "dyn-clone" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd" +checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" [[package]] name = "ecdsa" @@ -734,16 +808,16 @@ dependencies = [ [[package]] name = "ecdsa" -version = "0.16.8" +version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der 0.7.8", "digest 0.10.7", - "elliptic-curve 0.13.6", + "elliptic-curve 0.13.8", "rfc6979 0.4.0", - "signature 2.1.0", - "spki 0.7.2", + "signature 2.2.0", + "spki 0.7.3", ] [[package]] @@ -789,12 +863,12 @@ dependencies = [ [[package]] name = "elliptic-curve" -version = "0.13.6" +version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97ca172ae9dc9f9b779a6e3a65d308f2af74e5b8c921299075bdb4a0370e914" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct 0.2.0", - "crypto-bigint 0.5.3", + "crypto-bigint 0.5.5", "digest 0.10.7", "ff 0.13.0", "generic-array", @@ -845,9 +919,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", @@ -929,9 +1003,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "k256" @@ -952,44 +1026,59 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" dependencies = [ "cfg-if", - "ecdsa 0.16.8", - "elliptic-curve 0.13.6", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", "once_cell", "sha2 0.10.8", - "signature 2.1.0", + "signature 2.2.0", ] [[package]] name = "libc" -version = "0.2.149" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "neutron-auction" version = "1.0.0" dependencies = [ - "astroport 2.5.0 (git+https://github.com/astroport-fi/astroport-core.git?tag=v2.5.0)", + "astroport 3.11.0", "astroport-periphery", "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus 1.1.0", - "cw2 1.1.1", - "cw20 1.1.1", + "cw-storage-plus 1.2.0", + "cw2 1.1.2", + "cw20 1.1.2", ] [[package]] name = "neutron-lockdrop" -version = "1.2.1" +version = "1.3.0" +dependencies = [ + "astroport 3.11.0", + "astroport-periphery", + "cosmwasm-schema", + "cosmwasm-std", + "credits", + "cw-storage-plus 0.15.1", + "cw2 1.1.2", + "cw20 1.1.2", + "serde", +] + +[[package]] +name = "neutron-lockdrop-pcl" +version = "1.0.0" dependencies = [ - "astroport 2.5.0 (git+https://github.com/astroport-fi/astroport-core.git?tag=v2.5.0)", + "astroport 3.11.0", "astroport-periphery", "cosmwasm-schema", "cosmwasm-std", "credits", "cw-storage-plus 0.15.1", - "cw2 1.1.1", - "cw20 1.1.1", + "cw2 1.1.2", + "cw20 1.1.2", "serde", ] @@ -1001,17 +1090,17 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cw-band", - "cw-storage-plus 1.1.0", - "cw2 1.1.1", + "cw-storage-plus 1.2.0", + "cw2 1.1.2", "obi", "thiserror", ] [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] @@ -1043,15 +1132,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b00664fdffd7558a47a4c106c446104af3e789b740d7740885660c371eb0d09d" dependencies = [ "proc-macro2", - "quote 1.0.33", + "quote 1.0.35", "syn 1.0.109", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" @@ -1076,14 +1165,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ "der 0.7.8", - "spki 0.7.2", + "spki 0.7.3", ] [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -1107,7 +1196,7 @@ dependencies = [ "anyhow", "itertools 0.10.5", "proc-macro2", - "quote 1.0.33", + "quote 1.0.35", "syn 1.0.109", ] @@ -1128,9 +1217,9 @@ checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -1182,15 +1271,15 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "schemars" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f7b0ce13155372a76ee2e1c5ffba1fe61ede73fbea5630d61eee6fac4929c0c" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" dependencies = [ "dyn-clone", "schemars_derive", @@ -1200,12 +1289,12 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e85e2a16b12bdb763244c69ab79363d71db2b4b918a2def53f80b02e0574b13c" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" dependencies = [ "proc-macro2", - "quote 1.0.33", + "quote 1.0.35", "serde_derive_internals", "syn 1.0.109", ] @@ -1240,37 +1329,37 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" [[package]] name = "serde" -version = "1.0.189" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] [[package]] name = "serde-json-wasm" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16a62a1fad1e1828b24acac8f2b468971dade7b8c3c2e672bcadefefb1f8c137" +checksum = "9e9213a07d53faa0b8dd81e767a54a8188a242fdb9be99ab75ec576a774bfdd7" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.189" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", - "quote 1.0.33", - "syn 2.0.38", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] @@ -1280,15 +1369,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" dependencies = [ "proc-macro2", - "quote 1.0.33", + "quote 1.0.35", "syn 1.0.109", ] [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ "itoa", "ryu", @@ -1331,9 +1420,9 @@ dependencies = [ [[package]] name = "signature" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", "rand_core 0.6.4", @@ -1356,7 +1445,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1508efa03c362e23817f96cde18abed596a25219a8b2c66e8db33c03543d315b" dependencies = [ "proc-macro2", - "quote 1.0.33", + "quote 1.0.35", "syn 1.0.109", ] @@ -1372,9 +1461,9 @@ dependencies = [ [[package]] name = "spki" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", "der 0.7.8", @@ -1399,39 +1488,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", - "quote 1.0.33", + "quote 1.0.35", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.38" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", - "quote 1.0.33", + "quote 1.0.35", "unicode-ident", ] [[package]] name = "thiserror" -version = "1.0.49" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.49" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", - "quote 1.0.33", - "syn 2.0.38", + "quote 1.0.35", + "syn 2.0.48", ] [[package]] @@ -1471,9 +1560,9 @@ dependencies = [ "astroport 2.0.0", "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus 1.1.0", + "cw-storage-plus 1.2.0", "cw-utils 0.15.1", - "cw20 1.1.1", + "cw20 0.15.1", "thiserror", ] @@ -1485,25 +1574,43 @@ dependencies = [ "astroport-token", "cosmwasm-schema", "cosmwasm-std", - "cw-multi-test", + "cw-multi-test 0.16.5", "cw-utils 0.15.1", - "cw2 1.1.1", - "cw20 1.1.1", + "cw2 1.1.2", + "cw20 1.1.2", "vesting-base", ] [[package]] name = "vesting-lp" +version = "1.2.0" +dependencies = [ + "astroport 2.0.0", + "astroport-token", + "cosmwasm-schema", + "cosmwasm-std", + "cw-multi-test 0.15.1", + "cw-storage-plus 0.15.1", + "cw-utils 0.15.1", + "cw2 0.15.1", + "cw20 0.15.1", + "vesting-base", + "vesting-lp-pcl", +] + +[[package]] +name = "vesting-lp-pcl" version = "1.1.0" dependencies = [ "astroport 2.0.0", "astroport-token", "cosmwasm-schema", "cosmwasm-std", - "cw-multi-test", + "cw-multi-test 0.16.5", + "cw-storage-plus 0.15.1", "cw-utils 0.15.1", - "cw2 1.1.1", - "cw20 1.1.1", + "cw2 1.1.2", + "cw20 0.15.1", "vesting-base", ] @@ -1515,10 +1622,10 @@ dependencies = [ "astroport-token", "cosmwasm-schema", "cosmwasm-std", - "cw-multi-test", + "cw-multi-test 0.16.5", "cw-utils 0.15.1", - "cw2 1.1.1", - "cw20 1.1.1", + "cw2 1.1.2", + "cw20 1.1.2", "vesting-base", ] @@ -1530,6 +1637,6 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "zeroize" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/Cargo.toml b/Cargo.toml index 037caaaf..a0156b36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,13 +2,15 @@ members = [ "contracts/auction", "contracts/lockdrop", + "contracts/lockdrop-pcl", "contracts/credits", "contracts/vesting-lp", + "contracts/vesting-lp-pcl", "contracts/vesting-lti", "contracts/vesting-investors", "contracts/cw20-merkle-airdrop", "contracts/price-feed", - "contracts/astroport/*" + "contracts/astroport/*", ] [profile.release] @@ -33,6 +35,7 @@ cosmwasm-schema = { version = "1.4.1", default-features = false } astroport = { path = "packages/astroport", default-features = false } astroport-periphery = { path = "packages/astroport_periphery" } vesting-base = { path = "packages/vesting-base" } +vesting-base-pcl = { path = "packages/vesting-base-pcl" } # setting cw-multi-test to 0.17.0 enables cosmwasm_1_1, we don't want that cw-multi-test = "0.16.5" itertools = "0.11.0" diff --git a/contracts/astroport/oracle/src/contract.rs b/contracts/astroport/oracle/src/contract.rs index 756eae51..0368e1cb 100644 --- a/contracts/astroport/oracle/src/contract.rs +++ b/contracts/astroport/oracle/src/contract.rs @@ -7,8 +7,8 @@ use astroport::oracle::{Config, ExecuteMsg, InstantiateMsg, QueryMsg}; use astroport::pair::TWAP_PRECISION; use astroport::querier::query_pair_info; use cosmwasm_std::{ - entry_point, to_binary, Binary, Decimal256, Deps, DepsMut, Env, MessageInfo, Response, Uint128, - Uint256, Uint64, + entry_point, to_json_binary, Binary, Decimal256, Deps, DepsMut, Env, MessageInfo, Response, + Uint128, Uint256, Uint64, }; use cw2::set_contract_version; use std::ops::Div; @@ -181,12 +181,12 @@ pub fn update(deps: DepsMut, env: Env) -> Result { #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result { match msg { - QueryMsg::Consult { token, amount } => Ok(to_binary(&consult(deps, token, amount)?)?), + QueryMsg::Consult { token, amount } => Ok(to_json_binary(&consult(deps, token, amount)?)?), QueryMsg::TWAPAtHeight { token, height } => { - Ok(to_binary(&twap_at_height(deps, token, height)?)?) + Ok(to_json_binary(&twap_at_height(deps, token, height)?)?) } - QueryMsg::Config {} => Ok(to_binary(&query_config(deps)?)?), - QueryMsg::LastUpdateTimestamp {} => Ok(to_binary(&query_last_update_ts(deps)?)?), + QueryMsg::Config {} => Ok(to_json_binary(&query_config(deps)?)?), + QueryMsg::LastUpdateTimestamp {} => Ok(to_json_binary(&query_last_update_ts(deps)?)?), } } diff --git a/contracts/astroport/oracle/src/mock_querier.rs b/contracts/astroport/oracle/src/mock_querier.rs index 0bbf558f..2ddbe4d4 100644 --- a/contracts/astroport/oracle/src/mock_querier.rs +++ b/contracts/astroport/oracle/src/mock_querier.rs @@ -5,8 +5,8 @@ use astroport::pair::QueryMsg::{self, CumulativePrices}; use astroport::pair::{CumulativePricesResponse, SimulationResponse}; use cosmwasm_std::testing::{MockApi, MockQuerier, MockStorage, MOCK_CONTRACT_ADDR}; use cosmwasm_std::{ - from_binary, from_slice, to_binary, Addr, Coin, Empty, OwnedDeps, Querier, QuerierResult, - QueryRequest, SystemError, SystemResult, Uint128, WasmQuery, + from_json, to_json_binary, Addr, Coin, Empty, OwnedDeps, Querier, QuerierResult, QueryRequest, + SystemError, SystemResult, Uint128, WasmQuery, }; use cw20::{BalanceResponse, Cw20QueryMsg, TokenInfoResponse}; use std::collections::HashMap; @@ -82,7 +82,7 @@ pub(crate) fn balances_to_map( impl Querier for WasmMockQuerier { fn raw_query(&self, bin_request: &[u8]) -> QuerierResult { // MockQuerier doesn't support Custom, so we ignore it completely here - let request: QueryRequest = match from_slice(bin_request) { + let request: QueryRequest = match from_json(bin_request) { Ok(v) => v, Err(e) => { return SystemResult::Err(SystemError::InvalidRequest { @@ -100,9 +100,9 @@ impl WasmMockQuerier { match &request { QueryRequest::Wasm(WasmQuery::Smart { contract_addr, msg }) => { if contract_addr == "factory" { - match from_binary(msg).unwrap() { + match from_json(msg).unwrap() { Pair { asset_infos } => SystemResult::Ok( - to_binary(&PairInfo { + to_json_binary(&PairInfo { asset_infos, contract_addr: Addr::unchecked("pair"), liquidity_token: Addr::unchecked("lp_token"), @@ -113,9 +113,9 @@ impl WasmMockQuerier { _ => panic!("DO NOT ENTER HERE"), } } else if contract_addr == "astro-token" || contract_addr == "usdc-token" { - match from_binary(msg).unwrap() { + match from_json(msg).unwrap() { Cw20QueryMsg::TokenInfo {} => SystemResult::Ok( - to_binary(&TokenInfoResponse { + to_json_binary(&TokenInfoResponse { name: contract_addr.to_string(), symbol: contract_addr.to_string(), decimals: 6u8, @@ -126,7 +126,7 @@ impl WasmMockQuerier { _ => panic!("DO NOT ENTER HERE"), } } else if contract_addr == "pair" { - match from_binary(msg).unwrap() { + match from_json(msg).unwrap() { CumulativePrices { .. } => { let balance = match self.token_querier.pairs.get(contract_addr) { Some(v) => v, @@ -134,13 +134,13 @@ impl WasmMockQuerier { return SystemResult::Err(SystemError::Unknown {}); } }; - SystemResult::Ok(to_binary(&balance).into()) + SystemResult::Ok(to_json_binary(&balance).into()) } QueryMsg::Simulation { offer_asset, ask_asset_info: _, } => SystemResult::Ok( - to_binary(&SimulationResponse { + to_json_binary(&SimulationResponse { return_amount: offer_asset.amount, spread_amount: Uint128::zero(), commission_amount: Uint128::zero(), @@ -150,7 +150,7 @@ impl WasmMockQuerier { _ => panic!("DO NOT ENTER HERE"), } } else { - match from_binary(msg).unwrap() { + match from_json(msg).unwrap() { Cw20QueryMsg::TokenInfo {} => { let balances: &HashMap = match self.token_querier.balances.get(contract_addr) { @@ -167,7 +167,7 @@ impl WasmMockQuerier { } SystemResult::Ok( - to_binary(&TokenInfoResponse { + to_json_binary(&TokenInfoResponse { name: "mAPPL".to_string(), symbol: "mAPPL".to_string(), decimals: 6, @@ -193,7 +193,7 @@ impl WasmMockQuerier { }; SystemResult::Ok( - to_binary(&BalanceResponse { balance: *balance }).into(), + to_json_binary(&BalanceResponse { balance: *balance }).into(), ) } _ => panic!("DO NOT ENTER HERE"), diff --git a/contracts/astroport/oracle/src/testing.rs b/contracts/astroport/oracle/src/testing.rs index beffe17a..4cf01b11 100644 --- a/contracts/astroport/oracle/src/testing.rs +++ b/contracts/astroport/oracle/src/testing.rs @@ -5,7 +5,7 @@ use astroport::asset::{Asset, AssetInfo, PairInfo}; use astroport::oracle::{Config, ExecuteMsg, InstantiateMsg, QueryMsg}; use cosmwasm_std::testing::{mock_env, mock_info, MOCK_CONTRACT_ADDR}; use cosmwasm_std::{ - from_binary, Addr, Decimal256, DepsMut, Env, MessageInfo, Uint128, Uint256, Uint64, + from_json, Addr, Decimal256, DepsMut, Env, MessageInfo, Uint128, Uint256, Uint64, }; use std::ops::{Add, Mul}; @@ -205,7 +205,7 @@ fn cfg_and_last_update_ts() { // make sure config query works as expected let cfg: Config = - from_binary(&query(deps.as_ref(), env.clone(), QueryMsg::Config {}).unwrap()).unwrap(); + from_json(query(deps.as_ref(), env.clone(), QueryMsg::Config {}).unwrap()).unwrap(); assert_eq!( cfg, Config { @@ -249,7 +249,7 @@ fn cfg_and_last_update_ts() { ) .unwrap(); let last_update_ts: u64 = - from_binary(&query(deps.as_ref(), env.clone(), QueryMsg::LastUpdateTimestamp {}).unwrap()) + from_json(query(deps.as_ref(), env.clone(), QueryMsg::LastUpdateTimestamp {}).unwrap()) .unwrap(); assert_eq!(last_update_ts, first_update_ts); env.block.time = env.block.time.plus_seconds(100); @@ -261,7 +261,7 @@ fn cfg_and_last_update_ts() { ) .unwrap(); let last_update_ts: u64 = - from_binary(&query(deps.as_ref(), env.clone(), QueryMsg::LastUpdateTimestamp {}).unwrap()) + from_json(query(deps.as_ref(), env.clone(), QueryMsg::LastUpdateTimestamp {}).unwrap()) .unwrap(); assert_eq!(last_update_ts, first_update_ts.add(100)); @@ -274,12 +274,12 @@ fn cfg_and_last_update_ts() { ) .unwrap(); let cfg: Config = - from_binary(&query(deps.as_ref(), env.clone(), QueryMsg::Config {}).unwrap()).unwrap(); + from_json(query(deps.as_ref(), env.clone(), QueryMsg::Config {}).unwrap()).unwrap(); assert_eq!(cfg.period, 500u64); // make sure premature update doesn't work let last_update_ts: u64 = - from_binary(&query(deps.as_ref(), env.clone(), QueryMsg::LastUpdateTimestamp {}).unwrap()) + from_json(query(deps.as_ref(), env.clone(), QueryMsg::LastUpdateTimestamp {}).unwrap()) .unwrap(); assert_eq!(last_update_ts, first_update_ts.add(100)); env.block.time = env.block.time.plus_seconds(100); @@ -295,7 +295,7 @@ fn cfg_and_last_update_ts() { env.block.time = env.block.time.plus_seconds(500); execute(deps.as_mut(), env.clone(), info, ExecuteMsg::Update {}).unwrap(); let last_update_ts: u64 = - from_binary(&query(deps.as_ref(), env, QueryMsg::LastUpdateTimestamp {}).unwrap()).unwrap(); + from_json(query(deps.as_ref(), env, QueryMsg::LastUpdateTimestamp {}).unwrap()).unwrap(); assert_eq!(last_update_ts, first_update_ts.add(700)); } diff --git a/contracts/astroport/oracle/tests/integration.rs b/contracts/astroport/oracle/tests/integration.rs index 9e0c5040..5e91d8ac 100644 --- a/contracts/astroport/oracle/tests/integration.rs +++ b/contracts/astroport/oracle/tests/integration.rs @@ -1,7 +1,7 @@ use anyhow::Result; use cosmwasm_std::{ - attr, to_binary, Addr, BlockInfo, Coin, Decimal, Decimal256, QueryRequest, StdResult, Uint128, - Uint64, WasmQuery, + attr, to_json_binary, Addr, BlockInfo, Coin, Decimal, Decimal256, QueryRequest, StdResult, + Uint128, Uint64, WasmQuery, }; use cw20::{BalanceResponse, Cw20QueryMsg, MinterResponse}; use cw_multi_test::{App, AppResponse, ContractWrapper, Executor}; @@ -258,7 +258,7 @@ fn check_balance(router: &mut App, user: Addr, token: Addr, expected_amount: Uin let res: Result = router.wrap().query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: token.to_string(), - msg: to_binary(&msg).unwrap(), + msg: to_json_binary(&msg).unwrap(), })); let balance = res.unwrap(); @@ -364,7 +364,7 @@ fn create_pair( .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: factory_instance.clone().to_string(), - msg: to_binary(&astroport::factory::QueryMsg::Pair { asset_infos }).unwrap(), + msg: to_json_binary(&astroport::factory::QueryMsg::Pair { asset_infos }).unwrap(), })) .unwrap(); @@ -401,7 +401,7 @@ fn create_pair_stable( pair_type: PairType::Stable {}, asset_infos: asset_infos.clone(), init_params: Some( - to_binary(&StablePoolParams { + to_json_binary(&StablePoolParams { amp: 100, owner: None, }) @@ -423,7 +423,7 @@ fn create_pair_stable( .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: factory_instance.clone().to_string(), - msg: to_binary(&astroport::factory::QueryMsg::Pair { asset_infos }).unwrap(), + msg: to_json_binary(&astroport::factory::QueryMsg::Pair { asset_infos }).unwrap(), })) .unwrap(); @@ -575,7 +575,7 @@ fn consult() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: factory_instance.clone().to_string(), - msg: to_binary(&astroport::factory::QueryMsg::Pair { + msg: to_json_binary(&astroport::factory::QueryMsg::Pair { asset_infos: asset_infos.clone(), }) .unwrap(), @@ -668,7 +668,7 @@ fn consult() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: oracle_instance.to_string(), - msg: to_binary(&msg).unwrap(), + msg: to_json_binary(&msg).unwrap(), })) .unwrap(); assert_eq!(res[0].1, amount); @@ -724,7 +724,7 @@ fn twap_at_height() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: factory_instance.clone().to_string(), - msg: to_binary(&astroport::factory::QueryMsg::Pair { + msg: to_json_binary(&astroport::factory::QueryMsg::Pair { asset_infos: asset_infos.clone(), }) .unwrap(), @@ -825,7 +825,7 @@ fn twap_at_height() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: oracle_instance.to_string(), - msg: to_binary(&msg).unwrap(), + msg: to_json_binary(&msg).unwrap(), })) .unwrap(); assert_eq!(res[0].1, price); @@ -876,7 +876,7 @@ fn consult_pair_stable() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: factory_instance.clone().to_string(), - msg: to_binary(&astroport::factory::QueryMsg::Pair { + msg: to_json_binary(&astroport::factory::QueryMsg::Pair { asset_infos: asset_infos.clone(), }) .unwrap(), @@ -981,7 +981,7 @@ fn consult_pair_stable() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: oracle_instance.to_string(), - msg: to_binary(&msg).unwrap(), + msg: to_json_binary(&msg).unwrap(), })) .unwrap(); assert_eq!(res[0].1, amount); @@ -1032,7 +1032,7 @@ fn twap_at_height_pair_stable() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: factory_instance.clone().to_string(), - msg: to_binary(&astroport::factory::QueryMsg::Pair { + msg: to_json_binary(&astroport::factory::QueryMsg::Pair { asset_infos: asset_infos.clone(), }) .unwrap(), @@ -1137,7 +1137,7 @@ fn twap_at_height_pair_stable() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: oracle_instance.to_string(), - msg: to_binary(&msg).unwrap(), + msg: to_json_binary(&msg).unwrap(), })) .unwrap(); assert_eq!(res[0].1, amount); @@ -1363,7 +1363,7 @@ fn consult2() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: oracle_instance.to_string(), - msg: to_binary(&msg).unwrap(), + msg: to_json_binary(&msg).unwrap(), })) .unwrap(); assert_eq!(res[0].1, amount_exp); @@ -1416,7 +1416,7 @@ fn consult2() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: oracle_instance.to_string(), - msg: to_binary(&msg).unwrap(), + msg: to_json_binary(&msg).unwrap(), })) .unwrap(); assert_eq!(res[0].1, amount_exp); @@ -1570,7 +1570,7 @@ fn consult_zero_price() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: oracle_instance.to_string(), - msg: to_binary(&msg).unwrap(), + msg: to_json_binary(&msg).unwrap(), })) .unwrap(); assert_eq!(res[0].1, amount_out); @@ -1736,7 +1736,7 @@ fn consult_multiple_assets() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: factory_instance.clone().to_string(), - msg: to_binary(&astroport::factory::QueryMsg::Pair { + msg: to_json_binary(&astroport::factory::QueryMsg::Pair { asset_infos: asset_infos.clone(), }) .unwrap(), @@ -1917,7 +1917,7 @@ fn consult_multiple_assets() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: oracle_instance.to_string(), - msg: to_binary(&msg).unwrap(), + msg: to_json_binary(&msg).unwrap(), })) .unwrap(); assert_eq!(res, amounts_exp); @@ -2028,7 +2028,7 @@ fn consult_multiple_assets() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: oracle_instance.to_string(), - msg: to_binary(&msg).unwrap(), + msg: to_json_binary(&msg).unwrap(), })) .unwrap(); assert_eq!(res, amount_exp); @@ -2096,7 +2096,7 @@ fn twap_at_height_multiple_assets() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: factory_instance.clone().to_string(), - msg: to_binary(&astroport::factory::QueryMsg::Pair { + msg: to_json_binary(&astroport::factory::QueryMsg::Pair { asset_infos: asset_infos.clone(), }) .unwrap(), @@ -2319,7 +2319,7 @@ fn twap_at_height_multiple_assets() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: oracle_instance.to_string(), - msg: to_binary(&msg).unwrap(), + msg: to_json_binary(&msg).unwrap(), })) .unwrap(); assert_eq!(res, amount_exp); @@ -2388,7 +2388,7 @@ fn twap_at_height_multiple_assets() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: oracle_instance.to_string(), - msg: to_binary(&msg).unwrap(), + msg: to_json_binary(&msg).unwrap(), })) .unwrap(); assert_eq!(res, amount_exp); @@ -2457,7 +2457,7 @@ fn twap_at_height_multiple_assets() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: oracle_instance.to_string(), - msg: to_binary(&msg).unwrap(), + msg: to_json_binary(&msg).unwrap(), })) .unwrap(); assert_eq!(res, amount_exp); @@ -2525,7 +2525,7 @@ fn twap_at_height_multiple_assets_non_accurate_heights() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: factory_instance.clone().to_string(), - msg: to_binary(&astroport::factory::QueryMsg::Pair { + msg: to_json_binary(&astroport::factory::QueryMsg::Pair { asset_infos: asset_infos.clone(), }) .unwrap(), @@ -2753,7 +2753,7 @@ fn twap_at_height_multiple_assets_non_accurate_heights() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: oracle_instance.to_string(), - msg: to_binary(&msg).unwrap(), + msg: to_json_binary(&msg).unwrap(), })) .unwrap(); assert_eq!(res, amount_exp); @@ -2823,7 +2823,7 @@ fn twap_at_height_multiple_assets_non_accurate_heights() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: oracle_instance.to_string(), - msg: to_binary(&msg).unwrap(), + msg: to_json_binary(&msg).unwrap(), })) .unwrap(); assert_eq!(res, amount_exp); @@ -2894,7 +2894,7 @@ fn twap_at_height_multiple_assets_non_accurate_heights() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: oracle_instance.to_string(), - msg: to_binary(&msg).unwrap(), + msg: to_json_binary(&msg).unwrap(), })) .unwrap(); assert_eq!(res, amount_exp); @@ -2949,7 +2949,7 @@ fn contract_works_after_pair_info_is_set() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: factory_instance.clone().to_string(), - msg: to_binary(&astroport::factory::QueryMsg::Pair { + msg: to_json_binary(&astroport::factory::QueryMsg::Pair { asset_infos: asset_infos.clone(), }) .unwrap(), @@ -3042,7 +3042,7 @@ fn contract_works_after_pair_info_is_set() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: oracle_instance.to_string(), - msg: to_binary(&msg).unwrap(), + msg: to_json_binary(&msg).unwrap(), })) .unwrap(); assert_eq!(res[0].1, amount); @@ -3097,7 +3097,7 @@ fn only_manager_can_set_pair_info() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: factory_instance.clone().to_string(), - msg: to_binary(&astroport::factory::QueryMsg::Pair { + msg: to_json_binary(&astroport::factory::QueryMsg::Pair { asset_infos: asset_infos.clone(), }) .unwrap(), @@ -3202,7 +3202,7 @@ fn only_owner_can_change_manager() { .wrap() .query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: factory_instance.clone().to_string(), - msg: to_binary(&astroport::factory::QueryMsg::Pair { + msg: to_json_binary(&astroport::factory::QueryMsg::Pair { asset_infos: asset_infos.clone(), }) .unwrap(), diff --git a/contracts/auction/Cargo.toml b/contracts/auction/Cargo.toml index 3b1d828d..d0f577b7 100644 --- a/contracts/auction/Cargo.toml +++ b/contracts/auction/Cargo.toml @@ -23,7 +23,7 @@ backtraces = ["cosmwasm-std/backtraces"] library = [] [dependencies] -astroport = { git = "https://github.com/astroport-fi/astroport-core.git", tag = "v2.5.0" } +astroport = { git = "https://github.com/astroport-fi/astroport-core.git", tag = "v3.11.0" } astroport-periphery = { workspace = true } cw20 = { workspace = true } cw2 = { workspace = true } diff --git a/contracts/auction/README.md b/contracts/auction/README.md index c43ae90c..a4706ea5 100644 --- a/contracts/auction/README.md +++ b/contracts/auction/README.md @@ -20,7 +20,7 @@ The LP Bootstrap via auction contract facilitates cNTRN-NATIVE Neutron pool init ### Handle Messages | Message | Description | -| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +|-----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `ExecuteMsg::Receive` | ReceiveCW20 Hook which facilitates cNTRN tokens delegation by lockdrop participants / airdrop recipients | | `ExecuteMsg::UpdateConfig` | Admin function to update any of the configuration parameters. | | `ExecuteMsg::DepositUst` | Facilitates UST deposits by users | @@ -32,7 +32,7 @@ The LP Bootstrap via auction contract facilitates cNTRN-NATIVE Neutron pool init ### Handle Messages :: Callback | Message | Description | -| --------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | +|-----------------------------------------------------|------------------------------------------------------------------------------------------------------| | `CallbackMsg::UpdateStateOnLiquidityAdditionToPool` | Callback function to update state after liquidity is added to the cNTRN-UST Pool | | `CallbackMsg::UpdateStateOnRewardClaim` | Callback function to update state after cNTRN rewards are claimed from the generator | | `CallbackMsg::WithdrawUserRewardsCallback` | Callback function to facilitate cNTRN reward claiming and unlocked LP tokens withdrawal for the user | @@ -40,7 +40,7 @@ The LP Bootstrap via auction contract facilitates cNTRN-NATIVE Neutron pool init ### Query Messages | Message | Description | -| -------------------- | ----------------------------- | +|----------------------|-------------------------------| | `QueryMsg::Config` | Returns the config info | | `QueryMsg::State` | Returns state of the contract | | `QueryMsg::UserInfo` | Returns user position details | diff --git a/contracts/auction/src/contract.rs b/contracts/auction/src/contract.rs index 3e714122..adbef9d8 100644 --- a/contracts/auction/src/contract.rs +++ b/contracts/auction/src/contract.rs @@ -3,7 +3,7 @@ use astroport::U256; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - attr, to_binary, Addr, BankMsg, Binary, Coin, CosmosMsg, Decimal, Deps, DepsMut, Env, + attr, to_json_binary, Addr, BankMsg, Binary, Coin, CosmosMsg, Decimal, Deps, DepsMut, Env, MessageInfo, Order, Response, StdError, StdResult, Uint128, WasmMsg, }; use std::str::FromStr; @@ -239,9 +239,9 @@ pub fn execute_deposit(deps: DepsMut, env: Env, info: MessageInfo) -> Result StdResult { match msg { - QueryMsg::Config {} => to_binary(&CONFIG.load(deps.storage)?), - QueryMsg::State {} => to_binary(&STATE.load(deps.storage)?), - QueryMsg::UserInfo { address } => to_binary(&query_user_info(deps, _env, address)?), + QueryMsg::Config {} => to_json_binary(&CONFIG.load(deps.storage)?), + QueryMsg::State {} => to_json_binary(&STATE.load(deps.storage)?), + QueryMsg::UserInfo { address } => to_json_binary(&query_user_info(deps, _env, address)?), } } @@ -720,7 +720,7 @@ pub fn execute_finalize_init_pool( CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: ntrn_usdc_lp_token_address.to_string(), funds: vec![], - msg: to_binary(&Cw20ExecuteMsg::Transfer { + msg: to_json_binary(&Cw20ExecuteMsg::Transfer { recipient: config.reserve_contract_address.to_string(), amount: usdc_lp_to_reserve, })?, @@ -728,7 +728,7 @@ pub fn execute_finalize_init_pool( CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: ntrn_atom_lp_token_address.to_string(), funds: vec![], - msg: to_binary(&Cw20ExecuteMsg::Transfer { + msg: to_json_binary(&Cw20ExecuteMsg::Transfer { recipient: config.reserve_contract_address.to_string(), amount: atom_lp_to_reserve, })?, @@ -740,10 +740,10 @@ pub fn execute_finalize_init_pool( msgs.push(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: ntrn_atom_lp_token_address, funds: vec![], - msg: to_binary(&Cw20ExecuteMsg::Send { + msg: to_json_binary(&Cw20ExecuteMsg::Send { contract: lockdrop_address.to_string(), amount: state.atom_lp_locked, - msg: to_binary(&LockDropCw20HookMsg::InitializePool { + msg: to_json_binary(&LockDropCw20HookMsg::InitializePool { pool_type: LockDropPoolType::ATOM, incentives_share: state.atom_ntrn_size, })?, @@ -754,10 +754,10 @@ pub fn execute_finalize_init_pool( msgs.push(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: ntrn_usdc_lp_token_address, funds: vec![], - msg: to_binary(&Cw20ExecuteMsg::Send { + msg: to_json_binary(&Cw20ExecuteMsg::Send { contract: lockdrop_address.to_string(), amount: state.usdc_lp_locked, - msg: to_binary(&LockDropCw20HookMsg::InitializePool { + msg: to_json_binary(&LockDropCw20HookMsg::InitializePool { pool_type: LockDropPoolType::USDC, incentives_share: state.usdc_ntrn_size, })?, @@ -859,10 +859,10 @@ fn execute_migrate_to_vesting( msgs.push(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: pool_info.ntrn_atom_lp_token_address, funds: vec![], - msg: to_binary(&Cw20ExecuteMsg::Send { + msg: to_json_binary(&Cw20ExecuteMsg::Send { contract: config.vesting_atom_contract_address.to_string(), amount: atom_lp_amount, - msg: to_binary(&VestingExecuteMsg::RegisterVestingAccounts { + msg: to_json_binary(&VestingExecuteMsg::RegisterVestingAccounts { vesting_accounts: atom_users, })?, })?, @@ -872,10 +872,10 @@ fn execute_migrate_to_vesting( msgs.push(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: pool_info.ntrn_usdc_lp_token_address, funds: vec![], - msg: to_binary(&Cw20ExecuteMsg::Send { + msg: to_json_binary(&Cw20ExecuteMsg::Send { contract: config.vesting_usdc_contract_address.to_string(), amount: usdc_lp_amount, - msg: to_binary(&VestingExecuteMsg::RegisterVestingAccounts { + msg: to_json_binary(&VestingExecuteMsg::RegisterVestingAccounts { vesting_accounts: usdc_users, })?, })?, @@ -932,7 +932,7 @@ fn build_provide_liquidity_to_lp_pool_msg( Ok(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: pool_address, funds, - msg: to_binary(&astroport::pair::ExecuteMsg::ProvideLiquidity { + msg: to_json_binary(&astroport::pair::ExecuteMsg::ProvideLiquidity { assets: vec![base, other], slippage_tolerance: None, auto_stake: None, @@ -1033,7 +1033,7 @@ pub fn execute_lock_lp_tokens( let msg = CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: lockdrop_address.to_string(), funds: vec![], - msg: to_binary(&LockDropExecuteMsg::IncreaseLockupFor { + msg: to_json_binary(&LockDropExecuteMsg::IncreaseLockupFor { user_address: info.sender.to_string(), pool_type: asset, amount, @@ -1098,7 +1098,7 @@ pub fn execute_withdraw_lp_tokens( let msg = CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: lockdrop_address.to_string(), funds: vec![], - msg: to_binary(&LockDropExecuteMsg::WithdrawFromLockup { + msg: to_json_binary(&LockDropExecuteMsg::WithdrawFromLockup { user_address: info.sender.to_string(), pool_type: asset, amount, diff --git a/contracts/credits/src/contract.rs b/contracts/credits/src/contract.rs index 10f36e6b..7d167ebd 100644 --- a/contracts/credits/src/contract.rs +++ b/contracts/credits/src/contract.rs @@ -6,7 +6,7 @@ use ::cw20_base::ContractError as Cw20ContractError; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - to_binary, BankMsg, Binary, Coin, Deps, DepsMut, Env, MessageInfo, Response, StdError, + to_json_binary, BankMsg, Binary, Coin, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, Uint128, }; use cw2::set_contract_version; @@ -392,38 +392,40 @@ pub fn execute_mint(deps: DepsMut, env: Env, info: MessageInfo) -> Result StdResult { match msg { QueryMsg::WithdrawableAmount { address } => { - to_binary(&query_withdrawable_amount(deps, env, address)?) + to_json_binary(&query_withdrawable_amount(deps, env, address)?) } - QueryMsg::VestedAmount { address } => to_binary(&query_vested_amount(deps, env, address)?), - QueryMsg::Allocation { address } => to_binary(&query_allocation(deps, address)?), + QueryMsg::VestedAmount { address } => { + to_json_binary(&query_vested_amount(deps, env, address)?) + } + QueryMsg::Allocation { address } => to_json_binary(&query_allocation(deps, address)?), QueryMsg::Balance { address } => { - to_binary(&::cw20_base::contract::query_balance(deps, address)?) + to_json_binary(&::cw20_base::contract::query_balance(deps, address)?) } QueryMsg::TotalSupplyAtHeight { height } => { - to_binary(&query_total_supply_at_height(deps, height)?) + to_json_binary(&query_total_supply_at_height(deps, height)?) } QueryMsg::BalanceAtHeight { address, height } => { - to_binary(&query_balance_at_height(deps, address, height)?) + to_json_binary(&query_balance_at_height(deps, address, height)?) } - QueryMsg::TokenInfo {} => to_binary(&::cw20_base::contract::query_token_info(deps)?), - QueryMsg::Minter {} => to_binary(&::cw20_base::contract::query_minter(deps)?), - QueryMsg::Allowance { owner, spender } => to_binary( + QueryMsg::TokenInfo {} => to_json_binary(&::cw20_base::contract::query_token_info(deps)?), + QueryMsg::Minter {} => to_json_binary(&::cw20_base::contract::query_minter(deps)?), + QueryMsg::Allowance { owner, spender } => to_json_binary( &::cw20_base::allowances::query_allowance(deps, owner, spender)?, ), QueryMsg::AllAllowances { owner, start_after, limit, - } => to_binary(&::cw20_base::enumerable::query_all_allowances( + } => to_json_binary(&::cw20_base::enumerable::query_all_allowances( deps, owner, start_after, limit, )?), - QueryMsg::AllAccounts { start_after, limit } => to_binary( + QueryMsg::AllAccounts { start_after, limit } => to_json_binary( &::cw20_base::enumerable::query_all_accounts(deps, start_after, limit)?, ), - QueryMsg::Config {} => to_binary(&query_config(deps)?), + QueryMsg::Config {} => to_json_binary(&query_config(deps)?), } } diff --git a/contracts/credits/src/testing/tests.rs b/contracts/credits/src/testing/tests.rs index 2ed19104..9d095dab 100644 --- a/contracts/credits/src/testing/tests.rs +++ b/contracts/credits/src/testing/tests.rs @@ -564,7 +564,7 @@ mod withdraw { let res = execute_withdraw(deps.as_mut(), env, somebody_info); assert_eq!( res, - Err(Std(StdError::not_found("credits::state::Allocation"))) + Err(Std(StdError::not_found("type: credits::state::Allocation; key: [00, 0B, 61, 6C, 6C, 6F, 63, 61, 74, 69, 6F, 6E, 73, 73, 6F, 6D, 65, 62, 6F, 64, 79]"))) ); } } @@ -858,7 +858,7 @@ mod query_vested_amount { let query_res = query_vested_amount(deps.as_ref(), env, "noname".to_string()); assert_eq!( query_res, - Err(StdError::not_found("credits::state::Allocation")) + Err(StdError::not_found( "type: credits::state::Allocation; key: [00, 0B, 61, 6C, 6C, 6F, 63, 61, 74, 69, 6F, 6E, 73, 6E, 6F, 6E, 61, 6D, 65]")) ); } diff --git a/contracts/cw20-merkle-airdrop/src/contract.rs b/contracts/cw20-merkle-airdrop/src/contract.rs index dfd7a200..d30baa1d 100644 --- a/contracts/cw20-merkle-airdrop/src/contract.rs +++ b/contracts/cw20-merkle-airdrop/src/contract.rs @@ -2,8 +2,8 @@ use crate::enumerable::query_all_address_map; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - attr, coin, to_binary, BankMsg, Binary, CosmosMsg, Deps, DepsMut, Env, MessageInfo, Response, - StdResult, Uint128, WasmMsg, + attr, coin, to_json_binary, BankMsg, Binary, CosmosMsg, Deps, DepsMut, Env, MessageInfo, + Response, StdResult, Uint128, WasmMsg, }; use cw2::set_contract_version; use cw20::{BalanceResponse, Cw20Contract, Cw20ExecuteMsg, Cw20QueryMsg}; @@ -174,7 +174,7 @@ pub fn execute_claim( .map_err(ContractError::Std)?; let vesting_message = WasmMsg::Execute { contract_addr: config.credits_address.to_string(), - msg: to_binary(&AddVesting { + msg: to_json_binary(&AddVesting { address: info.sender.to_string(), amount, start_time: vesting_start, @@ -236,7 +236,7 @@ pub fn execute_withdraw_all( // Generate burn submessage and return a response let burn_message = CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: cfg.credits_address.to_string(), - msg: to_binary(&Cw20ExecuteMsg::Burn { + msg: to_json_binary(&Cw20ExecuteMsg::Burn { amount: amount_to_withdraw, })?, funds: vec![], @@ -335,16 +335,16 @@ pub fn execute_resume( #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { match msg { - QueryMsg::Config {} => to_binary(&query_config(deps)?), - QueryMsg::MerkleRoot {} => to_binary(&query_merkle_root(deps)?), - QueryMsg::IsClaimed { address } => to_binary(&query_is_claimed(deps, address)?), - QueryMsg::IsPaused {} => to_binary(&query_is_paused(deps)?), - QueryMsg::TotalClaimed {} => to_binary(&query_total_claimed(deps)?), + QueryMsg::Config {} => to_json_binary(&query_config(deps)?), + QueryMsg::MerkleRoot {} => to_json_binary(&query_merkle_root(deps)?), + QueryMsg::IsClaimed { address } => to_json_binary(&query_is_claimed(deps, address)?), + QueryMsg::IsPaused {} => to_json_binary(&query_is_paused(deps)?), + QueryMsg::TotalClaimed {} => to_json_binary(&query_total_claimed(deps)?), QueryMsg::AccountMap { external_address } => { - to_binary(&query_address_map(deps, external_address)?) + to_json_binary(&query_address_map(deps, external_address)?) } QueryMsg::AllAccountMaps { start_after, limit } => { - to_binary(&query_all_address_map(deps, start_after, limit)?) + to_json_binary(&query_all_address_map(deps, start_after, limit)?) } } } diff --git a/contracts/cw20-merkle-airdrop/src/msg.rs b/contracts/cw20-merkle-airdrop/src/msg.rs index ffbe2e88..41f20b7c 100644 --- a/contracts/cw20-merkle-airdrop/src/msg.rs +++ b/contracts/cw20-merkle-airdrop/src/msg.rs @@ -1,6 +1,6 @@ use crate::ContractError; use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::{from_slice, Binary, Uint128}; +use cosmwasm_std::{from_json, Binary, Uint128}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -133,7 +133,7 @@ pub struct SignatureInfo { } impl SignatureInfo { pub fn extract_addr(&self) -> Result { - let claim_msg = from_slice::(&self.claim_msg)?; + let claim_msg = from_json::(&self.claim_msg)?; Ok(claim_msg.address) } } diff --git a/contracts/cw20-merkle-airdrop/src/tests.rs b/contracts/cw20-merkle-airdrop/src/tests.rs index 99865ab8..b910bbdd 100644 --- a/contracts/cw20-merkle-airdrop/src/tests.rs +++ b/contracts/cw20-merkle-airdrop/src/tests.rs @@ -7,9 +7,9 @@ use crate::{ }, }; use cosmwasm_std::{ - attr, coin, from_binary, from_slice, + attr, coin, from_json, testing::{mock_dependencies, mock_env, mock_info}, - to_binary, Addr, BlockInfo, CosmosMsg, Empty, SubMsg, Timestamp, Uint128, WasmMsg, + to_json_binary, Addr, BlockInfo, CosmosMsg, Empty, SubMsg, Timestamp, Uint128, WasmMsg, }; use credits::msg::ExecuteMsg::AddVesting; use cw20::{BalanceResponse, Cw20ExecuteMsg}; @@ -68,7 +68,7 @@ fn proper_instantiation() { ); let res = query(deps.as_ref(), env.clone(), QueryMsg::MerkleRoot {}).unwrap(); - let merkle_root: MerkleRootResponse = from_binary(&res).unwrap(); + let merkle_root: MerkleRootResponse = from_json(res).unwrap(); assert_eq!( merkle_root, MerkleRootResponse { @@ -82,7 +82,7 @@ fn proper_instantiation() { ); let res = query(deps.as_ref(), env, QueryMsg::Config {}).unwrap(); - let config: ConfigResponse = from_binary(&res).unwrap(); + let config: ConfigResponse = from_json(res).unwrap(); assert_eq!( config, ConfigResponse { @@ -113,7 +113,7 @@ fn claim() { let airdrop_start = env.block.time.minus_seconds(5_000).seconds(); let vesting_start = env.block.time.plus_seconds(10_000).seconds(); let vesting_duration_seconds = 20_000; - let test_data: Encoded = from_slice(TEST_DATA_1).unwrap(); + let test_data: Encoded = from_json(TEST_DATA_1).unwrap(); let msg = InstantiateMsg { credits_address: "credits0000".to_string(), @@ -141,7 +141,7 @@ fn claim() { SubMsg::new(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: "credits0000".to_string(), funds: vec![], - msg: to_binary(&Cw20ExecuteMsg::Transfer { + msg: to_json_binary(&Cw20ExecuteMsg::Transfer { recipient: test_data.account.clone(), amount: test_data.amount, }) @@ -149,7 +149,7 @@ fn claim() { })), SubMsg::new(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: "credits0000".to_string(), - msg: to_binary(&AddVesting { + msg: to_json_binary(&AddVesting { address: test_data.account.clone(), amount: test_data.amount, start_time: vesting_start, @@ -172,7 +172,7 @@ fn claim() { // Check total claimed assert_eq!( - from_binary::( + from_json::( &query(deps.as_ref(), env.clone(), QueryMsg::TotalClaimed {},).unwrap() ) .unwrap() @@ -182,7 +182,7 @@ fn claim() { // Check address is claimed assert!( - from_binary::( + from_json::( &query( deps.as_ref(), env.clone(), @@ -225,7 +225,7 @@ fn multiple_claim() { let airdrop_start = env.block.time.minus_seconds(5_000).seconds(); let vesting_start = env.block.time.plus_seconds(10_000).seconds(); let vesting_duration_seconds = 20_000; - let test_data: MultipleData = from_slice(TEST_DATA_1_MULTI).unwrap(); + let test_data: MultipleData = from_json(TEST_DATA_1_MULTI).unwrap(); let msg = InstantiateMsg { credits_address: "credits0000".to_string(), @@ -255,7 +255,7 @@ fn multiple_claim() { SubMsg::new(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: "credits0000".to_string(), funds: vec![], - msg: to_binary(&Cw20ExecuteMsg::Transfer { + msg: to_json_binary(&Cw20ExecuteMsg::Transfer { recipient: account.account.clone(), amount: account.amount, }) @@ -263,7 +263,7 @@ fn multiple_claim() { })), SubMsg::new(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: "credits0000".to_string(), - msg: to_binary(&AddVesting { + msg: to_json_binary(&AddVesting { address: account.account.clone(), amount: account.amount, start_time: vesting_start, @@ -288,7 +288,7 @@ fn multiple_claim() { // Check total claimed let env = mock_env(); assert_eq!( - from_binary::( + from_json::( &query(deps.as_ref(), env, QueryMsg::TotalClaimed {}).unwrap() ) .unwrap() @@ -415,7 +415,7 @@ fn update_reserve_address() { ); assert_eq!( - from_binary::(&query(deps.as_ref(), env, QueryMsg::Config {}).unwrap()) + from_json::(&query(deps.as_ref(), env, QueryMsg::Config {}).unwrap()) .unwrap() .reserve_address, "reserve0002" @@ -424,7 +424,7 @@ fn update_reserve_address() { #[test] fn withdraw_all() { - let test_data: Encoded = from_slice(TEST_DATA_1).unwrap(); + let test_data: Encoded = from_json(TEST_DATA_1).unwrap(); let mut router = mock_app(); router .init_modules(|router, _api, storage| { diff --git a/contracts/lockdrop-pcl/.cargo/config b/contracts/lockdrop-pcl/.cargo/config new file mode 100644 index 00000000..386a66e5 --- /dev/null +++ b/contracts/lockdrop-pcl/.cargo/config @@ -0,0 +1,4 @@ +[alias] +wasm = "build --release --target wasm32-unknown-unknown" +unit-test = "test --lib" +schema = "run --example lockdrop_schema" diff --git a/contracts/lockdrop-pcl/Cargo.toml b/contracts/lockdrop-pcl/Cargo.toml new file mode 100644 index 00000000..aa5eec51 --- /dev/null +++ b/contracts/lockdrop-pcl/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "neutron-lockdrop-pcl" +version = "1.0.0" +authors = ["_astromartian", "sotnikov-s"] +edition = "2021" + + +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"] + +[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] +# we have to keep it 0.15.1 because it is the same version as in astroport +cw-storage-plus = { version = "0.15.1" } +astroport = { git = "https://github.com/astroport-fi/astroport-core.git", tag = "v3.11.0" } +credits = { path = "../credits" } +astroport-periphery = { workspace = true } +cosmwasm-std = { workspace = true } +cw20 = { workspace = true } +cw2 = { workspace = true } +serde = { workspace = true } + +[dev-dependencies] +cosmwasm-schema = { workspace = true } diff --git a/contracts/lockdrop-pcl/README.md b/contracts/lockdrop-pcl/README.md new file mode 100644 index 00000000..8a969628 --- /dev/null +++ b/contracts/lockdrop-pcl/README.md @@ -0,0 +1,3 @@ +# Lockdrop for PCL pools + +A shortened, simplified copy of the [Neutron lockdrop contract](https://github.com/neutron-org/neutron-tge-contracts/tree/main/contracts/lockdrop) extended with an entry point to receive lockdrop liquidity from the original contract in order to move it from XYK pools to PCL ones. \ No newline at end of file diff --git a/contracts/lockdrop-pcl/examples/lockdrop_schema.rs b/contracts/lockdrop-pcl/examples/lockdrop_schema.rs new file mode 100644 index 00000000..d8778255 --- /dev/null +++ b/contracts/lockdrop-pcl/examples/lockdrop_schema.rs @@ -0,0 +1,12 @@ +use cosmwasm_schema::write_api; + +use astroport_periphery::lockdrop_pcl::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}; + +fn main() { + write_api! { + instantiate: InstantiateMsg, + query: QueryMsg, + execute: ExecuteMsg, + migrate: MigrateMsg + } +} diff --git a/contracts/lockdrop-pcl/schema/neutron-lockdrop-pcl.json b/contracts/lockdrop-pcl/schema/neutron-lockdrop-pcl.json new file mode 100644 index 00000000..874d7e53 --- /dev/null +++ b/contracts/lockdrop-pcl/schema/neutron-lockdrop-pcl.json @@ -0,0 +1,1655 @@ +{ + "contract_name": "neutron-lockdrop-pcl", + "contract_version": "1.0.0", + "idl_version": "1.0.0", + "instantiate": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "type": "object", + "required": [ + "atom_incentives_share", + "atom_token", + "atom_weighted_amount", + "auction_contract", + "credits_contract", + "incentives", + "lockdrop_incentives", + "lockup_rewards_info", + "usdc_incentives_share", + "usdc_token", + "usdc_weighted_amount", + "xyk_lockdrop_contract" + ], + "properties": { + "atom_incentives_share": { + "description": "Share of total NTRN incentives allocated to the NTRN/ATOM PCL pool", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "atom_token": { + "description": "Address of the LP token of the NTRN/ATOM PCL pool", + "type": "string" + }, + "atom_weighted_amount": { + "description": "Weighted LP Token balance used to calculate NTRN rewards a particular NTRN/ATOM pool depositor can claim", + "allOf": [ + { + "$ref": "#/definitions/Uint256" + } + ] + }, + "auction_contract": { + "description": "Auction contract address", + "type": "string" + }, + "credits_contract": { + "description": "Credits contract address", + "type": "string" + }, + "incentives": { + "description": "Incentives (Staking for dual rewards) contract address", + "type": "string" + }, + "lockdrop_incentives": { + "description": "Total NTRN lockdrop incentives distributed among the users.", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "lockup_rewards_info": { + "description": "Describes rewards coefficients for each lockup duration", + "type": "array", + "items": { + "$ref": "#/definitions/LockupRewardsInfo" + } + }, + "owner": { + "description": "Account which can update config", + "type": [ + "string", + "null" + ] + }, + "usdc_incentives_share": { + "description": "Share of total NTRN incentives allocated to the NTRN/USDC PCL pool", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "usdc_token": { + "description": "Address of the LP token of the NTRN/USDC PCL pool", + "type": "string" + }, + "usdc_weighted_amount": { + "description": "Weighted LP Token balance used to calculate NTRN rewards a particular NTRN/USDC pool depositor can claim", + "allOf": [ + { + "$ref": "#/definitions/Uint256" + } + ] + }, + "xyk_lockdrop_contract": { + "description": "Original XYK lockdrop contract address", + "type": "string" + } + }, + "definitions": { + "Decimal256": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal256(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 115792089237316195423570985008687907853269984665640564039457.584007913129639935 (which is (2^256 - 1) / 10^18)", + "type": "string" + }, + "LockupRewardsInfo": { + "type": "object", + "required": [ + "coefficient", + "duration" + ], + "properties": { + "coefficient": { + "$ref": "#/definitions/Decimal256" + }, + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } + }, + "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" + }, + "Uint256": { + "description": "An implementation of u256 that is using strings for JSON encoding/decoding, such that the full u256 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 out of primitive uint types or `new` to provide big endian bytes:\n\n``` # use cosmwasm_std::Uint256; let a = Uint256::from(258u128); let b = Uint256::new([ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, ]); assert_eq!(a, b); ```", + "type": "string" + } + } + }, + "execute": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "update_config" + ], + "properties": { + "update_config": { + "type": "object", + "required": [ + "new_config" + ], + "properties": { + "new_config": { + "$ref": "#/definitions/UpdateConfigMsg" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "claim_rewards_and_optionally_unlock" + ], + "properties": { + "claim_rewards_and_optionally_unlock": { + "type": "object", + "required": [ + "duration", + "pool_type", + "withdraw_lp_stake" + ], + "properties": { + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "$ref": "#/definitions/PoolType" + }, + "withdraw_lp_stake": { + "type": "boolean" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Callbacks; only callable by the contract itself.", + "type": "object", + "required": [ + "callback" + ], + "properties": { + "callback": { + "$ref": "#/definitions/CallbackMsg" + } + }, + "additionalProperties": false + }, + { + "description": "ProposeNewOwner creates a proposal to change contract ownership. The validity period for the proposal is set in the `expires_in` variable.", + "type": "object", + "required": [ + "propose_new_owner" + ], + "properties": { + "propose_new_owner": { + "type": "object", + "required": [ + "expires_in", + "owner" + ], + "properties": { + "expires_in": { + "description": "The date after which this proposal expires", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "owner": { + "description": "Newly proposed contract owner", + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "DropOwnershipProposal removes the existing offer to change contract ownership.", + "type": "object", + "required": [ + "drop_ownership_proposal" + ], + "properties": { + "drop_ownership_proposal": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "description": "Used to claim contract ownership.", + "type": "object", + "required": [ + "claim_ownership" + ], + "properties": { + "claim_ownership": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "description": "A handler to receive lockdrop liquidity migrated from xyl pools to PCL ones. Only callable by the original lockdrop contract. Expects two **Coin**s to be attached as funds.", + "type": "object", + "required": [ + "migrate_xyk_liquidity" + ], + "properties": { + "migrate_xyk_liquidity": { + "type": "object", + "required": [ + "duration", + "lockup_info", + "pool_type", + "user_address_raw", + "user_info" + ], + "properties": { + "duration": { + "description": "The duration of the lock period.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "lockup_info": { + "description": "The lockup info from the XYK lockdrop contract. Is used to create a LockupInfoV2 entry on the PCL lockdrop contract's side.", + "allOf": [ + { + "$ref": "#/definitions/LockupInfoV2" + } + ] + }, + "pool_type": { + "description": "The type of the pool the lockup is related to.", + "allOf": [ + { + "$ref": "#/definitions/PoolType2" + } + ] + }, + "user_address_raw": { + "description": "The address of the user which owns the lockup.", + "type": "string" + }, + "user_info": { + "description": "The lockup owner's info from the XYK lockdrop contract. Is used to create a UserInfo entry on the PCL lockdrop contract's side.", + "allOf": [ + { + "$ref": "#/definitions/UserInfo" + } + ] + } + } + } + }, + "additionalProperties": false + } + ], + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "Asset": { + "description": "This enum describes a Terra asset (native or CW20).", + "type": "object", + "required": [ + "amount", + "info" + ], + "properties": { + "amount": { + "description": "A token amount", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "info": { + "description": "Information about an asset stored in a [`AssetInfo`] struct", + "allOf": [ + { + "$ref": "#/definitions/AssetInfo" + } + ] + } + }, + "additionalProperties": false + }, + "AssetInfo": { + "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "CallbackMsg": { + "oneOf": [ + { + "type": "object", + "required": [ + "update_pool_on_dual_rewards_claim" + ], + "properties": { + "update_pool_on_dual_rewards_claim": { + "type": "object", + "required": [ + "pool_type", + "prev_reward_balances" + ], + "properties": { + "pool_type": { + "$ref": "#/definitions/PoolType" + }, + "prev_reward_balances": { + "type": "array", + "items": { + "$ref": "#/definitions/Asset" + } + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "withdraw_user_lockup_rewards_callback" + ], + "properties": { + "withdraw_user_lockup_rewards_callback": { + "type": "object", + "required": [ + "duration", + "pool_type", + "user_address", + "withdraw_lp_stake" + ], + "properties": { + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "$ref": "#/definitions/PoolType" + }, + "user_address": { + "$ref": "#/definitions/Addr" + }, + "withdraw_lp_stake": { + "type": "boolean" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Completes the liquidity migration process by making all necessary state updates for the lockup position.", + "type": "object", + "required": [ + "finish_lockup_migration_callback" + ], + "properties": { + "finish_lockup_migration_callback": { + "type": "object", + "required": [ + "duration", + "lockup_info", + "lp_token", + "pool_type", + "staked_lp_token_amount", + "user_address", + "user_info" + ], + "properties": { + "duration": { + "description": "The duration of the lock period.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "lockup_info": { + "description": "The lockup info from the XYK lockdrop contract. Is used to create a LockupInfoV2 entry on the PCL lockdrop contract's side.", + "allOf": [ + { + "$ref": "#/definitions/LockupInfoV2" + } + ] + }, + "lp_token": { + "description": "The address of the LP token of the pool.", + "type": "string" + }, + "pool_type": { + "description": "The type of the pool the lockup is related to.", + "allOf": [ + { + "$ref": "#/definitions/PoolType" + } + ] + }, + "staked_lp_token_amount": { + "description": "The amount of staked LP token the PCL lockdrop contract possesses of before liquidity provision and staking to the incentives. Used to calculate LP token amount received for liquidity provision.", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "user_address": { + "description": "The address of the user which owns the lockup.", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "user_info": { + "description": "The lockup owner's info from the XYK lockdrop contract. Is used to create a UserInfo entry on the PCL lockdrop contract's side.", + "allOf": [ + { + "$ref": "#/definitions/UserInfo" + } + ] + } + } + } + }, + "additionalProperties": false + } + ] + }, + "LockupInfoV2": { + "type": "object", + "required": [ + "generator_ntrn_debt", + "generator_proxy_debt", + "lp_units_locked", + "ntrn_rewards", + "unlock_timestamp", + "withdrawal_flag" + ], + "properties": { + "astroport_lp_transferred": { + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "generator_ntrn_debt": { + "description": "Generator NTRN tokens loockup received as generator rewards", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "generator_proxy_debt": { + "description": "Generator Proxy tokens lockup received as generator rewards", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Uint128" + } + ] + }, + "lp_units_locked": { + "description": "Terraswap LP units locked by the user", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "ntrn_rewards": { + "description": "NTRN tokens received as rewards for participation in the lockdrop", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "unlock_timestamp": { + "description": "Timestamp beyond which this position can be unlocked", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "withdrawal_flag": { + "description": "Boolean value indicating if the user's has withdrawn funds post the only 1 withdrawal limit cutoff", + "type": "boolean" + } + } + }, + "PoolType": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + }, + "PoolType2": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + }, + "RestrictedVector_for_AssetInfo_and_Uint128": { + "description": "Vec wrapper for internal use. Some business logic relies on an order of this vector, thus it is forbidden to sort it or remove elements. New values can be added using .update() ONLY.", + "type": "array", + "items": { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AssetInfo" + }, + { + "$ref": "#/definitions/Uint128" + } + ], + "maxItems": 2, + "minItems": 2 + } + }, + "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" + }, + "UpdateConfigMsg": { + "type": "object", + "properties": { + "incentives_address": { + "description": "incentives (Staking for dual rewards) contract address", + "type": [ + "string", + "null" + ] + } + } + }, + "UserInfo": { + "type": "object", + "required": [ + "lockup_positions_index", + "ntrn_transferred", + "total_ntrn_rewards" + ], + "properties": { + "lockup_positions_index": { + "description": "Number of lockup positions the user is having", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "ntrn_transferred": { + "description": "NTRN tokens transferred to user", + "type": "boolean" + }, + "total_ntrn_rewards": { + "description": "Total NTRN tokens user received as rewards for participation in the lockdrop", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + } + } + } + } + }, + "query": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "config" + ], + "properties": { + "config": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "state" + ], + "properties": { + "state": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "pool" + ], + "properties": { + "pool": { + "type": "object", + "required": [ + "pool_type" + ], + "properties": { + "pool_type": { + "$ref": "#/definitions/PoolType" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "user_info" + ], + "properties": { + "user_info": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "user_info_with_lockups_list" + ], + "properties": { + "user_info_with_lockups_list": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "lock_up_info" + ], + "properties": { + "lock_up_info": { + "type": "object", + "required": [ + "duration", + "pool_type", + "user_address" + ], + "properties": { + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "$ref": "#/definitions/PoolType" + }, + "user_address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "query_user_lockup_total_at_height" + ], + "properties": { + "query_user_lockup_total_at_height": { + "type": "object", + "required": [ + "height", + "pool_type", + "user_address" + ], + "properties": { + "height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "$ref": "#/definitions/PoolType" + }, + "user_address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "query_lockup_total_at_height" + ], + "properties": { + "query_lockup_total_at_height": { + "type": "object", + "required": [ + "height", + "pool_type" + ], + "properties": { + "height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "$ref": "#/definitions/PoolType" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ], + "definitions": { + "PoolType": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + } + } + }, + "migrate": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "MigrateMsg", + "type": "object" + }, + "sudo": null, + "responses": { + "config": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Config", + "type": "object", + "required": [ + "auction_contract", + "credits_contract", + "incentives", + "lockdrop_incentives", + "lockup_rewards_info", + "owner", + "xyk_lockdrop_contract" + ], + "properties": { + "auction_contract": { + "description": "Bootstrap Auction contract address", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "credits_contract": { + "description": "Credits contract address", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "incentives": { + "description": "Incentives contract address", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "lockdrop_incentives": { + "description": "Total NTRN lockdrop incentives to be distributed among the users", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "lockup_rewards_info": { + "description": "Describes rewards coefficients for each lockup duration", + "type": "array", + "items": { + "$ref": "#/definitions/LockupRewardsInfo" + } + }, + "owner": { + "description": "Account which can update the config", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "xyk_lockdrop_contract": { + "description": "Original XYK lockdrop contract address", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + } + }, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "Decimal256": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal256(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 115792089237316195423570985008687907853269984665640564039457.584007913129639935 (which is (2^256 - 1) / 10^18)", + "type": "string" + }, + "LockupRewardsInfo": { + "type": "object", + "required": [ + "coefficient", + "duration" + ], + "properties": { + "coefficient": { + "$ref": "#/definitions/Decimal256" + }, + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } + }, + "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" + } + } + }, + "lock_up_info": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "LockUpInfoResponse", + "type": "object", + "required": [ + "astroport_lp_token", + "claimable_incentives_debt", + "duration", + "incentives_debt", + "lp_units_locked", + "ntrn_rewards", + "pool_type", + "unlock_timestamp", + "withdrawal_flag" + ], + "properties": { + "astroport_lp_token": { + "$ref": "#/definitions/Addr" + }, + "astroport_lp_transferred": { + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "astroport_lp_units": { + "description": "User's Astroport LP units, calculated as lp_units_locked (terraswap) / total LP units locked (terraswap) * Astroport LP units minted post migration", + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "claimable_incentives_debt": { + "description": "Tokens receivable as incentives rewards that user can claim", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Uint128" + } + ] + }, + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "incentives_debt": { + "description": "incentives tokens lockup received as incentives rewards", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Uint128" + } + ] + }, + "lp_units_locked": { + "description": "Terraswap LP units locked by the user", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "ntrn_rewards": { + "description": "NTRN tokens received as rewards for participation in the lockdrop", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "pool_type": { + "description": "Terraswap LP token", + "allOf": [ + { + "$ref": "#/definitions/PoolType" + } + ] + }, + "unlock_timestamp": { + "description": "Timestamp beyond which this position can be unlocked", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "withdrawal_flag": { + "description": "Boolean value indicating if the user's has withdrawn funds post the only 1 withdrawal limit cutoff", + "type": "boolean" + } + }, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "AssetInfo": { + "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "PoolType": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + }, + "RestrictedVector_for_AssetInfo_and_Uint128": { + "description": "Vec wrapper for internal use. Some business logic relies on an order of this vector, thus it is forbidden to sort it or remove elements. New values can be added using .update() ONLY.", + "type": "array", + "items": { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AssetInfo" + }, + { + "$ref": "#/definitions/Uint128" + } + ], + "maxItems": 2, + "minItems": 2 + } + }, + "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" + } + } + }, + "pool": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "PoolInfo", + "type": "object", + "required": [ + "amount_in_lockups", + "incentives_rewards_per_share", + "incentives_share", + "lp_token", + "weighted_amount" + ], + "properties": { + "amount_in_lockups": { + "$ref": "#/definitions/Uint128" + }, + "incentives_rewards_per_share": { + "description": "Ratio of incentives rewards accured to astroport pool share", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Decimal" + } + ] + }, + "incentives_share": { + "description": "Share of total NTRN incentives allocated to this pool", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "lp_token": { + "$ref": "#/definitions/Addr" + }, + "weighted_amount": { + "description": "Weighted LP Token balance used to calculate NTRN rewards a particular user can claim", + "allOf": [ + { + "$ref": "#/definitions/Uint256" + } + ] + } + }, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "AssetInfo": { + "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + }, + "RestrictedVector_for_AssetInfo_and_Decimal": { + "description": "Vec wrapper for internal use. Some business logic relies on an order of this vector, thus it is forbidden to sort it or remove elements. New values can be added using .update() ONLY.", + "type": "array", + "items": { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AssetInfo" + }, + { + "$ref": "#/definitions/Decimal" + } + ], + "maxItems": 2, + "minItems": 2 + } + }, + "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" + }, + "Uint256": { + "description": "An implementation of u256 that is using strings for JSON encoding/decoding, such that the full u256 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 out of primitive uint types or `new` to provide big endian bytes:\n\n``` # use cosmwasm_std::Uint256; let a = Uint256::from(258u128); let b = Uint256::new([ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, ]); assert_eq!(a, b); ```", + "type": "string" + } + } + }, + "query_lockup_total_at_height": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Nullable_Uint128", + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ], + "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" + } + } + }, + "query_user_lockup_total_at_height": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Nullable_Uint128", + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ], + "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" + } + } + }, + "state": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "StateResponse", + "type": "object", + "required": [ + "supported_pairs_list", + "total_incentives_share" + ], + "properties": { + "supported_pairs_list": { + "description": "Vector containing LP addresses for all the supported LP Pools", + "type": "array", + "items": { + "$ref": "#/definitions/PoolType" + } + }, + "total_incentives_share": { + "description": "Total NTRN incentives share", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + } + }, + "definitions": { + "PoolType": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + }, + "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" + } + } + }, + "user_info": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserInfoResponse", + "type": "object", + "required": [ + "claimable_incentives_debt", + "lockup_infos", + "lockup_positions_index", + "ntrn_transferred", + "total_ntrn_rewards" + ], + "properties": { + "claimable_incentives_debt": { + "description": "Tokens receivable as incentives rewards that user can claim", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Uint128" + } + ] + }, + "lockup_infos": { + "description": "Lockup positions", + "type": "array", + "items": { + "$ref": "#/definitions/LockUpInfoResponse" + } + }, + "lockup_positions_index": { + "description": "Number of lockup positions the user is having", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "ntrn_transferred": { + "description": "NTRN tokens transferred to user", + "type": "boolean" + }, + "total_ntrn_rewards": { + "description": "Total NTRN tokens user received as rewards for participation in the lockdrop", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + } + }, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "AssetInfo": { + "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "LockUpInfoResponse": { + "type": "object", + "required": [ + "astroport_lp_token", + "claimable_incentives_debt", + "duration", + "incentives_debt", + "lp_units_locked", + "ntrn_rewards", + "pool_type", + "unlock_timestamp", + "withdrawal_flag" + ], + "properties": { + "astroport_lp_token": { + "$ref": "#/definitions/Addr" + }, + "astroport_lp_transferred": { + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "astroport_lp_units": { + "description": "User's Astroport LP units, calculated as lp_units_locked (terraswap) / total LP units locked (terraswap) * Astroport LP units minted post migration", + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "claimable_incentives_debt": { + "description": "Tokens receivable as incentives rewards that user can claim", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Uint128" + } + ] + }, + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "incentives_debt": { + "description": "incentives tokens lockup received as incentives rewards", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Uint128" + } + ] + }, + "lp_units_locked": { + "description": "Terraswap LP units locked by the user", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "ntrn_rewards": { + "description": "NTRN tokens received as rewards for participation in the lockdrop", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "pool_type": { + "description": "Terraswap LP token", + "allOf": [ + { + "$ref": "#/definitions/PoolType" + } + ] + }, + "unlock_timestamp": { + "description": "Timestamp beyond which this position can be unlocked", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "withdrawal_flag": { + "description": "Boolean value indicating if the user's has withdrawn funds post the only 1 withdrawal limit cutoff", + "type": "boolean" + } + } + }, + "PoolType": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + }, + "RestrictedVector_for_AssetInfo_and_Uint128": { + "description": "Vec wrapper for internal use. Some business logic relies on an order of this vector, thus it is forbidden to sort it or remove elements. New values can be added using .update() ONLY.", + "type": "array", + "items": { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AssetInfo" + }, + { + "$ref": "#/definitions/Uint128" + } + ], + "maxItems": 2, + "minItems": 2 + } + }, + "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" + } + } + }, + "user_info_with_lockups_list": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserInfoWithListResponse", + "type": "object", + "required": [ + "lockup_infos", + "lockup_positions_index", + "ntrn_transferred", + "total_ntrn_rewards" + ], + "properties": { + "lockup_infos": { + "description": "Lockup positions", + "type": "array", + "items": { + "$ref": "#/definitions/LockUpInfoSummary" + } + }, + "lockup_positions_index": { + "description": "Number of lockup positions the user is having", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "ntrn_transferred": { + "description": "NTRN tokens transferred to user", + "type": "boolean" + }, + "total_ntrn_rewards": { + "description": "Total NTRN tokens user received as rewards for participation in the lockdrop", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + } + }, + "definitions": { + "LockUpInfoSummary": { + "type": "object", + "required": [ + "duration", + "pool_type" + ], + "properties": { + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "$ref": "#/definitions/PoolType" + } + } + }, + "PoolType": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + }, + "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/lockdrop-pcl/schema/raw/execute.json b/contracts/lockdrop-pcl/schema/raw/execute.json new file mode 100644 index 00000000..ea85cb11 --- /dev/null +++ b/contracts/lockdrop-pcl/schema/raw/execute.json @@ -0,0 +1,541 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "update_config" + ], + "properties": { + "update_config": { + "type": "object", + "required": [ + "new_config" + ], + "properties": { + "new_config": { + "$ref": "#/definitions/UpdateConfigMsg" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "claim_rewards_and_optionally_unlock" + ], + "properties": { + "claim_rewards_and_optionally_unlock": { + "type": "object", + "required": [ + "duration", + "pool_type", + "withdraw_lp_stake" + ], + "properties": { + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "$ref": "#/definitions/PoolType" + }, + "withdraw_lp_stake": { + "type": "boolean" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Callbacks; only callable by the contract itself.", + "type": "object", + "required": [ + "callback" + ], + "properties": { + "callback": { + "$ref": "#/definitions/CallbackMsg" + } + }, + "additionalProperties": false + }, + { + "description": "ProposeNewOwner creates a proposal to change contract ownership. The validity period for the proposal is set in the `expires_in` variable.", + "type": "object", + "required": [ + "propose_new_owner" + ], + "properties": { + "propose_new_owner": { + "type": "object", + "required": [ + "expires_in", + "owner" + ], + "properties": { + "expires_in": { + "description": "The date after which this proposal expires", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "owner": { + "description": "Newly proposed contract owner", + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "DropOwnershipProposal removes the existing offer to change contract ownership.", + "type": "object", + "required": [ + "drop_ownership_proposal" + ], + "properties": { + "drop_ownership_proposal": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "description": "Used to claim contract ownership.", + "type": "object", + "required": [ + "claim_ownership" + ], + "properties": { + "claim_ownership": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "description": "A handler to receive lockdrop liquidity migrated from xyl pools to PCL ones. Only callable by the original lockdrop contract. Expects two **Coin**s to be attached as funds.", + "type": "object", + "required": [ + "migrate_xyk_liquidity" + ], + "properties": { + "migrate_xyk_liquidity": { + "type": "object", + "required": [ + "duration", + "lockup_info", + "pool_type", + "user_address_raw", + "user_info" + ], + "properties": { + "duration": { + "description": "The duration of the lock period.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "lockup_info": { + "description": "The lockup info from the XYK lockdrop contract. Is used to create a LockupInfoV2 entry on the PCL lockdrop contract's side.", + "allOf": [ + { + "$ref": "#/definitions/LockupInfoV2" + } + ] + }, + "pool_type": { + "description": "The type of the pool the lockup is related to.", + "allOf": [ + { + "$ref": "#/definitions/PoolType2" + } + ] + }, + "user_address_raw": { + "description": "The address of the user which owns the lockup.", + "type": "string" + }, + "user_info": { + "description": "The lockup owner's info from the XYK lockdrop contract. Is used to create a UserInfo entry on the PCL lockdrop contract's side.", + "allOf": [ + { + "$ref": "#/definitions/UserInfo" + } + ] + } + } + } + }, + "additionalProperties": false + } + ], + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "Asset": { + "description": "This enum describes a Terra asset (native or CW20).", + "type": "object", + "required": [ + "amount", + "info" + ], + "properties": { + "amount": { + "description": "A token amount", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "info": { + "description": "Information about an asset stored in a [`AssetInfo`] struct", + "allOf": [ + { + "$ref": "#/definitions/AssetInfo" + } + ] + } + }, + "additionalProperties": false + }, + "AssetInfo": { + "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "CallbackMsg": { + "oneOf": [ + { + "type": "object", + "required": [ + "update_pool_on_dual_rewards_claim" + ], + "properties": { + "update_pool_on_dual_rewards_claim": { + "type": "object", + "required": [ + "pool_type", + "prev_reward_balances" + ], + "properties": { + "pool_type": { + "$ref": "#/definitions/PoolType" + }, + "prev_reward_balances": { + "type": "array", + "items": { + "$ref": "#/definitions/Asset" + } + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "withdraw_user_lockup_rewards_callback" + ], + "properties": { + "withdraw_user_lockup_rewards_callback": { + "type": "object", + "required": [ + "duration", + "pool_type", + "user_address", + "withdraw_lp_stake" + ], + "properties": { + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "$ref": "#/definitions/PoolType" + }, + "user_address": { + "$ref": "#/definitions/Addr" + }, + "withdraw_lp_stake": { + "type": "boolean" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Completes the liquidity migration process by making all necessary state updates for the lockup position.", + "type": "object", + "required": [ + "finish_lockup_migration_callback" + ], + "properties": { + "finish_lockup_migration_callback": { + "type": "object", + "required": [ + "duration", + "lockup_info", + "lp_token", + "pool_type", + "staked_lp_token_amount", + "user_address", + "user_info" + ], + "properties": { + "duration": { + "description": "The duration of the lock period.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "lockup_info": { + "description": "The lockup info from the XYK lockdrop contract. Is used to create a LockupInfoV2 entry on the PCL lockdrop contract's side.", + "allOf": [ + { + "$ref": "#/definitions/LockupInfoV2" + } + ] + }, + "lp_token": { + "description": "The address of the LP token of the pool.", + "type": "string" + }, + "pool_type": { + "description": "The type of the pool the lockup is related to.", + "allOf": [ + { + "$ref": "#/definitions/PoolType" + } + ] + }, + "staked_lp_token_amount": { + "description": "The amount of staked LP token the PCL lockdrop contract possesses of before liquidity provision and staking to the incentives. Used to calculate LP token amount received for liquidity provision.", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "user_address": { + "description": "The address of the user which owns the lockup.", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "user_info": { + "description": "The lockup owner's info from the XYK lockdrop contract. Is used to create a UserInfo entry on the PCL lockdrop contract's side.", + "allOf": [ + { + "$ref": "#/definitions/UserInfo" + } + ] + } + } + } + }, + "additionalProperties": false + } + ] + }, + "LockupInfoV2": { + "type": "object", + "required": [ + "generator_ntrn_debt", + "generator_proxy_debt", + "lp_units_locked", + "ntrn_rewards", + "unlock_timestamp", + "withdrawal_flag" + ], + "properties": { + "astroport_lp_transferred": { + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "generator_ntrn_debt": { + "description": "Generator NTRN tokens loockup received as generator rewards", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "generator_proxy_debt": { + "description": "Generator Proxy tokens lockup received as generator rewards", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Uint128" + } + ] + }, + "lp_units_locked": { + "description": "Terraswap LP units locked by the user", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "ntrn_rewards": { + "description": "NTRN tokens received as rewards for participation in the lockdrop", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "unlock_timestamp": { + "description": "Timestamp beyond which this position can be unlocked", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "withdrawal_flag": { + "description": "Boolean value indicating if the user's has withdrawn funds post the only 1 withdrawal limit cutoff", + "type": "boolean" + } + } + }, + "PoolType": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + }, + "PoolType2": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + }, + "RestrictedVector_for_AssetInfo_and_Uint128": { + "description": "Vec wrapper for internal use. Some business logic relies on an order of this vector, thus it is forbidden to sort it or remove elements. New values can be added using .update() ONLY.", + "type": "array", + "items": { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AssetInfo" + }, + { + "$ref": "#/definitions/Uint128" + } + ], + "maxItems": 2, + "minItems": 2 + } + }, + "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" + }, + "UpdateConfigMsg": { + "type": "object", + "properties": { + "incentives_address": { + "description": "incentives (Staking for dual rewards) contract address", + "type": [ + "string", + "null" + ] + } + } + }, + "UserInfo": { + "type": "object", + "required": [ + "lockup_positions_index", + "ntrn_transferred", + "total_ntrn_rewards" + ], + "properties": { + "lockup_positions_index": { + "description": "Number of lockup positions the user is having", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "ntrn_transferred": { + "description": "NTRN tokens transferred to user", + "type": "boolean" + }, + "total_ntrn_rewards": { + "description": "Total NTRN tokens user received as rewards for participation in the lockdrop", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + } + } + } + } +} diff --git a/contracts/lockdrop-pcl/schema/raw/instantiate.json b/contracts/lockdrop-pcl/schema/raw/instantiate.json new file mode 100644 index 00000000..7d301b3c --- /dev/null +++ b/contracts/lockdrop-pcl/schema/raw/instantiate.json @@ -0,0 +1,130 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "type": "object", + "required": [ + "atom_incentives_share", + "atom_token", + "atom_weighted_amount", + "auction_contract", + "credits_contract", + "incentives", + "lockdrop_incentives", + "lockup_rewards_info", + "usdc_incentives_share", + "usdc_token", + "usdc_weighted_amount", + "xyk_lockdrop_contract" + ], + "properties": { + "atom_incentives_share": { + "description": "Share of total NTRN incentives allocated to the NTRN/ATOM PCL pool", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "atom_token": { + "description": "Address of the LP token of the NTRN/ATOM PCL pool", + "type": "string" + }, + "atom_weighted_amount": { + "description": "Weighted LP Token balance used to calculate NTRN rewards a particular NTRN/ATOM pool depositor can claim", + "allOf": [ + { + "$ref": "#/definitions/Uint256" + } + ] + }, + "auction_contract": { + "description": "Auction contract address", + "type": "string" + }, + "credits_contract": { + "description": "Credits contract address", + "type": "string" + }, + "incentives": { + "description": "Incentives (Staking for dual rewards) contract address", + "type": "string" + }, + "lockdrop_incentives": { + "description": "Total NTRN lockdrop incentives distributed among the users.", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "lockup_rewards_info": { + "description": "Describes rewards coefficients for each lockup duration", + "type": "array", + "items": { + "$ref": "#/definitions/LockupRewardsInfo" + } + }, + "owner": { + "description": "Account which can update config", + "type": [ + "string", + "null" + ] + }, + "usdc_incentives_share": { + "description": "Share of total NTRN incentives allocated to the NTRN/USDC PCL pool", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "usdc_token": { + "description": "Address of the LP token of the NTRN/USDC PCL pool", + "type": "string" + }, + "usdc_weighted_amount": { + "description": "Weighted LP Token balance used to calculate NTRN rewards a particular NTRN/USDC pool depositor can claim", + "allOf": [ + { + "$ref": "#/definitions/Uint256" + } + ] + }, + "xyk_lockdrop_contract": { + "description": "Original XYK lockdrop contract address", + "type": "string" + } + }, + "definitions": { + "Decimal256": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal256(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 115792089237316195423570985008687907853269984665640564039457.584007913129639935 (which is (2^256 - 1) / 10^18)", + "type": "string" + }, + "LockupRewardsInfo": { + "type": "object", + "required": [ + "coefficient", + "duration" + ], + "properties": { + "coefficient": { + "$ref": "#/definitions/Decimal256" + }, + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } + }, + "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" + }, + "Uint256": { + "description": "An implementation of u256 that is using strings for JSON encoding/decoding, such that the full u256 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 out of primitive uint types or `new` to provide big endian bytes:\n\n``` # use cosmwasm_std::Uint256; let a = Uint256::from(258u128); let b = Uint256::new([ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, ]); assert_eq!(a, b); ```", + "type": "string" + } + } +} diff --git a/contracts/lockdrop-pcl/schema/raw/migrate.json b/contracts/lockdrop-pcl/schema/raw/migrate.json new file mode 100644 index 00000000..87b18ea7 --- /dev/null +++ b/contracts/lockdrop-pcl/schema/raw/migrate.json @@ -0,0 +1,5 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "MigrateMsg", + "type": "object" +} diff --git a/contracts/lockdrop-pcl/schema/raw/query.json b/contracts/lockdrop-pcl/schema/raw/query.json new file mode 100644 index 00000000..9f3ee6a9 --- /dev/null +++ b/contracts/lockdrop-pcl/schema/raw/query.json @@ -0,0 +1,193 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "config" + ], + "properties": { + "config": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "state" + ], + "properties": { + "state": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "pool" + ], + "properties": { + "pool": { + "type": "object", + "required": [ + "pool_type" + ], + "properties": { + "pool_type": { + "$ref": "#/definitions/PoolType" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "user_info" + ], + "properties": { + "user_info": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "user_info_with_lockups_list" + ], + "properties": { + "user_info_with_lockups_list": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "lock_up_info" + ], + "properties": { + "lock_up_info": { + "type": "object", + "required": [ + "duration", + "pool_type", + "user_address" + ], + "properties": { + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "$ref": "#/definitions/PoolType" + }, + "user_address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "query_user_lockup_total_at_height" + ], + "properties": { + "query_user_lockup_total_at_height": { + "type": "object", + "required": [ + "height", + "pool_type", + "user_address" + ], + "properties": { + "height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "$ref": "#/definitions/PoolType" + }, + "user_address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "query_lockup_total_at_height" + ], + "properties": { + "query_lockup_total_at_height": { + "type": "object", + "required": [ + "height", + "pool_type" + ], + "properties": { + "height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "$ref": "#/definitions/PoolType" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ], + "definitions": { + "PoolType": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + } + } +} diff --git a/contracts/lockdrop-pcl/schema/raw/response_to_config.json b/contracts/lockdrop-pcl/schema/raw/response_to_config.json new file mode 100644 index 00000000..7804611d --- /dev/null +++ b/contracts/lockdrop-pcl/schema/raw/response_to_config.json @@ -0,0 +1,102 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Config", + "type": "object", + "required": [ + "auction_contract", + "credits_contract", + "incentives", + "lockdrop_incentives", + "lockup_rewards_info", + "owner", + "xyk_lockdrop_contract" + ], + "properties": { + "auction_contract": { + "description": "Bootstrap Auction contract address", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "credits_contract": { + "description": "Credits contract address", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "incentives": { + "description": "Incentives contract address", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "lockdrop_incentives": { + "description": "Total NTRN lockdrop incentives to be distributed among the users", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "lockup_rewards_info": { + "description": "Describes rewards coefficients for each lockup duration", + "type": "array", + "items": { + "$ref": "#/definitions/LockupRewardsInfo" + } + }, + "owner": { + "description": "Account which can update the config", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "xyk_lockdrop_contract": { + "description": "Original XYK lockdrop contract address", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + } + }, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "Decimal256": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal256(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 115792089237316195423570985008687907853269984665640564039457.584007913129639935 (which is (2^256 - 1) / 10^18)", + "type": "string" + }, + "LockupRewardsInfo": { + "type": "object", + "required": [ + "coefficient", + "duration" + ], + "properties": { + "coefficient": { + "$ref": "#/definitions/Decimal256" + }, + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } + }, + "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/lockdrop-pcl/schema/raw/response_to_lock_up_info.json b/contracts/lockdrop-pcl/schema/raw/response_to_lock_up_info.json new file mode 100644 index 00000000..b88807de --- /dev/null +++ b/contracts/lockdrop-pcl/schema/raw/response_to_lock_up_info.json @@ -0,0 +1,180 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "LockUpInfoResponse", + "type": "object", + "required": [ + "astroport_lp_token", + "claimable_incentives_debt", + "duration", + "incentives_debt", + "lp_units_locked", + "ntrn_rewards", + "pool_type", + "unlock_timestamp", + "withdrawal_flag" + ], + "properties": { + "astroport_lp_token": { + "$ref": "#/definitions/Addr" + }, + "astroport_lp_transferred": { + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "astroport_lp_units": { + "description": "User's Astroport LP units, calculated as lp_units_locked (terraswap) / total LP units locked (terraswap) * Astroport LP units minted post migration", + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "claimable_incentives_debt": { + "description": "Tokens receivable as incentives rewards that user can claim", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Uint128" + } + ] + }, + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "incentives_debt": { + "description": "incentives tokens lockup received as incentives rewards", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Uint128" + } + ] + }, + "lp_units_locked": { + "description": "Terraswap LP units locked by the user", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "ntrn_rewards": { + "description": "NTRN tokens received as rewards for participation in the lockdrop", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "pool_type": { + "description": "Terraswap LP token", + "allOf": [ + { + "$ref": "#/definitions/PoolType" + } + ] + }, + "unlock_timestamp": { + "description": "Timestamp beyond which this position can be unlocked", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "withdrawal_flag": { + "description": "Boolean value indicating if the user's has withdrawn funds post the only 1 withdrawal limit cutoff", + "type": "boolean" + } + }, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "AssetInfo": { + "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "PoolType": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + }, + "RestrictedVector_for_AssetInfo_and_Uint128": { + "description": "Vec wrapper for internal use. Some business logic relies on an order of this vector, thus it is forbidden to sort it or remove elements. New values can be added using .update() ONLY.", + "type": "array", + "items": { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AssetInfo" + }, + { + "$ref": "#/definitions/Uint128" + } + ], + "maxItems": 2, + "minItems": 2 + } + }, + "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/lockdrop-pcl/schema/raw/response_to_pool.json b/contracts/lockdrop-pcl/schema/raw/response_to_pool.json new file mode 100644 index 00000000..c2cb8470 --- /dev/null +++ b/contracts/lockdrop-pcl/schema/raw/response_to_pool.json @@ -0,0 +1,128 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "PoolInfo", + "type": "object", + "required": [ + "amount_in_lockups", + "incentives_rewards_per_share", + "incentives_share", + "lp_token", + "weighted_amount" + ], + "properties": { + "amount_in_lockups": { + "$ref": "#/definitions/Uint128" + }, + "incentives_rewards_per_share": { + "description": "Ratio of incentives rewards accured to astroport pool share", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Decimal" + } + ] + }, + "incentives_share": { + "description": "Share of total NTRN incentives allocated to this pool", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "lp_token": { + "$ref": "#/definitions/Addr" + }, + "weighted_amount": { + "description": "Weighted LP Token balance used to calculate NTRN rewards a particular user can claim", + "allOf": [ + { + "$ref": "#/definitions/Uint256" + } + ] + } + }, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "AssetInfo": { + "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + }, + "RestrictedVector_for_AssetInfo_and_Decimal": { + "description": "Vec wrapper for internal use. Some business logic relies on an order of this vector, thus it is forbidden to sort it or remove elements. New values can be added using .update() ONLY.", + "type": "array", + "items": { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AssetInfo" + }, + { + "$ref": "#/definitions/Decimal" + } + ], + "maxItems": 2, + "minItems": 2 + } + }, + "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" + }, + "Uint256": { + "description": "An implementation of u256 that is using strings for JSON encoding/decoding, such that the full u256 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 out of primitive uint types or `new` to provide big endian bytes:\n\n``` # use cosmwasm_std::Uint256; let a = Uint256::from(258u128); let b = Uint256::new([ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, ]); assert_eq!(a, b); ```", + "type": "string" + } + } +} diff --git a/contracts/lockdrop-pcl/schema/raw/response_to_query_lockup_total_at_height.json b/contracts/lockdrop-pcl/schema/raw/response_to_query_lockup_total_at_height.json new file mode 100644 index 00000000..2eaf6e96 --- /dev/null +++ b/contracts/lockdrop-pcl/schema/raw/response_to_query_lockup_total_at_height.json @@ -0,0 +1,18 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Nullable_Uint128", + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ], + "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" + } + } +} diff --git a/contracts/lockdrop-pcl/schema/raw/response_to_query_user_lockup_total_at_height.json b/contracts/lockdrop-pcl/schema/raw/response_to_query_user_lockup_total_at_height.json new file mode 100644 index 00000000..2eaf6e96 --- /dev/null +++ b/contracts/lockdrop-pcl/schema/raw/response_to_query_user_lockup_total_at_height.json @@ -0,0 +1,18 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Nullable_Uint128", + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ], + "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" + } + } +} diff --git a/contracts/lockdrop-pcl/schema/raw/response_to_state.json b/contracts/lockdrop-pcl/schema/raw/response_to_state.json new file mode 100644 index 00000000..cdb65ce0 --- /dev/null +++ b/contracts/lockdrop-pcl/schema/raw/response_to_state.json @@ -0,0 +1,39 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "StateResponse", + "type": "object", + "required": [ + "supported_pairs_list", + "total_incentives_share" + ], + "properties": { + "supported_pairs_list": { + "description": "Vector containing LP addresses for all the supported LP Pools", + "type": "array", + "items": { + "$ref": "#/definitions/PoolType" + } + }, + "total_incentives_share": { + "description": "Total NTRN incentives share", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + } + }, + "definitions": { + "PoolType": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + }, + "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/lockdrop-pcl/schema/raw/response_to_user_info.json b/contracts/lockdrop-pcl/schema/raw/response_to_user_info.json new file mode 100644 index 00000000..fe7527b7 --- /dev/null +++ b/contracts/lockdrop-pcl/schema/raw/response_to_user_info.json @@ -0,0 +1,225 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserInfoResponse", + "type": "object", + "required": [ + "claimable_incentives_debt", + "lockup_infos", + "lockup_positions_index", + "ntrn_transferred", + "total_ntrn_rewards" + ], + "properties": { + "claimable_incentives_debt": { + "description": "Tokens receivable as incentives rewards that user can claim", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Uint128" + } + ] + }, + "lockup_infos": { + "description": "Lockup positions", + "type": "array", + "items": { + "$ref": "#/definitions/LockUpInfoResponse" + } + }, + "lockup_positions_index": { + "description": "Number of lockup positions the user is having", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "ntrn_transferred": { + "description": "NTRN tokens transferred to user", + "type": "boolean" + }, + "total_ntrn_rewards": { + "description": "Total NTRN tokens user received as rewards for participation in the lockdrop", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + } + }, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "AssetInfo": { + "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "LockUpInfoResponse": { + "type": "object", + "required": [ + "astroport_lp_token", + "claimable_incentives_debt", + "duration", + "incentives_debt", + "lp_units_locked", + "ntrn_rewards", + "pool_type", + "unlock_timestamp", + "withdrawal_flag" + ], + "properties": { + "astroport_lp_token": { + "$ref": "#/definitions/Addr" + }, + "astroport_lp_transferred": { + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "astroport_lp_units": { + "description": "User's Astroport LP units, calculated as lp_units_locked (terraswap) / total LP units locked (terraswap) * Astroport LP units minted post migration", + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "claimable_incentives_debt": { + "description": "Tokens receivable as incentives rewards that user can claim", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Uint128" + } + ] + }, + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "incentives_debt": { + "description": "incentives tokens lockup received as incentives rewards", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Uint128" + } + ] + }, + "lp_units_locked": { + "description": "Terraswap LP units locked by the user", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "ntrn_rewards": { + "description": "NTRN tokens received as rewards for participation in the lockdrop", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "pool_type": { + "description": "Terraswap LP token", + "allOf": [ + { + "$ref": "#/definitions/PoolType" + } + ] + }, + "unlock_timestamp": { + "description": "Timestamp beyond which this position can be unlocked", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "withdrawal_flag": { + "description": "Boolean value indicating if the user's has withdrawn funds post the only 1 withdrawal limit cutoff", + "type": "boolean" + } + } + }, + "PoolType": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + }, + "RestrictedVector_for_AssetInfo_and_Uint128": { + "description": "Vec wrapper for internal use. Some business logic relies on an order of this vector, thus it is forbidden to sort it or remove elements. New values can be added using .update() ONLY.", + "type": "array", + "items": { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AssetInfo" + }, + { + "$ref": "#/definitions/Uint128" + } + ], + "maxItems": 2, + "minItems": 2 + } + }, + "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/lockdrop-pcl/schema/raw/response_to_user_info_with_lockups_list.json b/contracts/lockdrop-pcl/schema/raw/response_to_user_info_with_lockups_list.json new file mode 100644 index 00000000..0809050c --- /dev/null +++ b/contracts/lockdrop-pcl/schema/raw/response_to_user_info_with_lockups_list.json @@ -0,0 +1,68 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserInfoWithListResponse", + "type": "object", + "required": [ + "lockup_infos", + "lockup_positions_index", + "ntrn_transferred", + "total_ntrn_rewards" + ], + "properties": { + "lockup_infos": { + "description": "Lockup positions", + "type": "array", + "items": { + "$ref": "#/definitions/LockUpInfoSummary" + } + }, + "lockup_positions_index": { + "description": "Number of lockup positions the user is having", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "ntrn_transferred": { + "description": "NTRN tokens transferred to user", + "type": "boolean" + }, + "total_ntrn_rewards": { + "description": "Total NTRN tokens user received as rewards for participation in the lockdrop", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + } + }, + "definitions": { + "LockUpInfoSummary": { + "type": "object", + "required": [ + "duration", + "pool_type" + ], + "properties": { + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "$ref": "#/definitions/PoolType" + } + } + }, + "PoolType": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + }, + "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/lockdrop-pcl/src/contract.rs b/contracts/lockdrop-pcl/src/contract.rs new file mode 100644 index 00000000..92bf7ab2 --- /dev/null +++ b/contracts/lockdrop-pcl/src/contract.rs @@ -0,0 +1,1323 @@ +use std::cmp::min; +use std::ops::Sub; +use std::str::FromStr; + +use astroport::asset::{Asset, AssetInfo}; +use astroport::common::{claim_ownership, drop_ownership_proposal, propose_new_owner}; +use astroport::cosmwasm_ext::IntegerToDecimal; +use astroport::incentives::{ + ExecuteMsg as IncentivesExecuteMsg, QueryMsg as IncentivesQueryMsg, RewardInfo, RewardType, +}; +use astroport::pair::ExecuteMsg::ProvideLiquidity; +use astroport::restricted_vector::RestrictedVector; +use astroport::DecimalCheckedOps; +use cosmwasm_std::{ + attr, coins, entry_point, to_json_binary, Addr, BankMsg, Binary, CosmosMsg, Decimal, + Decimal256, Deps, DepsMut, Env, MessageInfo, Order, Response, StdError, StdResult, Uint128, + Uint256, WasmMsg, +}; +use cw2::set_contract_version; +use cw20::{BalanceResponse, Cw20ExecuteMsg, Cw20QueryMsg, MinterResponse}; + +use astroport_periphery::lockdrop::{ + LockupInfoV2 as LockdropXYKLockupInfoV2, PoolType as LockdropXYKPoolType, + UserInfo as LockdropXYKUserInfo, +}; +use astroport_periphery::lockdrop_pcl::{ + CallbackMsg, Config, ExecuteMsg, InstantiateMsg, LockUpInfoResponse, LockUpInfoSummary, + LockupInfo, MigrateMsg, PoolInfo, PoolType, QueryMsg, State, StateResponse, UpdateConfigMsg, + UserInfo, UserInfoResponse, UserInfoWithListResponse, +}; +use astroport_periphery::utils::Decimal256CheckedOps; + +use crate::raw_queries::{raw_balance, raw_incentives_deposit}; +use crate::state::{ + ASSET_POOLS, CONFIG, LOCKUP_INFO, OWNERSHIP_PROPOSAL, STATE, TOTAL_USER_LOCKUP_AMOUNT, + USER_INFO, +}; + +const AIRDROP_REWARDS_MULTIPLIER: &str = "1.0"; + +pub const UNTRN_DENOM: &str = "untrn"; + +/// Contract name that is used for migration. +const CONTRACT_NAME: &str = "neutron_lockdrop_pcl"; +/// Contract version that is used for migration. +const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +/// Creates a new contract with the specified parameters packed in the `msg` variable. +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: InstantiateMsg, +) -> StdResult { + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + + if msg.lockup_rewards_info.is_empty() { + return Err(StdError::generic_err("Invalid lockup rewards info")); + } + for lr_info in &msg.lockup_rewards_info { + if lr_info.duration == 0 { + return Err(StdError::generic_err( + "Invalid Lockup info rewards duration", + )); + } + } + + let config = Config { + owner: msg + .owner + .map(|v| deps.api.addr_validate(&v)) + .transpose()? + .unwrap_or(info.sender), + xyk_lockdrop_contract: deps.api.addr_validate(&msg.xyk_lockdrop_contract)?, + credits_contract: deps.api.addr_validate(&msg.credits_contract)?, + auction_contract: deps.api.addr_validate(&msg.auction_contract)?, + incentives: deps.api.addr_validate(&msg.incentives)?, + lockdrop_incentives: msg.lockdrop_incentives, + lockup_rewards_info: msg.lockup_rewards_info, + }; + CONFIG.save(deps.storage, &config)?; + + // Initialize NTRN/ATOM pool + let pool_info = PoolInfo { + lp_token: deps.api.addr_validate(&msg.atom_token)?, + amount_in_lockups: Default::default(), + incentives_share: msg.atom_incentives_share, + weighted_amount: msg.atom_weighted_amount, + incentives_rewards_per_share: RestrictedVector::default(), + is_staked: false, + }; + ASSET_POOLS.save(deps.storage, PoolType::ATOM, &pool_info, env.block.height)?; + + // Initialize NTRN/USDC pool + let pool_info = PoolInfo { + lp_token: deps.api.addr_validate(&msg.usdc_token)?, + amount_in_lockups: Default::default(), + incentives_share: msg.usdc_incentives_share, + weighted_amount: msg.usdc_weighted_amount, + incentives_rewards_per_share: RestrictedVector::default(), + is_staked: false, + }; + ASSET_POOLS.save(deps.storage, PoolType::USDC, &pool_info, env.block.height)?; + + STATE.save(deps.storage, &State::default())?; + Ok(Response::default()) +} + +/// Exposes all the execute functions available in the contract. +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> StdResult { + match msg { + ExecuteMsg::ClaimRewardsAndOptionallyUnlock { + pool_type, + duration, + withdraw_lp_stake, + } => handle_claim_rewards_and_unlock_for_lockup( + deps, + env, + info, + pool_type, + duration, + withdraw_lp_stake, + ), + ExecuteMsg::Callback(msg) => _handle_callback(deps, env, info, msg), + ExecuteMsg::ProposeNewOwner { owner, expires_in } => { + let config: Config = CONFIG.load(deps.storage)?; + propose_new_owner( + deps, + info, + env, + owner, + expires_in, + config.owner, + OWNERSHIP_PROPOSAL, + ) + } + ExecuteMsg::DropOwnershipProposal {} => { + let config: Config = CONFIG.load(deps.storage)?; + drop_ownership_proposal(deps, info, config.owner, OWNERSHIP_PROPOSAL) + } + ExecuteMsg::ClaimOwnership {} => { + claim_ownership(deps, info, env, OWNERSHIP_PROPOSAL, |deps, new_owner| { + CONFIG.update::<_, StdError>(deps.storage, |mut v| { + v.owner = new_owner; + Ok(v) + })?; + Ok(()) + }) + } + ExecuteMsg::UpdateConfig { new_config } => { + handle_update_config(deps, env, info, new_config) + } + ExecuteMsg::MigrateXYKLiquidity { + pool_type, + user_address_raw, + duration, + user_info, + lockup_info, + stake, + } => handle_migrate_xyk_liquidity( + deps, + env, + info, + pool_type, + user_address_raw, + duration, + user_info, + lockup_info, + stake, + ), + } +} + +/// Handles callback. +fn _handle_callback( + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: CallbackMsg, +) -> StdResult { + // Only the contract itself can call callbacks + if info.sender != env.contract.address { + return Err(StdError::generic_err( + "callbacks cannot be invoked externally", + )); + } + match msg { + CallbackMsg::UpdatePoolOnDualRewardsClaim { + pool_type, + prev_reward_balances, + } => update_pool_on_dual_rewards_claim(deps, env, pool_type, prev_reward_balances), + CallbackMsg::WithdrawUserLockupRewardsCallback { + pool_type, + user_address, + duration, + withdraw_lp_stake, + } => callback_withdraw_user_rewards_for_lockup_optional_withdraw( + deps, + env, + pool_type, + user_address, + duration, + withdraw_lp_stake, + ), + CallbackMsg::FinishLockupMigrationCallback { + pool_type, + user_address, + duration, + lp_token, + prev_lp_token_amount, + user_info, + lockup_info, + stake, + } => callback_finish_lockup_migration( + deps, + env, + pool_type, + user_address, + duration, + lp_token, + prev_lp_token_amount, + user_info, + lockup_info, + stake, + ), + } +} + +/// Exposes all the queries available in the contract. +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { + match msg { + QueryMsg::Config {} => to_json_binary(&CONFIG.load(deps.storage)?), + QueryMsg::State {} => to_json_binary(&query_state(deps)?), + QueryMsg::Pool { pool_type } => to_json_binary(&query_pool(deps, pool_type)?), + QueryMsg::UserInfo { address } => to_json_binary(&query_user_info(deps, env, address)?), + QueryMsg::UserInfoWithLockupsList { address } => { + to_json_binary(&query_user_info_with_lockups_list(deps, env, address)?) + } + QueryMsg::LockUpInfo { + user_address, + pool_type, + duration, + } => to_json_binary(&query_lockup_info( + deps, + &env, + &user_address, + pool_type, + duration, + )?), + QueryMsg::QueryUserLockupTotalAtHeight { + pool_type, + user_address, + height, + } => to_json_binary(&query_user_lockup_total_at_height( + deps, + pool_type, + deps.api.addr_validate(&user_address)?, + height, + )?), + QueryMsg::QueryLockupTotalAtHeight { pool_type, height } => { + to_json_binary(&query_lockup_total_at_height(deps, pool_type, height)?) + } + } +} + +/// Used for contract migration. +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn migrate(_deps: DepsMut, _env: Env, _msg: MigrateMsg) -> StdResult { + Ok(Response::default()) +} + +/// Admin function to update Configuration parameters. Returns a default object of type [`Response`]. +/// ## Params +/// * **deps** is an object of type [`DepsMut`]. +/// +/// * **info** is an object of type [`MessageInfo`]. +/// +/// * **new_config** is an object of type [`UpdateConfigMsg`]. Same as UpdateConfigMsg struct +pub fn handle_update_config( + deps: DepsMut, + env: Env, + info: MessageInfo, + new_config: UpdateConfigMsg, +) -> StdResult { + let mut config = CONFIG.load(deps.storage)?; + let mut attributes = vec![attr("action", "update_config")]; + + // CHECK :: Only owner can call this function + if info.sender != config.owner { + return Err(StdError::generic_err("Unauthorized")); + } + + if let Some(incentives) = new_config.incentives_address { + // If incentives is set, we check is any LP tokens are currently staked before updating incentives address + for pool_type in ASSET_POOLS + .keys(deps.storage, None, None, Order::Ascending) + .collect::, StdError>>()? + { + let pool_info = ASSET_POOLS.load(deps.storage, pool_type)?; + + let staked_lp_token_amount: Uint128 = deps.querier.query_wasm_smart( + config.incentives.to_string(), + &IncentivesQueryMsg::Deposit { + lp_token: pool_info.lp_token.to_string(), + user: env.contract.address.to_string(), + }, + )?; + + if !staked_lp_token_amount.is_zero() { + return Err(StdError::generic_err(format!( + "{:?} astro LP tokens already staked. Unstake them before updating incentives contract", + pool_type + ))); + } + } + + config.incentives = deps.api.addr_validate(&incentives)?; + attributes.push(attr("new_incentives", incentives)) + } + + CONFIG.save(deps.storage, &config)?; + Ok(Response::new().add_attributes(attributes)) +} + +#[allow(clippy::too_many_arguments)] +/// Creates a lockup position based on the provided parameters and XYK lockdrop contract's state. No +/// validation is performed on the lockup parameters, they are expected to be valid ones because the +/// only valid sender of the message is the XYK lockdrop contract which has already validated them +/// in the beginning of the TGE. +/// +/// Exactly two **Coin**s are expected to be attached to the message as funds. These **Coin**s are +/// used in ProvideLiquidity message sent to the PCL pool, the minted LP tokens are staked to the +/// incentives. +/// +/// Liquidity migration process consists of several sequential messages invocation and from this +/// contract's point of view it mostly mimics (and clones code of) the **IncreaseLockupFor** exec +/// handler of the XYK lockdrop contract called for each lockup position. So, for this contract's +/// state, liquidity migration looks like lockups creation just like it happened in the beginning +/// of the token generation event (TGE). +pub fn handle_migrate_xyk_liquidity( + deps: DepsMut, + env: Env, + info: MessageInfo, + pool_type: LockdropXYKPoolType, + user_address_raw: String, + duration: u64, + user_info: LockdropXYKUserInfo, + lockup_info: LockdropXYKLockupInfoV2, + stake: bool, +) -> StdResult { + let config = CONFIG.load(deps.storage)?; + if info.sender != config.xyk_lockdrop_contract { + return Err(StdError::generic_err( + "only the XYK lockdrop contract is authorized to call the liquidity migration handler", + )); + } + if info.funds.len() != 2 { + return Err(StdError::generic_err( + "exactly two assets are expected to be attached to the message", + )); + } + + // determine the PCL pool info and the current amount of lp tokens on contract's account + let pool_info = ASSET_POOLS.load(deps.storage, pool_type.into())?; + let astroport_pool: String = deps + .querier + .query_wasm_smart::( + pool_info.lp_token.to_string(), + &cw20::Cw20QueryMsg::Minter {}, + )? + .minter; + let lp_token_amount: Uint128 = deps + .querier + .query_wasm_smart::( + pool_info.lp_token.to_string(), + &Cw20QueryMsg::Balance { + address: env.contract.address.to_string(), + }, + )? + .balance; + + Ok(Response::default().add_messages(vec![ + // provide the transferred liquidity to the PCL pool + CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: astroport_pool.to_string(), + funds: info.funds.clone(), + msg: to_json_binary(&ProvideLiquidity { + assets: info + .funds + .iter() + .map(|f| Asset { + info: AssetInfo::NativeToken { + denom: f.denom.clone(), + }, + amount: f.amount, + }) + .collect(), + slippage_tolerance: None, + auto_stake: Some(false), // for each pool staking is done at the last user migration + receiver: None, + })?, + }), + // invoke callback that creates a lockup entry for the provided liquidity + CallbackMsg::FinishLockupMigrationCallback { + pool_type: pool_type.into(), + user_address: deps.api.addr_validate(&user_address_raw)?, + duration, + lp_token: pool_info.lp_token.to_string(), + prev_lp_token_amount: lp_token_amount, + user_info, + lockup_info, + stake, + } + .to_cosmos_msg(&env)?, + ])) +} + +/// Claims user Rewards for a particular Lockup position. Returns a default object of type [`Response`]. +/// ## Params +/// * **deps** is an object of type [`DepsMut`]. +/// +/// * **env** is an object of type [`Env`]. +/// +/// * **info** is an object of type [`MessageInfo`]. +/// +/// * **pool_type** is an object of type [`PoolType`]. LiquidPool type - USDC or ATOM +/// +/// * **duration** is an object of type [`u64`]. Lockup duration (number of weeks). +/// +/// * **withdraw_lp_stake** is an object of type [`bool`]. Boolean value indicating if the LP tokens are to be withdrawn or not. +pub fn handle_claim_rewards_and_unlock_for_lockup( + mut deps: DepsMut, + env: Env, + info: MessageInfo, + pool_type: PoolType, + duration: u64, + withdraw_lp_stake: bool, +) -> StdResult { + let config = CONFIG.load(deps.storage)?; + let state = STATE.load(deps.storage)?; + + let user_address = info.sender; + + // CHECK ::: Is LP Token Pool supported or not ? + let pool_info = ASSET_POOLS.load(deps.storage, pool_type)?; + + let mut user_info = USER_INFO.load(deps.storage, &user_address)?; + + // If user's total NTRN rewards == 0 :: We update all of the user's lockup positions to calculate NTRN rewards and for each alongwith their equivalent Astroport LP Shares + if user_info.total_ntrn_rewards == Uint128::zero() { + user_info.total_ntrn_rewards = update_user_lockup_positions_and_calc_rewards( + deps.branch(), + &config, + &state, + &user_address, + )?; + } + + USER_INFO.save(deps.storage, &user_address, &user_info)?; + + // Check is there lockup or not ? + let lockup_key = (pool_type, &user_address, duration); + let lockup_info = LOCKUP_INFO.load(deps.storage, lockup_key)?; + + // CHECK :: Can the Lockup position be unlocked or not ? + if withdraw_lp_stake && env.block.time.seconds() < lockup_info.unlock_timestamp { + return Err(StdError::generic_err(format!( + "{} seconds to unlock", + lockup_info.unlock_timestamp - env.block.time.seconds() + ))); + } + + if lockup_info.astroport_lp_transferred.is_some() { + return Err(StdError::generic_err( + "Astro LP Tokens have already been claimed!", + )); + } + + let astroport_lp_token = pool_info.lp_token; + + let mut cosmos_msgs = vec![]; + if pool_info.is_staked { + let incentives = &config.incentives; + // QUERY :: Check if there are any pending staking rewards + let pending_rewards_response: Vec = deps.querier.query_wasm_smart( + incentives, + &IncentivesQueryMsg::PendingRewards { + lp_token: astroport_lp_token.to_string(), + user: env.contract.address.to_string(), + }, + )?; + + if pending_rewards_response + .iter() + .any(|asset| !asset.amount.is_zero()) + { + let prev_pending_rewards_balances: Vec = pending_rewards_response + .iter() + .map(|asset| { + let balance = asset + .info + .query_pool(&deps.querier, env.contract.address.clone()) + .unwrap_or_default(); + + Asset { + info: asset.info.clone(), + amount: balance, + } + }) + .collect(); + + cosmos_msgs.push(CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: incentives.to_string(), + funds: vec![], + msg: to_json_binary(&IncentivesExecuteMsg::ClaimRewards { + lp_tokens: vec![astroport_lp_token.to_string()], + })?, + })); + + cosmos_msgs.push( + CallbackMsg::UpdatePoolOnDualRewardsClaim { + pool_type, + prev_reward_balances: prev_pending_rewards_balances, + } + .to_cosmos_msg(&env)?, + ); + } + } + + cosmos_msgs.push( + CallbackMsg::WithdrawUserLockupRewardsCallback { + pool_type, + user_address, + duration, + withdraw_lp_stake, + } + .to_cosmos_msg(&env)?, + ); + + Ok(Response::new().add_messages(cosmos_msgs)) +} + +/// Claims unvested user's airdrop rewards from the Credits Contract plus part of vested tokens (NTRN Lockdrop rewards amount * AIDROP_REWARDS_MULTIPLIER) Returns a [`CosmosMsg`]. +/// ## Params +/// * **deps** is an object of type [`DepsMut`]. +/// +/// * **env** is an object of type [`Env`]. +/// +/// * **credits_contract** is an object of type [`Addr`]. Address of the Credits Contract. +/// +/// * **user_addr** is an object of type [`Addr`]. Address of the user for who claims rewards. +/// +/// * **ntrn_lockdrop_rewards** is an object of type [`Addr`]. Amount of Lockdrop rewards in uNTRN. +pub fn claim_airdrop_tokens_with_multiplier_msg( + deps: Deps, + credits_contract: Addr, + user_addr: Addr, + ntrn_lockdrop_rewards: Uint128, +) -> StdResult { + // unvested tokens amount + let unvested_tokens_amount: credits::msg::WithdrawableAmountResponse = + deps.querier.query_wasm_smart( + &credits_contract, + &credits::msg::QueryMsg::WithdrawableAmount { + address: user_addr.to_string(), + }, + )?; + // vested tokens amount + let vested_tokens_amount: credits::msg::VestedAmountResponse = deps.querier.query_wasm_smart( + &credits_contract, + &credits::msg::QueryMsg::VestedAmount { + address: user_addr.to_string(), + }, + )?; + + let airdrop_rewards_multiplier = Decimal::from_str(AIRDROP_REWARDS_MULTIPLIER)?; + + // either we claim whole vested amount or NTRN lockdrop rewards + let claimable_vested_amount = min( + vested_tokens_amount.amount, + ntrn_lockdrop_rewards + .to_decimal() + .checked_mul(airdrop_rewards_multiplier)? + .to_uint_floor(), + ); + + Ok(CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: credits_contract.to_string(), + msg: to_json_binary(&Cw20ExecuteMsg::BurnFrom { + owner: user_addr.to_string(), + amount: claimable_vested_amount.checked_add(unvested_tokens_amount.amount)?, + })?, + funds: vec![], + })) +} + +/// Updates contract state after dual staking rewards are claimed from the incentives contract. Returns a default object of type [`Response`]. +/// ## Params +/// * **deps** is an object of type [`DepsMut`]. +/// +/// * **env** is an object of type [`Env`]. +/// +/// * **pool_type** is an object of type [`PoolType`]. LiquidPool type - USDC or ATOM +/// +/// * **prev_pending_rewards_balances** is a vector of type [`Asset`]. Contract's Incentives reward token balance before claim. +pub fn update_pool_on_dual_rewards_claim( + deps: DepsMut, + env: Env, + pool_type: PoolType, + prev_pending_rewards_balances: Vec, +) -> StdResult { + let config = CONFIG.load(deps.storage)?; + let mut pool_info = ASSET_POOLS.load(deps.storage, pool_type)?; + let incentives = &config.incentives; + let astroport_lp_token = pool_info.lp_token.clone(); + + let lp_balance: Uint128 = deps.querier.query_wasm_smart( + incentives, + &IncentivesQueryMsg::Deposit { + lp_token: astroport_lp_token.to_string(), + user: env.contract.address.to_string(), + }, + )?; + + // Increment claimed rewards per LP share + for prev_balance in prev_pending_rewards_balances { + let current_balance = prev_balance + .info + .query_pool(&deps.querier, env.contract.address.clone())?; + let received_amount = current_balance.checked_sub(prev_balance.amount)?; + + pool_info.incentives_rewards_per_share.update( + &prev_balance.info, + Decimal::from_ratio(received_amount, lp_balance), + )?; + } + + // SAVE UPDATED STATE OF THE POOL + ASSET_POOLS.save(deps.storage, pool_type, &pool_info, env.block.height)?; + + Ok(Response::new().add_attributes(vec![ + attr("action", "update_incentives_dual_rewards"), + attr("pool_type", format!("{:?}", pool_type)), + ])) +} + +/// Withdraws user rewards and LP Tokens after claims / unlocks. Returns a default object of type [`Response`]. +/// ## Params +/// * **deps** is an object of type [`DepsMut`]. +/// +/// * **env** is an object of type [`Env`]. +/// +/// * **pool_type** is an object of type [`PoolType`]. LiquidPool type - USDC or ATOM +/// +/// * **user_address** is an object of type [`Addr`]. User address who is claiming the rewards / unlocking his lockup position. +/// +/// * **duration** is a vector of type [`u64`]. Duration of the lockup for which rewards have been claimed / position unlocked. +/// +/// * **withdraw_lp_stake** is an object of type [`bool`]. Boolean value indicating if the ASTRO LP Tokens are to be sent to the user or not. +/// +/// * **reward_tokens** is vector of [`AssetInfo`]. A list of assets to calculate claimable staking rewards for. +pub fn callback_withdraw_user_rewards_for_lockup_optional_withdraw( + deps: DepsMut, + env: Env, + pool_type: PoolType, + user_address: Addr, + duration: u64, + withdraw_lp_stake: bool, +) -> StdResult { + let config = CONFIG.load(deps.storage)?; + let mut pool_info = ASSET_POOLS.load(deps.storage, pool_type)?; + let lockup_key = (pool_type, &user_address, duration); + let mut lockup_info = LOCKUP_INFO.load(deps.storage, lockup_key)?; + + let mut user_info = USER_INFO + .may_load(deps.storage, &user_address)? + .unwrap_or_default(); + + let mut cosmos_msgs = vec![]; + let mut attributes = vec![ + attr("action", "withdraw_rewards_and_or_unlock"), + attr("pool_type", format!("{:?}", pool_type)), + attr("user_address", &user_address), + attr("duration", duration.to_string()), + ]; + + let astroport_lp_token = pool_info.lp_token.clone(); + let incentives = &config.incentives; + + // Calculate Astro LP share for the lockup position + let astroport_lp_amount: Uint128 = { + let balance: Uint128 = if pool_info.is_staked { + deps.querier.query_wasm_smart( + incentives, + &IncentivesQueryMsg::Deposit { + lp_token: astroport_lp_token.to_string(), + user: env.contract.address.to_string(), + }, + )? + } else { + let res: BalanceResponse = deps.querier.query_wasm_smart( + astroport_lp_token.clone(), + &Cw20QueryMsg::Balance { + address: env.contract.address.to_string(), + }, + )?; + res.balance + }; + + (lockup_info + .lp_units_locked + .full_mul(balance) + .checked_div(Uint256::from(pool_info.amount_in_lockups))?) + .try_into()? + }; + + if pool_info.is_staked { + // QUERY :: Get list of all reward assets for the lp token + let reward_infos: Vec = deps.querier.query_wasm_smart( + &config.incentives, + &IncentivesQueryMsg::RewardInfo { + lp_token: astroport_lp_token.to_string(), + }, + )?; + + let mut pending_reward_assets: Vec = vec![]; + // If this LP token is getting incentives + // Calculate claimable staking rewards for this lockup + for reward_info in reward_infos { + let reward_token: AssetInfo = match reward_info.reward { + RewardType::Int(asset) => asset, + RewardType::Ext { + info, + next_update_ts: _, + } => info, + }; + let incentives_rewards_per_share = pool_info + .incentives_rewards_per_share + .load(&reward_token) + .unwrap_or_default(); + if incentives_rewards_per_share.is_zero() { + continue; + }; + + let total_lockup_rewards = incentives_rewards_per_share + .checked_mul(astroport_lp_amount.to_decimal())? + .to_uint_floor(); + let debt = lockup_info + .incentives_debt + .load(&reward_token) + .unwrap_or_default(); + let pending_reward = total_lockup_rewards.checked_sub(debt)?; + + if !pending_reward.is_zero() { + pending_reward_assets.push(Asset { + info: reward_token.clone(), + amount: pending_reward, + }); + } + + lockup_info + .incentives_debt + .update(&reward_token, pending_reward)?; + } + + // If this is a void transaction (no state change), then return error. + // Void tx scenario = not unlocking LP tokens in this tx, NTRN already claimed, 0 pending staking reward + if !withdraw_lp_stake && user_info.ntrn_transferred && pending_reward_assets.is_empty() { + return Err(StdError::generic_err("No rewards available to claim!")); + } + + // If there are claimable staking rewards, send them to the user + for pending_reward in pending_reward_assets { + cosmos_msgs.push(pending_reward.into_msg(user_address.clone())?); + } + + // COSMOSMSG :: If LP Tokens are staked, we unstake the amount which needs to be returned to the user + if withdraw_lp_stake { + cosmos_msgs.push(CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: incentives.to_string(), + funds: vec![], + msg: to_json_binary(&IncentivesExecuteMsg::Withdraw { + lp_token: astroport_lp_token.to_string(), + amount: astroport_lp_amount, + })?, + })); + } + } + + if withdraw_lp_stake { + // COSMOSMSG :: Returns LP units locked by the user in the current lockup position + cosmos_msgs.push(CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: astroport_lp_token.to_string(), + msg: to_json_binary(&Cw20ExecuteMsg::Transfer { + recipient: user_address.to_string(), + amount: astroport_lp_amount, + })?, + funds: vec![], + })); + pool_info.amount_in_lockups = pool_info + .amount_in_lockups + .checked_sub(lockup_info.lp_units_locked)?; + ASSET_POOLS.save(deps.storage, pool_type, &pool_info, env.block.height)?; + + attributes.push(attr("astroport_lp_unlocked", astroport_lp_amount)); + lockup_info.astroport_lp_transferred = Some(astroport_lp_amount); + TOTAL_USER_LOCKUP_AMOUNT.update( + deps.storage, + (pool_type, &user_address), + env.block.height, + |lockup_amount| -> StdResult { + if let Some(la) = lockup_amount { + Ok(la.checked_sub(lockup_info.lp_units_locked)?) + } else { + Ok(Uint128::zero()) + } + }, + )?; + } + LOCKUP_INFO.save(deps.storage, lockup_key, &lockup_info)?; + + // Transfers claimable one time NTRN rewards to the user that the user gets for all his lock + if !user_info.ntrn_transferred { + // Calculating how much NTRN user can claim (from total one time reward) + let total_claimable_ntrn_rewards = user_info.total_ntrn_rewards; + if total_claimable_ntrn_rewards > Uint128::zero() { + cosmos_msgs.push(CosmosMsg::Bank(BankMsg::Send { + to_address: user_address.to_string(), + amount: coins(total_claimable_ntrn_rewards.u128(), UNTRN_DENOM), + })) + } + + // claim airdrop rewards for airdrop participants + let res: BalanceResponse = deps.querier.query_wasm_smart( + config.credits_contract.clone(), + &Cw20QueryMsg::Balance { + address: user_address.to_string(), + }, + )?; + if res.balance > Uint128::zero() { + cosmos_msgs.push(claim_airdrop_tokens_with_multiplier_msg( + deps.as_ref(), + config.credits_contract, + user_address.clone(), + total_claimable_ntrn_rewards, + )?); + } + + user_info.ntrn_transferred = true; + attributes.push(attr( + "total_claimable_ntrn_reward", + total_claimable_ntrn_rewards, + )); + USER_INFO.save(deps.storage, &user_address, &user_info)?; + } + + Ok(Response::new() + .add_messages(cosmos_msgs) + .add_attributes(attributes)) +} + +#[allow(clippy::too_many_arguments)] +/// Completes the liquidity migration process by making all necessary state updates for the lockup +/// position. +pub fn callback_finish_lockup_migration( + deps: DepsMut, + env: Env, + pool_type: PoolType, + user_address: Addr, + duration: u64, + lp_token: String, + prev_lp_token_amount: Uint128, + user_info: LockdropXYKUserInfo, + lockup_info: LockdropXYKLockupInfoV2, + stake: bool, +) -> StdResult { + let lp_token_amount = deps + .querier + .query_wasm_smart::( + lp_token.to_string(), + &Cw20QueryMsg::Balance { + address: env.contract.address.to_string(), + }, + )? + .balance; + let lp_token_amount_diff = lp_token_amount.sub(prev_lp_token_amount); + + let user_info: UserInfo = user_info.into(); + let lockup_info: LockupInfo = + LockupInfo::from_xyk_lockup_info(lockup_info, lp_token_amount_diff); + let mut pool_info = ASSET_POOLS.load(deps.storage, pool_type)?; + let config = CONFIG.load(deps.storage)?; + + pool_info.weighted_amount = pool_info.weighted_amount.checked_add(calculate_weight( + lp_token_amount_diff, + duration, + &config, + )?)?; + pool_info.amount_in_lockups = pool_info + .amount_in_lockups + .checked_add(lp_token_amount_diff)?; + + let lockup_key = (pool_type, &user_address, duration); + LOCKUP_INFO.save(deps.storage, lockup_key, &lockup_info)?; + + TOTAL_USER_LOCKUP_AMOUNT.update( + deps.storage, + (pool_type, &user_address), + env.block.height, + |lockup_amount| -> StdResult { + if let Some(la) = lockup_amount { + Ok(la.checked_add(lp_token_amount_diff)?) + } else { + Ok(lp_token_amount_diff) + } + }, + )?; + + ASSET_POOLS.save(deps.storage, pool_type, &pool_info, env.block.height)?; + USER_INFO.save(deps.storage, &user_address, &user_info)?; + + let mut resp = Response::default(); + if stake { + resp = resp.add_message(CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: lp_token.to_string(), + funds: vec![], + msg: to_json_binary(&Cw20ExecuteMsg::Send { + contract: config.incentives.to_string(), + msg: to_json_binary(&IncentivesExecuteMsg::Deposit { recipient: None })?, + amount: lp_token_amount, + })?, + })); + + pool_info.is_staked = true; + ASSET_POOLS.save(deps.storage, pool_type, &pool_info, env.block.height)?; + } + + Ok(resp) +} + +/// Returns the contract's State. +/// ## Params +/// * **deps** is an object of type [`Deps`]. +pub fn query_state(deps: Deps) -> StdResult { + let state: State = STATE.load(deps.storage)?; + Ok(StateResponse { + total_incentives_share: state.total_incentives_share, + supported_pairs_list: ASSET_POOLS + .keys(deps.storage, None, None, Order::Ascending) + .collect::, StdError>>()?, + }) +} + +/// Returns the pool's State. +/// ## Params +/// * **deps** is an object of type [`Deps`]. +/// +/// * **pool_type** is an object of type [`PoolType`]. LiquidPool type - USDC or ATOM +pub fn query_pool(deps: Deps, pool_type: PoolType) -> StdResult { + let pool_info: PoolInfo = ASSET_POOLS.load(deps.storage, pool_type)?; + Ok(pool_info) +} + +/// Returns summarized details regarding the user. +/// ## Params +/// * **deps** is an object of type [`Deps`]. +/// +/// * **env** is an object of type [`Env`]. +/// +/// * **user** is an object of type [`String`]. +pub fn query_user_info(deps: Deps, env: Env, user: String) -> StdResult { + let user_address = deps.api.addr_validate(&user)?; + let user_info = USER_INFO + .may_load(deps.storage, &user_address)? + .unwrap_or_default(); + + let mut total_astro_rewards = Uint128::zero(); + let mut lockup_infos = vec![]; + let mut claimable_incentives_debt: RestrictedVector = Default::default(); + for pool_type in ASSET_POOLS + .keys(deps.storage, None, None, Order::Ascending) + .collect::, StdError>>()? + { + for duration in LOCKUP_INFO + .prefix((pool_type, &user_address)) + .keys(deps.storage, None, None, Order::Ascending) + .collect::, StdError>>()? + { + let lockup_info = query_lockup_info(deps, &env, &user, pool_type, duration)?; + total_astro_rewards = total_astro_rewards.checked_add(lockup_info.ntrn_rewards)?; + + for v in lockup_info.claimable_incentives_debt.inner_ref().iter() { + claimable_incentives_debt.update(&v.0, v.1)?; + } + lockup_infos.push(lockup_info); + } + } + + Ok(UserInfoResponse { + total_ntrn_rewards: total_astro_rewards, + ntrn_transferred: user_info.ntrn_transferred, + lockup_infos, + claimable_incentives_debt, + lockup_positions_index: user_info.lockup_positions_index, + }) +} + +/// Returns summarized details regarding the user with lockups list. +/// ## Params +/// * **deps** is an object of type [`Deps`]. +/// +/// * **_env** is an object of type [`Env`]. +/// +/// * **user** is an object of type [`String`]. +pub fn query_user_info_with_lockups_list( + deps: Deps, + _env: Env, + user: String, +) -> StdResult { + let user_address = deps.api.addr_validate(&user)?; + let user_info = USER_INFO + .may_load(deps.storage, &user_address)? + .unwrap_or_default(); + + let mut lockup_infos = vec![]; + + for pool_type in ASSET_POOLS + .keys(deps.storage, None, None, Order::Ascending) + .collect::, StdError>>()? + { + for duration in LOCKUP_INFO + .prefix((pool_type, &user_address)) + .keys(deps.storage, None, None, Order::Ascending) + .collect::, StdError>>()? + { + lockup_infos.push(LockUpInfoSummary { + pool_type, + duration, + }); + } + } + + Ok(UserInfoWithListResponse { + total_ntrn_rewards: user_info.total_ntrn_rewards, + ntrn_transferred: user_info.ntrn_transferred, + lockup_infos, + lockup_positions_index: user_info.lockup_positions_index, + }) +} + +/// Returns locked amount of LP tokens for the specified user for the specified pool at a specific height. +/// ## Params +/// * **deps** is an object of type [`Deps`]. +/// +/// * **pool_type** is an object of type [`PoolType`]. +/// +/// * **user** is an object of type [`Addr`]. +/// +/// * **height** is an object of type [`u64`]. +pub fn query_user_lockup_total_at_height( + deps: Deps, + pool: PoolType, + user: Addr, + height: u64, +) -> StdResult> { + TOTAL_USER_LOCKUP_AMOUNT.may_load_at_height(deps.storage, (pool, &user), height) +} + +/// Returns a total amount of LP tokens for the specified pool at a specific height. +/// ## Params +/// * **deps** is an object of type [`Deps`]. +/// +/// * **pool_type** is an object of type [`PoolType`]. +/// +/// * **height** is an object of type [`u64`]. +pub fn query_lockup_total_at_height( + deps: Deps, + pool: PoolType, + height: u64, +) -> StdResult> { + if let Some(pool) = ASSET_POOLS.may_load_at_height(deps.storage, pool, height)? { + return Ok(Some(pool.amount_in_lockups)); + } + Ok(Some(Uint128::zero())) +} + +/// Returns summarized details regarding the user +/// ## Params +/// * **deps** is an object of type [`Deps`]. +/// +/// * **env** is an object of type [`Env`]. +/// +/// * **user_address** is an object of type [`&str`]. +/// +/// * **pool_type** is an object of type [`PoolType`]. LiquidPool type - USDC or ATOM +/// +/// * **duration** is an object of type [`u64`]. +pub fn query_lockup_info( + deps: Deps, + env: &Env, + user_address: &str, + pool_type: PoolType, + duration: u64, +) -> StdResult { + let config = CONFIG.load(deps.storage)?; + let state = STATE.load(deps.storage)?; + + let user_address = deps.api.addr_validate(user_address)?; + + let lockup_key = (pool_type, &user_address, duration); + let mut pool_info = ASSET_POOLS.load(deps.storage, pool_type)?; + let mut lockup_info = LOCKUP_INFO.load(deps.storage, lockup_key)?; + + let lockup_astroport_lp_units_opt: Option; + let astroport_lp_token_opt: Addr; + let mut claimable_incentives_rewards_debt: RestrictedVector = + RestrictedVector::default(); + if let Some(astroport_lp_transferred) = lockup_info.astroport_lp_transferred { + lockup_astroport_lp_units_opt = Some(astroport_lp_transferred); + astroport_lp_token_opt = pool_info.lp_token; + } else { + let astroport_lp_token = pool_info.lp_token; + let pool_astroport_lp_units; + let lockup_astroport_lp_units = { + // Query Astro LP Tokens balance for the pool + pool_astroport_lp_units = if pool_info.is_staked { + raw_incentives_deposit( + deps.querier, + &config.incentives, + astroport_lp_token.as_bytes(), + env.contract.address.as_bytes(), + )? + } else { + raw_balance( + deps.querier, + &astroport_lp_token, + env.contract.address.as_bytes(), + )? + }; + // Calculate Lockup Astro LP shares + (lockup_info + .lp_units_locked + .full_mul(pool_astroport_lp_units) + .checked_div(Uint256::from(pool_info.amount_in_lockups))?) + .try_into()? + }; + lockup_astroport_lp_units_opt = Some(lockup_astroport_lp_units); + astroport_lp_token_opt = astroport_lp_token.clone(); + // If LP tokens are staked, calculate the rewards claimable by the user for this lockup position + if pool_info.is_staked && !lockup_astroport_lp_units.is_zero() { + let incentives = &config.incentives; + // QUERY :: Check if there are any pending staking rewards + let pending_rewards: Vec = deps.querier.query_wasm_smart( + incentives, + &IncentivesQueryMsg::PendingRewards { + lp_token: astroport_lp_token.to_string(), + user: env.contract.address.to_string(), + }, + )?; + + // Calculate claimable staking rewards for this lockup + for reward in pending_rewards { + let incentives_rewards_per_share = pool_info.incentives_rewards_per_share.update( + &reward.info, + Decimal::from_ratio(reward.amount, pool_astroport_lp_units), + )?; + + let debt = incentives_rewards_per_share + .checked_mul_uint128(lockup_astroport_lp_units)? + .checked_sub( + lockup_info + .incentives_debt + .inner_ref() + .iter() + .find_map(|a| if reward.info == a.0 { Some(a.1) } else { None }) + .unwrap_or_default(), + )?; + + claimable_incentives_rewards_debt.update(&reward.info, debt)?; + } + } + } + // Calculate currently expected ASTRO Rewards if not finalized + if lockup_info.ntrn_rewards == Uint128::zero() { + let weighted_lockup_balance = + calculate_weight(lockup_info.lp_units_locked, duration, &config)?; + lockup_info.ntrn_rewards = calculate_astro_incentives_for_lockup( + weighted_lockup_balance, + pool_info.weighted_amount, + pool_info.incentives_share, + state.total_incentives_share, + config.lockdrop_incentives, + )?; + } + + Ok(LockUpInfoResponse { + pool_type, + lp_units_locked: lockup_info.lp_units_locked, + withdrawal_flag: lockup_info.withdrawal_flag, + ntrn_rewards: lockup_info.ntrn_rewards, + incentives_debt: lockup_info.incentives_debt, + claimable_incentives_debt: claimable_incentives_rewards_debt, + unlock_timestamp: lockup_info.unlock_timestamp, + astroport_lp_units: lockup_astroport_lp_units_opt, + astroport_lp_token: astroport_lp_token_opt, + astroport_lp_transferred: lockup_info.astroport_lp_transferred, + duration, + }) +} + +/// Calculates ASTRO rewards for a particular Lockup position +/// ## Params +/// * **lockup_weighted_balance** is an object of type [`Uint256`]. Lockup position's weighted terraswap LP balance +/// +/// * **total_weighted_amount** is an object of type [`Uint256`]. Total weighted terraswap LP balance of the Pool +/// +/// * **pool_incentives_share** is an object of type [`u64`]. Share of total ASTRO incentives allocated to this pool +/// +/// * **total_incentives_share** is an object of type [`u64`]. Calculated total incentives share for allocating among pools +/// +/// * **total_lockdrop_incentives** is an object of type [`Uint128`]. Total ASTRO incentives to be distributed among Lockdrop participants +pub fn calculate_astro_incentives_for_lockup( + lockup_weighted_balance: Uint256, + total_weighted_amount: Uint256, + pool_incentives_share: Uint128, + total_incentives_share: Uint128, + total_lockdrop_incentives: Uint128, +) -> StdResult { + if total_incentives_share.is_zero() || total_weighted_amount.is_zero() { + Ok(Uint128::zero()) + } else { + Ok(Decimal256::from_ratio( + Uint256::from(pool_incentives_share).checked_mul(lockup_weighted_balance)?, + Uint256::from(total_incentives_share).checked_mul(total_weighted_amount)?, + ) + .checked_mul_uint256(total_lockdrop_incentives.into())?) + } +} + +/// Returns effective weight for the amount to be used for calculating lockdrop rewards. +/// ## Params +/// * **amount** is an object of type [`Uint128`]. Number of LP tokens. +/// +/// * **duration** is an object of type [`u64`]. Number of seconds. +/// +/// * **config** is an object of type [`Config`]. Config with weekly multiplier and divider. +fn calculate_weight(amount: Uint128, duration: u64, config: &Config) -> StdResult { + if let Some(info) = config + .lockup_rewards_info + .iter() + .find(|info| info.duration == duration) + { + let lock_weight = Decimal256::one() + info.coefficient; + Ok(lock_weight.checked_mul_uint256(amount.into())?.into()) + } else { + Err(StdError::generic_err("invalid duration")) + } +} + +/// Calculates ASTRO rewards for each of the user position. +/// ## Params +/// * **deps** is an object of type [`DepsMut`]. +/// +/// * **config** is an object of type [`Config`]. +/// +/// * **state** is an object of type [`State`]. +/// +/// * **user_address** is an object of type [`Addr`] +fn update_user_lockup_positions_and_calc_rewards( + deps: DepsMut, + config: &Config, + state: &State, + user_address: &Addr, +) -> StdResult { + let mut total_astro_rewards = Uint128::zero(); + + let mut keys: Vec<(PoolType, u64)> = vec![]; + + for pool_type in ASSET_POOLS + .keys(deps.storage, None, None, Order::Ascending) + .collect::, StdError>>()? + { + for duration in LOCKUP_INFO + .prefix((pool_type, user_address)) + .keys(deps.storage, None, None, Order::Ascending) + .collect::, StdError>>()? + { + keys.push((pool_type, duration)); + } + } + for (pool_type, duration) in keys { + let pool_info = ASSET_POOLS.load(deps.storage, pool_type)?; + let lockup_key = (pool_type, user_address, duration); + let mut lockup_info = LOCKUP_INFO.load(deps.storage, lockup_key)?; + + if lockup_info.ntrn_rewards == Uint128::zero() { + // Weighted lockup balance (using terraswap LP units to calculate as pool's total weighted balance is calculated on terraswap LP deposits summed over each deposit tx) + let weighted_lockup_balance = + calculate_weight(lockup_info.lp_units_locked, duration, config)?; + + // Calculate ASTRO Lockdrop rewards for the lockup position + lockup_info.ntrn_rewards = calculate_astro_incentives_for_lockup( + weighted_lockup_balance, + pool_info.weighted_amount, + pool_info.incentives_share, + state.total_incentives_share, + config.lockdrop_incentives, + )?; + + LOCKUP_INFO.save(deps.storage, lockup_key, &lockup_info)?; + }; + + let lockup_astro_rewards = lockup_info.ntrn_rewards; + + // Save updated Lockup state + total_astro_rewards = total_astro_rewards.checked_add(lockup_astro_rewards)?; + } + + Ok(total_astro_rewards) +} diff --git a/contracts/lockdrop-pcl/src/lib.rs b/contracts/lockdrop-pcl/src/lib.rs new file mode 100644 index 00000000..127e2860 --- /dev/null +++ b/contracts/lockdrop-pcl/src/lib.rs @@ -0,0 +1,3 @@ +pub mod contract; +pub mod raw_queries; +pub mod state; diff --git a/contracts/lockdrop-pcl/src/raw_queries.rs b/contracts/lockdrop-pcl/src/raw_queries.rs new file mode 100644 index 00000000..8a7cfa7a --- /dev/null +++ b/contracts/lockdrop-pcl/src/raw_queries.rs @@ -0,0 +1,53 @@ +use astroport::asset::AssetInfo; +use cosmwasm_std::{from_json, Addr, Empty, QuerierWrapper, StdError, StdResult, Uint128}; +use cw_storage_plus::Path; +use serde::Deserialize; + +/// Returns incentives deposit of tokens for the specified address +pub fn raw_incentives_deposit( + querier: QuerierWrapper, + incentives: &Addr, + lp_token: &[u8], + address: &[u8], +) -> StdResult { + #[derive(Deserialize)] + struct UserInfo { + amount: Uint128, + } + + let key: Path = Path::new(b"user_info", &[lp_token, address]); + if let Some(res) = &querier.query_wasm_raw(incentives, key.to_vec())? { + let UserInfo { amount } = from_json(res)?; + Ok(amount) + } else { + Ok(Uint128::zero()) + } +} + +/// Returns balance of tokens for the specified address +pub fn raw_balance(querier: QuerierWrapper, token: &Addr, address: &[u8]) -> StdResult { + let key: Path = Path::new(b"balance", &[address]); + if let Some(res) = &querier.query_wasm_raw(token, key.to_vec())? { + let res: Uint128 = from_json(res)?; + Ok(res) + } else { + Ok(Uint128::zero()) + } +} + +/// Returns AssetInfo for the specified proxy address from incentives storage +pub fn raw_proxy_asset( + querier: QuerierWrapper, + incentives: &Addr, + address: &[u8], +) -> StdResult { + let key: Path = Path::new(b"proxy_reward_asset", &[address]); + if let Some(res) = &querier.query_wasm_raw(incentives, key.to_vec())? { + let res: AssetInfo = from_json(res)?; + return Ok(res); + } + Err(StdError::generic_err(format!( + "Proxy asset not found: {}", + String::from_utf8(address.to_vec())? + ))) +} diff --git a/contracts/lockdrop-pcl/src/state.rs b/contracts/lockdrop-pcl/src/state.rs new file mode 100644 index 00000000..2abdc0c2 --- /dev/null +++ b/contracts/lockdrop-pcl/src/state.rs @@ -0,0 +1,29 @@ +use astroport::common::OwnershipProposal; +use astroport_periphery::lockdrop_pcl::{Config, LockupInfo, PoolInfo, PoolType, State, UserInfo}; +use astroport_periphery::U64Key; +use cosmwasm_std::{Addr, Uint128}; +use cw_storage_plus::{Item, Map, SnapshotMap, Strategy}; + +pub const CONFIG: Item = Item::new("config"); +pub const STATE: Item = Item::new("state"); + +/// Key is an Terraswap LP token address +pub const ASSET_POOLS: SnapshotMap = SnapshotMap::new( + "LiquidityPools", + "LiquitidyPools_checkpoints", + "LiquidityPools_changelog", + Strategy::EveryBlock, +); +/// Key is an user address +pub const USER_INFO: Map<&Addr, UserInfo> = Map::new("users"); +/// Key consists of an Terraswap LP token address, an user address, and a duration +pub const LOCKUP_INFO: Map<(PoolType, &Addr, U64Key), LockupInfo> = Map::new("lockup_position"); + +pub const TOTAL_USER_LOCKUP_AMOUNT: SnapshotMap<(PoolType, &Addr), Uint128> = SnapshotMap::new( + "total_user_lockup_info", + "total_user_lockup_info_checkpoints", + "total_lockup_info_changelog", + Strategy::EveryBlock, +); + +pub const OWNERSHIP_PROPOSAL: Item = Item::new("ownership_proposal"); diff --git a/contracts/lockdrop/Cargo.toml b/contracts/lockdrop/Cargo.toml index d3167f93..ff26a052 100644 --- a/contracts/lockdrop/Cargo.toml +++ b/contracts/lockdrop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "neutron-lockdrop" -version = "1.2.1" +version = "1.3.0" authors = ["_astromartian"] edition = "2021" @@ -26,7 +26,7 @@ library = [] [dependencies] # we have to keep it 0.15.1 because it is the same version as in astroport cw-storage-plus = { version = "0.15.1" } -astroport = { git = "https://github.com/astroport-fi/astroport-core.git", tag = "v2.5.0" } +astroport = { git = "https://github.com/astroport-fi/astroport-core.git", tag = "v3.11.0" } credits = { path = "../credits" } astroport-periphery = { workspace = true } cosmwasm-std = { workspace = true } diff --git a/contracts/lockdrop/README.md b/contracts/lockdrop/README.md index 0bc572b1..ae990b11 100644 --- a/contracts/lockdrop/README.md +++ b/contracts/lockdrop/README.md @@ -10,24 +10,24 @@ Note - Users can open muliple lockup positions with different lockup duration fo ### Handle Messages -| Message | Description | -|-----------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `ExecuteMsg::UpdateConfig` | Can only be called by the admin. Facilitates updating configuration parameters | -| `ExecuteMsg::EnableClaims` | Executed by the Bootstrap auction contract when liquidity is added to the ASTRO-UST pool. Enables ASTRO withdrawals by the lockdrop recipients. | -| `ExecuteMsg::InitializePool` | Admin function. Facilitates addition of new Pool (Terraswap Pools) whose LP tokens can then be locked in the lockdrop contract | -| `ExecuteMsg::UpdatePool` | Admin function to update any configuraton parameter for a terraswap pool whose LP tokens are currently accepted for the lockdrop | -| `ExecuteMsg::IncreaseLockup` | Facilitates opening a new user position or adding to an existing position | -| `ExecuteMsg::IncreaseAstroIncentives` | Admin function to increase the ASTRO incentives that are to be distributed | +| Message | Description | +|-----------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `ExecuteMsg::UpdateConfig` | Can only be called by the admin. Facilitates updating configuration parameters | +| `ExecuteMsg::EnableClaims` | Executed by the Bootstrap auction contract when liquidity is added to the ASTRO-UST pool. Enables ASTRO withdrawals by the lockdrop recipients. | +| `ExecuteMsg::InitializePool` | Admin function. Facilitates addition of new Pool (Terraswap Pools) whose LP tokens can then be locked in the lockdrop contract | +| `ExecuteMsg::UpdatePool` | Admin function to update any configuraton parameter for a terraswap pool whose LP tokens are currently accepted for the lockdrop | +| `ExecuteMsg::IncreaseLockup` | Facilitates opening a new user position or adding to an existing position | +| `ExecuteMsg::IncreaseAstroIncentives` | Admin function to increase the ASTRO incentives that are to be distributed | | `ExecuteMsg::WithdrawFromLockup` | Facilitates LP token withdrawals from lockup positions by users. 100% amount can be withdrawn during deposit window, which is then limited to 50% during 1st half of deposit window which then decreases linearly during 2nd half of deposit window. Only 1 withdrawal can be made by a user during the withdrawal windows | -| `ExecuteMsg::MigrateLiquidity` | Admin function. Facilitates migration of liquidity (locked terraswap LP tokens) from Terraswap to Astroport (Astroport LP tokens) | -| `ExecuteMsg::StakeLpTokens` | Admin function. Facilitates staking of Astroport LP tokens for a particular LP pool with the generator contract | -| `ExecuteMsg::DelegateAstroToAuction` | This function facilitates ASTRO tokens delegation to the Bootstrap auction contract during the bootstrap auction phase. Delegated ASTRO tokens are added to the user's position in the bootstrap auction contract | -| `ExecuteMsg::ClaimRewardsAndOptionallyUnlock` | Facilitates rewards claim by users for a particular lockup position along with unlock when possible | -| `ExecuteMsg::ClaimAssetReward` | Collects assets reward from LP and distribute reward to user if all requirements are met | -| `ExecuteMsg::TogglePoolRewards` | Admin function. Enables assets reward for specified LP | -| `ExecuteMsg::ProposeNewOwner` | Admin function. Creates an offer to change the contract ownership. The validity period of the offer is set in the `expires_in` variable. After `expires_in` seconds pass, the proposal expires and cannot be accepted anymore. | -| `ExecuteMsg::DropOwnershipProposal` | Admin function. Removes an existing offer to change the contract owner. | -| `ExecuteMsg::ClaimOwnership` | Admin function. Used to claim contract ownership. | +| `ExecuteMsg::MigrateLiquidity` | Admin function. Facilitates migration of liquidity (locked terraswap LP tokens) from Terraswap to Astroport (Astroport LP tokens) | +| `ExecuteMsg::StakeLpTokens` | Admin function. Facilitates staking of Astroport LP tokens for a particular LP pool with the generator contract | +| `ExecuteMsg::DelegateAstroToAuction` | This function facilitates ASTRO tokens delegation to the Bootstrap auction contract during the bootstrap auction phase. Delegated ASTRO tokens are added to the user's position in the bootstrap auction contract | +| `ExecuteMsg::ClaimRewardsAndOptionallyUnlock` | Facilitates rewards claim by users for a particular lockup position along with unlock when possible | +| `ExecuteMsg::ClaimAssetReward` | Collects assets reward from LP and distribute reward to user if all requirements are met | +| `ExecuteMsg::TogglePoolRewards` | Admin function. Enables assets reward for specified LP | +| `ExecuteMsg::ProposeNewOwner` | Admin function. Creates an offer to change the contract ownership. The validity period of the offer is set in the `expires_in` variable. After `expires_in` seconds pass, the proposal expires and cannot be accepted anymore. | +| `ExecuteMsg::DropOwnershipProposal` | Admin function. Removes an existing offer to change the contract owner. | +| `ExecuteMsg::ClaimOwnership` | Admin function. Used to claim contract ownership. | ### Handle Messages :: Callback diff --git a/contracts/lockdrop/schema/neutron-lockdrop.json b/contracts/lockdrop/schema/neutron-lockdrop.json index cf59d5f9..09c431a1 100644 --- a/contracts/lockdrop/schema/neutron-lockdrop.json +++ b/contracts/lockdrop/schema/neutron-lockdrop.json @@ -347,6 +347,28 @@ } }, "additionalProperties": false + }, + { + "description": "Migrates user's locked liquidity from XYK pools to PCL ones, transferring lockdrop participation rewards to the address which liquidity has been migrated.", + "type": "object", + "required": [ + "migrate_liquidity_to_pcl_pools" + ], + "properties": { + "migrate_liquidity_to_pcl_pools": { + "type": "object", + "properties": { + "user_address_raw": { + "description": "The address which liquidity is supposed to be transferred. If no user address is provided, the message sender's address is used.", + "type": [ + "string", + "null" + ] + } + } + } + }, + "additionalProperties": false } ], "definitions": { @@ -437,6 +459,7 @@ "CallbackMsg": { "oneOf": [ { + "description": "Updates contract state after dual staking rewards are claimed from the generator contract.", "type": "object", "required": [ "update_pool_on_dual_rewards_claim" @@ -468,6 +491,7 @@ "additionalProperties": false }, { + "description": "Withdraws user rewards and LP Tokens after claims / unlocks.", "type": "object", "required": [ "withdraw_user_lockup_rewards_callback" @@ -500,6 +524,224 @@ } }, "additionalProperties": false + }, + { + "description": "Entry point for a single lockup position migration to PCL lockdrop contract. Performs generator rewards claiming and initializes liquidity withdrawal+transfer process by invocation of the respective callback message.", + "type": "object", + "required": [ + "init_migrate_lockup_to_pcl_pools_callback" + ], + "properties": { + "init_migrate_lockup_to_pcl_pools_callback": { + "type": "object", + "required": [ + "duration", + "pool_type", + "user_address" + ], + "properties": { + "duration": { + "description": "The duration of the lock period.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "description": "The type of the pool the lockup is related to.", + "allOf": [ + { + "$ref": "#/definitions/PoolType" + } + ] + }, + "user_address": { + "description": "The address of the user which owns the lockup.", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + } + } + } + }, + "additionalProperties": false + }, + { + "description": "The second step in the lockup's XYK -> PCL liquidity migration process. Claims all possible rewards that the user is eligible of and transfers them to the user.", + "type": "object", + "required": [ + "transfer_all_rewards_before_migration_callback" + ], + "properties": { + "transfer_all_rewards_before_migration_callback": { + "type": "object", + "required": [ + "duration", + "pool_type", + "user_address" + ], + "properties": { + "duration": { + "description": "The duration of the lock period.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "description": "The type of the pool the lockup is related to.", + "allOf": [ + { + "$ref": "#/definitions/PoolType" + } + ] + }, + "user_address": { + "description": "The address of the user which owns the lockup.", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + } + } + } + }, + "additionalProperties": false + }, + { + "description": "The third step in the lockup's XYK -> PCL liquidity migration process. Handles withdrawal of staked liquidity from the generator contract and liquidity transfer to the PCL lockdrop contract.", + "type": "object", + "required": [ + "withdraw_user_lockup_callback" + ], + "properties": { + "withdraw_user_lockup_callback": { + "type": "object", + "required": [ + "astroport_lp_amount", + "astroport_lp_token", + "duration", + "generator", + "pool_type", + "user_address" + ], + "properties": { + "astroport_lp_amount": { + "description": "The amount of LP token to be unstaked and withdrawn.", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "astroport_lp_token": { + "description": "The address of the pool's liquidity token.", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "duration": { + "description": "The duration of the lock period.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "generator": { + "description": "The address of the generator which possesses the staked liquidity.", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "pool_type": { + "description": "The type of the pool the lockup is related to.", + "allOf": [ + { + "$ref": "#/definitions/PoolType" + } + ] + }, + "user_address": { + "description": "The address of the user which owns the lockup.", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + } + } + } + }, + "additionalProperties": false + }, + { + "description": "The fourth step in the lockup's XYK -> PCL liquidity migration process. Invokes the PCL lockdrop contract's MigrateXYKLiquidity handler which creates an LP position in the PCL pool and a lockup in the PCL lockdrop contract in accordance with the withdrawn user's lockup position.", + "type": "object", + "required": [ + "migrate_user_lockup_to_pcl_pair_callback" + ], + "properties": { + "migrate_user_lockup_to_pcl_pair_callback": { + "type": "object", + "required": [ + "duration", + "ntrn_balance", + "paired_asset_balance", + "paired_asset_denom", + "pool_type", + "user_address" + ], + "properties": { + "duration": { + "description": "The duration of the lock period.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "ntrn_balance": { + "description": "The balance in untrn of the XYK lockdrop contract at the third migration step. Is used in the callback to calculate the amount of untrn been withdrawn from the XYK pool.", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "paired_asset_balance": { + "description": "The balance in the paired denom of the XYK lockdrop contract at the third migration step. Is used in the callback to calculate the amount of the paired asset been withdrawn from the XYK pool.", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "paired_asset_denom": { + "description": "The denom of the paired asset (the asset paired with untrn in the pool).", + "type": "string" + }, + "pool_type": { + "description": "The type of the pool the lockup is related to.", + "allOf": [ + { + "$ref": "#/definitions/PoolType" + } + ] + }, + "user_address": { + "description": "The address of the user which owns the lockup.", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + } + } + } + }, + "additionalProperties": false } ] }, @@ -752,7 +994,16 @@ "migrate": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "MigrateMsg", - "type": "object" + "type": "object", + "required": [ + "pcl_lockdrop_contract" + ], + "properties": { + "pcl_lockdrop_contract": { + "description": "The address of the lockdrop contract working with PCL pools. Used to transfer the lockdrop's liquidity locked in XYK pools to more efficient pools.", + "type": "string" + } + } }, "sudo": null, "responses": { diff --git a/contracts/lockdrop/schema/raw/execute.json b/contracts/lockdrop/schema/raw/execute.json index 97932b6d..b0e991e6 100644 --- a/contracts/lockdrop/schema/raw/execute.json +++ b/contracts/lockdrop/schema/raw/execute.json @@ -239,6 +239,28 @@ } }, "additionalProperties": false + }, + { + "description": "Migrates user's locked liquidity from XYK pools to PCL ones, transferring lockdrop participation rewards to the address which liquidity has been migrated.", + "type": "object", + "required": [ + "migrate_liquidity_to_pcl_pools" + ], + "properties": { + "migrate_liquidity_to_pcl_pools": { + "type": "object", + "properties": { + "user_address_raw": { + "description": "The address which liquidity is supposed to be transferred. If no user address is provided, the message sender's address is used.", + "type": [ + "string", + "null" + ] + } + } + } + }, + "additionalProperties": false } ], "definitions": { @@ -329,6 +351,7 @@ "CallbackMsg": { "oneOf": [ { + "description": "Updates contract state after dual staking rewards are claimed from the generator contract.", "type": "object", "required": [ "update_pool_on_dual_rewards_claim" @@ -360,6 +383,7 @@ "additionalProperties": false }, { + "description": "Withdraws user rewards and LP Tokens after claims / unlocks.", "type": "object", "required": [ "withdraw_user_lockup_rewards_callback" @@ -392,6 +416,224 @@ } }, "additionalProperties": false + }, + { + "description": "Entry point for a single lockup position migration to PCL lockdrop contract. Performs generator rewards claiming and initializes liquidity withdrawal+transfer process by invocation of the respective callback message.", + "type": "object", + "required": [ + "init_migrate_lockup_to_pcl_pools_callback" + ], + "properties": { + "init_migrate_lockup_to_pcl_pools_callback": { + "type": "object", + "required": [ + "duration", + "pool_type", + "user_address" + ], + "properties": { + "duration": { + "description": "The duration of the lock period.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "description": "The type of the pool the lockup is related to.", + "allOf": [ + { + "$ref": "#/definitions/PoolType" + } + ] + }, + "user_address": { + "description": "The address of the user which owns the lockup.", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + } + } + } + }, + "additionalProperties": false + }, + { + "description": "The second step in the lockup's XYK -> PCL liquidity migration process. Claims all possible rewards that the user is eligible of and transfers them to the user.", + "type": "object", + "required": [ + "transfer_all_rewards_before_migration_callback" + ], + "properties": { + "transfer_all_rewards_before_migration_callback": { + "type": "object", + "required": [ + "duration", + "pool_type", + "user_address" + ], + "properties": { + "duration": { + "description": "The duration of the lock period.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "description": "The type of the pool the lockup is related to.", + "allOf": [ + { + "$ref": "#/definitions/PoolType" + } + ] + }, + "user_address": { + "description": "The address of the user which owns the lockup.", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + } + } + } + }, + "additionalProperties": false + }, + { + "description": "The third step in the lockup's XYK -> PCL liquidity migration process. Handles withdrawal of staked liquidity from the generator contract and liquidity transfer to the PCL lockdrop contract.", + "type": "object", + "required": [ + "withdraw_user_lockup_callback" + ], + "properties": { + "withdraw_user_lockup_callback": { + "type": "object", + "required": [ + "astroport_lp_amount", + "astroport_lp_token", + "duration", + "generator", + "pool_type", + "user_address" + ], + "properties": { + "astroport_lp_amount": { + "description": "The amount of LP token to be unstaked and withdrawn.", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "astroport_lp_token": { + "description": "The address of the pool's liquidity token.", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "duration": { + "description": "The duration of the lock period.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "generator": { + "description": "The address of the generator which possesses the staked liquidity.", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "pool_type": { + "description": "The type of the pool the lockup is related to.", + "allOf": [ + { + "$ref": "#/definitions/PoolType" + } + ] + }, + "user_address": { + "description": "The address of the user which owns the lockup.", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + } + } + } + }, + "additionalProperties": false + }, + { + "description": "The fourth step in the lockup's XYK -> PCL liquidity migration process. Invokes the PCL lockdrop contract's MigrateXYKLiquidity handler which creates an LP position in the PCL pool and a lockup in the PCL lockdrop contract in accordance with the withdrawn user's lockup position.", + "type": "object", + "required": [ + "migrate_user_lockup_to_pcl_pair_callback" + ], + "properties": { + "migrate_user_lockup_to_pcl_pair_callback": { + "type": "object", + "required": [ + "duration", + "ntrn_balance", + "paired_asset_balance", + "paired_asset_denom", + "pool_type", + "user_address" + ], + "properties": { + "duration": { + "description": "The duration of the lock period.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "ntrn_balance": { + "description": "The balance in untrn of the XYK lockdrop contract at the third migration step. Is used in the callback to calculate the amount of untrn been withdrawn from the XYK pool.", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "paired_asset_balance": { + "description": "The balance in the paired denom of the XYK lockdrop contract at the third migration step. Is used in the callback to calculate the amount of the paired asset been withdrawn from the XYK pool.", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "paired_asset_denom": { + "description": "The denom of the paired asset (the asset paired with untrn in the pool).", + "type": "string" + }, + "pool_type": { + "description": "The type of the pool the lockup is related to.", + "allOf": [ + { + "$ref": "#/definitions/PoolType" + } + ] + }, + "user_address": { + "description": "The address of the user which owns the lockup.", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + } + } + } + }, + "additionalProperties": false } ] }, diff --git a/contracts/lockdrop/schema/raw/migrate.json b/contracts/lockdrop/schema/raw/migrate.json index 87b18ea7..1efd732d 100644 --- a/contracts/lockdrop/schema/raw/migrate.json +++ b/contracts/lockdrop/schema/raw/migrate.json @@ -1,5 +1,14 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "title": "MigrateMsg", - "type": "object" + "type": "object", + "required": [ + "pcl_lockdrop_contract" + ], + "properties": { + "pcl_lockdrop_contract": { + "description": "The address of the lockdrop contract working with PCL pools. Used to transfer the lockdrop's liquidity locked in XYK pools to more efficient pools.", + "type": "string" + } + } } diff --git a/contracts/lockdrop/src/contract.rs b/contracts/lockdrop/src/contract.rs index 50aee229..207b96cb 100644 --- a/contracts/lockdrop/src/contract.rs +++ b/contracts/lockdrop/src/contract.rs @@ -1,5 +1,6 @@ use std::cmp::min; use std::convert::TryInto; +use std::ops::Sub; use std::str::FromStr; use astroport::asset::{Asset, AssetInfo}; @@ -10,25 +11,26 @@ use astroport::generator::{ }; use astroport::restricted_vector::RestrictedVector; use astroport::DecimalCheckedOps; -use astroport_periphery::utils::Decimal256CheckedOps; use cosmwasm_std::{ - attr, coins, entry_point, from_binary, to_binary, Addr, BankMsg, Binary, Coin, CosmosMsg, + attr, coins, entry_point, from_json, to_json_binary, Addr, BankMsg, Binary, Coin, CosmosMsg, Decimal, Decimal256, Deps, DepsMut, Env, MessageInfo, Order, Response, StdError, StdResult, Uint128, Uint256, WasmMsg, }; use cw2::set_contract_version; -use cw20::{BalanceResponse, Cw20ExecuteMsg, Cw20QueryMsg, Cw20ReceiveMsg}; +use cw20::{BalanceResponse, Cw20ExecuteMsg, Cw20QueryMsg, Cw20ReceiveMsg, MinterResponse}; -use crate::raw_queries::{raw_balance, raw_generator_deposit}; use astroport_periphery::lockdrop::{ CallbackMsg, Config, Cw20HookMsg, ExecuteMsg, InstantiateMsg, LockUpInfoResponse, LockUpInfoSummary, LockupInfoV2, MigrateMsg, PoolInfo, PoolType, QueryMsg, State, StateResponse, UpdateConfigMsg, UserInfoResponse, UserInfoWithListResponse, }; +use astroport_periphery::lockdrop_pcl::ExecuteMsg as LockdropPCLExecuteMsg; +use astroport_periphery::utils::Decimal256CheckedOps; +use crate::raw_queries::{raw_balance, raw_generator_deposit}; use crate::state::{ - CompatibleLoader, ASSET_POOLS, CONFIG, LOCKUP_INFO, OWNERSHIP_PROPOSAL, STATE, - TOTAL_USER_LOCKUP_AMOUNT, USER_INFO, + CompatibleLoader, ASSET_POOLS, CONFIG, LOCKUP_INFO, OWNERSHIP_PROPOSAL, PCL_LOCKDROP_CONTRACT, + STATE, TOTAL_USER_LOCKUP_AMOUNT, USER_INFO, }; const AIRDROP_REWARDS_MULTIPLIER: &str = "1.0"; @@ -212,6 +214,9 @@ pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> S atom_token, generator, } => handle_set_token_info(deps, env, info, usdc_token, atom_token, generator), + ExecuteMsg::MigrateLiquidityToPCLPools { user_address_raw } => { + handle_migrate_liquidity_to_pcl_pools(deps, info, env, user_address_raw) + } } } @@ -240,7 +245,7 @@ pub fn receive_cw20( )); } - match from_binary(&cw20_msg.msg)? { + match from_json(&cw20_msg.msg)? { Cw20HookMsg::InitializePool { pool_type, incentives_share, @@ -303,6 +308,58 @@ fn _handle_callback( duration, withdraw_lp_stake, ), + CallbackMsg::InitMigrateLockupToPCLPoolsCallback { + pool_type, + user_address, + duration, + } => { + callback_init_migrate_lockup_to_pcl_pools(deps, env, pool_type, user_address, duration) + } + CallbackMsg::TransferAllRewardsBeforeMigrationCallback { + pool_type, + user_address, + duration, + } => callback_transfer_all_rewards_before_migration( + deps, + env, + pool_type, + user_address, + duration, + ), + CallbackMsg::WithdrawUserLockupCallback { + pool_type, + user_address, + duration, + generator, + astroport_lp_token, + astroport_lp_amount, + } => callback_withdraw_user_lockup( + deps, + env, + pool_type, + user_address, + duration, + generator, + astroport_lp_token, + astroport_lp_amount, + ), + CallbackMsg::MigrateUserLockupToPCLPairCallback { + pool_type, + user_address, + duration, + ntrn_balance, + paired_asset_denom, + paired_asset_balance, + } => callback_migrate_user_lockup_to_pcl_pair( + deps, + env, + pool_type, + user_address, + duration, + ntrn_balance, + paired_asset_denom, + paired_asset_balance, + ), } } @@ -350,18 +407,18 @@ fn _handle_callback( #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { match msg { - QueryMsg::Config {} => to_binary(&CONFIG.load(deps.storage)?), - QueryMsg::State {} => to_binary(&query_state(deps)?), - QueryMsg::Pool { pool_type } => to_binary(&query_pool(deps, pool_type)?), - QueryMsg::UserInfo { address } => to_binary(&query_user_info(deps, env, address)?), + QueryMsg::Config {} => to_json_binary(&CONFIG.load(deps.storage)?), + QueryMsg::State {} => to_json_binary(&query_state(deps)?), + QueryMsg::Pool { pool_type } => to_json_binary(&query_pool(deps, pool_type)?), + QueryMsg::UserInfo { address } => to_json_binary(&query_user_info(deps, env, address)?), QueryMsg::UserInfoWithLockupsList { address } => { - to_binary(&query_user_info_with_lockups_list(deps, env, address)?) + to_json_binary(&query_user_info_with_lockups_list(deps, env, address)?) } QueryMsg::LockUpInfo { user_address, pool_type, duration, - } => to_binary(&query_lockup_info( + } => to_json_binary(&query_lockup_info( deps, &env, &user_address, @@ -372,14 +429,14 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { pool_type, user_address, height, - } => to_binary(&query_user_lockup_total_at_height( + } => to_json_binary(&query_user_lockup_total_at_height( deps, pool_type, deps.api.addr_validate(&user_address)?, height, )?), QueryMsg::QueryLockupTotalAtHeight { pool_type, height } => { - to_binary(&query_lockup_total_at_height(deps, pool_type, height)?) + to_json_binary(&query_lockup_total_at_height(deps, pool_type, height)?) } } } @@ -392,7 +449,13 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { /// /// * **_msg** is an object of type [`MigrateMsg`]. #[cfg_attr(not(feature = "library"), entry_point)] -pub fn migrate(_deps: DepsMut, _env: Env, _msg: MigrateMsg) -> StdResult { +pub fn migrate(deps: DepsMut, _env: Env, msg: MigrateMsg) -> StdResult { + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + + PCL_LOCKDROP_CONTRACT.save( + deps.storage, + &deps.api.addr_validate(&msg.pcl_lockdrop_contract)?, + )?; Ok(Response::default()) } @@ -446,6 +509,178 @@ pub fn handle_update_config( Ok(Response::new().add_attributes(attributes)) } +/// Liquidity migration entry point. Starts the locked liquidity migration from this lockdrop contract +/// which stores the liquidity in XYK pools to another lockdrop contract which works with PCL pools. +/// A single call to this handler migrates all lockup positions of a single user. If user is not +/// specified, the caller's address is used to determine the lockup positions to migrate. +/// +/// Liquidity migration process consists of several sequential messages invocation and from this +/// contract's point of view it mostly mimics (and clones code of) the **ClaimRewardsAndOptionallyUnlock** +/// called with **withdraw_lp_stake=true** for each lockup position. So, for this contract's state, +/// liquidity migration looks like lockup positions unlock by the user. +pub fn handle_migrate_liquidity_to_pcl_pools( + mut deps: DepsMut, + info: MessageInfo, + env: Env, + user_address_raw: Option, +) -> StdResult { + let user_address = match user_address_raw { + Some(addr) => deps.api.addr_validate(&addr)?, + None => info.sender, + }; + + let config = CONFIG.load(deps.storage)?; + let state = STATE.load(deps.storage)?; + + let mut user_info = USER_INFO.load(deps.storage, &user_address)?; + // If user's total NTRN rewards == 0 :: We update all of the user's lockup positions to + // calculate NTRN rewards and for each alongwith their equivalent Astroport LP Shares + if user_info.total_ntrn_rewards == Uint128::zero() { + user_info.total_ntrn_rewards = update_user_lockup_positions_and_calc_rewards( + deps.branch(), + &config, + &state, + &user_address, + )?; + USER_INFO.save(deps.storage, &user_address, &user_info)?; + } + + // collect all user's lockups + let mut user_lockups: Vec<(PoolType, u64)> = vec![]; + for pool_type in ASSET_POOLS + .keys(deps.storage, None, None, Order::Ascending) + .collect::, StdError>>()? + { + for duration in LOCKUP_INFO + .prefix((pool_type, &user_address)) + .keys(deps.storage, None, None, Order::Ascending) + .collect::, StdError>>()? + { + user_lockups.push((pool_type, duration)); + } + } + + let mut cosmos_msgs = vec![]; + // migrate all user lockups sequentially + for (pool_type, duration) in user_lockups { + cosmos_msgs.push( + CallbackMsg::InitMigrateLockupToPCLPoolsCallback { + pool_type, + user_address: user_address.clone(), + duration, + } + .to_cosmos_msg(&env)?, + ); + } + Ok(Response::default().add_messages(cosmos_msgs)) +} + +/// Entry point for a single lockup position migration to PCL lockdrop contract. Performs generator +/// rewards claiming and initializes liquidity withdrawal+transfer process by invocation of the +/// respective callback message. +fn callback_init_migrate_lockup_to_pcl_pools( + deps: DepsMut, + env: Env, + pool_type: PoolType, + user_address: Addr, + duration: u64, +) -> Result { + let lockup_info = query_lockup_info( + deps.as_ref(), + &env, + user_address.as_str(), + pool_type, + duration, + )?; + + if lockup_info.astroport_lp_transferred.is_some() { + return Ok(Response::default().add_attribute( + format!("{:?}_for_{}", pool_type, duration), + "already_been_withdrawn", + )); + } + + let config = CONFIG.load(deps.storage)?; + let pool_info = ASSET_POOLS.load(deps.storage, pool_type)?; + let astroport_lp_token = pool_info.lp_token; + let generator = config + .generator + .as_ref() + .ok_or_else(|| StdError::generic_err("Generator should be set at this moment!"))?; + + // QUERY :: Check if there are any pending staking rewards + let pending_rewards: PendingTokenResponse = deps.querier.query_wasm_smart( + generator, + &GenQueryMsg::PendingToken { + lp_token: astroport_lp_token.to_string(), + user: env.contract.address.to_string(), + }, + )?; + let pending_on_proxy = &pending_rewards.pending_on_proxy.unwrap_or_default(); + let mut cosmos_msgs = vec![]; + if !pending_rewards.pending.is_zero() + || pending_on_proxy.iter().any(|asset| !asset.amount.is_zero()) + { + let rwi: RewardInfoResponse = deps.querier.query_wasm_smart( + generator, + &GenQueryMsg::RewardInfo { + lp_token: astroport_lp_token.to_string(), + }, + )?; + + let reward_token_balance = deps + .querier + .query_balance( + env.contract.address.clone(), + rwi.base_reward_token.to_string(), + )? + .amount; + + let prev_proxy_reward_balances: Vec = pending_on_proxy + .iter() + .map(|asset| { + let balance = asset + .info + .query_pool(&deps.querier, env.contract.address.clone()) + .unwrap_or_default(); + + Asset { + info: asset.info.clone(), + amount: balance, + } + }) + .collect(); + + cosmos_msgs.push(CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: generator.to_string(), + funds: vec![], + msg: to_json_binary(&GenExecuteMsg::ClaimRewards { + lp_tokens: vec![astroport_lp_token.to_string()], + })?, + })); + + cosmos_msgs.push( + CallbackMsg::UpdatePoolOnDualRewardsClaim { + pool_type, + prev_ntrn_balance: reward_token_balance, + prev_proxy_reward_balances, + } + .to_cosmos_msg(&env)?, + ); + } + + cosmos_msgs.push( + CallbackMsg::TransferAllRewardsBeforeMigrationCallback { + pool_type, + user_address, + duration, + } + .to_cosmos_msg(&env)?, + ); + + Ok(Response::default().add_messages(cosmos_msgs)) +} + pub fn handle_set_token_info( deps: DepsMut, env: Env, @@ -619,7 +854,7 @@ fn stake_messages( cosmos_msgs.push(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: lp_token_address.to_string(), funds: vec![], - msg: to_binary(&Cw20ExecuteMsg::IncreaseAllowance { + msg: to_json_binary(&Cw20ExecuteMsg::IncreaseAllowance { spender: generator.to_string(), amount, expires: Some(cw20::Expiration::AtHeight(height)), @@ -629,9 +864,9 @@ fn stake_messages( cosmos_msgs.push(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: lp_token_address.to_string(), funds: vec![], - msg: to_binary(&Cw20ExecuteMsg::Send { + msg: to_json_binary(&Cw20ExecuteMsg::Send { contract: generator.to_string(), - msg: to_binary(&astroport::generator::Cw20HookMsg::Deposit {})?, + msg: to_json_binary(&astroport::generator::Cw20HookMsg::Deposit {})?, amount, })?, })); @@ -955,9 +1190,7 @@ pub fn handle_claim_rewards_and_unlock_for_lockup( // CHECK ::: Is LP Token Pool supported or not ? let pool_info = ASSET_POOLS.load(deps.storage, pool_type)?; - let mut user_info = USER_INFO - .may_load(deps.storage, &user_address)? - .unwrap_or_default(); + let mut user_info = USER_INFO.load(deps.storage, &user_address)?; // If user's total NTRN rewards == 0 :: We update all of the user's lockup positions to calculate NTRN rewards and for each alongwith their equivalent Astroport LP Shares if user_info.total_ntrn_rewards == Uint128::zero() { @@ -1046,7 +1279,7 @@ pub fn handle_claim_rewards_and_unlock_for_lockup( cosmos_msgs.push(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: generator.to_string(), funds: vec![], - msg: to_binary(&GenExecuteMsg::ClaimRewards { + msg: to_json_binary(&GenExecuteMsg::ClaimRewards { lp_tokens: vec![astroport_lp_token.to_string()], })?, })); @@ -1123,7 +1356,7 @@ pub fn claim_airdrop_tokens_with_multiplier_msg( Ok(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: credits_contract.to_string(), - msg: to_binary(&Cw20ExecuteMsg::BurnFrom { + msg: to_json_binary(&Cw20ExecuteMsg::BurnFrom { owner: user_addr.to_string(), amount: claimable_vested_amount.checked_add(unvested_tokens_amount.amount)?, })?, @@ -1355,7 +1588,7 @@ pub fn callback_withdraw_user_rewards_for_lockup_optional_withdraw( // If claimable proxy staking rewards > 0, claim them for pending_proxy_reward in pending_proxy_rewards { - cosmos_msgs.push(pending_proxy_reward.into_msg(&deps.querier, user_address.clone())?); + cosmos_msgs.push(pending_proxy_reward.into_msg(user_address.clone())?); } // COSMOSMSG :: If LP Tokens are staked, we unstake the amount which needs to be returned to the user @@ -1363,7 +1596,7 @@ pub fn callback_withdraw_user_rewards_for_lockup_optional_withdraw( cosmos_msgs.push(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: generator.to_string(), funds: vec![], - msg: to_binary(&GenExecuteMsg::Withdraw { + msg: to_json_binary(&GenExecuteMsg::Withdraw { lp_token: astroport_lp_token.to_string(), amount: astroport_lp_amount, })?, @@ -1375,7 +1608,7 @@ pub fn callback_withdraw_user_rewards_for_lockup_optional_withdraw( // COSMOSMSG :: Returns LP units locked by the user in the current lockup position cosmos_msgs.push(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: astroport_lp_token.to_string(), - msg: to_binary(&Cw20ExecuteMsg::Transfer { + msg: to_json_binary(&Cw20ExecuteMsg::Transfer { recipient: user_address.to_string(), amount: astroport_lp_amount, })?, @@ -1443,6 +1676,354 @@ pub fn callback_withdraw_user_rewards_for_lockup_optional_withdraw( .add_attributes(attributes)) } +/// Claims all possible rewards for the user. The claimed user's rewards are generator staking +/// rewards and proxy rewards, one time NTRN rewards and rewards for airdrop participants. This +/// makes sure the XYK lockdrop contract has no obligations once the liquidity is migrated, and +/// the only obligations the PCL lockdrop contract will have are the minted LP tokens and further +/// generator staking rewards and proxy rewards associated with the LP tokens. +pub fn callback_transfer_all_rewards_before_migration( + deps: DepsMut, + env: Env, + pool_type: PoolType, + user_address: Addr, + duration: u64, +) -> StdResult { + let config = CONFIG.load(deps.storage)?; + let pool_info = ASSET_POOLS.load(deps.storage, pool_type)?; + let lockup_key = (pool_type, &user_address, duration); + let mut lockup_info = + LOCKUP_INFO.compatible_load(deps.as_ref(), lockup_key, &config.generator)?; + + let mut user_info = USER_INFO + .may_load(deps.storage, &user_address)? + .unwrap_or_default(); + + let mut cosmos_msgs = vec![]; + + let astroport_lp_token = pool_info.lp_token.clone(); + + let generator = config + .generator + .as_ref() + .ok_or_else(|| StdError::generic_err("Generator should be set"))?; + + // Calculate Astro LP share for the lockup position + let astroport_lp_amount: Uint128 = { + let balance: Uint128 = if pool_info.is_staked { + deps.querier.query_wasm_smart( + generator, + &GenQueryMsg::Deposit { + lp_token: astroport_lp_token.to_string(), + user: env.contract.address.to_string(), + }, + )? + } else { + let res: BalanceResponse = deps.querier.query_wasm_smart( + astroport_lp_token.clone(), + &Cw20QueryMsg::Balance { + address: env.contract.address.to_string(), + }, + )?; + res.balance + }; + + (lockup_info + .lp_units_locked + .full_mul(balance) + .checked_div(Uint256::from(pool_info.amount_in_lockups))?) + .try_into()? + }; + + let rwi: RewardInfoResponse = deps.querier.query_wasm_smart( + generator, + &GenQueryMsg::RewardInfo { + lp_token: astroport_lp_token.to_string(), + }, + )?; + + // Calculate claimable staking rewards for this lockup + let total_lockup_astro_rewards = pool_info + .generator_ntrn_per_share + .checked_mul(astroport_lp_amount.to_decimal())? + .to_uint_floor(); + let pending_astro_rewards = + total_lockup_astro_rewards.checked_sub(lockup_info.generator_ntrn_debt)?; + lockup_info.generator_ntrn_debt = total_lockup_astro_rewards; + + // If claimable staking rewards > 0, claim them and send to the user + if pending_astro_rewards > Uint128::zero() { + cosmos_msgs.push(CosmosMsg::Bank(BankMsg::Send { + to_address: user_address.to_string(), + amount: vec![Coin { + denom: rwi.base_reward_token.to_string(), + amount: pending_astro_rewards, + }], + })); + } + + let mut pending_proxy_rewards: Vec = vec![]; + // If this LP token is getting dual incentives + // Calculate claimable proxy staking rewards for this lockup + lockup_info.generator_proxy_debt = lockup_info + .generator_proxy_debt + .inner_ref() + .iter() + .map(|(asset, debt)| { + let generator_proxy_per_share = pool_info + .generator_proxy_per_share + .load(asset) + .unwrap_or_default(); + let total_lockup_proxy_reward = + generator_proxy_per_share.checked_mul_uint128(astroport_lp_amount)?; + let pending_proxy_reward: Uint128 = total_lockup_proxy_reward.checked_sub(*debt)?; + + if !pending_proxy_reward.is_zero() { + pending_proxy_rewards.push(Asset { + info: asset.clone(), + amount: pending_proxy_reward, + }); + } + Ok((asset.clone(), total_lockup_proxy_reward)) + }) + .collect::>>()? + .into(); + + // If claimable proxy staking rewards > 0, claim them + for pending_proxy_reward in pending_proxy_rewards { + cosmos_msgs.push(pending_proxy_reward.into_msg(user_address.clone())?); + } + + // Transfers claimable one time NTRN rewards to the user that the user gets for all his lock + if !user_info.ntrn_transferred { + // Calculating how much NTRN user can claim (from total one time reward) + let total_claimable_ntrn_rewards = user_info.total_ntrn_rewards; + if total_claimable_ntrn_rewards > Uint128::zero() { + cosmos_msgs.push(CosmosMsg::Bank(BankMsg::Send { + to_address: user_address.to_string(), + amount: coins(total_claimable_ntrn_rewards.u128(), UNTRN_DENOM), + })) + } + + // claim airdrop rewards for airdrop participants + let res: BalanceResponse = deps.querier.query_wasm_smart( + config.credits_contract.clone(), + &Cw20QueryMsg::Balance { + address: user_address.to_string(), + }, + )?; + if res.balance > Uint128::zero() { + cosmos_msgs.push(claim_airdrop_tokens_with_multiplier_msg( + deps.as_ref(), + config.credits_contract, + user_address.clone(), + total_claimable_ntrn_rewards, + )?); + } + + user_info.ntrn_transferred = true; + USER_INFO.save(deps.storage, &user_address, &user_info)?; + } + + cosmos_msgs.push( + CallbackMsg::WithdrawUserLockupCallback { + pool_type, + user_address: user_address.clone(), + duration, + generator: generator.clone(), + astroport_lp_token, + astroport_lp_amount, + } + .to_cosmos_msg(&env)?, + ); + + Ok(Response::new().add_messages(cosmos_msgs)) +} + +#[allow(clippy::too_many_arguments)] +// Unstakes the staked LP amount, withdraws it from the pool and invokes callback that will +// send the withdrawn assets to the PCL lockdrop contract +pub fn callback_withdraw_user_lockup( + deps: DepsMut, + env: Env, + pool_type: PoolType, + user_address: Addr, + duration: u64, + generator: Addr, + astroport_lp_token: Addr, + astroport_lp_amount: Uint128, +) -> StdResult { + let mut cosmos_msgs = vec![]; + + // withdraw the staked lp tokens from the generator + cosmos_msgs.push(CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: generator.to_string(), + funds: vec![], + msg: to_json_binary(&GenExecuteMsg::Withdraw { + lp_token: astroport_lp_token.to_string(), + amount: astroport_lp_amount, + })?, + })); + + // determine the pool address and the denom of the second (not untrn) token in the pool + let astroport_pool: String = deps + .querier + .query_wasm_smart::( + astroport_lp_token.to_string(), + &cw20::Cw20QueryMsg::Minter {}, + )? + .minter; + let astroport_pool_info: astroport::pair::PoolResponse = deps + .querier + .query_wasm_smart(astroport_pool.clone(), &astroport::pair::QueryMsg::Pool {})?; + let paired_asset_denom = astroport_pool_info + .assets + .iter() + .find_map(|x| match &x.info { + AssetInfo::NativeToken { denom } if denom != UNTRN_DENOM => Some(denom.clone()), + _ => None, + }) + .ok_or_else(|| StdError::generic_err("No second leg of pair found"))?; + + // determine contract balances before withdrawal + let ntrn_balance = deps + .querier + .query_balance(&env.contract.address, UNTRN_DENOM)? + .amount; + let paired_asset_balance = deps + .querier + .query_balance(&env.contract.address, paired_asset_denom.clone())? + .amount; + + // withdraw liquidity from the XYK pool + cosmos_msgs.push(CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: astroport_lp_token.to_string(), + funds: vec![], + msg: to_json_binary(&Cw20ExecuteMsg::Send { + contract: astroport_pool, + amount: astroport_lp_amount, + msg: to_json_binary(&astroport::pair::Cw20HookMsg::WithdrawLiquidity { + assets: vec![], + })?, + })?, + })); + + // update contract's state in accordance with the just made withdrawal + let config = CONFIG.load(deps.storage)?; + let lockup_key = (pool_type, &user_address, duration); + let mut lockup_info = + LOCKUP_INFO.compatible_load(deps.as_ref(), lockup_key, &config.generator)?; + let mut pool_info = ASSET_POOLS.load(deps.storage, pool_type)?; + pool_info.amount_in_lockups = pool_info + .amount_in_lockups + .checked_sub(lockup_info.lp_units_locked)?; + ASSET_POOLS.save(deps.storage, pool_type, &pool_info, env.block.height)?; + lockup_info.astroport_lp_transferred = Some(astroport_lp_amount); + TOTAL_USER_LOCKUP_AMOUNT.update( + deps.storage, + (pool_type, &user_address), + env.block.height, + |lockup_amount| -> StdResult { + if let Some(la) = lockup_amount { + Ok(la.checked_sub(lockup_info.lp_units_locked)?) + } else { + Ok(Uint128::zero()) + } + }, + )?; + LOCKUP_INFO.save(deps.storage, lockup_key, &lockup_info)?; + + cosmos_msgs.push( + CallbackMsg::MigrateUserLockupToPCLPairCallback { + pool_type, + user_address: user_address.clone(), + duration, + ntrn_balance, + paired_asset_denom, + paired_asset_balance, + } + .to_cosmos_msg(&env)?, + ); + + Ok(Response::new().add_messages(cosmos_msgs)) +} + +#[allow(clippy::too_many_arguments)] +/// Invokes the PCL lockdrop contract's MigrateXYKLiquidity handler which creates an LP position in +/// the PCL pool and a lockup in the PCL lockdrop contract in accordance with the withdrawn user's +/// lockup position. The funds attached to the MigrateXYKLiquidity message are calculated based on +/// the balance differences of the assets from the WithdrawLiquidity made at the previous step of the +/// migration process. +pub fn callback_migrate_user_lockup_to_pcl_pair( + deps: DepsMut, + env: Env, + pool_type: PoolType, + user_address: Addr, + duration: u64, + ntrn_balance: Uint128, + paired_asset_denom: String, + paired_asset_balance: Uint128, +) -> StdResult { + let config = CONFIG.load(deps.storage)?; + let lockup_key = (pool_type, &user_address, duration); + let lockup_info = LOCKUP_INFO.compatible_load(deps.as_ref(), lockup_key, &config.generator)?; + let user_info = USER_INFO + .may_load(deps.storage, &user_address)? + .unwrap_or_default(); + + // determine withdrawn amounts + let ntrn_withdrawn = deps + .querier + .query_balance(&env.contract.address, UNTRN_DENOM)? + .amount + .sub(ntrn_balance); + let paired_asset_withdrawn = deps + .querier + .query_balance(&env.contract.address, paired_asset_denom.clone())? + .amount + .sub(paired_asset_balance); + + let pcl_lockdrop = PCL_LOCKDROP_CONTRACT.load(deps.storage)?; + + let pool_info = ASSET_POOLS.load(deps.storage, pool_type)?; + let generator = config + .generator + .as_ref() + .ok_or_else(|| StdError::generic_err("Generator should be set"))?; + let staked_lp_tokens: Uint128 = deps.querier.query_wasm_smart( + generator, + &GenQueryMsg::Deposit { + lp_token: pool_info.lp_token.to_string(), + user: env.contract.address.to_string(), + }, + )?; + + Ok( + Response::default().add_message(CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: pcl_lockdrop.to_string(), + funds: vec![ + Coin { + denom: UNTRN_DENOM.to_string(), + amount: ntrn_withdrawn, + }, + Coin { + denom: paired_asset_denom.to_string(), + amount: paired_asset_withdrawn, + }, + ], + msg: to_json_binary(&LockdropPCLExecuteMsg::MigrateXYKLiquidity { + pool_type, + user_address_raw: user_address.to_string(), + duration, + user_info, + lockup_info, + // zero LP tokens left for the XYK lockdrop contract means this is the last + // lockdrop participant being migrated, => time to stake pool's LP tokens + stake: staked_lp_tokens.is_zero(), + })?, + })), + ) +} + /// Returns the contract's State. /// ## Params /// * **deps** is an object of type [`Deps`]. diff --git a/contracts/lockdrop/src/raw_queries.rs b/contracts/lockdrop/src/raw_queries.rs index e491fdf4..fa8ead99 100644 --- a/contracts/lockdrop/src/raw_queries.rs +++ b/contracts/lockdrop/src/raw_queries.rs @@ -1,5 +1,5 @@ use astroport::asset::AssetInfo; -use cosmwasm_std::{from_slice, Addr, Empty, QuerierWrapper, StdError, StdResult, Uint128}; +use cosmwasm_std::{from_json, Addr, Empty, QuerierWrapper, StdError, StdResult, Uint128}; use cw_storage_plus::Path; use serde::Deserialize; @@ -17,7 +17,7 @@ pub fn raw_generator_deposit( let key: Path = Path::new(b"user_info", &[lp_token, address]); if let Some(res) = &querier.query_wasm_raw(generator, key.to_vec())? { - let UserInfo { amount } = from_slice(res)?; + let UserInfo { amount } = from_json(res)?; Ok(amount) } else { Ok(Uint128::zero()) @@ -28,7 +28,7 @@ pub fn raw_generator_deposit( pub fn raw_balance(querier: QuerierWrapper, token: &Addr, address: &[u8]) -> StdResult { let key: Path = Path::new(b"balance", &[address]); if let Some(res) = &querier.query_wasm_raw(token, key.to_vec())? { - let res: Uint128 = from_slice(res)?; + let res: Uint128 = from_json(res)?; Ok(res) } else { Ok(Uint128::zero()) @@ -43,7 +43,7 @@ pub fn raw_proxy_asset( ) -> StdResult { let key: Path = Path::new(b"proxy_reward_asset", &[address]); if let Some(res) = &querier.query_wasm_raw(generator, key.to_vec())? { - let res: AssetInfo = from_slice(res)?; + let res: AssetInfo = from_json(res)?; return Ok(res); } Err(StdError::generic_err(format!( diff --git a/contracts/lockdrop/src/state.rs b/contracts/lockdrop/src/state.rs index 5b817721..9eab8c25 100644 --- a/contracts/lockdrop/src/state.rs +++ b/contracts/lockdrop/src/state.rs @@ -14,6 +14,9 @@ use crate::raw_queries::raw_proxy_asset; pub const CONFIG: Item = Item::new("config"); pub const STATE: Item = Item::new("state"); +/// The address of the lockdrop contract working with PCL pools. Used in users' locked liquidity +/// migration from XYK pools to PCL ones. +pub const PCL_LOCKDROP_CONTRACT: Item = Item::new("pcl_lockdrop_contract"); /// Key is an Terraswap LP token address pub const ASSET_POOLS: SnapshotMap = SnapshotMap::new( diff --git a/contracts/lockdrop/src/testing.rs b/contracts/lockdrop/src/testing.rs index 526c0362..97d8c772 100644 --- a/contracts/lockdrop/src/testing.rs +++ b/contracts/lockdrop/src/testing.rs @@ -3,7 +3,7 @@ use astroport_periphery::lockdrop::{ Config, ExecuteMsg, InstantiateMsg, LockupRewardsInfo, QueryMsg, }; use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info}; -use cosmwasm_std::{coin, from_binary, Addr, Decimal256, StdError, Uint128}; +use cosmwasm_std::{coin, from_json, Addr, Decimal256, StdError, Uint128}; #[test] fn update_owner() { @@ -89,7 +89,7 @@ fn update_owner() { // Let's query the state let config: Config = - from_binary(&query(deps.as_ref(), env, QueryMsg::Config {}).unwrap()).unwrap(); + from_json(query(deps.as_ref(), env, QueryMsg::Config {}).unwrap()).unwrap(); assert_eq!(new_owner, config.owner); } @@ -132,7 +132,7 @@ fn increase_ntrn_incentives() { assert!(res.is_ok()); let config: Config = - from_binary(&query(deps.as_ref(), env, QueryMsg::Config {}).unwrap()).unwrap(); + from_json(query(deps.as_ref(), env, QueryMsg::Config {}).unwrap()).unwrap(); assert_eq!(Uint128::new(100u128), config.lockdrop_incentives); // invalid coin diff --git a/contracts/price-feed/src/contract.rs b/contracts/price-feed/src/contract.rs index 9e3630b6..deecc189 100644 --- a/contracts/price-feed/src/contract.rs +++ b/contracts/price-feed/src/contract.rs @@ -6,7 +6,7 @@ use astroport_periphery::pricefeed::{ #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - to_binary, Binary, Deps, DepsMut, Empty, Env, IbcMsg, IbcTimeout, MessageInfo, Response, + to_json_binary, Binary, Deps, DepsMut, Empty, Env, IbcMsg, IbcTimeout, MessageInfo, Response, StdResult, }; use cw2::set_contract_version; @@ -105,7 +105,7 @@ pub fn try_request(deps: DepsMut, env: Env) -> Result { let msg = IbcMsg::SendPacket { channel_id: endpoint.channel_id, - data: to_binary(&packet)?, + data: to_json_binary(&packet)?, timeout: IbcTimeout::with_timestamp(env.block.time.plus_seconds(60)), }; LAST_UPDATE.save(deps.storage, &env.block.time.seconds())?; @@ -180,9 +180,9 @@ pub fn migrate(_deps: DepsMut, _env: Env, _msg: Empty) -> StdResult { #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { match msg { - QueryMsg::GetRate {} => to_binary(&query_rate(deps)?), - QueryMsg::GetError {} => to_binary(&query_error(deps)?), - QueryMsg::GetConfig {} => to_binary(&query_config(deps)?), + QueryMsg::GetRate {} => to_json_binary(&query_rate(deps)?), + QueryMsg::GetError {} => to_json_binary(&query_error(deps)?), + QueryMsg::GetConfig {} => to_json_binary(&query_config(deps)?), } } diff --git a/contracts/price-feed/src/ibc.rs b/contracts/price-feed/src/ibc.rs index b1ac0349..c0a72b05 100644 --- a/contracts/price-feed/src/ibc.rs +++ b/contracts/price-feed/src/ibc.rs @@ -1,7 +1,7 @@ #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - attr, from_slice, Binary, DepsMut, Env, Ibc3ChannelOpenResponse, IbcBasicResponse, IbcChannel, + attr, from_json, Binary, DepsMut, Env, Ibc3ChannelOpenResponse, IbcBasicResponse, IbcChannel, IbcChannelCloseMsg, IbcChannelConnectMsg, IbcChannelOpenMsg, IbcChannelOpenResponse, IbcOrder, IbcPacket, IbcPacketAckMsg, IbcPacketReceiveMsg, IbcPacketTimeoutMsg, IbcReceiveResponse, StdResult, Uint64, @@ -95,7 +95,7 @@ fn do_ibc_packet_receive( env: Env, packet: &IbcPacket, ) -> Result { - let resp: OracleResponsePacketData = from_slice(&packet.data)?; + let resp: OracleResponsePacketData = from_json(&packet.data)?; let config = CONFIG.load(deps.storage)?; let symbols = config.symbols; deps.api @@ -153,6 +153,6 @@ fn ttt() { let res: Vec = OBIDecode::decode(&mut b.as_slice()).unwrap(); println!("{:?}\n{:?}", res, b.len()); - // let result: Result, _> = from_slice(b.as_slice()); + // let result: Result, _> = from_json(b.as_slice()); // println!("{:?}", result); } diff --git a/contracts/vesting-investors/src/tests/integration.rs b/contracts/vesting-investors/src/tests/integration.rs index c971d6c6..e101baf5 100644 --- a/contracts/vesting-investors/src/tests/integration.rs +++ b/contracts/vesting-investors/src/tests/integration.rs @@ -2,7 +2,7 @@ use crate::msg::InstantiateMsg; use astroport::asset::{native_asset_info, token_asset_info}; use astroport::querier::query_balance; use astroport::token::InstantiateMsg as TokenInstantiateMsg; -use cosmwasm_std::{coin, coins, to_binary, Addr, StdResult, Timestamp, Uint128}; +use cosmwasm_std::{coin, coins, to_json_binary, Addr, StdResult, Timestamp, Uint128}; use cw20::{BalanceResponse, Cw20ExecuteMsg, Cw20QueryMsg, MinterResponse}; use cw_multi_test::{App, ContractWrapper, Executor}; use cw_utils::PaymentError; @@ -37,7 +37,7 @@ fn claim() { let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![ @@ -85,7 +85,7 @@ fn claim() { let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![ @@ -213,7 +213,7 @@ fn claim_native() { let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![VestingSchedule { @@ -383,7 +383,7 @@ fn register_vesting_accounts() { let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![VestingSchedule { @@ -409,7 +409,7 @@ fn register_vesting_accounts() { let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![VestingSchedule { @@ -495,7 +495,7 @@ fn register_vesting_accounts() { // Let's check user1's final vesting amount after add schedule for a new one let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user2.to_string(), schedules: vec![VestingSchedule { @@ -542,7 +542,7 @@ fn register_vesting_accounts() { // Add one more vesting schedule; final amount to vest must increase let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![VestingSchedule { @@ -636,7 +636,7 @@ fn register_vesting_accounts_native() { let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![VestingSchedule { @@ -1142,7 +1142,7 @@ fn remove_vesting_accounts() { let res: StdResult = app.wrap().query_wasm_smart(vesting_instance.clone(), &msg); assert_eq!( res.unwrap_err().to_string(), - "Generic error: Querier contract error: vesting_base::types::VestingInfo not found" + "Generic error: Querier contract error: type: vesting_base::types::VestingInfo; key: [00, 0C, 76, 65, 73, 74, 69, 6E, 67, 5F, 69, 6E, 66, 6F, 75, 73, 65, 72, 31] not found" ); // Check vesting balance @@ -1281,7 +1281,7 @@ fn remove_vesting_accounts() { let res: StdResult = app.wrap().query_wasm_smart(vesting_instance.clone(), &msg); assert_eq!( res.unwrap_err().to_string(), - "Generic error: Querier contract error: vesting_base::types::VestingInfo not found" + "Generic error: Querier contract error: type: vesting_base::types::VestingInfo; key: [00, 0C, 76, 65, 73, 74, 69, 6E, 67, 5F, 69, 6E, 66, 6F, 75, 73, 65, 72, 31] not found" ); // Check vesting balance diff --git a/contracts/vesting-lp-pcl/.cargo/config b/contracts/vesting-lp-pcl/.cargo/config new file mode 100644 index 00000000..f2fbc6a9 --- /dev/null +++ b/contracts/vesting-lp-pcl/.cargo/config @@ -0,0 +1,6 @@ +[alias] +wasm = "build --release --target wasm32-unknown-unknown" +wasm-debug = "build --target wasm32-unknown-unknown" +unit-test = "test --lib" +integration-test = "test --test integration" +schema = "run --example vesting-lp_schema" diff --git a/contracts/vesting-lp-pcl/Cargo.toml b/contracts/vesting-lp-pcl/Cargo.toml new file mode 100644 index 00000000..43b07451 --- /dev/null +++ b/contracts/vesting-lp-pcl/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "vesting-lp-pcl" +version = "1.1.0" +authors = ["Neutron"] +edition = "2021" +description = "Vesting contract with a voting capabilities. Provides queries to get the amount of tokens are being held by user at certain height." + +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +# for more explicit tests, cargo test --features=backtraces +backtraces = ["cosmwasm-std/backtraces"] +# use library feature to disable all init/handle/query exports +library = [] + +[dependencies] +cw2 = { workspace = true } +cw20 = { version = "0.15" } +astroport = { path= "../../packages/astroport"} +vesting-base = {path = "../../packages/vesting-base"} +cosmwasm-schema = { workspace = true } +cosmwasm-std = { workspace = true } +cw-storage-plus = "0.15" + +[dev-dependencies] +cw-multi-test = { workspace = true } +astroport-token = {git = "https://github.com/astroport-fi/astroport-core.git", rev = "65ce7d1879cc5d95b09fa14202f0423bba52ae0e" } +cw-utils = "0.15" diff --git a/contracts/vesting-lp-pcl/examples/vesting-lp-pcl_schema.rs b/contracts/vesting-lp-pcl/examples/vesting-lp-pcl_schema.rs new file mode 100644 index 00000000..186bbaf1 --- /dev/null +++ b/contracts/vesting-lp-pcl/examples/vesting-lp-pcl_schema.rs @@ -0,0 +1,12 @@ +use cosmwasm_schema::write_api; +use vesting_base::msg::{MigrateMsg, QueryMsg}; +use vesting_lp_pcl::msg::{ExecuteMsg, InstantiateMsg}; + +fn main() { + write_api! { + instantiate: InstantiateMsg, + query: QueryMsg, + execute: ExecuteMsg, + migrate: MigrateMsg + } +} diff --git a/contracts/vesting-lp-pcl/schema/neutron-lockdrop-pcl.json b/contracts/vesting-lp-pcl/schema/neutron-lockdrop-pcl.json new file mode 100644 index 00000000..874d7e53 --- /dev/null +++ b/contracts/vesting-lp-pcl/schema/neutron-lockdrop-pcl.json @@ -0,0 +1,1655 @@ +{ + "contract_name": "neutron-lockdrop-pcl", + "contract_version": "1.0.0", + "idl_version": "1.0.0", + "instantiate": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "type": "object", + "required": [ + "atom_incentives_share", + "atom_token", + "atom_weighted_amount", + "auction_contract", + "credits_contract", + "incentives", + "lockdrop_incentives", + "lockup_rewards_info", + "usdc_incentives_share", + "usdc_token", + "usdc_weighted_amount", + "xyk_lockdrop_contract" + ], + "properties": { + "atom_incentives_share": { + "description": "Share of total NTRN incentives allocated to the NTRN/ATOM PCL pool", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "atom_token": { + "description": "Address of the LP token of the NTRN/ATOM PCL pool", + "type": "string" + }, + "atom_weighted_amount": { + "description": "Weighted LP Token balance used to calculate NTRN rewards a particular NTRN/ATOM pool depositor can claim", + "allOf": [ + { + "$ref": "#/definitions/Uint256" + } + ] + }, + "auction_contract": { + "description": "Auction contract address", + "type": "string" + }, + "credits_contract": { + "description": "Credits contract address", + "type": "string" + }, + "incentives": { + "description": "Incentives (Staking for dual rewards) contract address", + "type": "string" + }, + "lockdrop_incentives": { + "description": "Total NTRN lockdrop incentives distributed among the users.", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "lockup_rewards_info": { + "description": "Describes rewards coefficients for each lockup duration", + "type": "array", + "items": { + "$ref": "#/definitions/LockupRewardsInfo" + } + }, + "owner": { + "description": "Account which can update config", + "type": [ + "string", + "null" + ] + }, + "usdc_incentives_share": { + "description": "Share of total NTRN incentives allocated to the NTRN/USDC PCL pool", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "usdc_token": { + "description": "Address of the LP token of the NTRN/USDC PCL pool", + "type": "string" + }, + "usdc_weighted_amount": { + "description": "Weighted LP Token balance used to calculate NTRN rewards a particular NTRN/USDC pool depositor can claim", + "allOf": [ + { + "$ref": "#/definitions/Uint256" + } + ] + }, + "xyk_lockdrop_contract": { + "description": "Original XYK lockdrop contract address", + "type": "string" + } + }, + "definitions": { + "Decimal256": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal256(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 115792089237316195423570985008687907853269984665640564039457.584007913129639935 (which is (2^256 - 1) / 10^18)", + "type": "string" + }, + "LockupRewardsInfo": { + "type": "object", + "required": [ + "coefficient", + "duration" + ], + "properties": { + "coefficient": { + "$ref": "#/definitions/Decimal256" + }, + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } + }, + "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" + }, + "Uint256": { + "description": "An implementation of u256 that is using strings for JSON encoding/decoding, such that the full u256 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 out of primitive uint types or `new` to provide big endian bytes:\n\n``` # use cosmwasm_std::Uint256; let a = Uint256::from(258u128); let b = Uint256::new([ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, ]); assert_eq!(a, b); ```", + "type": "string" + } + } + }, + "execute": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "update_config" + ], + "properties": { + "update_config": { + "type": "object", + "required": [ + "new_config" + ], + "properties": { + "new_config": { + "$ref": "#/definitions/UpdateConfigMsg" + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "claim_rewards_and_optionally_unlock" + ], + "properties": { + "claim_rewards_and_optionally_unlock": { + "type": "object", + "required": [ + "duration", + "pool_type", + "withdraw_lp_stake" + ], + "properties": { + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "$ref": "#/definitions/PoolType" + }, + "withdraw_lp_stake": { + "type": "boolean" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Callbacks; only callable by the contract itself.", + "type": "object", + "required": [ + "callback" + ], + "properties": { + "callback": { + "$ref": "#/definitions/CallbackMsg" + } + }, + "additionalProperties": false + }, + { + "description": "ProposeNewOwner creates a proposal to change contract ownership. The validity period for the proposal is set in the `expires_in` variable.", + "type": "object", + "required": [ + "propose_new_owner" + ], + "properties": { + "propose_new_owner": { + "type": "object", + "required": [ + "expires_in", + "owner" + ], + "properties": { + "expires_in": { + "description": "The date after which this proposal expires", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "owner": { + "description": "Newly proposed contract owner", + "type": "string" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "DropOwnershipProposal removes the existing offer to change contract ownership.", + "type": "object", + "required": [ + "drop_ownership_proposal" + ], + "properties": { + "drop_ownership_proposal": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "description": "Used to claim contract ownership.", + "type": "object", + "required": [ + "claim_ownership" + ], + "properties": { + "claim_ownership": { + "type": "object" + } + }, + "additionalProperties": false + }, + { + "description": "A handler to receive lockdrop liquidity migrated from xyl pools to PCL ones. Only callable by the original lockdrop contract. Expects two **Coin**s to be attached as funds.", + "type": "object", + "required": [ + "migrate_xyk_liquidity" + ], + "properties": { + "migrate_xyk_liquidity": { + "type": "object", + "required": [ + "duration", + "lockup_info", + "pool_type", + "user_address_raw", + "user_info" + ], + "properties": { + "duration": { + "description": "The duration of the lock period.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "lockup_info": { + "description": "The lockup info from the XYK lockdrop contract. Is used to create a LockupInfoV2 entry on the PCL lockdrop contract's side.", + "allOf": [ + { + "$ref": "#/definitions/LockupInfoV2" + } + ] + }, + "pool_type": { + "description": "The type of the pool the lockup is related to.", + "allOf": [ + { + "$ref": "#/definitions/PoolType2" + } + ] + }, + "user_address_raw": { + "description": "The address of the user which owns the lockup.", + "type": "string" + }, + "user_info": { + "description": "The lockup owner's info from the XYK lockdrop contract. Is used to create a UserInfo entry on the PCL lockdrop contract's side.", + "allOf": [ + { + "$ref": "#/definitions/UserInfo" + } + ] + } + } + } + }, + "additionalProperties": false + } + ], + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "Asset": { + "description": "This enum describes a Terra asset (native or CW20).", + "type": "object", + "required": [ + "amount", + "info" + ], + "properties": { + "amount": { + "description": "A token amount", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "info": { + "description": "Information about an asset stored in a [`AssetInfo`] struct", + "allOf": [ + { + "$ref": "#/definitions/AssetInfo" + } + ] + } + }, + "additionalProperties": false + }, + "AssetInfo": { + "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "CallbackMsg": { + "oneOf": [ + { + "type": "object", + "required": [ + "update_pool_on_dual_rewards_claim" + ], + "properties": { + "update_pool_on_dual_rewards_claim": { + "type": "object", + "required": [ + "pool_type", + "prev_reward_balances" + ], + "properties": { + "pool_type": { + "$ref": "#/definitions/PoolType" + }, + "prev_reward_balances": { + "type": "array", + "items": { + "$ref": "#/definitions/Asset" + } + } + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "withdraw_user_lockup_rewards_callback" + ], + "properties": { + "withdraw_user_lockup_rewards_callback": { + "type": "object", + "required": [ + "duration", + "pool_type", + "user_address", + "withdraw_lp_stake" + ], + "properties": { + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "$ref": "#/definitions/PoolType" + }, + "user_address": { + "$ref": "#/definitions/Addr" + }, + "withdraw_lp_stake": { + "type": "boolean" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Completes the liquidity migration process by making all necessary state updates for the lockup position.", + "type": "object", + "required": [ + "finish_lockup_migration_callback" + ], + "properties": { + "finish_lockup_migration_callback": { + "type": "object", + "required": [ + "duration", + "lockup_info", + "lp_token", + "pool_type", + "staked_lp_token_amount", + "user_address", + "user_info" + ], + "properties": { + "duration": { + "description": "The duration of the lock period.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "lockup_info": { + "description": "The lockup info from the XYK lockdrop contract. Is used to create a LockupInfoV2 entry on the PCL lockdrop contract's side.", + "allOf": [ + { + "$ref": "#/definitions/LockupInfoV2" + } + ] + }, + "lp_token": { + "description": "The address of the LP token of the pool.", + "type": "string" + }, + "pool_type": { + "description": "The type of the pool the lockup is related to.", + "allOf": [ + { + "$ref": "#/definitions/PoolType" + } + ] + }, + "staked_lp_token_amount": { + "description": "The amount of staked LP token the PCL lockdrop contract possesses of before liquidity provision and staking to the incentives. Used to calculate LP token amount received for liquidity provision.", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "user_address": { + "description": "The address of the user which owns the lockup.", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "user_info": { + "description": "The lockup owner's info from the XYK lockdrop contract. Is used to create a UserInfo entry on the PCL lockdrop contract's side.", + "allOf": [ + { + "$ref": "#/definitions/UserInfo" + } + ] + } + } + } + }, + "additionalProperties": false + } + ] + }, + "LockupInfoV2": { + "type": "object", + "required": [ + "generator_ntrn_debt", + "generator_proxy_debt", + "lp_units_locked", + "ntrn_rewards", + "unlock_timestamp", + "withdrawal_flag" + ], + "properties": { + "astroport_lp_transferred": { + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "generator_ntrn_debt": { + "description": "Generator NTRN tokens loockup received as generator rewards", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "generator_proxy_debt": { + "description": "Generator Proxy tokens lockup received as generator rewards", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Uint128" + } + ] + }, + "lp_units_locked": { + "description": "Terraswap LP units locked by the user", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "ntrn_rewards": { + "description": "NTRN tokens received as rewards for participation in the lockdrop", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "unlock_timestamp": { + "description": "Timestamp beyond which this position can be unlocked", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "withdrawal_flag": { + "description": "Boolean value indicating if the user's has withdrawn funds post the only 1 withdrawal limit cutoff", + "type": "boolean" + } + } + }, + "PoolType": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + }, + "PoolType2": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + }, + "RestrictedVector_for_AssetInfo_and_Uint128": { + "description": "Vec wrapper for internal use. Some business logic relies on an order of this vector, thus it is forbidden to sort it or remove elements. New values can be added using .update() ONLY.", + "type": "array", + "items": { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AssetInfo" + }, + { + "$ref": "#/definitions/Uint128" + } + ], + "maxItems": 2, + "minItems": 2 + } + }, + "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" + }, + "UpdateConfigMsg": { + "type": "object", + "properties": { + "incentives_address": { + "description": "incentives (Staking for dual rewards) contract address", + "type": [ + "string", + "null" + ] + } + } + }, + "UserInfo": { + "type": "object", + "required": [ + "lockup_positions_index", + "ntrn_transferred", + "total_ntrn_rewards" + ], + "properties": { + "lockup_positions_index": { + "description": "Number of lockup positions the user is having", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "ntrn_transferred": { + "description": "NTRN tokens transferred to user", + "type": "boolean" + }, + "total_ntrn_rewards": { + "description": "Total NTRN tokens user received as rewards for participation in the lockdrop", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + } + } + } + } + }, + "query": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "config" + ], + "properties": { + "config": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "state" + ], + "properties": { + "state": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "pool" + ], + "properties": { + "pool": { + "type": "object", + "required": [ + "pool_type" + ], + "properties": { + "pool_type": { + "$ref": "#/definitions/PoolType" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "user_info" + ], + "properties": { + "user_info": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "user_info_with_lockups_list" + ], + "properties": { + "user_info_with_lockups_list": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "lock_up_info" + ], + "properties": { + "lock_up_info": { + "type": "object", + "required": [ + "duration", + "pool_type", + "user_address" + ], + "properties": { + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "$ref": "#/definitions/PoolType" + }, + "user_address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "query_user_lockup_total_at_height" + ], + "properties": { + "query_user_lockup_total_at_height": { + "type": "object", + "required": [ + "height", + "pool_type", + "user_address" + ], + "properties": { + "height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "$ref": "#/definitions/PoolType" + }, + "user_address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "query_lockup_total_at_height" + ], + "properties": { + "query_lockup_total_at_height": { + "type": "object", + "required": [ + "height", + "pool_type" + ], + "properties": { + "height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "$ref": "#/definitions/PoolType" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ], + "definitions": { + "PoolType": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + } + } + }, + "migrate": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "MigrateMsg", + "type": "object" + }, + "sudo": null, + "responses": { + "config": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Config", + "type": "object", + "required": [ + "auction_contract", + "credits_contract", + "incentives", + "lockdrop_incentives", + "lockup_rewards_info", + "owner", + "xyk_lockdrop_contract" + ], + "properties": { + "auction_contract": { + "description": "Bootstrap Auction contract address", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "credits_contract": { + "description": "Credits contract address", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "incentives": { + "description": "Incentives contract address", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "lockdrop_incentives": { + "description": "Total NTRN lockdrop incentives to be distributed among the users", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "lockup_rewards_info": { + "description": "Describes rewards coefficients for each lockup duration", + "type": "array", + "items": { + "$ref": "#/definitions/LockupRewardsInfo" + } + }, + "owner": { + "description": "Account which can update the config", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "xyk_lockdrop_contract": { + "description": "Original XYK lockdrop contract address", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + } + }, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "Decimal256": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal256(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 115792089237316195423570985008687907853269984665640564039457.584007913129639935 (which is (2^256 - 1) / 10^18)", + "type": "string" + }, + "LockupRewardsInfo": { + "type": "object", + "required": [ + "coefficient", + "duration" + ], + "properties": { + "coefficient": { + "$ref": "#/definitions/Decimal256" + }, + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } + }, + "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" + } + } + }, + "lock_up_info": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "LockUpInfoResponse", + "type": "object", + "required": [ + "astroport_lp_token", + "claimable_incentives_debt", + "duration", + "incentives_debt", + "lp_units_locked", + "ntrn_rewards", + "pool_type", + "unlock_timestamp", + "withdrawal_flag" + ], + "properties": { + "astroport_lp_token": { + "$ref": "#/definitions/Addr" + }, + "astroport_lp_transferred": { + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "astroport_lp_units": { + "description": "User's Astroport LP units, calculated as lp_units_locked (terraswap) / total LP units locked (terraswap) * Astroport LP units minted post migration", + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "claimable_incentives_debt": { + "description": "Tokens receivable as incentives rewards that user can claim", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Uint128" + } + ] + }, + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "incentives_debt": { + "description": "incentives tokens lockup received as incentives rewards", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Uint128" + } + ] + }, + "lp_units_locked": { + "description": "Terraswap LP units locked by the user", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "ntrn_rewards": { + "description": "NTRN tokens received as rewards for participation in the lockdrop", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "pool_type": { + "description": "Terraswap LP token", + "allOf": [ + { + "$ref": "#/definitions/PoolType" + } + ] + }, + "unlock_timestamp": { + "description": "Timestamp beyond which this position can be unlocked", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "withdrawal_flag": { + "description": "Boolean value indicating if the user's has withdrawn funds post the only 1 withdrawal limit cutoff", + "type": "boolean" + } + }, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "AssetInfo": { + "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "PoolType": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + }, + "RestrictedVector_for_AssetInfo_and_Uint128": { + "description": "Vec wrapper for internal use. Some business logic relies on an order of this vector, thus it is forbidden to sort it or remove elements. New values can be added using .update() ONLY.", + "type": "array", + "items": { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AssetInfo" + }, + { + "$ref": "#/definitions/Uint128" + } + ], + "maxItems": 2, + "minItems": 2 + } + }, + "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" + } + } + }, + "pool": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "PoolInfo", + "type": "object", + "required": [ + "amount_in_lockups", + "incentives_rewards_per_share", + "incentives_share", + "lp_token", + "weighted_amount" + ], + "properties": { + "amount_in_lockups": { + "$ref": "#/definitions/Uint128" + }, + "incentives_rewards_per_share": { + "description": "Ratio of incentives rewards accured to astroport pool share", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Decimal" + } + ] + }, + "incentives_share": { + "description": "Share of total NTRN incentives allocated to this pool", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "lp_token": { + "$ref": "#/definitions/Addr" + }, + "weighted_amount": { + "description": "Weighted LP Token balance used to calculate NTRN rewards a particular user can claim", + "allOf": [ + { + "$ref": "#/definitions/Uint256" + } + ] + } + }, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "AssetInfo": { + "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + }, + "RestrictedVector_for_AssetInfo_and_Decimal": { + "description": "Vec wrapper for internal use. Some business logic relies on an order of this vector, thus it is forbidden to sort it or remove elements. New values can be added using .update() ONLY.", + "type": "array", + "items": { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AssetInfo" + }, + { + "$ref": "#/definitions/Decimal" + } + ], + "maxItems": 2, + "minItems": 2 + } + }, + "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" + }, + "Uint256": { + "description": "An implementation of u256 that is using strings for JSON encoding/decoding, such that the full u256 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 out of primitive uint types or `new` to provide big endian bytes:\n\n``` # use cosmwasm_std::Uint256; let a = Uint256::from(258u128); let b = Uint256::new([ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, ]); assert_eq!(a, b); ```", + "type": "string" + } + } + }, + "query_lockup_total_at_height": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Nullable_Uint128", + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ], + "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" + } + } + }, + "query_user_lockup_total_at_height": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Nullable_Uint128", + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ], + "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" + } + } + }, + "state": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "StateResponse", + "type": "object", + "required": [ + "supported_pairs_list", + "total_incentives_share" + ], + "properties": { + "supported_pairs_list": { + "description": "Vector containing LP addresses for all the supported LP Pools", + "type": "array", + "items": { + "$ref": "#/definitions/PoolType" + } + }, + "total_incentives_share": { + "description": "Total NTRN incentives share", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + } + }, + "definitions": { + "PoolType": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + }, + "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" + } + } + }, + "user_info": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserInfoResponse", + "type": "object", + "required": [ + "claimable_incentives_debt", + "lockup_infos", + "lockup_positions_index", + "ntrn_transferred", + "total_ntrn_rewards" + ], + "properties": { + "claimable_incentives_debt": { + "description": "Tokens receivable as incentives rewards that user can claim", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Uint128" + } + ] + }, + "lockup_infos": { + "description": "Lockup positions", + "type": "array", + "items": { + "$ref": "#/definitions/LockUpInfoResponse" + } + }, + "lockup_positions_index": { + "description": "Number of lockup positions the user is having", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "ntrn_transferred": { + "description": "NTRN tokens transferred to user", + "type": "boolean" + }, + "total_ntrn_rewards": { + "description": "Total NTRN tokens user received as rewards for participation in the lockdrop", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + } + }, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "AssetInfo": { + "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "LockUpInfoResponse": { + "type": "object", + "required": [ + "astroport_lp_token", + "claimable_incentives_debt", + "duration", + "incentives_debt", + "lp_units_locked", + "ntrn_rewards", + "pool_type", + "unlock_timestamp", + "withdrawal_flag" + ], + "properties": { + "astroport_lp_token": { + "$ref": "#/definitions/Addr" + }, + "astroport_lp_transferred": { + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "astroport_lp_units": { + "description": "User's Astroport LP units, calculated as lp_units_locked (terraswap) / total LP units locked (terraswap) * Astroport LP units minted post migration", + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "claimable_incentives_debt": { + "description": "Tokens receivable as incentives rewards that user can claim", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Uint128" + } + ] + }, + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "incentives_debt": { + "description": "incentives tokens lockup received as incentives rewards", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Uint128" + } + ] + }, + "lp_units_locked": { + "description": "Terraswap LP units locked by the user", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "ntrn_rewards": { + "description": "NTRN tokens received as rewards for participation in the lockdrop", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "pool_type": { + "description": "Terraswap LP token", + "allOf": [ + { + "$ref": "#/definitions/PoolType" + } + ] + }, + "unlock_timestamp": { + "description": "Timestamp beyond which this position can be unlocked", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "withdrawal_flag": { + "description": "Boolean value indicating if the user's has withdrawn funds post the only 1 withdrawal limit cutoff", + "type": "boolean" + } + } + }, + "PoolType": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + }, + "RestrictedVector_for_AssetInfo_and_Uint128": { + "description": "Vec wrapper for internal use. Some business logic relies on an order of this vector, thus it is forbidden to sort it or remove elements. New values can be added using .update() ONLY.", + "type": "array", + "items": { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AssetInfo" + }, + { + "$ref": "#/definitions/Uint128" + } + ], + "maxItems": 2, + "minItems": 2 + } + }, + "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" + } + } + }, + "user_info_with_lockups_list": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserInfoWithListResponse", + "type": "object", + "required": [ + "lockup_infos", + "lockup_positions_index", + "ntrn_transferred", + "total_ntrn_rewards" + ], + "properties": { + "lockup_infos": { + "description": "Lockup positions", + "type": "array", + "items": { + "$ref": "#/definitions/LockUpInfoSummary" + } + }, + "lockup_positions_index": { + "description": "Number of lockup positions the user is having", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "ntrn_transferred": { + "description": "NTRN tokens transferred to user", + "type": "boolean" + }, + "total_ntrn_rewards": { + "description": "Total NTRN tokens user received as rewards for participation in the lockdrop", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + } + }, + "definitions": { + "LockUpInfoSummary": { + "type": "object", + "required": [ + "duration", + "pool_type" + ], + "properties": { + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "$ref": "#/definitions/PoolType" + } + } + }, + "PoolType": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + }, + "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/vesting-lp-pcl/schema/raw/execute.json b/contracts/vesting-lp-pcl/schema/raw/execute.json new file mode 100644 index 00000000..eef7340b --- /dev/null +++ b/contracts/vesting-lp-pcl/schema/raw/execute.json @@ -0,0 +1,658 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "propose_new_owner" + ], + "properties": { + "propose_new_owner": { + "type": "object", + "required": [ + "expires_in", + "owner" + ], + "properties": { + "expires_in": { + "description": "The validity period of the offer to change the owner", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "owner": { + "description": "The newly proposed owner", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Removes a request to change contract ownership ## Executor Only the current owner can execute this", + "type": "object", + "required": [ + "drop_ownership_proposal" + ], + "properties": { + "drop_ownership_proposal": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Claims contract ownership ## Executor Only the newly proposed owner can execute this", + "type": "object", + "required": [ + "claim_ownership" + ], + "properties": { + "claim_ownership": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Sets vesting token ## Executor Only the current owner or token info manager can execute this", + "type": "object", + "required": [ + "set_vesting_token" + ], + "properties": { + "set_vesting_token": { + "type": "object", + "required": [ + "vesting_token" + ], + "properties": { + "vesting_token": { + "$ref": "#/definitions/AssetInfo" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Contains messages associated with the managed extension for vesting contracts.", + "type": "object", + "required": [ + "managed_extension" + ], + "properties": { + "managed_extension": { + "type": "object", + "required": [ + "msg" + ], + "properties": { + "msg": { + "$ref": "#/definitions/ExecuteMsgManaged" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Contains messages associated with the with_managers extension for vesting contracts.", + "type": "object", + "required": [ + "with_managers_extension" + ], + "properties": { + "with_managers_extension": { + "type": "object", + "required": [ + "msg" + ], + "properties": { + "msg": { + "$ref": "#/definitions/ExecuteMsgWithManagers" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Contains messages associated with the historical extension for vesting contracts.", + "type": "object", + "required": [ + "historical_extension" + ], + "properties": { + "historical_extension": { + "type": "object", + "required": [ + "msg" + ], + "properties": { + "msg": { + "$ref": "#/definitions/ExecuteMsgHistorical" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "receive" + ], + "properties": { + "receive": { + "$ref": "#/definitions/Cw20ReceiveMsg" + } + }, + "additionalProperties": false + }, + { + "description": "A handler to receive lockdrop liquidity migrated from xyl pools to PCL ones. Only callable by the original lockdrop contract. Expects two **Coin**s to be attached as funds.", + "type": "object", + "required": [ + "migrate_xyk_liquidity" + ], + "properties": { + "migrate_xyk_liquidity": { + "type": "object", + "required": [ + "duration", + "lockup_info", + "pool_type", + "user_address_raw", + "user_info" + ], + "properties": { + "duration": { + "description": "The duration of the lock period.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "lockup_info": { + "description": "The lockup info from the XYK lockdrop contract. Is used to create a LockupInfoV2 entry on the PCL lockdrop contract's side.", + "allOf": [ + { + "$ref": "#/definitions/LockupInfoV2" + } + ] + }, + "pool_type": { + "description": "The type of the pool the lockup is related to.", + "allOf": [ + { + "$ref": "#/definitions/PoolType2" + } + ] + }, + "user_address_raw": { + "description": "The address of the user which owns the lockup.", + "type": "string" + }, + "user_info": { + "description": "The lockup owner's info from the XYK lockdrop contract. Is used to create a UserInfo entry on the PCL lockdrop contract's side.", + "allOf": [ + { + "$ref": "#/definitions/UserInfo" + } + ] + } + } + } + }, + "additionalProperties": false + } + ], + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "AssetInfo": { + "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "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" + }, + "Cw20ReceiveMsg": { + "description": "Cw20ReceiveMsg should be de/serialized under `Receive()` variant in a ExecuteMsg", + "type": "object", + "required": [ + "amount", + "msg", + "sender" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "msg": { + "$ref": "#/definitions/Binary" + }, + "sender": { + "type": "string" + } + }, + "additionalProperties": false + }, + "ExecuteMsgHistorical": { + "description": "This structure describes the execute messages available in a historical vesting contract.", + "type": "string", + "enum": [] + }, + "ExecuteMsgManaged": { + "description": "This structure describes the execute messages available in a managed vesting contract.", + "CallbackMsg": { + "oneOf": [ + { + "description": "Removes vesting targets/accounts. ## Executor Only the current owner can execute this", + "type": "object", + "required": [ + "remove_vesting_accounts" + ], + "properties": { + "remove_vesting_accounts": { + "type": "object", + "required": [ + "clawback_account", + "vesting_accounts" + ], + "properties": { + "clawback_account": { + "description": "Specifies the account that will receive the funds taken from the vesting accounts.", + "type": "string" + }, + "vesting_accounts": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "ExecuteMsgWithManagers": { + "description": "This structure describes the execute messages available in a with_managers vesting contract.", + "oneOf": [ + { + "description": "Adds vesting managers ## Executor Only the current owner can execute this", + "type": "object", + "required": [ + "add_vesting_managers" + ], + "properties": { + "add_vesting_managers": { + "type": "object", + "required": [ + "managers" + ], + "properties": { + "duration": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "pool_type": { + "$ref": "#/definitions/PoolType" + }, + "user_address": { + "$ref": "#/definitions/Addr" + }, + "withdraw_lp_stake": { + "type": "boolean" + } + } + } + }, + "additionalProperties": false + }, + { + "description": "Completes the liquidity migration process by making all necessary state updates for the lockup position.", + "type": "object", + "required": [ + "finish_lockup_migration_callback" + ], + "properties": { + "finish_lockup_migration_callback": { + "type": "object", + "required": [ + "duration", + "lockup_info", + "lp_token", + "pool_type", + "staked_lp_token_amount", + "user_address", + "user_info" + ], + "properties": { + "duration": { + "description": "The duration of the lock period.", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "lockup_info": { + "description": "The lockup info from the XYK lockdrop contract. Is used to create a LockupInfoV2 entry on the PCL lockdrop contract's side.", + "allOf": [ + { + "$ref": "#/definitions/LockupInfoV2" + } + ] + }, + "lp_token": { + "description": "The address of the LP token of the pool.", + "type": "string" + }, + "pool_type": { + "description": "The type of the pool the lockup is related to.", + "allOf": [ + { + "$ref": "#/definitions/PoolType" + } + ] + }, + "staked_lp_token_amount": { + "description": "The amount of staked LP token the PCL lockdrop contract possesses of before liquidity provision and staking to the incentives. Used to calculate LP token amount received for liquidity provision.", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "user_address": { + "description": "The address of the user which owns the lockup.", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "user_info": { + "description": "The lockup owner's info from the XYK lockdrop contract. Is used to create a UserInfo entry on the PCL lockdrop contract's side.", + "allOf": [ + { + "$ref": "#/definitions/UserInfo" + } + ] + } + } + } + }, + "additionalProperties": false + } + ] + }, + "LockupInfoV2": { + "type": "object", + "required": [ + "generator_ntrn_debt", + "generator_proxy_debt", + "lp_units_locked", + "ntrn_rewards", + "unlock_timestamp", + "withdrawal_flag" + ], + "properties": { + "astroport_lp_transferred": { + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "generator_ntrn_debt": { + "description": "Generator NTRN tokens loockup received as generator rewards", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "generator_proxy_debt": { + "description": "Generator Proxy tokens lockup received as generator rewards", + "allOf": [ + { + "$ref": "#/definitions/RestrictedVector_for_AssetInfo_and_Uint128" + } + ] + }, + "lp_units_locked": { + "description": "Terraswap LP units locked by the user", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "ntrn_rewards": { + "description": "NTRN tokens received as rewards for participation in the lockdrop", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "unlock_timestamp": { + "description": "Timestamp beyond which this position can be unlocked", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "withdrawal_flag": { + "description": "Boolean value indicating if the user's has withdrawn funds post the only 1 withdrawal limit cutoff", + "type": "boolean" + } + } + }, + "PoolType": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + }, + "PoolType2": { + "type": "string", + "enum": [ + "USDC", + "ATOM" + ] + }, + "RestrictedVector_for_AssetInfo_and_Uint128": { + "description": "Vec wrapper for internal use. Some business logic relies on an order of this vector, thus it is forbidden to sort it or remove elements. New values can be added using .update() ONLY.", + "type": "array", + "items": { + "type": "array", + "items": [ + { + "$ref": "#/definitions/AssetInfo" + }, + { + "$ref": "#/definitions/Uint128" + } + ], + "maxItems": 2, + "minItems": 2 + } + }, + "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" + }, + "VestingAccount": { + "description": "This structure stores vesting information for a specific address that is getting tokens.", + "type": "object", + "required": [ + "address", + "schedules" + ], + "properties": { + "address": { + "description": "The address that is getting tokens", + "type": "string" + }, + "schedules": { + "description": "The vesting schedules targeted at the `address`", + "type": "array", + "items": { + "$ref": "#/definitions/VestingSchedule" + } + } + }, + "additionalProperties": false + }, + "VestingSchedule": { + "description": "This structure stores parameters for a specific vesting schedule", + "type": "object", + "required": [ + "start_point" + ], + "properties": { + "end_point": { + "description": "The end point for the vesting schedule", + "anyOf": [ + { + "$ref": "#/definitions/VestingSchedulePoint" + }, + { + "type": "null" + } + "incentives_address": { + "description": "incentives (Staking for dual rewards) contract address", + "type": [ + "string", + "null" + ] + } + } + }, + "UserInfo": { + "type": "object", + "required": [ + "lockup_positions_index", + "ntrn_transferred", + "total_ntrn_rewards" + ], + "properties": { + "lockup_positions_index": { + "description": "Number of lockup positions the user is having", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "start_point": { + "description": "The start date for the vesting schedule", + "allOf": [ + { + "$ref": "#/definitions/VestingSchedulePoint" + } + "ntrn_transferred": { + "description": "NTRN tokens transferred to user", + "type": "boolean" + }, + "total_ntrn_rewards": { + "description": "Total NTRN tokens user received as rewards for participation in the lockdrop", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + } + }, + "additionalProperties": false + }, + "VestingSchedulePoint": { + "description": "This structure stores the parameters used to create a vesting schedule.", + "type": "object", + "required": [ + "amount", + "time" + ], + "properties": { + "amount": { + "description": "The amount of tokens being vested", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "time": { + "description": "The start time for the vesting schedule", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + } +} diff --git a/contracts/vesting-lp-pcl/schema/raw/instantiate.json b/contracts/vesting-lp-pcl/schema/raw/instantiate.json new file mode 100644 index 00000000..cf950c42 --- /dev/null +++ b/contracts/vesting-lp-pcl/schema/raw/instantiate.json @@ -0,0 +1,92 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "description": "This structure describes the parameters used for creating a contract.", + "type": "object", + "required": [ + "owner", + "token_info_manager", + "vesting_managers", + "vesting_token", + "xyk_vesting_lp_contract" + ], + "properties": { + "owner": { + "description": "Address allowed to change contract parameters", + "type": "string" + }, + "token_info_manager": { + "description": "Token info manager address", + "type": "string" + }, + "vesting_managers": { + "description": "Initial list of whitelisted vesting managers", + "type": "array", + "items": { + "type": "string" + } + }, + "vesting_token": { + "$ref": "#/definitions/AssetInfo" + }, + "xyk_vesting_lp_contract": { + "type": "string" + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "AssetInfo": { + "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } +} diff --git a/contracts/vesting-lp-pcl/schema/raw/migrate.json b/contracts/vesting-lp-pcl/schema/raw/migrate.json new file mode 100644 index 00000000..1b9dcecf --- /dev/null +++ b/contracts/vesting-lp-pcl/schema/raw/migrate.json @@ -0,0 +1,7 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "MigrateMsg", + "description": "This structure describes a migration message. We currently take no arguments for migrations.", + "type": "object", + "additionalProperties": false +} diff --git a/contracts/vesting-lp-pcl/schema/raw/query.json b/contracts/vesting-lp-pcl/schema/raw/query.json new file mode 100644 index 00000000..64a0b398 --- /dev/null +++ b/contracts/vesting-lp-pcl/schema/raw/query.json @@ -0,0 +1,290 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "description": "This structure describes the query messages available in a vesting contract.", + "oneOf": [ + { + "description": "Returns the configuration for the contract using a [`ConfigResponse`] object.", + "type": "object", + "required": [ + "config" + ], + "properties": { + "config": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Returns information about an address vesting tokens using a [`VestingAccountResponse`] object.", + "type": "object", + "required": [ + "vesting_account" + ], + "properties": { + "vesting_account": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Returns a list of addresses that are vesting tokens using a [`VestingAccountsResponse`] object.", + "type": "object", + "required": [ + "vesting_accounts" + ], + "properties": { + "vesting_accounts": { + "type": "object", + "properties": { + "limit": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "order_by": { + "anyOf": [ + { + "$ref": "#/definitions/OrderBy" + }, + { + "type": "null" + } + ] + }, + "start_after": { + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Returns the total unvested amount of tokens for a specific address.", + "type": "object", + "required": [ + "available_amount" + ], + "properties": { + "available_amount": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Timestamp returns the current timestamp", + "type": "object", + "required": [ + "timestamp" + ], + "properties": { + "timestamp": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "VestingState returns the current vesting state.", + "type": "object", + "required": [ + "vesting_state" + ], + "properties": { + "vesting_state": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Contains messages associated with the managed extension for vesting contracts.", + "type": "object", + "required": [ + "managed_extension" + ], + "properties": { + "managed_extension": { + "type": "object", + "required": [ + "msg" + ], + "properties": { + "msg": { + "$ref": "#/definitions/QueryMsgManaged" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Contains messages associated with the with_managers extension for vesting contracts.", + "type": "object", + "required": [ + "with_managers_extension" + ], + "properties": { + "with_managers_extension": { + "type": "object", + "required": [ + "msg" + ], + "properties": { + "msg": { + "$ref": "#/definitions/QueryMsgWithManagers" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Contains messages associated with the historical extension for vesting contracts.", + "type": "object", + "required": [ + "historical_extension" + ], + "properties": { + "historical_extension": { + "type": "object", + "required": [ + "msg" + ], + "properties": { + "msg": { + "$ref": "#/definitions/QueryMsgHistorical" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ], + "definitions": { + "OrderBy": { + "description": "This enum describes the types of sorting that can be applied to some piece of data", + "type": "string", + "enum": [ + "asc", + "desc" + ] + }, + "QueryMsgHistorical": { + "description": "This structure describes the query messages available in a historical vesting contract.", + "oneOf": [ + { + "description": "Returns the total unclaimed amount of tokens for a specific address at certain height.", + "type": "object", + "required": [ + "unclaimed_amount_at_height" + ], + "properties": { + "unclaimed_amount_at_height": { + "type": "object", + "required": [ + "address", + "height" + ], + "properties": { + "address": { + "type": "string" + }, + "height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Returns the total unclaimed amount of tokens for all the users at certain height.", + "type": "object", + "required": [ + "unclaimed_total_amount_at_height" + ], + "properties": { + "unclaimed_total_amount_at_height": { + "type": "object", + "required": [ + "height" + ], + "properties": { + "height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "QueryMsgManaged": { + "description": "This structure describes the query messages available in a managed vesting contract.", + "type": "string", + "enum": [] + }, + "QueryMsgWithManagers": { + "description": "This structure describes the query messages available in a with_managers vesting contract.", + "oneOf": [ + { + "description": "Returns list of vesting managers (the persons who are able to add/remove vesting schedules)", + "type": "object", + "required": [ + "vesting_managers" + ], + "properties": { + "vesting_managers": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } +} diff --git a/contracts/vesting-lp-pcl/schema/raw/response_to_available_amount.json b/contracts/vesting-lp-pcl/schema/raw/response_to_available_amount.json new file mode 100644 index 00000000..25b73e8f --- /dev/null +++ b/contracts/vesting-lp-pcl/schema/raw/response_to_available_amount.json @@ -0,0 +1,6 @@ +{ + "$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/vesting-lp-pcl/schema/raw/response_to_config.json b/contracts/vesting-lp-pcl/schema/raw/response_to_config.json new file mode 100644 index 00000000..de35d970 --- /dev/null +++ b/contracts/vesting-lp-pcl/schema/raw/response_to_config.json @@ -0,0 +1,128 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Config", + "description": "This structure stores the main parameters for the generator vesting contract.", + "type": "object", + "required": [ + "extensions", + "owner", + "token_info_manager" + ], + "properties": { + "extensions": { + "description": "Contains extensions information of the contract", + "allOf": [ + { + "$ref": "#/definitions/Extensions" + } + ] + }, + "owner": { + "description": "Address that's allowed to change contract parameters", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "token_info_manager": { + "description": "Address that's allowed to change vesting token", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "vesting_token": { + "description": "[`AssetInfo`] of the vested token", + "anyOf": [ + { + "$ref": "#/definitions/AssetInfo" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "AssetInfo": { + "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Extensions": { + "description": "Contains extensions information for the contract.", + "type": "object", + "required": [ + "historical", + "managed", + "with_managers" + ], + "properties": { + "historical": { + "description": "Whether the historical extension is enabled for the contract.", + "type": "boolean" + }, + "managed": { + "description": "Whether the managed extension is enabled for the contract.", + "type": "boolean" + }, + "with_managers": { + "description": "Whether the with_managers extension is enabled for the contract.", + "type": "boolean" + } + }, + "additionalProperties": false + } + } +} diff --git a/contracts/vesting-lp-pcl/schema/raw/response_to_historical_extension.json b/contracts/vesting-lp-pcl/schema/raw/response_to_historical_extension.json new file mode 100644 index 00000000..83edad79 --- /dev/null +++ b/contracts/vesting-lp-pcl/schema/raw/response_to_historical_extension.json @@ -0,0 +1,59 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsgHistorical", + "description": "This structure describes the query messages available in a historical vesting contract.", + "oneOf": [ + { + "description": "Returns the total unclaimed amount of tokens for a specific address at certain height.", + "type": "object", + "required": [ + "unclaimed_amount_at_height" + ], + "properties": { + "unclaimed_amount_at_height": { + "type": "object", + "required": [ + "address", + "height" + ], + "properties": { + "address": { + "type": "string" + }, + "height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Returns the total unclaimed amount of tokens for all the users at certain height.", + "type": "object", + "required": [ + "unclaimed_total_amount_at_height" + ], + "properties": { + "unclaimed_total_amount_at_height": { + "type": "object", + "required": [ + "height" + ], + "properties": { + "height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] +} diff --git a/contracts/vesting-lp-pcl/schema/raw/response_to_managed_extension.json b/contracts/vesting-lp-pcl/schema/raw/response_to_managed_extension.json new file mode 100644 index 00000000..a46573aa --- /dev/null +++ b/contracts/vesting-lp-pcl/schema/raw/response_to_managed_extension.json @@ -0,0 +1,6 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "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" +} diff --git a/contracts/vesting-lp-pcl/schema/raw/response_to_timestamp.json b/contracts/vesting-lp-pcl/schema/raw/response_to_timestamp.json new file mode 100644 index 00000000..7b729a7b --- /dev/null +++ b/contracts/vesting-lp-pcl/schema/raw/response_to_timestamp.json @@ -0,0 +1,7 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "uint64", + "type": "integer", + "format": "uint64", + "minimum": 0.0 +} diff --git a/contracts/vesting-lp-pcl/schema/raw/response_to_vesting_account.json b/contracts/vesting-lp-pcl/schema/raw/response_to_vesting_account.json new file mode 100644 index 00000000..b85fc3d3 --- /dev/null +++ b/contracts/vesting-lp-pcl/schema/raw/response_to_vesting_account.json @@ -0,0 +1,119 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "VestingAccountResponse", + "description": "This structure describes a custom struct used to return vesting data about a specific vesting target.", + "type": "object", + "required": [ + "address", + "info" + ], + "properties": { + "address": { + "description": "The address that's vesting tokens", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "info": { + "description": "Vesting information", + "allOf": [ + { + "$ref": "#/definitions/VestingInfo" + } + ] + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "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" + }, + "VestingInfo": { + "description": "This structure stores parameters for a batch of vesting schedules.", + "type": "object", + "required": [ + "released_amount", + "schedules" + ], + "properties": { + "released_amount": { + "description": "The total amount of vested tokens already claimed", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "schedules": { + "description": "The vesting schedules", + "type": "array", + "items": { + "$ref": "#/definitions/VestingSchedule" + } + } + }, + "additionalProperties": false + }, + "VestingSchedule": { + "description": "This structure stores parameters for a specific vesting schedule", + "type": "object", + "required": [ + "start_point" + ], + "properties": { + "end_point": { + "description": "The end point for the vesting schedule", + "anyOf": [ + { + "$ref": "#/definitions/VestingSchedulePoint" + }, + { + "type": "null" + } + ] + }, + "start_point": { + "description": "The start date for the vesting schedule", + "allOf": [ + { + "$ref": "#/definitions/VestingSchedulePoint" + } + ] + } + }, + "additionalProperties": false + }, + "VestingSchedulePoint": { + "description": "This structure stores the parameters used to create a vesting schedule.", + "type": "object", + "required": [ + "amount", + "time" + ], + "properties": { + "amount": { + "description": "The amount of tokens being vested", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "time": { + "description": "The start time for the vesting schedule", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + } +} diff --git a/contracts/vesting-lp-pcl/schema/raw/response_to_vesting_accounts.json b/contracts/vesting-lp-pcl/schema/raw/response_to_vesting_accounts.json new file mode 100644 index 00000000..6d2af531 --- /dev/null +++ b/contracts/vesting-lp-pcl/schema/raw/response_to_vesting_accounts.json @@ -0,0 +1,136 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "VestingAccountsResponse", + "description": "This structure describes a custom struct used to return vesting data for multiple vesting targets.", + "type": "object", + "required": [ + "vesting_accounts" + ], + "properties": { + "vesting_accounts": { + "description": "A list of accounts that are vesting tokens", + "type": "array", + "items": { + "$ref": "#/definitions/VestingAccountResponse" + } + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "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" + }, + "VestingAccountResponse": { + "description": "This structure describes a custom struct used to return vesting data about a specific vesting target.", + "type": "object", + "required": [ + "address", + "info" + ], + "properties": { + "address": { + "description": "The address that's vesting tokens", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "info": { + "description": "Vesting information", + "allOf": [ + { + "$ref": "#/definitions/VestingInfo" + } + ] + } + }, + "additionalProperties": false + }, + "VestingInfo": { + "description": "This structure stores parameters for a batch of vesting schedules.", + "type": "object", + "required": [ + "released_amount", + "schedules" + ], + "properties": { + "released_amount": { + "description": "The total amount of vested tokens already claimed", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "schedules": { + "description": "The vesting schedules", + "type": "array", + "items": { + "$ref": "#/definitions/VestingSchedule" + } + } + }, + "additionalProperties": false + }, + "VestingSchedule": { + "description": "This structure stores parameters for a specific vesting schedule", + "type": "object", + "required": [ + "start_point" + ], + "properties": { + "end_point": { + "description": "The end point for the vesting schedule", + "anyOf": [ + { + "$ref": "#/definitions/VestingSchedulePoint" + }, + { + "type": "null" + } + ] + }, + "start_point": { + "description": "The start date for the vesting schedule", + "allOf": [ + { + "$ref": "#/definitions/VestingSchedulePoint" + } + ] + } + }, + "additionalProperties": false + }, + "VestingSchedulePoint": { + "description": "This structure stores the parameters used to create a vesting schedule.", + "type": "object", + "required": [ + "amount", + "time" + ], + "properties": { + "amount": { + "description": "The amount of tokens being vested", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "time": { + "description": "The start time for the vesting schedule", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + } +} diff --git a/contracts/vesting-lp-pcl/schema/raw/response_to_vesting_state.json b/contracts/vesting-lp-pcl/schema/raw/response_to_vesting_state.json new file mode 100644 index 00000000..b38701e4 --- /dev/null +++ b/contracts/vesting-lp-pcl/schema/raw/response_to_vesting_state.json @@ -0,0 +1,35 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "VestingState", + "description": "This structure stores the accumulated vesting information for all addresses.", + "type": "object", + "required": [ + "total_granted", + "total_released" + ], + "properties": { + "total_granted": { + "description": "The total amount of tokens granted to the users", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "total_released": { + "description": "The total amount of tokens already claimed", + "allOf": [ + { + "$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" + } + } +} diff --git a/contracts/vesting-lp-pcl/schema/raw/response_to_with_managers_extension.json b/contracts/vesting-lp-pcl/schema/raw/response_to_with_managers_extension.json new file mode 100644 index 00000000..bcacc2ac --- /dev/null +++ b/contracts/vesting-lp-pcl/schema/raw/response_to_with_managers_extension.json @@ -0,0 +1,21 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsgWithManagers", + "description": "This structure describes the query messages available in a with_managers vesting contract.", + "oneOf": [ + { + "description": "Returns list of vesting managers (the persons who are able to add/remove vesting schedules)", + "type": "object", + "required": [ + "vesting_managers" + ], + "properties": { + "vesting_managers": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] +} diff --git a/contracts/vesting-lp-pcl/schema/vesting-lp-pcl.json b/contracts/vesting-lp-pcl/schema/vesting-lp-pcl.json new file mode 100644 index 00000000..d05a001f --- /dev/null +++ b/contracts/vesting-lp-pcl/schema/vesting-lp-pcl.json @@ -0,0 +1,1391 @@ +{ + "contract_name": "vesting-lp-pcl", + "contract_version": "1.1.0", + "idl_version": "1.0.0", + "instantiate": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "description": "This structure describes the parameters used for creating a contract.", + "type": "object", + "required": [ + "owner", + "token_info_manager", + "vesting_managers", + "vesting_token", + "xyk_vesting_lp_contract" + ], + "properties": { + "owner": { + "description": "Address allowed to change contract parameters", + "type": "string" + }, + "token_info_manager": { + "description": "Token info manager address", + "type": "string" + }, + "vesting_managers": { + "description": "Initial list of whitelisted vesting managers", + "type": "array", + "items": { + "type": "string" + } + }, + "vesting_token": { + "$ref": "#/definitions/AssetInfo" + }, + "xyk_vesting_lp_contract": { + "type": "string" + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "AssetInfo": { + "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + }, + "execute": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "claim" + ], + "properties": { + "claim": { + "type": "object", + "properties": { + "amount": { + "description": "The amount of tokens to claim", + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "recipient": { + "description": "The address that receives the vested tokens", + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "RegisterVestingAccounts registers vesting targets/accounts", + "type": "object", + "required": [ + "register_vesting_accounts" + ], + "properties": { + "register_vesting_accounts": { + "type": "object", + "required": [ + "vesting_accounts" + ], + "properties": { + "vesting_accounts": { + "type": "array", + "items": { + "$ref": "#/definitions/VestingAccount" + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Creates a request to change contract ownership ## Executor Only the current owner can execute this", + "type": "object", + "required": [ + "propose_new_owner" + ], + "properties": { + "propose_new_owner": { + "type": "object", + "required": [ + "expires_in", + "owner" + ], + "properties": { + "expires_in": { + "description": "The validity period of the offer to change the owner", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "owner": { + "description": "The newly proposed owner", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Removes a request to change contract ownership ## Executor Only the current owner can execute this", + "type": "object", + "required": [ + "drop_ownership_proposal" + ], + "properties": { + "drop_ownership_proposal": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Claims contract ownership ## Executor Only the newly proposed owner can execute this", + "type": "object", + "required": [ + "claim_ownership" + ], + "properties": { + "claim_ownership": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Sets vesting token ## Executor Only the current owner or token info manager can execute this", + "type": "object", + "required": [ + "set_vesting_token" + ], + "properties": { + "set_vesting_token": { + "type": "object", + "required": [ + "vesting_token" + ], + "properties": { + "vesting_token": { + "$ref": "#/definitions/AssetInfo" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Contains messages associated with the managed extension for vesting contracts.", + "type": "object", + "required": [ + "managed_extension" + ], + "properties": { + "managed_extension": { + "type": "object", + "required": [ + "msg" + ], + "properties": { + "msg": { + "$ref": "#/definitions/ExecuteMsgManaged" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Contains messages associated with the with_managers extension for vesting contracts.", + "type": "object", + "required": [ + "with_managers_extension" + ], + "properties": { + "with_managers_extension": { + "type": "object", + "required": [ + "msg" + ], + "properties": { + "msg": { + "$ref": "#/definitions/ExecuteMsgWithManagers" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Contains messages associated with the historical extension for vesting contracts.", + "type": "object", + "required": [ + "historical_extension" + ], + "properties": { + "historical_extension": { + "type": "object", + "required": [ + "msg" + ], + "properties": { + "msg": { + "$ref": "#/definitions/ExecuteMsgHistorical" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "receive" + ], + "properties": { + "receive": { + "$ref": "#/definitions/Cw20ReceiveMsg" + } + }, + "additionalProperties": false + } + ], + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "AssetInfo": { + "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "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" + }, + "Cw20ReceiveMsg": { + "description": "Cw20ReceiveMsg should be de/serialized under `Receive()` variant in a ExecuteMsg", + "type": "object", + "required": [ + "amount", + "msg", + "sender" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "msg": { + "$ref": "#/definitions/Binary" + }, + "sender": { + "type": "string" + } + }, + "additionalProperties": false + }, + "ExecuteMsgHistorical": { + "description": "This structure describes the execute messages available in a historical vesting contract.", + "type": "string", + "enum": [] + }, + "ExecuteMsgManaged": { + "description": "This structure describes the execute messages available in a managed vesting contract.", + "oneOf": [ + { + "description": "Removes vesting targets/accounts. ## Executor Only the current owner can execute this", + "type": "object", + "required": [ + "remove_vesting_accounts" + ], + "properties": { + "remove_vesting_accounts": { + "type": "object", + "required": [ + "clawback_account", + "vesting_accounts" + ], + "properties": { + "clawback_account": { + "description": "Specifies the account that will receive the funds taken from the vesting accounts.", + "type": "string" + }, + "vesting_accounts": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "ExecuteMsgWithManagers": { + "description": "This structure describes the execute messages available in a with_managers vesting contract.", + "oneOf": [ + { + "description": "Adds vesting managers ## Executor Only the current owner can execute this", + "type": "object", + "required": [ + "add_vesting_managers" + ], + "properties": { + "add_vesting_managers": { + "type": "object", + "required": [ + "managers" + ], + "properties": { + "managers": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Removes vesting managers ## Executor Only the current owner can execute this", + "type": "object", + "required": [ + "remove_vesting_managers" + ], + "properties": { + "remove_vesting_managers": { + "type": "object", + "required": [ + "managers" + ], + "properties": { + "managers": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "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" + }, + "VestingAccount": { + "description": "This structure stores vesting information for a specific address that is getting tokens.", + "type": "object", + "required": [ + "address", + "schedules" + ], + "properties": { + "address": { + "description": "The address that is getting tokens", + "type": "string" + }, + "schedules": { + "description": "The vesting schedules targeted at the `address`", + "type": "array", + "items": { + "$ref": "#/definitions/VestingSchedule" + } + } + }, + "additionalProperties": false + }, + "VestingSchedule": { + "description": "This structure stores parameters for a specific vesting schedule", + "type": "object", + "required": [ + "start_point" + ], + "properties": { + "end_point": { + "description": "The end point for the vesting schedule", + "anyOf": [ + { + "$ref": "#/definitions/VestingSchedulePoint" + }, + { + "type": "null" + } + ] + }, + "start_point": { + "description": "The start date for the vesting schedule", + "allOf": [ + { + "$ref": "#/definitions/VestingSchedulePoint" + } + ] + } + }, + "additionalProperties": false + }, + "VestingSchedulePoint": { + "description": "This structure stores the parameters used to create a vesting schedule.", + "type": "object", + "required": [ + "amount", + "time" + ], + "properties": { + "amount": { + "description": "The amount of tokens being vested", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "time": { + "description": "The start time for the vesting schedule", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + } + }, + "query": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "description": "This structure describes the query messages available in a vesting contract.", + "oneOf": [ + { + "description": "Returns the configuration for the contract using a [`ConfigResponse`] object.", + "type": "object", + "required": [ + "config" + ], + "properties": { + "config": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Returns information about an address vesting tokens using a [`VestingAccountResponse`] object.", + "type": "object", + "required": [ + "vesting_account" + ], + "properties": { + "vesting_account": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Returns a list of addresses that are vesting tokens using a [`VestingAccountsResponse`] object.", + "type": "object", + "required": [ + "vesting_accounts" + ], + "properties": { + "vesting_accounts": { + "type": "object", + "properties": { + "limit": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "order_by": { + "anyOf": [ + { + "$ref": "#/definitions/OrderBy" + }, + { + "type": "null" + } + ] + }, + "start_after": { + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Returns the total unvested amount of tokens for a specific address.", + "type": "object", + "required": [ + "available_amount" + ], + "properties": { + "available_amount": { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Timestamp returns the current timestamp", + "type": "object", + "required": [ + "timestamp" + ], + "properties": { + "timestamp": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "VestingState returns the current vesting state.", + "type": "object", + "required": [ + "vesting_state" + ], + "properties": { + "vesting_state": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Contains messages associated with the managed extension for vesting contracts.", + "type": "object", + "required": [ + "managed_extension" + ], + "properties": { + "managed_extension": { + "type": "object", + "required": [ + "msg" + ], + "properties": { + "msg": { + "$ref": "#/definitions/QueryMsgManaged" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Contains messages associated with the with_managers extension for vesting contracts.", + "type": "object", + "required": [ + "with_managers_extension" + ], + "properties": { + "with_managers_extension": { + "type": "object", + "required": [ + "msg" + ], + "properties": { + "msg": { + "$ref": "#/definitions/QueryMsgWithManagers" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Contains messages associated with the historical extension for vesting contracts.", + "type": "object", + "required": [ + "historical_extension" + ], + "properties": { + "historical_extension": { + "type": "object", + "required": [ + "msg" + ], + "properties": { + "msg": { + "$ref": "#/definitions/QueryMsgHistorical" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ], + "definitions": { + "OrderBy": { + "description": "This enum describes the types of sorting that can be applied to some piece of data", + "type": "string", + "enum": [ + "asc", + "desc" + ] + }, + "QueryMsgHistorical": { + "description": "This structure describes the query messages available in a historical vesting contract.", + "oneOf": [ + { + "description": "Returns the total unclaimed amount of tokens for a specific address at certain height.", + "type": "object", + "required": [ + "unclaimed_amount_at_height" + ], + "properties": { + "unclaimed_amount_at_height": { + "type": "object", + "required": [ + "address", + "height" + ], + "properties": { + "address": { + "type": "string" + }, + "height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Returns the total unclaimed amount of tokens for all the users at certain height.", + "type": "object", + "required": [ + "unclaimed_total_amount_at_height" + ], + "properties": { + "unclaimed_total_amount_at_height": { + "type": "object", + "required": [ + "height" + ], + "properties": { + "height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "QueryMsgManaged": { + "description": "This structure describes the query messages available in a managed vesting contract.", + "type": "string", + "enum": [] + }, + "QueryMsgWithManagers": { + "description": "This structure describes the query messages available in a with_managers vesting contract.", + "oneOf": [ + { + "description": "Returns list of vesting managers (the persons who are able to add/remove vesting schedules)", + "type": "object", + "required": [ + "vesting_managers" + ], + "properties": { + "vesting_managers": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + }, + "migrate": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "MigrateMsg", + "description": "This structure describes a migration message. We currently take no arguments for migrations.", + "type": "object", + "additionalProperties": false + }, + "sudo": null, + "responses": { + "available_amount": { + "$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" + }, + "config": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Config", + "description": "This structure stores the main parameters for the generator vesting contract.", + "type": "object", + "required": [ + "extensions", + "owner", + "token_info_manager" + ], + "properties": { + "extensions": { + "description": "Contains extensions information of the contract", + "allOf": [ + { + "$ref": "#/definitions/Extensions" + } + ] + }, + "owner": { + "description": "Address that's allowed to change contract parameters", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "token_info_manager": { + "description": "Address that's allowed to change vesting token", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "vesting_token": { + "description": "[`AssetInfo`] of the vested token", + "anyOf": [ + { + "$ref": "#/definitions/AssetInfo" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "AssetInfo": { + "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", + "oneOf": [ + { + "description": "Non-native Token", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Native token", + "type": "object", + "required": [ + "native_token" + ], + "properties": { + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "Extensions": { + "description": "Contains extensions information for the contract.", + "type": "object", + "required": [ + "historical", + "managed", + "with_managers" + ], + "properties": { + "historical": { + "description": "Whether the historical extension is enabled for the contract.", + "type": "boolean" + }, + "managed": { + "description": "Whether the managed extension is enabled for the contract.", + "type": "boolean" + }, + "with_managers": { + "description": "Whether the with_managers extension is enabled for the contract.", + "type": "boolean" + } + }, + "additionalProperties": false + } + } + }, + "historical_extension": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsgHistorical", + "description": "This structure describes the query messages available in a historical vesting contract.", + "oneOf": [ + { + "description": "Returns the total unclaimed amount of tokens for a specific address at certain height.", + "type": "object", + "required": [ + "unclaimed_amount_at_height" + ], + "properties": { + "unclaimed_amount_at_height": { + "type": "object", + "required": [ + "address", + "height" + ], + "properties": { + "address": { + "type": "string" + }, + "height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Returns the total unclaimed amount of tokens for all the users at certain height.", + "type": "object", + "required": [ + "unclaimed_total_amount_at_height" + ], + "properties": { + "unclaimed_total_amount_at_height": { + "type": "object", + "required": [ + "height" + ], + "properties": { + "height": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "managed_extension": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "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" + }, + "timestamp": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "uint64", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "vesting_account": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "VestingAccountResponse", + "description": "This structure describes a custom struct used to return vesting data about a specific vesting target.", + "type": "object", + "required": [ + "address", + "info" + ], + "properties": { + "address": { + "description": "The address that's vesting tokens", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "info": { + "description": "Vesting information", + "allOf": [ + { + "$ref": "#/definitions/VestingInfo" + } + ] + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "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" + }, + "VestingInfo": { + "description": "This structure stores parameters for a batch of vesting schedules.", + "type": "object", + "required": [ + "released_amount", + "schedules" + ], + "properties": { + "released_amount": { + "description": "The total amount of vested tokens already claimed", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "schedules": { + "description": "The vesting schedules", + "type": "array", + "items": { + "$ref": "#/definitions/VestingSchedule" + } + } + }, + "additionalProperties": false + }, + "VestingSchedule": { + "description": "This structure stores parameters for a specific vesting schedule", + "type": "object", + "required": [ + "start_point" + ], + "properties": { + "end_point": { + "description": "The end point for the vesting schedule", + "anyOf": [ + { + "$ref": "#/definitions/VestingSchedulePoint" + }, + { + "type": "null" + } + ] + }, + "start_point": { + "description": "The start date for the vesting schedule", + "allOf": [ + { + "$ref": "#/definitions/VestingSchedulePoint" + } + ] + } + }, + "additionalProperties": false + }, + "VestingSchedulePoint": { + "description": "This structure stores the parameters used to create a vesting schedule.", + "type": "object", + "required": [ + "amount", + "time" + ], + "properties": { + "amount": { + "description": "The amount of tokens being vested", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "time": { + "description": "The start time for the vesting schedule", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + } + }, + "vesting_accounts": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "VestingAccountsResponse", + "description": "This structure describes a custom struct used to return vesting data for multiple vesting targets.", + "type": "object", + "required": [ + "vesting_accounts" + ], + "properties": { + "vesting_accounts": { + "description": "A list of accounts that are vesting tokens", + "type": "array", + "items": { + "$ref": "#/definitions/VestingAccountResponse" + } + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "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" + }, + "VestingAccountResponse": { + "description": "This structure describes a custom struct used to return vesting data about a specific vesting target.", + "type": "object", + "required": [ + "address", + "info" + ], + "properties": { + "address": { + "description": "The address that's vesting tokens", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "info": { + "description": "Vesting information", + "allOf": [ + { + "$ref": "#/definitions/VestingInfo" + } + ] + } + }, + "additionalProperties": false + }, + "VestingInfo": { + "description": "This structure stores parameters for a batch of vesting schedules.", + "type": "object", + "required": [ + "released_amount", + "schedules" + ], + "properties": { + "released_amount": { + "description": "The total amount of vested tokens already claimed", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "schedules": { + "description": "The vesting schedules", + "type": "array", + "items": { + "$ref": "#/definitions/VestingSchedule" + } + } + }, + "additionalProperties": false + }, + "VestingSchedule": { + "description": "This structure stores parameters for a specific vesting schedule", + "type": "object", + "required": [ + "start_point" + ], + "properties": { + "end_point": { + "description": "The end point for the vesting schedule", + "anyOf": [ + { + "$ref": "#/definitions/VestingSchedulePoint" + }, + { + "type": "null" + } + ] + }, + "start_point": { + "description": "The start date for the vesting schedule", + "allOf": [ + { + "$ref": "#/definitions/VestingSchedulePoint" + } + ] + } + }, + "additionalProperties": false + }, + "VestingSchedulePoint": { + "description": "This structure stores the parameters used to create a vesting schedule.", + "type": "object", + "required": [ + "amount", + "time" + ], + "properties": { + "amount": { + "description": "The amount of tokens being vested", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "time": { + "description": "The start time for the vesting schedule", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + } + } + }, + "vesting_state": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "VestingState", + "description": "This structure stores the accumulated vesting information for all addresses.", + "type": "object", + "required": [ + "total_granted", + "total_released" + ], + "properties": { + "total_granted": { + "description": "The total amount of tokens granted to the users", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "total_released": { + "description": "The total amount of tokens already claimed", + "allOf": [ + { + "$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" + } + } + }, + "with_managers_extension": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsgWithManagers", + "description": "This structure describes the query messages available in a with_managers vesting contract.", + "oneOf": [ + { + "description": "Returns list of vesting managers (the persons who are able to add/remove vesting schedules)", + "type": "object", + "required": [ + "vesting_managers" + ], + "properties": { + "vesting_managers": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } +} diff --git a/contracts/vesting-lp-pcl/src/contract.rs b/contracts/vesting-lp-pcl/src/contract.rs new file mode 100644 index 00000000..89f3d6dd --- /dev/null +++ b/contracts/vesting-lp-pcl/src/contract.rs @@ -0,0 +1,176 @@ +use crate::msg::{Cw20HookMsg, ExecuteMsg, InstantiateMsg}; +use crate::state::XYK_VESTING_LP_CONTRACT; +use astroport::asset::token_asset_info; +use cosmwasm_std::{ + entry_point, from_json, Addr, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult, + Storage, Uint128, +}; +use cw2::set_contract_version; +use cw20::Cw20ReceiveMsg; +use vesting_base::error::ContractError; +use vesting_base::handlers::{execute as base_execute, query as base_query}; +use vesting_base::handlers::{get_vesting_token, register_vesting_accounts}; +use vesting_base::msg::{ExecuteMsg as BaseExecute, QueryMsg}; +use vesting_base::state::{vesting_info, vesting_state, CONFIG, VESTING_MANAGERS}; +use vesting_base::types::{Config, Extensions, VestingInfo}; + +/// Contract name that is used for migration. +const CONTRACT_NAME: &str = "neutron-vesting-lp-pcl"; +/// Contract version that is used for migration. +const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +/// Creates a new contract with the specified parameters packed in the `msg` variable. +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + deps: DepsMut, + _env: Env, + _info: MessageInfo, + msg: InstantiateMsg, +) -> StdResult { + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + let owner = deps.api.addr_validate(&msg.owner)?; + CONFIG.save( + deps.storage, + &Config { + owner, + vesting_token: Option::from(msg.vesting_token), + token_info_manager: deps.api.addr_validate(&msg.token_info_manager)?, + + extensions: Extensions { + historical: true, + managed: false, + with_managers: true, + }, + }, + )?; + for m in msg.vesting_managers.iter() { + let ma = deps.api.addr_validate(m)?; + VESTING_MANAGERS.save(deps.storage, ma, &())?; + } + XYK_VESTING_LP_CONTRACT.save( + deps.storage, + &deps + .api + .addr_validate(&msg.xyk_vesting_lp_contract.clone())?, + )?; + Ok(Response::default()) +} + +/// Exposes execute functions available in the contract. +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: ExecuteMsg, +) -> Result { + match msg { + ExecuteMsg::Receive(msg) => receive_cw20(deps, env, info, msg), + _ => { + let base_msg: BaseExecute = msg.into(); + base_execute(deps, env, info, base_msg) + } + } +} + +/// Receives a message of type [`Cw20HookMsg`] and processes it depending on the received template. +/// +/// * **cw20_msg** CW20 message to process. +fn receive_cw20( + deps: DepsMut, + env: Env, + info: MessageInfo, + cw20_msg: Cw20ReceiveMsg, +) -> Result { + let config = CONFIG.load(deps.storage)?; + let vesting_token = get_vesting_token(&config)?; + let sender = info.sender; + + match from_json(&cw20_msg.msg)? { + Cw20HookMsg::RegisterVestingAccounts { vesting_accounts } => { + if !is_sender_whitelisted( + deps.storage, + &config, + &deps.api.addr_validate(cw20_msg.sender.as_str())?, + ) || token_asset_info(sender.clone()) != vesting_token + { + return Err(ContractError::Unauthorized {}); + } + register_vesting_accounts(deps, vesting_accounts, cw20_msg.amount, env.block.height) + } + Cw20HookMsg::MigrateXYKLiquidity { + user_address_raw, + user_vesting_info, + } => { + if !is_sender_xyk_vesting_lp( + deps.storage, + &deps.api.addr_validate(cw20_msg.sender.as_str())?, + ) { + return Err(ContractError::Unauthorized {}); + } + handle_migrate_xyk_liquidity(deps, env, user_address_raw, user_vesting_info) + } + } +} + +fn is_sender_whitelisted(store: &mut dyn Storage, config: &Config, sender: &Addr) -> bool { + if *sender == config.owner { + return true; + } + if VESTING_MANAGERS.has(store, sender.clone()) { + return true; + } + + false +} + +fn is_sender_xyk_vesting_lp(store: &mut dyn Storage, sender: &Addr) -> bool { + let xyk_vesting_lp_contract = XYK_VESTING_LP_CONTRACT.load(store).unwrap(); + if *sender == xyk_vesting_lp_contract { + return true; + } + + false +} + +fn handle_migrate_xyk_liquidity( + deps: DepsMut, + env: Env, + user_addr: Addr, + user_vesting_info: VestingInfo, +) -> Result { + let height = env.block.height; + let config = CONFIG.load(deps.storage)?; + + let mut to_deposit = Uint128::zero(); + for sch in &user_vesting_info.schedules { + let amount = if let Some(end_point) = &sch.end_point { + end_point.amount + } else { + sch.start_point.amount + }; + to_deposit = to_deposit.checked_add(amount)?; + } + + let vesting_info = vesting_info(config.extensions.historical); + + vesting_info.save(deps.storage, user_addr, &user_vesting_info, height)?; + + vesting_state(config.extensions.historical).update::<_, ContractError>( + deps.storage, + height, + |s| { + let mut state = s.unwrap_or_default(); + state.total_granted = state.total_granted.checked_add(to_deposit)?; + Ok(state) + }, + )?; + + Ok(Response::default()) +} + +/// Exposes all the queries available in the contract. +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { + base_query(deps, env, msg) +} diff --git a/contracts/vesting-lp-pcl/src/lib.rs b/contracts/vesting-lp-pcl/src/lib.rs new file mode 100644 index 00000000..4934c19d --- /dev/null +++ b/contracts/vesting-lp-pcl/src/lib.rs @@ -0,0 +1,3 @@ +pub mod contract; +pub mod msg; +pub mod state; diff --git a/contracts/vesting-lp-pcl/src/msg.rs b/contracts/vesting-lp-pcl/src/msg.rs new file mode 100644 index 00000000..2af63d0d --- /dev/null +++ b/contracts/vesting-lp-pcl/src/msg.rs @@ -0,0 +1,110 @@ +use astroport::asset::AssetInfo; +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{Addr, Uint128}; +use cw20::Cw20ReceiveMsg; +use vesting_base::msg::{ + ExecuteMsg as BaseExecute, ExecuteMsgHistorical, ExecuteMsgManaged, ExecuteMsgWithManagers, +}; +use vesting_base::types::{VestingAccount, VestingInfo}; + +/// This structure describes the parameters used for creating a contract. +#[cw_serde] +pub struct InstantiateMsg { + /// Address allowed to change contract parameters + pub owner: String, + /// Initial list of whitelisted vesting managers + pub vesting_managers: Vec, + /// Token info manager address + pub token_info_manager: String, + pub xyk_vesting_lp_contract: String, + pub vesting_token: AssetInfo, +} + +#[cw_serde] +pub enum ExecuteMsg { + // Claim claims vested tokens and sends them to a recipient + Claim { + /// The address that receives the vested tokens + recipient: Option, + /// The amount of tokens to claim + amount: Option, + }, + /// RegisterVestingAccounts registers vesting targets/accounts + RegisterVestingAccounts { + vesting_accounts: Vec, + }, + /// Creates a request to change contract ownership + /// ## Executor + /// Only the current owner can execute this + ProposeNewOwner { + /// The newly proposed owner + owner: String, + /// The validity period of the offer to change the owner + expires_in: u64, + }, + /// Removes a request to change contract ownership + /// ## Executor + /// Only the current owner can execute this + DropOwnershipProposal {}, + /// Claims contract ownership + /// ## Executor + /// Only the newly proposed owner can execute this + ClaimOwnership {}, + /// Sets vesting token + /// ## Executor + /// Only the current owner or token info manager can execute this + SetVestingToken { + vesting_token: AssetInfo, + }, + /// Contains messages associated with the managed extension for vesting contracts. + ManagedExtension { + msg: ExecuteMsgManaged, + }, + /// Contains messages associated with the with_managers extension for vesting contracts. + WithManagersExtension { + msg: ExecuteMsgWithManagers, + }, + /// Contains messages associated with the historical extension for vesting contracts. + HistoricalExtension { + msg: ExecuteMsgHistorical, + }, + Receive(Cw20ReceiveMsg), +} + +/// This structure describes a CW20 hook message. +#[cw_serde] +pub enum Cw20HookMsg { + /// RegisterVestingAccounts registers vesting targets/accounts + RegisterVestingAccounts { + vesting_accounts: Vec, + }, + #[serde(rename = "migrate_xyk_liquidity")] + MigrateXYKLiquidity { + /// The address of the user which owns the vested tokens. + user_address_raw: Addr, + user_vesting_info: VestingInfo, + }, +} + +impl From for BaseExecute { + fn from(item: ExecuteMsg) -> Self { + match item { + ExecuteMsg::Claim { recipient, amount } => BaseExecute::Claim { recipient, amount }, + ExecuteMsg::RegisterVestingAccounts { vesting_accounts } => { + BaseExecute::RegisterVestingAccounts { vesting_accounts } + } + ExecuteMsg::ProposeNewOwner { owner, expires_in } => { + BaseExecute::ProposeNewOwner { owner, expires_in } + } + ExecuteMsg::DropOwnershipProposal {} => BaseExecute::DropOwnershipProposal {}, + ExecuteMsg::ClaimOwnership {} => BaseExecute::ClaimOwnership {}, + ExecuteMsg::SetVestingToken { vesting_token } => { + BaseExecute::SetVestingToken { vesting_token } + } + ExecuteMsg::ManagedExtension { msg } => BaseExecute::ManagedExtension { msg }, + ExecuteMsg::WithManagersExtension { msg } => BaseExecute::WithManagersExtension { msg }, + ExecuteMsg::HistoricalExtension { msg } => BaseExecute::HistoricalExtension { msg }, + _ => panic!("Unhandled ExecuteMsg variant"), + } + } +} diff --git a/contracts/vesting-lp-pcl/src/state.rs b/contracts/vesting-lp-pcl/src/state.rs new file mode 100644 index 00000000..e3fb2078 --- /dev/null +++ b/contracts/vesting-lp-pcl/src/state.rs @@ -0,0 +1,3 @@ +use cosmwasm_std::Addr; +use cw_storage_plus::Item; +pub(crate) const XYK_VESTING_LP_CONTRACT: Item = Item::new("xyk_vesting_lp_contract"); diff --git a/contracts/vesting-lp/.cargo/config b/contracts/vesting-lp/.cargo/config index f2fbc6a9..a79b8fdb 100644 --- a/contracts/vesting-lp/.cargo/config +++ b/contracts/vesting-lp/.cargo/config @@ -3,4 +3,4 @@ wasm = "build --release --target wasm32-unknown-unknown" wasm-debug = "build --target wasm32-unknown-unknown" unit-test = "test --lib" integration-test = "test --test integration" -schema = "run --example vesting-lp_schema" +schema = "run --example vesting_schema" diff --git a/contracts/vesting-lp/Cargo.toml b/contracts/vesting-lp/Cargo.toml index 31f70c7c..1ff8cfd2 100644 --- a/contracts/vesting-lp/Cargo.toml +++ b/contracts/vesting-lp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "vesting-lp" -version = "1.1.0" +version = "1.2.0" authors = ["Neutron"] edition = "2021" description = "Vesting contract with a voting capabilities. Provides queries to get the amount of tokens are being held by user at certain height." @@ -9,20 +9,21 @@ description = "Vesting contract with a voting capabilities. Provides queries to crate-type = ["cdylib", "rlib"] [features] -# for more explicit tests, cargo test --features=backtraces -backtraces = ["cosmwasm-std/backtraces"] # use library feature to disable all init/handle/query exports library = [] [dependencies] -cw2 = { workspace = true } -cw20 = { workspace = true } -astroport = { workspace = true } -vesting-base = { workspace = true } -cosmwasm-schema = { workspace = true } -cosmwasm-std = { workspace = true } +cw2 = { version = "0.15" } +vesting-base = { path = "../../packages/vesting-base" } +vesting-lp-pcl = { path = "../vesting-lp-pcl" } +astroport = { path = "../../packages/astroport" } +cosmwasm-schema = { version = "1.1", default-features = false } +cosmwasm-std = { version = "1.1" } +cw-storage-plus = "0.15" +cw20 = { version = "0.15" } [dev-dependencies] -cw-multi-test = { workspace = true } -astroport-token = {git = "https://github.com/astroport-fi/astroport-core.git", rev = "65ce7d1879cc5d95b09fa14202f0423bba52ae0e" } +cw-multi-test = "0.15" +astroport-token = { git = "https://github.com/astroport-fi/astroport-core.git", rev = "65ce7d1879cc5d95b09fa14202f0423bba52ae0e" } +cw20 = { version = "0.15" } cw-utils = "0.15" diff --git a/contracts/vesting-lp/examples/vesting-lp_schema.rs b/contracts/vesting-lp/examples/vesting-lp_schema.rs index 90284134..821d12fc 100644 --- a/contracts/vesting-lp/examples/vesting-lp_schema.rs +++ b/contracts/vesting-lp/examples/vesting-lp_schema.rs @@ -1,6 +1,6 @@ use cosmwasm_schema::write_api; -use vesting_base::msg::{ExecuteMsg, MigrateMsg, QueryMsg}; -use vesting_lp::msg::InstantiateMsg; +use vesting_base::msg::QueryMsg; +use vesting_lp::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg}; fn main() { write_api! { diff --git a/contracts/vesting-lp/schema/raw/execute.json b/contracts/vesting-lp/schema/raw/execute.json index e5aa732d..c981b115 100644 --- a/contracts/vesting-lp/schema/raw/execute.json +++ b/contracts/vesting-lp/schema/raw/execute.json @@ -1,31 +1,29 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "title": "ExecuteMsg", - "description": "This structure describes the execute messages available in a vesting contract.", "oneOf": [ { - "description": "Claim claims vested tokens and sends them to a recipient", "type": "object", "required": [ - "claim" + "base" ], "properties": { - "claim": { + "base": { + "$ref": "#/definitions/ExecuteMsg" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "migrate_liquidity_to_pcl_pool" + ], + "properties": { + "migrate_liquidity_to_pcl_pool": { "type": "object", "properties": { - "amount": { - "description": "The amount of tokens to claim", - "anyOf": [ - { - "$ref": "#/definitions/Uint128" - }, - { - "type": "null" - } - ] - }, - "recipient": { - "description": "The address that receives the vested tokens", + "user": { "type": [ "string", "null" @@ -38,213 +36,369 @@ "additionalProperties": false }, { - "description": "Receives a message of type [`Cw20ReceiveMsg`] and processes it depending on the received template", + "description": "Callbacks; only callable by the contract itself.", "type": "object", "required": [ - "receive" + "callback" ], "properties": { - "receive": { - "$ref": "#/definitions/Cw20ReceiveMsg" + "callback": { + "$ref": "#/definitions/CallbackMsg" } }, "additionalProperties": false + } + ], + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" }, - { - "description": "RegisterVestingAccounts registers vesting targets/accounts", - "type": "object", - "required": [ - "register_vesting_accounts" - ], - "properties": { - "register_vesting_accounts": { + "AssetInfo": { + "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", + "oneOf": [ + { + "description": "Non-native Token", "type": "object", "required": [ - "vesting_accounts" + "token" ], "properties": { - "vesting_accounts": { - "type": "array", - "items": { - "$ref": "#/definitions/VestingAccount" - } + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false } }, "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Creates a request to change contract ownership ## Executor Only the current owner can execute this", - "type": "object", - "required": [ - "propose_new_owner" - ], - "properties": { - "propose_new_owner": { + }, + { + "description": "Native token", "type": "object", "required": [ - "expires_in", - "owner" + "native_token" ], "properties": { - "expires_in": { - "description": "The validity period of the offer to change the owner", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "owner": { - "description": "The newly proposed owner", - "type": "string" + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false } }, "additionalProperties": false } - }, - "additionalProperties": false + ] }, - { - "description": "Removes a request to change contract ownership ## Executor Only the current owner can execute this", - "type": "object", - "required": [ - "drop_ownership_proposal" - ], - "properties": { - "drop_ownership_proposal": { + "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" + }, + "CallbackMsg": { + "oneOf": [ + { + "type": "object", + "required": [ + "migrate_liquidity_to_cl_pair" + ], + "properties": { + "migrate_liquidity_to_cl_pair": { + "type": "object", + "required": [ + "amount", + "cl_pair", + "ntrn_denom", + "paired_asset_denom", + "slippage_tolerance", + "user", + "xyk_lp_token", + "xyk_pair" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "cl_pair": { + "$ref": "#/definitions/Addr" + }, + "ntrn_denom": { + "type": "string" + }, + "paired_asset_denom": { + "type": "string" + }, + "slippage_tolerance": { + "$ref": "#/definitions/Decimal" + }, + "user": { + "$ref": "#/definitions/VestingAccountResponse" + }, + "xyk_lp_token": { + "$ref": "#/definitions/Addr" + }, + "xyk_pair": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { "type": "object", + "required": [ + "provide_liquidity_to_cl_pair_after_withdrawal" + ], + "properties": { + "provide_liquidity_to_cl_pair_after_withdrawal": { + "type": "object", + "required": [ + "cl_pair", + "ntrn_denom", + "ntrn_init_balance", + "paired_asset_denom", + "paired_asset_init_balance", + "slippage_tolerance", + "user" + ], + "properties": { + "cl_pair": { + "$ref": "#/definitions/Addr" + }, + "ntrn_denom": { + "type": "string" + }, + "ntrn_init_balance": { + "$ref": "#/definitions/Uint128" + }, + "paired_asset_denom": { + "type": "string" + }, + "paired_asset_init_balance": { + "$ref": "#/definitions/Uint128" + }, + "slippage_tolerance": { + "$ref": "#/definitions/Decimal" + }, + "user": { + "$ref": "#/definitions/VestingAccountResponse" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "post_migration_vesting_reschedule" + ], + "properties": { + "post_migration_vesting_reschedule": { + "type": "object", + "required": [ + "user" + ], + "properties": { + "user": { + "$ref": "#/definitions/VestingAccountResponse" + } + }, + "additionalProperties": false + } + }, "additionalProperties": false } - }, - "additionalProperties": false + ] }, - { - "description": "Claims contract ownership ## Executor Only the newly proposed owner can execute this", + "Cw20ReceiveMsg": { + "description": "Cw20ReceiveMsg should be de/serialized under `Receive()` variant in a ExecuteMsg", "type": "object", "required": [ - "claim_ownership" + "amount", + "msg", + "sender" ], "properties": { - "claim_ownership": { - "type": "object", - "additionalProperties": false + "amount": { + "$ref": "#/definitions/Uint128" + }, + "msg": { + "$ref": "#/definitions/Binary" + }, + "sender": { + "type": "string" } }, "additionalProperties": false }, - { - "description": "Sets vesting token ## Executor Only the current owner or token info manager can execute this", - "type": "object", - "required": [ - "set_vesting_token" - ], - "properties": { - "set_vesting_token": { + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + }, + "ExecuteMsg": { + "description": "This structure describes the execute messages available in a vesting contract.", + "oneOf": [ + { + "description": "Claim claims vested tokens and sends them to a recipient", "type": "object", "required": [ - "vesting_token" + "claim" ], "properties": { - "vesting_token": { - "$ref": "#/definitions/AssetInfo" + "claim": { + "type": "object", + "properties": { + "amount": { + "description": "The amount of tokens to claim", + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "recipient": { + "description": "The address that receives the vested tokens", + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false } }, "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Contains messages associated with the managed extension for vesting contracts.", - "type": "object", - "required": [ - "managed_extension" - ], - "properties": { - "managed_extension": { + }, + { + "description": "Receives a message of type [`Cw20ReceiveMsg`] and processes it depending on the received template", "type": "object", "required": [ - "msg" + "receive" ], "properties": { - "msg": { - "$ref": "#/definitions/ExecuteMsgManaged" + "receive": { + "$ref": "#/definitions/Cw20ReceiveMsg" } }, "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Contains messages associated with the with_managers extension for vesting contracts.", - "type": "object", - "required": [ - "with_managers_extension" - ], - "properties": { - "with_managers_extension": { + }, + { + "description": "RegisterVestingAccounts registers vesting targets/accounts", "type": "object", "required": [ - "msg" + "register_vesting_accounts" ], "properties": { - "msg": { - "$ref": "#/definitions/ExecuteMsgWithManagers" + "register_vesting_accounts": { + "type": "object", + "required": [ + "vesting_accounts" + ], + "properties": { + "vesting_accounts": { + "type": "array", + "items": { + "$ref": "#/definitions/VestingAccount" + } + } + }, + "additionalProperties": false } }, "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Contains messages associated with the historical extension for vesting contracts.", - "type": "object", - "required": [ - "historical_extension" - ], - "properties": { - "historical_extension": { + }, + { + "description": "Creates a request to change contract ownership ## Executor Only the current owner can execute this", "type": "object", "required": [ - "msg" + "propose_new_owner" ], "properties": { - "msg": { - "$ref": "#/definitions/ExecuteMsgHistorical" + "propose_new_owner": { + "type": "object", + "required": [ + "expires_in", + "owner" + ], + "properties": { + "expires_in": { + "description": "The validity period of the offer to change the owner", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "owner": { + "description": "The newly proposed owner", + "type": "string" + } + }, + "additionalProperties": false } }, "additionalProperties": false - } - }, - "additionalProperties": false - } - ], - "definitions": { - "Addr": { - "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", - "type": "string" - }, - "AssetInfo": { - "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", - "oneOf": [ + }, { - "description": "Non-native Token", + "description": "Removes a request to change contract ownership ## Executor Only the current owner can execute this", "type": "object", "required": [ - "token" + "drop_ownership_proposal" ], "properties": { - "token": { + "drop_ownership_proposal": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Claims contract ownership ## Executor Only the newly proposed owner can execute this", + "type": "object", + "required": [ + "claim_ownership" + ], + "properties": { + "claim_ownership": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Sets vesting token ## Executor Only the current owner or token info manager can execute this", + "type": "object", + "required": [ + "set_vesting_token" + ], + "properties": { + "set_vesting_token": { "type": "object", "required": [ - "contract_addr" + "vesting_token" ], "properties": { - "contract_addr": { - "$ref": "#/definitions/Addr" + "vesting_token": { + "$ref": "#/definitions/AssetInfo" } }, "additionalProperties": false @@ -253,53 +407,72 @@ "additionalProperties": false }, { - "description": "Native token", + "description": "Contains messages associated with the managed extension for vesting contracts.", "type": "object", "required": [ - "native_token" + "managed_extension" ], "properties": { - "native_token": { + "managed_extension": { "type": "object", "required": [ - "denom" + "msg" ], "properties": { - "denom": { - "type": "string" + "msg": { + "$ref": "#/definitions/ExecuteMsgManaged" } }, "additionalProperties": false } }, "additionalProperties": false - } - ] - }, - "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" - }, - "Cw20ReceiveMsg": { - "description": "Cw20ReceiveMsg should be de/serialized under `Receive()` variant in a ExecuteMsg", - "type": "object", - "required": [ - "amount", - "msg", - "sender" - ], - "properties": { - "amount": { - "$ref": "#/definitions/Uint128" }, - "msg": { - "$ref": "#/definitions/Binary" + { + "description": "Contains messages associated with the with_managers extension for vesting contracts.", + "type": "object", + "required": [ + "with_managers_extension" + ], + "properties": { + "with_managers_extension": { + "type": "object", + "required": [ + "msg" + ], + "properties": { + "msg": { + "$ref": "#/definitions/ExecuteMsgWithManagers" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false }, - "sender": { - "type": "string" + { + "description": "Contains messages associated with the historical extension for vesting contracts.", + "type": "object", + "required": [ + "historical_extension" + ], + "properties": { + "historical_extension": { + "type": "object", + "required": [ + "msg" + ], + "properties": { + "msg": { + "$ref": "#/definitions/ExecuteMsgHistorical" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false } - }, - "additionalProperties": false + ] }, "ExecuteMsgHistorical": { "description": "This structure describes the execute messages available in a historical vesting contract.", @@ -422,6 +595,59 @@ }, "additionalProperties": false }, + "VestingAccountResponse": { + "description": "This structure describes a custom struct used to return vesting data about a specific vesting target.", + "type": "object", + "required": [ + "address", + "info" + ], + "properties": { + "address": { + "description": "The address that's vesting tokens", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "info": { + "description": "Vesting information", + "allOf": [ + { + "$ref": "#/definitions/VestingInfo" + } + ] + } + }, + "additionalProperties": false + }, + "VestingInfo": { + "description": "This structure stores parameters for a batch of vesting schedules.", + "type": "object", + "required": [ + "released_amount", + "schedules" + ], + "properties": { + "released_amount": { + "description": "The total amount of vested tokens already claimed", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "schedules": { + "description": "The vesting schedules", + "type": "array", + "items": { + "$ref": "#/definitions/VestingSchedule" + } + } + }, + "additionalProperties": false + }, "VestingSchedule": { "description": "This structure stores parameters for a specific vesting schedule", "type": "object", diff --git a/contracts/vesting-lp/schema/raw/migrate.json b/contracts/vesting-lp/schema/raw/migrate.json index 1b9dcecf..c8134b6c 100644 --- a/contracts/vesting-lp/schema/raw/migrate.json +++ b/contracts/vesting-lp/schema/raw/migrate.json @@ -3,5 +3,43 @@ "title": "MigrateMsg", "description": "This structure describes a migration message. We currently take no arguments for migrations.", "type": "object", - "additionalProperties": false + "required": [ + "cl_pair", + "max_slippage", + "new_lp_token", + "ntrn_denom", + "paired_denom", + "pcl_vesting", + "xyk_pair" + ], + "properties": { + "cl_pair": { + "type": "string" + }, + "max_slippage": { + "$ref": "#/definitions/Decimal" + }, + "new_lp_token": { + "type": "string" + }, + "ntrn_denom": { + "type": "string" + }, + "paired_denom": { + "type": "string" + }, + "pcl_vesting": { + "type": "string" + }, + "xyk_pair": { + "type": "string" + } + }, + "additionalProperties": false, + "definitions": { + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + } + } } diff --git a/contracts/vesting-lp/schema/vesting-lp.json b/contracts/vesting-lp/schema/vesting-lp.json index 395775f8..8a8f1873 100644 --- a/contracts/vesting-lp/schema/vesting-lp.json +++ b/contracts/vesting-lp/schema/vesting-lp.json @@ -34,31 +34,29 @@ "execute": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "ExecuteMsg", - "description": "This structure describes the execute messages available in a vesting contract.", "oneOf": [ { - "description": "Claim claims vested tokens and sends them to a recipient", "type": "object", "required": [ - "claim" + "base" ], "properties": { - "claim": { + "base": { + "$ref": "#/definitions/ExecuteMsg" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "migrate_liquidity_to_pcl_pool" + ], + "properties": { + "migrate_liquidity_to_pcl_pool": { "type": "object", "properties": { - "amount": { - "description": "The amount of tokens to claim", - "anyOf": [ - { - "$ref": "#/definitions/Uint128" - }, - { - "type": "null" - } - ] - }, - "recipient": { - "description": "The address that receives the vested tokens", + "user": { "type": [ "string", "null" @@ -71,213 +69,369 @@ "additionalProperties": false }, { - "description": "Receives a message of type [`Cw20ReceiveMsg`] and processes it depending on the received template", + "description": "Callbacks; only callable by the contract itself.", "type": "object", "required": [ - "receive" + "callback" ], "properties": { - "receive": { - "$ref": "#/definitions/Cw20ReceiveMsg" + "callback": { + "$ref": "#/definitions/CallbackMsg" } }, "additionalProperties": false + } + ], + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" }, - { - "description": "RegisterVestingAccounts registers vesting targets/accounts", - "type": "object", - "required": [ - "register_vesting_accounts" - ], - "properties": { - "register_vesting_accounts": { + "AssetInfo": { + "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", + "oneOf": [ + { + "description": "Non-native Token", "type": "object", "required": [ - "vesting_accounts" + "token" ], "properties": { - "vesting_accounts": { - "type": "array", - "items": { - "$ref": "#/definitions/VestingAccount" - } + "token": { + "type": "object", + "required": [ + "contract_addr" + ], + "properties": { + "contract_addr": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false } }, "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Creates a request to change contract ownership ## Executor Only the current owner can execute this", - "type": "object", - "required": [ - "propose_new_owner" - ], - "properties": { - "propose_new_owner": { + }, + { + "description": "Native token", "type": "object", "required": [ - "expires_in", - "owner" + "native_token" ], "properties": { - "expires_in": { - "description": "The validity period of the offer to change the owner", - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "owner": { - "description": "The newly proposed owner", - "type": "string" + "native_token": { + "type": "object", + "required": [ + "denom" + ], + "properties": { + "denom": { + "type": "string" + } + }, + "additionalProperties": false } }, "additionalProperties": false } - }, - "additionalProperties": false + ] }, - { - "description": "Removes a request to change contract ownership ## Executor Only the current owner can execute this", - "type": "object", - "required": [ - "drop_ownership_proposal" - ], - "properties": { - "drop_ownership_proposal": { + "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" + }, + "CallbackMsg": { + "oneOf": [ + { "type": "object", + "required": [ + "migrate_liquidity_to_cl_pair" + ], + "properties": { + "migrate_liquidity_to_cl_pair": { + "type": "object", + "required": [ + "amount", + "cl_pair", + "ntrn_denom", + "paired_asset_denom", + "slippage_tolerance", + "user", + "xyk_lp_token", + "xyk_pair" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "cl_pair": { + "$ref": "#/definitions/Addr" + }, + "ntrn_denom": { + "type": "string" + }, + "paired_asset_denom": { + "type": "string" + }, + "slippage_tolerance": { + "$ref": "#/definitions/Decimal" + }, + "user": { + "$ref": "#/definitions/VestingAccountResponse" + }, + "xyk_lp_token": { + "$ref": "#/definitions/Addr" + }, + "xyk_pair": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "provide_liquidity_to_cl_pair_after_withdrawal" + ], + "properties": { + "provide_liquidity_to_cl_pair_after_withdrawal": { + "type": "object", + "required": [ + "cl_pair", + "ntrn_denom", + "ntrn_init_balance", + "paired_asset_denom", + "paired_asset_init_balance", + "slippage_tolerance", + "user" + ], + "properties": { + "cl_pair": { + "$ref": "#/definitions/Addr" + }, + "ntrn_denom": { + "type": "string" + }, + "ntrn_init_balance": { + "$ref": "#/definitions/Uint128" + }, + "paired_asset_denom": { + "type": "string" + }, + "paired_asset_init_balance": { + "$ref": "#/definitions/Uint128" + }, + "slippage_tolerance": { + "$ref": "#/definitions/Decimal" + }, + "user": { + "$ref": "#/definitions/VestingAccountResponse" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "post_migration_vesting_reschedule" + ], + "properties": { + "post_migration_vesting_reschedule": { + "type": "object", + "required": [ + "user" + ], + "properties": { + "user": { + "$ref": "#/definitions/VestingAccountResponse" + } + }, + "additionalProperties": false + } + }, "additionalProperties": false } - }, - "additionalProperties": false + ] }, - { - "description": "Claims contract ownership ## Executor Only the newly proposed owner can execute this", + "Cw20ReceiveMsg": { + "description": "Cw20ReceiveMsg should be de/serialized under `Receive()` variant in a ExecuteMsg", "type": "object", "required": [ - "claim_ownership" + "amount", + "msg", + "sender" ], "properties": { - "claim_ownership": { - "type": "object", - "additionalProperties": false + "amount": { + "$ref": "#/definitions/Uint128" + }, + "msg": { + "$ref": "#/definitions/Binary" + }, + "sender": { + "type": "string" } }, "additionalProperties": false }, - { - "description": "Sets vesting token ## Executor Only the current owner or token info manager can execute this", - "type": "object", - "required": [ - "set_vesting_token" - ], - "properties": { - "set_vesting_token": { + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + }, + "ExecuteMsg": { + "description": "This structure describes the execute messages available in a vesting contract.", + "oneOf": [ + { + "description": "Claim claims vested tokens and sends them to a recipient", "type": "object", "required": [ - "vesting_token" + "claim" ], "properties": { - "vesting_token": { - "$ref": "#/definitions/AssetInfo" + "claim": { + "type": "object", + "properties": { + "amount": { + "description": "The amount of tokens to claim", + "anyOf": [ + { + "$ref": "#/definitions/Uint128" + }, + { + "type": "null" + } + ] + }, + "recipient": { + "description": "The address that receives the vested tokens", + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false } }, "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Contains messages associated with the managed extension for vesting contracts.", - "type": "object", - "required": [ - "managed_extension" - ], - "properties": { - "managed_extension": { + }, + { + "description": "Receives a message of type [`Cw20ReceiveMsg`] and processes it depending on the received template", "type": "object", "required": [ - "msg" + "receive" ], "properties": { - "msg": { - "$ref": "#/definitions/ExecuteMsgManaged" + "receive": { + "$ref": "#/definitions/Cw20ReceiveMsg" } }, "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Contains messages associated with the with_managers extension for vesting contracts.", - "type": "object", - "required": [ - "with_managers_extension" - ], - "properties": { - "with_managers_extension": { + }, + { + "description": "RegisterVestingAccounts registers vesting targets/accounts", "type": "object", "required": [ - "msg" + "register_vesting_accounts" ], "properties": { - "msg": { - "$ref": "#/definitions/ExecuteMsgWithManagers" + "register_vesting_accounts": { + "type": "object", + "required": [ + "vesting_accounts" + ], + "properties": { + "vesting_accounts": { + "type": "array", + "items": { + "$ref": "#/definitions/VestingAccount" + } + } + }, + "additionalProperties": false } }, "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "description": "Contains messages associated with the historical extension for vesting contracts.", - "type": "object", - "required": [ - "historical_extension" - ], - "properties": { - "historical_extension": { + }, + { + "description": "Creates a request to change contract ownership ## Executor Only the current owner can execute this", "type": "object", "required": [ - "msg" + "propose_new_owner" ], "properties": { - "msg": { - "$ref": "#/definitions/ExecuteMsgHistorical" + "propose_new_owner": { + "type": "object", + "required": [ + "expires_in", + "owner" + ], + "properties": { + "expires_in": { + "description": "The validity period of the offer to change the owner", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "owner": { + "description": "The newly proposed owner", + "type": "string" + } + }, + "additionalProperties": false } }, "additionalProperties": false - } - }, - "additionalProperties": false - } - ], - "definitions": { - "Addr": { - "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", - "type": "string" - }, - "AssetInfo": { - "description": "This enum describes available Token types. ## Examples ``` # use cosmwasm_std::Addr; # use astroport::asset::AssetInfo::{NativeToken, Token}; Token { contract_addr: Addr::unchecked(\"stake...\") }; NativeToken { denom: String::from(\"uluna\") }; ```", - "oneOf": [ + }, { - "description": "Non-native Token", + "description": "Removes a request to change contract ownership ## Executor Only the current owner can execute this", "type": "object", "required": [ - "token" + "drop_ownership_proposal" ], "properties": { - "token": { + "drop_ownership_proposal": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Claims contract ownership ## Executor Only the newly proposed owner can execute this", + "type": "object", + "required": [ + "claim_ownership" + ], + "properties": { + "claim_ownership": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + }, + { + "description": "Sets vesting token ## Executor Only the current owner or token info manager can execute this", + "type": "object", + "required": [ + "set_vesting_token" + ], + "properties": { + "set_vesting_token": { "type": "object", "required": [ - "contract_addr" + "vesting_token" ], "properties": { - "contract_addr": { - "$ref": "#/definitions/Addr" + "vesting_token": { + "$ref": "#/definitions/AssetInfo" } }, "additionalProperties": false @@ -286,53 +440,72 @@ "additionalProperties": false }, { - "description": "Native token", + "description": "Contains messages associated with the managed extension for vesting contracts.", "type": "object", "required": [ - "native_token" + "managed_extension" ], "properties": { - "native_token": { + "managed_extension": { "type": "object", "required": [ - "denom" + "msg" ], "properties": { - "denom": { - "type": "string" + "msg": { + "$ref": "#/definitions/ExecuteMsgManaged" } }, "additionalProperties": false } }, "additionalProperties": false - } - ] - }, - "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" - }, - "Cw20ReceiveMsg": { - "description": "Cw20ReceiveMsg should be de/serialized under `Receive()` variant in a ExecuteMsg", - "type": "object", - "required": [ - "amount", - "msg", - "sender" - ], - "properties": { - "amount": { - "$ref": "#/definitions/Uint128" }, - "msg": { - "$ref": "#/definitions/Binary" + { + "description": "Contains messages associated with the with_managers extension for vesting contracts.", + "type": "object", + "required": [ + "with_managers_extension" + ], + "properties": { + "with_managers_extension": { + "type": "object", + "required": [ + "msg" + ], + "properties": { + "msg": { + "$ref": "#/definitions/ExecuteMsgWithManagers" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false }, - "sender": { - "type": "string" + { + "description": "Contains messages associated with the historical extension for vesting contracts.", + "type": "object", + "required": [ + "historical_extension" + ], + "properties": { + "historical_extension": { + "type": "object", + "required": [ + "msg" + ], + "properties": { + "msg": { + "$ref": "#/definitions/ExecuteMsgHistorical" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false } - }, - "additionalProperties": false + ] }, "ExecuteMsgHistorical": { "description": "This structure describes the execute messages available in a historical vesting contract.", @@ -455,6 +628,59 @@ }, "additionalProperties": false }, + "VestingAccountResponse": { + "description": "This structure describes a custom struct used to return vesting data about a specific vesting target.", + "type": "object", + "required": [ + "address", + "info" + ], + "properties": { + "address": { + "description": "The address that's vesting tokens", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] + }, + "info": { + "description": "Vesting information", + "allOf": [ + { + "$ref": "#/definitions/VestingInfo" + } + ] + } + }, + "additionalProperties": false + }, + "VestingInfo": { + "description": "This structure stores parameters for a batch of vesting schedules.", + "type": "object", + "required": [ + "released_amount", + "schedules" + ], + "properties": { + "released_amount": { + "description": "The total amount of vested tokens already claimed", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "schedules": { + "description": "The vesting schedules", + "type": "array", + "items": { + "$ref": "#/definitions/VestingSchedule" + } + } + }, + "additionalProperties": false + }, "VestingSchedule": { "description": "This structure stores parameters for a specific vesting schedule", "type": "object", @@ -806,7 +1032,45 @@ "title": "MigrateMsg", "description": "This structure describes a migration message. We currently take no arguments for migrations.", "type": "object", - "additionalProperties": false + "required": [ + "cl_pair", + "max_slippage", + "new_lp_token", + "ntrn_denom", + "paired_denom", + "pcl_vesting", + "xyk_pair" + ], + "properties": { + "cl_pair": { + "type": "string" + }, + "max_slippage": { + "$ref": "#/definitions/Decimal" + }, + "new_lp_token": { + "type": "string" + }, + "ntrn_denom": { + "type": "string" + }, + "paired_denom": { + "type": "string" + }, + "pcl_vesting": { + "type": "string" + }, + "xyk_pair": { + "type": "string" + } + }, + "additionalProperties": false, + "definitions": { + "Decimal": { + "description": "A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0\n\nThe greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)", + "type": "string" + } + } }, "sudo": null, "responses": { diff --git a/contracts/vesting-lp/src/contract.rs b/contracts/vesting-lp/src/contract.rs index 4b3a4659..32d4f6e1 100644 --- a/contracts/vesting-lp/src/contract.rs +++ b/contracts/vesting-lp/src/contract.rs @@ -1,10 +1,25 @@ -use crate::msg::InstantiateMsg; -use cosmwasm_std::{entry_point, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; +use crate::msg::{CallbackMsg, ExecuteMsg, InstantiateMsg, MigrateMsg}; +use crate::state::{XykToClMigrationConfig, XYK_TO_CL_MIGRATION_CONFIG}; +use astroport::asset::{native_asset, Asset, PairInfo}; +use astroport::pair::QueryMsg::Share; +use astroport::pair::{ + Cw20HookMsg as PairCw20HookMsg, ExecuteMsg as PairExecuteMsg, QueryMsg as PairQueryMsg, +}; +use cosmwasm_std::{ + entry_point, to_json_binary, Addr, Binary, Coin, CosmosMsg, Decimal, Deps, DepsMut, Env, + MessageInfo, Response, StdResult, Uint128, WasmMsg, +}; use cw2::set_contract_version; +use cw20::{BalanceResponse, Cw20ExecuteMsg, Cw20QueryMsg}; use vesting_base::builder::VestingBaseBuilder; use vesting_base::error::ContractError; -use vesting_base::handlers::{execute as base_execute, query as base_query}; -use vesting_base::msg::{ExecuteMsg, QueryMsg}; +use vesting_base::handlers::execute as base_execute; +use vesting_base::handlers::query as base_query; +use vesting_base::msg::{ExecuteMsg as BaseExecute, QueryMsg}; +use vesting_base::state::{vesting_info, vesting_state, CONFIG}; +use vesting_base::types::{ + VestingAccountFullInfo, VestingInfo, VestingSchedule, VestingSchedulePoint, +}; /// Contract name that is used for migration. const CONTRACT_NAME: &str = "neutron-vesting-lp"; @@ -36,7 +51,16 @@ pub fn execute( info: MessageInfo, msg: ExecuteMsg, ) -> Result { - base_execute(deps, env, info, msg) + match msg { + ExecuteMsg::MigrateLiquidityToPCLPool { user } => { + execute_migrate_liquidity(deps, info, env, None, user) + } + ExecuteMsg::Callback(msg) => _handle_callback(deps, env, info, msg), + _ => { + let base_msg: BaseExecute = msg.into(); + base_execute(deps, env, info, base_msg) + } + } } /// Exposes all the queries available in the contract. @@ -44,3 +68,379 @@ pub fn execute( pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { base_query(deps, env, msg) } + +/// Manages contract migration. +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn migrate(deps: DepsMut, _env: Env, msg: MigrateMsg) -> Result { + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + + XYK_TO_CL_MIGRATION_CONFIG.save( + deps.storage, + &XykToClMigrationConfig { + max_slippage: msg.max_slippage, + ntrn_denom: msg.ntrn_denom, + xyk_pair: deps.api.addr_validate(msg.xyk_pair.as_str())?, + paired_denom: msg.paired_denom, + cl_pair: deps.api.addr_validate(msg.cl_pair.as_str())?, + new_lp_token: deps.api.addr_validate(msg.new_lp_token.as_str())?, + pcl_vesting: deps.api.addr_validate(msg.pcl_vesting.as_str())?, + }, + )?; + + Ok(Response::default()) +} + +fn execute_migrate_liquidity( + deps: DepsMut, + info: MessageInfo, + env: Env, + slippage_tolerance: Option, + user: Option, +) -> Result { + let config = CONFIG.load(deps.storage)?; + let migration_config: XykToClMigrationConfig = XYK_TO_CL_MIGRATION_CONFIG.load(deps.storage)?; + let address = match user { + Some(val) => deps.api.addr_validate(&val)?, + None => info.sender, + }; + let vesting_info = vesting_info(config.extensions.historical); + let info = vesting_info.load(deps.storage, address.clone())?; + let mut resp = Response::default(); + let user = VestingAccountFullInfo { + address, + info: info.clone(), + }; + + // get pairs LP token addresses + let pair_info: PairInfo = deps + .querier + .query_wasm_smart(migration_config.xyk_pair.clone(), &PairQueryMsg::Pair {})?; + + let user_share = compute_share(&user.info)?; + let user_share_assets: Vec = deps.querier.query_wasm_smart( + migration_config.xyk_pair.clone(), + &Share { amount: user_share }, + )?; + + // if there is nothing to migrate just update vi and quit. + // if there is only dust, then send it back to user, update vi and quit + if user_share_assets.iter().any(|a| a.amount.is_zero()) { + if !user_share.is_zero() { + resp = resp.add_message(CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: pair_info.liquidity_token.to_string(), + msg: to_json_binary(&Cw20ExecuteMsg::Transfer { + recipient: user.address.to_string(), + amount: user_share, + })?, + funds: vec![], + })); + } + + if !info.schedules.is_empty() { + vesting_info.save( + deps.storage, + user.address.clone(), + &VestingInfo { + schedules: vec![], + released_amount: Uint128::zero(), + }, + env.block.height, + )?; + } + return Ok(resp); + }; + + if let Some(slippage_tolerance) = slippage_tolerance { + if slippage_tolerance.gt(&migration_config.max_slippage) { + return Err(ContractError::MigrationError {}); + } + } + + let slippage_tolerance = slippage_tolerance.unwrap_or(migration_config.max_slippage); + + resp = resp.add_message( + CallbackMsg::MigrateLiquidityToClPair { + xyk_pair: migration_config.xyk_pair.clone(), + xyk_lp_token: pair_info.liquidity_token.clone(), + amount: user_share, + slippage_tolerance, + cl_pair: migration_config.cl_pair.clone(), + ntrn_denom: migration_config.ntrn_denom.clone(), + paired_asset_denom: migration_config.paired_denom.clone(), + user, + } + .to_cosmos_msg(&env)?, + ); + + Ok(resp) +} + +fn _handle_callback( + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: CallbackMsg, +) -> Result { + // Only the contract itself can call callbacks + if info.sender != env.contract.address { + return Err(ContractError::Unauthorized {}); + } + match msg { + CallbackMsg::MigrateLiquidityToClPair { + xyk_pair, + xyk_lp_token, + amount, + slippage_tolerance, + cl_pair, + ntrn_denom, + paired_asset_denom, + user, + } => migrate_liquidity_to_cl_pair_callback( + deps, + env, + xyk_pair, + xyk_lp_token, + amount, + slippage_tolerance, + cl_pair, + ntrn_denom, + paired_asset_denom, + user, + ), + CallbackMsg::ProvideLiquidityToClPairAfterWithdrawal { + ntrn_denom, + ntrn_init_balance, + paired_asset_denom, + paired_asset_init_balance, + cl_pair, + slippage_tolerance, + user, + } => provide_liquidity_to_cl_pair_after_withdrawal_callback( + deps, + env, + ntrn_denom, + ntrn_init_balance, + paired_asset_denom, + paired_asset_init_balance, + cl_pair, + slippage_tolerance, + user, + ), + CallbackMsg::PostMigrationVestingReschedule { + user, + init_balance_pcl_lp, + } => post_migration_vesting_reschedule_callback(deps, env, &user, init_balance_pcl_lp), + } +} + +#[allow(clippy::too_many_arguments)] +fn migrate_liquidity_to_cl_pair_callback( + deps: DepsMut, + env: Env, + xyk_pair: Addr, + xyk_lp_token: Addr, + amount: Uint128, + slippage_tolerance: Decimal, + cl_pair: Addr, + ntrn_denom: String, + paired_asset_denom: String, + user: VestingAccountFullInfo, +) -> Result { + let ntrn_init_balance = deps + .querier + .query_balance(env.contract.address.to_string(), ntrn_denom.clone())? + .amount; + let paired_asset_init_balance = deps + .querier + .query_balance(env.contract.address.to_string(), paired_asset_denom.clone())? + .amount; + + let mut msgs: Vec = vec![]; + + // push message to withdraw liquidity from the xyk pair + msgs.push(CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: xyk_lp_token.to_string(), + msg: to_json_binary(&Cw20ExecuteMsg::Send { + contract: xyk_pair.to_string(), + amount, + msg: to_json_binary(&PairCw20HookMsg::WithdrawLiquidity { assets: vec![] })?, + })?, + funds: vec![], + })); + let config = CONFIG.load(deps.storage)?; + vesting_state(config.extensions.historical).update::<_, ContractError>( + deps.storage, + env.block.height, + |s| { + let mut state = s.unwrap_or_default(); + state.total_granted = state.total_granted.checked_sub(amount)?; + Ok(state) + }, + )?; + // push the next migration step as a callback message + msgs.push( + CallbackMsg::ProvideLiquidityToClPairAfterWithdrawal { + ntrn_denom, + ntrn_init_balance, + paired_asset_denom, + paired_asset_init_balance, + cl_pair, + slippage_tolerance, + user, + } + .to_cosmos_msg(&env)?, + ); + + Ok(Response::default().add_messages(msgs)) +} + +#[allow(clippy::too_many_arguments)] +fn provide_liquidity_to_cl_pair_after_withdrawal_callback( + deps: DepsMut, + env: Env, + ntrn_denom: String, + ntrn_init_balance: Uint128, + paired_asset_denom: String, + paired_asset_init_balance: Uint128, + cl_pair_address: Addr, + slippage_tolerance: Decimal, + user: VestingAccountFullInfo, +) -> Result { + let ntrn_balance_after_withdrawal = deps + .querier + .query_balance(env.contract.address.to_string(), ntrn_denom.clone())? + .amount; + let paired_asset_balance_after_withdrawal = deps + .querier + .query_balance(env.contract.address.to_string(), paired_asset_denom.clone())? + .amount; + + // calc amount of assets that's been withdrawn + let withdrawn_ntrn_amount = ntrn_balance_after_withdrawal.checked_sub(ntrn_init_balance)?; + let withdrawn_paired_asset_amount = + paired_asset_balance_after_withdrawal.checked_sub(paired_asset_init_balance)?; + + let mut msgs: Vec = vec![]; + + let migration_config: XykToClMigrationConfig = XYK_TO_CL_MIGRATION_CONFIG.load(deps.storage)?; + + let balance_response: BalanceResponse = deps.querier.query_wasm_smart( + migration_config.new_lp_token, + &Cw20QueryMsg::Balance { + address: env.contract.address.to_string(), + }, + )?; + let current_balance = balance_response.balance; + + msgs.push(CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: cl_pair_address.to_string(), + msg: to_json_binary(&PairExecuteMsg::ProvideLiquidity { + assets: vec![ + native_asset(ntrn_denom.clone(), withdrawn_ntrn_amount), + native_asset(paired_asset_denom.clone(), withdrawn_paired_asset_amount), + ], + slippage_tolerance: Some(slippage_tolerance), + auto_stake: None, + receiver: None, + })?, + funds: vec![ + Coin::new(withdrawn_ntrn_amount.into(), ntrn_denom), + Coin::new(withdrawn_paired_asset_amount.into(), paired_asset_denom), + ], + })); + + msgs.push( + CallbackMsg::PostMigrationVestingReschedule { + user, + init_balance_pcl_lp: current_balance, + } + .to_cosmos_msg(&env)?, + ); + + Ok(Response::default().add_messages(msgs)) +} + +fn post_migration_vesting_reschedule_callback( + deps: DepsMut, + env: Env, + user: &VestingAccountFullInfo, + init_balance_pcl_lp: Uint128, +) -> Result { + let config = CONFIG.load(deps.storage)?; + let migration_config: XykToClMigrationConfig = XYK_TO_CL_MIGRATION_CONFIG.load(deps.storage)?; + let balance_response: BalanceResponse = deps.querier.query_wasm_smart( + &migration_config.new_lp_token, + &Cw20QueryMsg::Balance { + address: env.contract.address.to_string(), + }, + )?; + let balance_diff = balance_response.balance.checked_sub(init_balance_pcl_lp)?; + + let schedule = user + .info + .schedules + .last() + .ok_or(ContractError::VestingScheduleExtractError( + user.address.to_string(), + ))?; + + let new_end_point = match &schedule.end_point { + Some(end_point) => Option::from(VestingSchedulePoint { + time: end_point.time, + amount: balance_diff, + }), + None => None, + }; + + let new_schedule = VestingSchedule { + start_point: VestingSchedulePoint { + time: schedule.start_point.time, + amount: Uint128::zero(), + }, + end_point: new_end_point, + }; + + let vesting_info = vesting_info(config.extensions.historical); + + vesting_info.save( + deps.storage, + user.address.clone(), + &VestingInfo { + schedules: vec![], + released_amount: Uint128::zero(), + }, + env.block.height, + )?; + if !balance_diff.is_zero() { + let msgs = vec![CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: migration_config.new_lp_token.to_string(), + funds: vec![], + msg: to_json_binary(&Cw20ExecuteMsg::Send { + contract: migration_config.pcl_vesting.to_string(), + amount: balance_diff, + msg: to_json_binary(&vesting_lp_pcl::msg::Cw20HookMsg::MigrateXYKLiquidity { + user_address_raw: user.address.clone(), + user_vesting_info: VestingInfo { + schedules: vec![new_schedule], + released_amount: Uint128::zero(), + }, + })?, + })?, + })]; + + Ok(Response::new().add_messages(msgs)) + } else { + Ok(Response::new()) + } +} + +fn compute_share(vesting_info: &VestingInfo) -> StdResult { + let mut available_amount: Uint128 = Uint128::zero(); + for sch in &vesting_info.schedules { + if let Some(end_point) = &sch.end_point { + available_amount = available_amount.checked_add(end_point.amount)? + } + } + + Ok(available_amount.checked_sub(vesting_info.released_amount)?) +} diff --git a/contracts/vesting-lp/src/lib.rs b/contracts/vesting-lp/src/lib.rs index 08d6d688..172c45a6 100644 --- a/contracts/vesting-lp/src/lib.rs +++ b/contracts/vesting-lp/src/lib.rs @@ -1,5 +1,5 @@ +extern crate core; + pub mod contract; pub mod msg; - -#[cfg(test)] -mod tests; +pub mod state; diff --git a/contracts/vesting-lp/src/msg.rs b/contracts/vesting-lp/src/msg.rs index b35ee7ff..0936bc33 100644 --- a/contracts/vesting-lp/src/msg.rs +++ b/contracts/vesting-lp/src/msg.rs @@ -1,4 +1,11 @@ +use astroport::asset::AssetInfo; use cosmwasm_schema::cw_serde; +use cosmwasm_std::{to_json_binary, Addr, CosmosMsg, Decimal, Env, StdResult, Uint128, WasmMsg}; +use cw20::Cw20ReceiveMsg; +use vesting_base::msg::{ + ExecuteMsg as BaseExecute, ExecuteMsgHistorical, ExecuteMsgManaged, ExecuteMsgWithManagers, +}; +use vesting_base::types::{VestingAccount, VestingAccountFullInfo}; /// This structure describes the parameters used for creating a contract. #[cw_serde] @@ -10,3 +17,128 @@ pub struct InstantiateMsg { /// Token info manager address pub token_info_manager: String, } + +#[cw_serde] +pub enum ExecuteMsg { + /// Claim claims vested tokens and sends them to a recipient + Claim { + /// The address that receives the vested tokens + recipient: Option, + /// The amount of tokens to claim + amount: Option, + }, + /// Receives a message of type [`Cw20ReceiveMsg`] and processes it depending on the received template + Receive(Cw20ReceiveMsg), + /// RegisterVestingAccounts registers vesting targets/accounts + RegisterVestingAccounts { + vesting_accounts: Vec, + }, + /// Creates a request to change contract ownership + /// ## Executor + /// Only the current owner can execute this + ProposeNewOwner { + /// The newly proposed owner + owner: String, + /// The validity period of the offer to change the owner + expires_in: u64, + }, + /// Removes a request to change contract ownership + /// ## Executor + /// Only the current owner can execute this + DropOwnershipProposal {}, + /// Claims contract ownership + /// ## Executor + /// Only the newly proposed owner can execute this + ClaimOwnership {}, + /// Sets vesting token + /// ## Executor + /// Only the current owner or token info manager can execute this + SetVestingToken { vesting_token: AssetInfo }, + /// Contains messages associated with the managed extension for vesting contracts. + ManagedExtension { msg: ExecuteMsgManaged }, + /// Contains messages associated with the with_managers extension for vesting contracts. + WithManagersExtension { msg: ExecuteMsgWithManagers }, + /// Contains messages associated with the historical extension for vesting contracts. + HistoricalExtension { msg: ExecuteMsgHistorical }, + #[serde(rename = "migrate_liquidity_to_pcl_pool")] + MigrateLiquidityToPCLPool { user: Option }, + /// Callbacks; only callable by the contract itself. + Callback(CallbackMsg), +} + +#[cw_serde] +pub enum CallbackMsg { + MigrateLiquidityToClPair { + xyk_pair: Addr, + xyk_lp_token: Addr, + amount: Uint128, + slippage_tolerance: Decimal, + cl_pair: Addr, + ntrn_denom: String, + paired_asset_denom: String, + user: VestingAccountFullInfo, + }, + ProvideLiquidityToClPairAfterWithdrawal { + ntrn_denom: String, + ntrn_init_balance: Uint128, + paired_asset_denom: String, + paired_asset_init_balance: Uint128, + cl_pair: Addr, + slippage_tolerance: Decimal, + user: VestingAccountFullInfo, + }, + PostMigrationVestingReschedule { + user: VestingAccountFullInfo, + init_balance_pcl_lp: Uint128, + }, +} + +// Modified from +// https://github.com/CosmWasm/cosmwasm-plus/blob/v0.2.3/packages/cw20/src/receiver.rs#L15 +impl CallbackMsg { + pub fn to_cosmos_msg(self, env: &Env) -> StdResult { + Ok(CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: env.contract.address.to_string(), + msg: to_json_binary(&ExecuteMsg::Callback(self))?, + funds: vec![], + })) + } +} + +/// This structure describes a migration message. +/// We currently take no arguments for migrations. +#[cw_serde] +#[serde(rename_all = "snake_case")] +pub struct MigrateMsg { + pub max_slippage: Decimal, + pub ntrn_denom: String, + pub paired_denom: String, + pub xyk_pair: String, + pub cl_pair: String, + pub new_lp_token: String, + pub pcl_vesting: String, +} + +impl From for BaseExecute { + fn from(item: ExecuteMsg) -> Self { + match item { + ExecuteMsg::Claim { recipient, amount } => BaseExecute::Claim { recipient, amount }, + ExecuteMsg::Receive(msg) => BaseExecute::Receive(msg), + ExecuteMsg::RegisterVestingAccounts { vesting_accounts } => { + BaseExecute::RegisterVestingAccounts { vesting_accounts } + } + ExecuteMsg::ProposeNewOwner { owner, expires_in } => { + BaseExecute::ProposeNewOwner { owner, expires_in } + } + ExecuteMsg::DropOwnershipProposal {} => BaseExecute::DropOwnershipProposal {}, + ExecuteMsg::ClaimOwnership {} => BaseExecute::ClaimOwnership {}, + ExecuteMsg::SetVestingToken { vesting_token } => { + BaseExecute::SetVestingToken { vesting_token } + } + ExecuteMsg::ManagedExtension { msg } => BaseExecute::ManagedExtension { msg }, + ExecuteMsg::WithManagersExtension { msg } => BaseExecute::WithManagersExtension { msg }, + ExecuteMsg::HistoricalExtension { msg } => BaseExecute::HistoricalExtension { msg }, + _ => panic!("Unhandled ExecuteMsg variant"), + } + } +} diff --git a/contracts/vesting-lp/src/state.rs b/contracts/vesting-lp/src/state.rs new file mode 100644 index 00000000..9cf45b80 --- /dev/null +++ b/contracts/vesting-lp/src/state.rs @@ -0,0 +1,19 @@ +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{Addr, Decimal}; +use cw_storage_plus::Item; + +/// Config for xyk->CL liquidity migration. +#[cw_serde] +pub struct XykToClMigrationConfig { + /// The maximum allowed slippage tolerance for xyk to CL liquidity migration calls. + pub max_slippage: Decimal, + pub ntrn_denom: String, + pub xyk_pair: Addr, + pub paired_denom: String, + pub cl_pair: Addr, + pub new_lp_token: Addr, + pub pcl_vesting: Addr, +} + +pub const XYK_TO_CL_MIGRATION_CONFIG: Item = + Item::new("xyk_to_cl_migration_config"); diff --git a/contracts/vesting-lp/src/tests/integration.rs b/contracts/vesting-lp/src/tests/integration.rs index 5a150e97..311bf01b 100644 --- a/contracts/vesting-lp/src/tests/integration.rs +++ b/contracts/vesting-lp/src/tests/integration.rs @@ -2,7 +2,7 @@ use crate::msg::InstantiateMsg; use astroport::asset::{native_asset_info, token_asset_info}; use astroport::querier::query_balance; use astroport::token::InstantiateMsg as TokenInstantiateMsg; -use cosmwasm_std::{coin, coins, to_binary, Addr, StdResult, Timestamp, Uint128}; +use cosmwasm_std::{coin, coins, to_json_binary, Addr, StdResult, Timestamp, Uint128}; use cw20::{BalanceResponse, Cw20ExecuteMsg, Cw20QueryMsg, MinterResponse}; use cw_multi_test::{App, ContractWrapper, Executor}; use cw_utils::PaymentError; @@ -39,7 +39,7 @@ fn claim() { let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![ @@ -87,7 +87,7 @@ fn claim() { let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![ @@ -215,7 +215,7 @@ fn claim_native() { let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![VestingSchedule { @@ -385,7 +385,7 @@ fn register_vesting_accounts() { let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![VestingSchedule { @@ -411,7 +411,7 @@ fn register_vesting_accounts() { let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![VestingSchedule { @@ -497,7 +497,7 @@ fn register_vesting_accounts() { // Let's check user1's final vesting amount after add schedule for a new one let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user2.to_string(), schedules: vec![VestingSchedule { @@ -544,7 +544,7 @@ fn register_vesting_accounts() { // Add one more vesting schedule; final amount to vest must increase let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![VestingSchedule { @@ -638,7 +638,7 @@ fn register_vesting_accounts_native() { let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![VestingSchedule { diff --git a/contracts/vesting-lti/src/tests/integration.rs b/contracts/vesting-lti/src/tests/integration.rs index dd94da54..529ca1b4 100644 --- a/contracts/vesting-lti/src/tests/integration.rs +++ b/contracts/vesting-lti/src/tests/integration.rs @@ -2,7 +2,7 @@ use crate::msg::InstantiateMsg; use astroport::asset::{native_asset_info, token_asset_info}; use astroport::querier::query_balance; use astroport::token::InstantiateMsg as TokenInstantiateMsg; -use cosmwasm_std::{coin, coins, to_binary, Addr, StdResult, Timestamp, Uint128}; +use cosmwasm_std::{coin, coins, to_json_binary, Addr, StdResult, Timestamp, Uint128}; use cw20::{BalanceResponse, Cw20ExecuteMsg, Cw20QueryMsg, MinterResponse}; use cw_multi_test::{App, ContractWrapper, Executor}; use cw_utils::PaymentError; @@ -40,7 +40,7 @@ fn claim() { let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![ @@ -88,7 +88,7 @@ fn claim() { let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![ @@ -217,7 +217,7 @@ fn claim_native() { let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![VestingSchedule { @@ -391,7 +391,7 @@ fn register_vesting_accounts() { let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![VestingSchedule { @@ -417,7 +417,7 @@ fn register_vesting_accounts() { let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![VestingSchedule { @@ -503,7 +503,7 @@ fn register_vesting_accounts() { // Let's check user1's final vesting amount after add schedule for a new one let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user2.to_string(), schedules: vec![VestingSchedule { @@ -550,7 +550,7 @@ fn register_vesting_accounts() { // Add one more vesting schedule; final amount to vest must increase let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![VestingSchedule { @@ -644,7 +644,7 @@ fn register_vesting_accounts_native() { let msg = Cw20ExecuteMsg::Send { contract: vesting_instance.to_string(), - msg: to_binary(&Cw20HookMsg::RegisterVestingAccounts { + msg: to_json_binary(&Cw20HookMsg::RegisterVestingAccounts { vesting_accounts: vec![VestingAccount { address: user1.to_string(), schedules: vec![VestingSchedule { @@ -974,7 +974,7 @@ fn remove_vesting_accounts() { let res: StdResult = app.wrap().query_wasm_smart(vesting_instance.clone(), &msg); assert_eq!( res.unwrap_err().to_string(), - "Generic error: Querier contract error: vesting_base::types::VestingInfo not found" + "Generic error: Querier contract error: type: vesting_base::types::VestingInfo; key: [00, 0C, 76, 65, 73, 74, 69, 6E, 67, 5F, 69, 6E, 66, 6F, 75, 73, 65, 72, 31] not found" ); // Check vesting balance @@ -1113,7 +1113,7 @@ fn remove_vesting_accounts() { let res: StdResult = app.wrap().query_wasm_smart(vesting_instance.clone(), &msg); assert_eq!( res.unwrap_err().to_string(), - "Generic error: Querier contract error: vesting_base::types::VestingInfo not found" + "Generic error: Querier contract error: type: vesting_base::types::VestingInfo; key: [00, 0C, 76, 65, 73, 74, 69, 6E, 67, 5F, 69, 6E, 66, 6F, 75, 73, 65, 72, 31] not found" ); // Check vesting balance diff --git a/packages/astroport/src/asset.rs b/packages/astroport/src/asset.rs index 60a029ce..cff5ca2a 100644 --- a/packages/astroport/src/asset.rs +++ b/packages/astroport/src/asset.rs @@ -7,8 +7,8 @@ use crate::querier::{ query_balance, query_token_balance, query_token_precision, query_token_symbol, }; use cosmwasm_std::{ - to_binary, Addr, Api, BankMsg, Coin, ConversionOverflowError, CosmosMsg, Decimal256, Fraction, - MessageInfo, QuerierWrapper, StdError, StdResult, Uint128, Uint256, WasmMsg, + to_json_binary, Addr, Api, BankMsg, Coin, ConversionOverflowError, CosmosMsg, Decimal256, + Fraction, MessageInfo, QuerierWrapper, StdError, StdResult, Uint128, Uint256, WasmMsg, }; use cw20::{Cw20ExecuteMsg, Cw20QueryMsg, MinterResponse}; use itertools::Itertools; @@ -79,7 +79,7 @@ impl Asset { match &self.info { AssetInfo::Token { contract_addr } => Ok(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: contract_addr.to_string(), - msg: to_binary(&Cw20ExecuteMsg::Transfer { + msg: to_json_binary(&Cw20ExecuteMsg::Transfer { recipient, amount: self.amount, })?, diff --git a/packages/astroport/src/generator.rs b/packages/astroport/src/generator.rs index 998adf2d..bf52fc92 100644 --- a/packages/astroport/src/generator.rs +++ b/packages/astroport/src/generator.rs @@ -2,7 +2,9 @@ use crate::asset::{Asset, AssetInfo}; use crate::factory::PairType; use crate::restricted_vector::RestrictedVector; use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::{to_binary, Addr, Decimal, Env, StdResult, SubMsg, Uint128, Uint64, WasmMsg}; +use cosmwasm_std::{ + to_json_binary, Addr, Decimal, Env, StdResult, SubMsg, Uint128, Uint64, WasmMsg, +}; use cw20::Cw20ReceiveMsg; /// This structure describes the parameters used for creating a contract. @@ -201,7 +203,7 @@ impl ExecuteOnReply { pub fn into_submsg(self, env: &Env) -> StdResult { let msg = SubMsg::new(WasmMsg::Execute { contract_addr: env.contract.address.to_string(), - msg: to_binary(&ExecuteMsg::Callback { action: self })?, + msg: to_json_binary(&ExecuteMsg::Callback { action: self })?, funds: vec![], }); diff --git a/packages/astroport/src/mock_querier.rs b/packages/astroport/src/mock_querier.rs index 528fc737..d8ad0342 100644 --- a/packages/astroport/src/mock_querier.rs +++ b/packages/astroport/src/mock_querier.rs @@ -1,7 +1,7 @@ use cosmwasm_std::testing::{MockApi, MockQuerier, MockStorage, MOCK_CONTRACT_ADDR}; use cosmwasm_std::{ - from_binary, from_slice, to_binary, Coin, Empty, OwnedDeps, Querier, QuerierResult, - QueryRequest, SystemError, SystemResult, Uint128, WasmQuery, + from_json, to_json_binary, Coin, Empty, OwnedDeps, Querier, QuerierResult, QueryRequest, + SystemError, SystemResult, Uint128, WasmQuery, }; use std::collections::HashMap; @@ -89,7 +89,7 @@ pub(crate) fn pairs_to_map(pairs: &[(&String, &PairInfo)]) -> HashMap QuerierResult { // MockQuerier doesn't support Custom, so we ignore it completely here - let request: QueryRequest = match from_slice(bin_request) { + let request: QueryRequest = match from_json(bin_request) { Ok(v) => v, Err(e) => { return SystemResult::Err(SystemError::InvalidRequest { @@ -119,7 +119,7 @@ impl CW20QueryHandler { pub fn execute(&self, request: &QueryRequest) -> QuerierResult { match &request { QueryRequest::Wasm(WasmQuery::Smart { contract_addr, msg }) => { - match from_binary(msg).unwrap() { + match from_json(msg).unwrap() { Cw20QueryMsg::TokenInfo {} => { let balances: &HashMap = match self.token_querier.balances.get(contract_addr) { @@ -136,7 +136,7 @@ impl CW20QueryHandler { } SystemResult::Ok( - to_binary(&TokenInfoResponse { + to_json_binary(&TokenInfoResponse { name: "mAPPL".to_string(), symbol: "mAPPL".to_string(), decimals: 6, @@ -161,7 +161,9 @@ impl CW20QueryHandler { } }; - SystemResult::Ok(to_binary(&BalanceResponse { balance: *balance }).into()) + SystemResult::Ok( + to_json_binary(&BalanceResponse { balance: *balance }).into(), + ) } _ => panic!("DO NOT ENTER HERE"), } @@ -182,11 +184,11 @@ impl DefaultQueryHandler { QueryRequest::Wasm(WasmQuery::Smart { contract_addr: _, msg, - }) => match from_binary(msg).unwrap() { + }) => match from_json(msg).unwrap() { FactoryQueryMsg::Pair { asset_infos } => { let key = asset_infos[0].to_string() + asset_infos[1].to_string().as_str(); match self.astroport_factory_querier.pairs.get(&key) { - Some(v) => SystemResult::Ok(to_binary(&v).into()), + Some(v) => SystemResult::Ok(to_json_binary(&v).into()), None => SystemResult::Err(SystemError::InvalidRequest { error: "No pair info exists".to_string(), request: msg.as_slice().into(), diff --git a/packages/astroport/src/pair.rs b/packages/astroport/src/pair.rs index 3900ecce..cfcbc706 100644 --- a/packages/astroport/src/pair.rs +++ b/packages/astroport/src/pair.rs @@ -2,7 +2,7 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; use crate::asset::{Asset, AssetInfo, PairInfo}; -use cosmwasm_std::{from_slice, Addr, Binary, Decimal, QuerierWrapper, StdResult, Uint128}; +use cosmwasm_std::{from_json, Addr, Binary, Decimal, QuerierWrapper, StdResult, Uint128}; use cw20::Cw20ReceiveMsg; /// The default swap slippage @@ -208,7 +208,7 @@ pub fn migration_check( pair_addr: &Addr, ) -> StdResult { if let Some(res) = querier.query_wasm_raw(factory, b"pairs_to_migrate".as_slice())? { - let res: Vec = from_slice(&res)?; + let res: Vec = from_json(res)?; Ok(res.contains(pair_addr)) } else { Ok(false) @@ -219,7 +219,7 @@ pub fn migration_check( mod tests { use super::*; use crate::asset::native_asset_info; - use cosmwasm_std::{from_binary, to_binary}; + use cosmwasm_std::{from_json, to_json_binary}; #[cw_serde] pub struct LegacyInstantiateMsg { @@ -247,17 +247,17 @@ mod tests { init_params: None, }; - let ser_msg = to_binary(&inst_msg).unwrap(); + let ser_msg = to_json_binary(&inst_msg).unwrap(); // This .unwrap() is enough to make sure that [AssetInfo; 2] and Vec are compatible. - let _: InstantiateMsg = from_binary(&ser_msg).unwrap(); + let _: InstantiateMsg = from_json(ser_msg).unwrap(); } #[test] fn test_config_response_compatability() { - let ser_msg = to_binary(&LegacyConfigResponse { + let ser_msg = to_json_binary(&LegacyConfigResponse { block_time_last: 12, params: Some( - to_binary(&StablePoolConfig { + to_json_binary(&StablePoolConfig { amp: Decimal::one(), }) .unwrap(), @@ -265,12 +265,12 @@ mod tests { }) .unwrap(); - let _: ConfigResponse = from_binary(&ser_msg).unwrap(); + let _: ConfigResponse = from_json(ser_msg).unwrap(); } #[test] fn check_empty_vec_deserialization() { - let variant: Cw20HookMsg = from_slice(br#"{"withdraw_liquidity": {} }"#).unwrap(); + let variant: Cw20HookMsg = from_json(br#"{"withdraw_liquidity": {} }"#).unwrap(); assert_eq!(variant, Cw20HookMsg::WithdrawLiquidity { assets: vec![] }); } } diff --git a/packages/astroport/src/testing.rs b/packages/astroport/src/testing.rs index 0a197683..2b4c6953 100644 --- a/packages/astroport/src/testing.rs +++ b/packages/astroport/src/testing.rs @@ -7,7 +7,7 @@ use crate::querier::{ use crate::factory::PairType; use crate::DecimalCheckedOps; use cosmwasm_std::testing::MOCK_CONTRACT_ADDR; -use cosmwasm_std::{to_binary, Addr, BankMsg, Coin, CosmosMsg, Decimal, Uint128, WasmMsg}; +use cosmwasm_std::{to_json_binary, Addr, BankMsg, Coin, CosmosMsg, Decimal, Uint128, WasmMsg}; use cw20::Cw20ExecuteMsg; #[test] @@ -209,7 +209,7 @@ fn test_asset() { .unwrap(), CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: String::from("asset0000"), - msg: to_binary(&Cw20ExecuteMsg::Transfer { + msg: to_json_binary(&Cw20ExecuteMsg::Transfer { recipient: String::from("addr0000"), amount: Uint128::new(123123u128), }) diff --git a/packages/astroport_periphery/Cargo.toml b/packages/astroport_periphery/Cargo.toml index 14843f44..f3ff340e 100644 --- a/packages/astroport_periphery/Cargo.toml +++ b/packages/astroport_periphery/Cargo.toml @@ -17,6 +17,6 @@ cw20 = { workspace = true } cw-storage-plus = "0.15.1" cosmwasm-std = { workspace = true } cosmwasm-schema = { workspace = true } -astroport = { git = "https://github.com/astroport-fi/astroport-core.git", tag = "v2.5.0" } +astroport = { git = "https://github.com/astroport-fi/astroport-core.git", tag = "v3.11.0" } schemars = { workspace = true } serde = { workspace = true } diff --git a/packages/astroport_periphery/src/auction.rs b/packages/astroport_periphery/src/auction.rs index 525abbc3..a76dab9c 100644 --- a/packages/astroport_periphery/src/auction.rs +++ b/packages/astroport_periphery/src/auction.rs @@ -1,5 +1,5 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::{to_binary, Addr, CosmosMsg, Env, StdResult, Uint128, WasmMsg}; +use cosmwasm_std::{to_json_binary, Addr, CosmosMsg, Env, StdResult, Uint128, WasmMsg}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -90,7 +90,7 @@ impl CallbackMsg { pub fn to_cosmos_msg(&self, env: &Env) -> StdResult { Ok(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: env.contract.address.to_string(), - msg: to_binary(&ExecuteMsg::Callback(self.clone()))?, + msg: to_json_binary(&ExecuteMsg::Callback(self.clone()))?, funds: vec![], })) } diff --git a/packages/astroport_periphery/src/helpers.rs b/packages/astroport_periphery/src/helpers.rs index 15c53fd6..36ef76a7 100644 --- a/packages/astroport_periphery/src/helpers.rs +++ b/packages/astroport_periphery/src/helpers.rs @@ -1,6 +1,6 @@ use cosmwasm_std::{ - to_binary, Addr, Binary, CosmosMsg, QuerierWrapper, QueryRequest, StdResult, Uint128, WasmMsg, - WasmQuery, + to_json_binary, Addr, Binary, CosmosMsg, QuerierWrapper, QueryRequest, StdResult, Uint128, + WasmMsg, WasmQuery, }; use cw20::{BalanceResponse, Cw20ExecuteMsg, Cw20QueryMsg}; @@ -15,7 +15,7 @@ pub fn build_transfer_cw20_token_msg( ) -> StdResult { Ok(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: token_contract_address, - msg: to_binary(&Cw20ExecuteMsg::Transfer { + msg: to_json_binary(&Cw20ExecuteMsg::Transfer { recipient: recipient.into(), amount, })?, @@ -36,7 +36,7 @@ pub fn build_send_cw20_token_msg( ) -> StdResult { Ok(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: token_contract_address, - msg: to_binary(&Cw20ExecuteMsg::Send { + msg: to_json_binary(&Cw20ExecuteMsg::Send { contract: recipient_contract_addr, amount, msg: msg_, @@ -59,7 +59,7 @@ pub fn cntrn_get_balance( ) -> StdResult { let query: BalanceResponse = querier.query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: token_address.into(), - msg: to_binary(&Cw20QueryMsg::Balance { + msg: to_json_binary(&Cw20QueryMsg::Balance { address: account_addr.into(), })?, }))?; @@ -82,7 +82,7 @@ pub fn build_approve_cntrn_msg( ) -> StdResult { Ok(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: token_contract_address, - msg: to_binary(&Cw20ExecuteMsg::IncreaseAllowance { + msg: to_json_binary(&Cw20ExecuteMsg::IncreaseAllowance { spender: spender_address, amount: allowance_amount, expires: Some(cw20::Expiration::AtHeight(expiration_block)), diff --git a/packages/astroport_periphery/src/lib.rs b/packages/astroport_periphery/src/lib.rs index 37ab064d..9cd6ad7f 100644 --- a/packages/astroport_periphery/src/lib.rs +++ b/packages/astroport_periphery/src/lib.rs @@ -2,6 +2,7 @@ pub mod airdrop; pub mod auction; pub mod helpers; pub mod lockdrop; +pub mod lockdrop_pcl; pub mod pricefeed; pub mod simple_airdrop; pub mod utils; diff --git a/packages/astroport_periphery/src/lockdrop.rs b/packages/astroport_periphery/src/lockdrop.rs index 6dcbd342..47f6fa8a 100644 --- a/packages/astroport_periphery/src/lockdrop.rs +++ b/packages/astroport_periphery/src/lockdrop.rs @@ -2,8 +2,8 @@ use astroport::asset::{Asset, AssetInfo}; use astroport::restricted_vector::RestrictedVector; use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::{ - to_binary, Addr, CosmosMsg, Decimal, Decimal256, Env, StdError, StdResult, Uint128, Uint256, - WasmMsg, + to_json_binary, Addr, CosmosMsg, Decimal, Decimal256, Env, StdError, StdResult, Uint128, + Uint256, WasmMsg, }; use cw20::Cw20ReceiveMsg; use cw_storage_plus::{Key, KeyDeserialize, Prefixer, PrimaryKey}; @@ -163,6 +163,14 @@ pub enum ExecuteMsg { DropOwnershipProposal {}, /// Used to claim contract ownership. ClaimOwnership {}, + /// Migrates user's locked liquidity from XYK pools to PCL ones, transferring lockdrop participation + /// rewards to the address which liquidity has been migrated. + #[serde(rename = "migrate_liquidity_to_pcl_pools")] + MigrateLiquidityToPCLPools { + /// The address which liquidity is supposed to be transferred. If no user address is + /// provided, the message sender's address is used. + user_address_raw: Option, + }, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] @@ -181,23 +189,80 @@ pub enum Cw20HookMsg { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum CallbackMsg { + /// Updates contract state after dual staking rewards are claimed from the generator contract. UpdatePoolOnDualRewardsClaim { pool_type: PoolType, prev_ntrn_balance: Uint128, prev_proxy_reward_balances: Vec, }, + /// Withdraws user rewards and LP Tokens after claims / unlocks. WithdrawUserLockupRewardsCallback { pool_type: PoolType, user_address: Addr, duration: u64, withdraw_lp_stake: bool, }, - // WithdrawLiquidityFromTerraswapCallback { - // terraswap_lp_token: Addr, - // astroport_pool: Addr, - // prev_assets: [terraswap::asset::Asset; 2], - // slippage_tolerance: Option, - // }, + /// Entry point for a single lockup position migration to PCL lockdrop contract. Performs + /// generator rewards claiming and initializes liquidity withdrawal+transfer process by + /// invocation of the respective callback message. + #[serde(rename = "init_migrate_lockup_to_pcl_pools_callback")] + InitMigrateLockupToPCLPoolsCallback { + /// The type of the pool the lockup is related to. + pool_type: PoolType, + /// The address of the user which owns the lockup. + user_address: Addr, + /// The duration of the lock period. + duration: u64, + }, + /// The second step in the lockup's XYK -> PCL liquidity migration process. + /// Claims all possible rewards that the user is eligible of and transfers them to the user. + TransferAllRewardsBeforeMigrationCallback { + /// The type of the pool the lockup is related to. + pool_type: PoolType, + /// The address of the user which owns the lockup. + user_address: Addr, + /// The duration of the lock period. + duration: u64, + }, + /// The third step in the lockup's XYK -> PCL liquidity migration process. + /// Handles withdrawal of staked liquidity from the generator contract and liquidity transfer to + /// the PCL lockdrop contract. + WithdrawUserLockupCallback { + /// The type of the pool the lockup is related to. + pool_type: PoolType, + /// The address of the user which owns the lockup. + user_address: Addr, + /// The duration of the lock period. + duration: u64, + /// The address of the generator which possesses the staked liquidity. + generator: Addr, + /// The address of the pool's liquidity token. + astroport_lp_token: Addr, + /// The amount of LP token to be unstaked and withdrawn. + astroport_lp_amount: Uint128, + }, + /// The fourth step in the lockup's XYK -> PCL liquidity migration process. + /// Invokes the PCL lockdrop contract's MigrateXYKLiquidity handler which creates an LP position + /// in the PCL pool and a lockup in the PCL lockdrop contract in accordance with the withdrawn + /// user's lockup position. + #[serde(rename = "migrate_user_lockup_to_pcl_pair_callback")] + MigrateUserLockupToPCLPairCallback { + /// The type of the pool the lockup is related to. + pool_type: PoolType, + /// The address of the user which owns the lockup. + user_address: Addr, + /// The duration of the lock period. + duration: u64, + /// The balance in untrn of the XYK lockdrop contract at the third migration step. Is used + /// in the callback to calculate the amount of untrn been withdrawn from the XYK pool. + ntrn_balance: Uint128, + /// The denom of the paired asset (the asset paired with untrn in the pool). + paired_asset_denom: String, + /// The balance in the paired denom of the XYK lockdrop contract at the third migration step. + /// Is used in the callback to calculate the amount of the paired asset been withdrawn + /// from the XYK pool. + paired_asset_balance: Uint128, + }, } // Modified from @@ -206,7 +271,7 @@ impl CallbackMsg { pub fn to_cosmos_msg(self, env: &Env) -> StdResult { Ok(CosmosMsg::Wasm(WasmMsg::Execute { contract_addr: env.contract.address.to_string(), - msg: to_binary(&ExecuteMsg::Callback(self))?, + msg: to_json_binary(&ExecuteMsg::Callback(self))?, funds: vec![], })) } @@ -242,7 +307,11 @@ pub enum QueryMsg { } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] -pub struct MigrateMsg {} +pub struct MigrateMsg { + /// The address of the lockdrop contract working with PCL pools. Used to transfer + /// the lockdrop's liquidity locked in XYK pools to more efficient pools. + pub pcl_lockdrop_contract: String, +} #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, JsonSchema)] pub struct MigrationInfo { diff --git a/packages/astroport_periphery/src/lockdrop_pcl.rs b/packages/astroport_periphery/src/lockdrop_pcl.rs new file mode 100644 index 00000000..15a8bea8 --- /dev/null +++ b/packages/astroport_periphery/src/lockdrop_pcl.rs @@ -0,0 +1,422 @@ +use crate::lockdrop::{ + LockupInfoV2 as LockdropXYKLockupInfoV2, PoolType as LockdropXYKPoolType, + UserInfo as LockdropXYKUserInfo, +}; +use astroport::asset::{Asset, AssetInfo}; +use astroport::restricted_vector::RestrictedVector; +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::{ + to_json_binary, Addr, CosmosMsg, Decimal, Decimal256, Env, StdError, StdResult, Uint128, + Uint256, WasmMsg, +}; +use cw_storage_plus::{Key, KeyDeserialize, Prefixer, PrimaryKey}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +// TODO: implement display trait +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, Copy)] +pub enum PoolType { + USDC, + ATOM, +} + +impl From for PoolType { + fn from(t: LockdropXYKPoolType) -> PoolType { + match t { + LockdropXYKPoolType::USDC => PoolType::USDC, + LockdropXYKPoolType::ATOM => PoolType::ATOM, + } + } +} + +#[allow(clippy::from_over_into)] +impl Into for PoolType { + fn into(self) -> String { + match self { + PoolType::USDC => "usdc".to_string(), + PoolType::ATOM => "atom".to_string(), + } + } +} + +impl PoolType { + fn bytes(&self) -> &[u8] { + match self { + PoolType::USDC => "usdc".as_bytes(), + PoolType::ATOM => "atom".as_bytes(), + } + } +} + +impl KeyDeserialize for PoolType { + type Output = PoolType; + + fn from_vec(value: Vec) -> StdResult { + match value.as_slice() { + b"usdc" => Ok(PoolType::USDC), + b"atom" => Ok(PoolType::ATOM), + _ => Err(StdError::generic_err("Invalid PoolType")), + } + } +} + +impl<'a> PrimaryKey<'a> for PoolType { + type Prefix = (); + type SubPrefix = (); + type Suffix = Self; + type SuperSuffix = Self; + + fn key(&self) -> Vec { + vec![Key::Ref(self.bytes())] + } +} + +impl<'a> Prefixer<'a> for PoolType { + fn prefix(&self) -> Vec { + vec![Key::Ref(self.bytes())] + } +} + +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct InstantiateMsg { + /// Account which can update config + pub owner: Option, + /// Original XYK lockdrop contract address + pub xyk_lockdrop_contract: String, + /// Credits contract address + pub credits_contract: String, + /// Auction contract address + pub auction_contract: String, + /// Incentives (Staking for dual rewards) contract address + pub incentives: String, + /// Describes rewards coefficients for each lockup duration + pub lockup_rewards_info: Vec, + /// Address of the LP token of the NTRN/USDC PCL pool + pub usdc_token: String, + /// Address of the LP token of the NTRN/ATOM PCL pool + pub atom_token: String, + + /* + Since no NTRN rewards are distributed from the PCL lockdrop contract, the fields below are + just used to fill the contract's state with the same values as it is in the XYK lockdrop + contract. So the values should be just copied from the XYK lockdrop contract's state. + */ + /// Total NTRN lockdrop incentives distributed among the users. + pub lockdrop_incentives: Uint128, + /// Share of total NTRN incentives allocated to the NTRN/USDC PCL pool + pub usdc_incentives_share: Uint128, + /// Weighted LP Token balance used to calculate NTRN rewards a particular NTRN/USDC pool + /// depositor can claim + pub usdc_weighted_amount: Uint256, + /// Share of total NTRN incentives allocated to the NTRN/ATOM PCL pool + pub atom_incentives_share: Uint128, + /// Weighted LP Token balance used to calculate NTRN rewards a particular NTRN/ATOM pool + /// depositor can claim + pub atom_weighted_amount: Uint256, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +pub struct UpdateConfigMsg { + /// incentives (Staking for dual rewards) contract address + pub incentives_address: Option, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum ExecuteMsg { + // ADMIN Function ::: To update configuration + UpdateConfig { + new_config: UpdateConfigMsg, + }, + // Facilitates ASTRO reward withdrawal which have not been delegated to bootstrap auction along with optional Unlock (can be forceful) + // If withdraw_lp_stake is true and force_unlock is false, it Unlocks the lockup position if its lockup duration has concluded + // If both withdraw_lp_stake and force_unlock are true, it forcefully unlocks the positon. user needs to approve ASTRO Token to + // be transferred by the lockdrop contract to itself for forceful unlock + ClaimRewardsAndOptionallyUnlock { + pool_type: PoolType, + duration: u64, + withdraw_lp_stake: bool, + }, + /// Callbacks; only callable by the contract itself. + Callback(CallbackMsg), + /// ProposeNewOwner creates a proposal to change contract ownership. + /// The validity period for the proposal is set in the `expires_in` variable. + ProposeNewOwner { + /// Newly proposed contract owner + owner: String, + /// The date after which this proposal expires + expires_in: u64, + }, + /// DropOwnershipProposal removes the existing offer to change contract ownership. + DropOwnershipProposal {}, + /// Used to claim contract ownership. + ClaimOwnership {}, + /// A handler to receive lockdrop liquidity migrated from XYK pools to PCL ones. Only callable + /// by the original lockdrop contract. Expects two **Coin**s to be attached as funds. + #[serde(rename = "migrate_xyk_liquidity")] + MigrateXYKLiquidity { + /// The type of the pool the lockup is related to. + pool_type: LockdropXYKPoolType, + /// The address of the user which owns the lockup. + user_address_raw: String, + /// The duration of the lock period. + duration: u64, + /// The lockup owner's info from the XYK lockdrop contract. Is used to create a UserInfo + /// entry on the PCL lockdrop contract's side. + user_info: LockdropXYKUserInfo, + /// The lockup info from the XYK lockdrop contract. Is used to create a LockupInfoV2 entry + /// on the PCL lockdrop contract's side. + lockup_info: LockdropXYKLockupInfoV2, + /// Whether to stake all LP tokens in PCL Lockdrop possession to the incentives contract. + /// Should be false unless the last lockdrop participant is being migrated for a given + /// pool type. Before staked, all LP tokens are just collected on the PCL Lockdrop + /// contract's account and therefore no incentive rewards are accrued. + stake: bool, + }, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum CallbackMsg { + UpdatePoolOnDualRewardsClaim { + pool_type: PoolType, + prev_reward_balances: Vec, + }, + WithdrawUserLockupRewardsCallback { + pool_type: PoolType, + user_address: Addr, + duration: u64, + withdraw_lp_stake: bool, + }, + /// Completes the liquidity migration process by making all necessary state updates for the + /// lockup position. + FinishLockupMigrationCallback { + /// The type of the pool the lockup is related to. + pool_type: PoolType, + /// The address of the user which owns the lockup. + user_address: Addr, + /// The duration of the lock period. + duration: u64, + /// The address of the LP token of the pool. + lp_token: String, + /// The amount of LP token the PCL lockdrop contract possesses of before liquidity provision. + /// Used to calculate LP token amount received for liquidity provision. + prev_lp_token_amount: Uint128, + /// The lockup owner's info from the XYK lockdrop contract. Is used to create a UserInfo + /// entry on the PCL lockdrop contract's side. + user_info: LockdropXYKUserInfo, + /// The lockup info from the XYK lockdrop contract. Is used to create a LockupInfoV2 entry + /// on the PCL lockdrop contract's side. + lockup_info: LockdropXYKLockupInfoV2, + /// Whether to stake all LP tokens in PCL Lockdrop possession to the incentives contract. + /// Should be false unless the last lockdrop participant is being migrated for a given + /// pool type. Before staked, all LP tokens are just collected on the PCL Lockdrop + /// contract's account and therefore no incentive rewards are accrued. + stake: bool, + }, +} + +// Modified from +// https://github.com/CosmWasm/cosmwasm-plus/blob/v0.2.3/packages/cw20/src/receiver.rs#L15 +impl CallbackMsg { + pub fn to_cosmos_msg(self, env: &Env) -> StdResult { + Ok(CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: env.contract.address.to_string(), + msg: to_json_binary(&ExecuteMsg::Callback(self))?, + funds: vec![], + })) + } +} + +#[cw_serde] +#[derive(QueryResponses)] +pub enum QueryMsg { + #[returns(Config)] + Config {}, + #[returns(StateResponse)] + State {}, + #[returns(PoolInfo)] + Pool { pool_type: PoolType }, + #[returns(UserInfoResponse)] + UserInfo { address: String }, + #[returns(UserInfoWithListResponse)] + UserInfoWithLockupsList { address: String }, + #[returns(LockUpInfoResponse)] + LockUpInfo { + user_address: String, + pool_type: PoolType, + duration: u64, + }, + #[returns(Option)] + QueryUserLockupTotalAtHeight { + pool_type: PoolType, + user_address: String, + height: u64, + }, + #[returns(Option)] + QueryLockupTotalAtHeight { pool_type: PoolType, height: u64 }, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +pub struct MigrateMsg {} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +pub struct LockupRewardsInfo { + pub duration: u64, + pub coefficient: Decimal256, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +pub struct Config { + /// Account which can update the config + pub owner: Addr, + /// Original XYK lockdrop contract address + pub xyk_lockdrop_contract: Addr, + /// Credits contract address + pub credits_contract: Addr, + /// Bootstrap Auction contract address + pub auction_contract: Addr, + /// Incentives contract address + pub incentives: Addr, + /// Total NTRN lockdrop incentives to be distributed among the users + pub lockdrop_incentives: Uint128, + /// Describes rewards coefficients for each lockup duration + pub lockup_rewards_info: Vec, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, Default)] +pub struct State { + /// Total NTRN incentives share + pub total_incentives_share: Uint128, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct PoolInfo { + pub lp_token: Addr, + pub amount_in_lockups: Uint128, + /// Share of total NTRN incentives allocated to this pool + pub incentives_share: Uint128, + /// Weighted LP Token balance used to calculate NTRN rewards a particular user can claim + pub weighted_amount: Uint256, + /// Ratio of incentives rewards accured to astroport pool share + pub incentives_rewards_per_share: RestrictedVector, + /// Boolean value indicating if the LP Tokens are staked with the Incentives contract + pub is_staked: bool, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema, Default)] +pub struct UserInfo { + /// Total NTRN tokens user received as rewards for participation in the lockdrop + pub total_ntrn_rewards: Uint128, + /// NTRN tokens transferred to user + pub ntrn_transferred: bool, + /// Number of lockup positions the user is having + pub lockup_positions_index: u32, +} + +impl From for UserInfo { + fn from(i: LockdropXYKUserInfo) -> UserInfo { + UserInfo { + total_ntrn_rewards: i.total_ntrn_rewards, + ntrn_transferred: i.ntrn_transferred, + lockup_positions_index: i.lockup_positions_index, + } + } +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct LockupInfo { + /// Terraswap LP units locked by the user + pub lp_units_locked: Uint128, + pub astroport_lp_transferred: Option, + /// Boolean value indicating if the user's has withdrawn funds post the only 1 withdrawal limit cutoff + pub withdrawal_flag: bool, + /// NTRN tokens received as rewards for participation in the lockdrop + pub ntrn_rewards: Uint128, + /// incentives tokens lockup received as incentives rewards + pub incentives_debt: RestrictedVector, + /// Timestamp beyond which this position can be unlocked + pub unlock_timestamp: u64, +} + +impl LockupInfo { + /// Creates a lockup entry for PCL lockdrop contract based on a lockup entry for XYK lockdrop + /// contract. The **lp_units_locked** field is the amount of lp tokens minted by the PCL pool. + pub fn from_xyk_lockup_info( + i: LockdropXYKLockupInfoV2, + lp_units_locked: Uint128, + ) -> LockupInfo { + LockupInfo { + lp_units_locked, + astroport_lp_transferred: None, + withdrawal_flag: i.withdrawal_flag, + ntrn_rewards: i.ntrn_rewards, + incentives_debt: Default::default(), + unlock_timestamp: i.unlock_timestamp, + } + } +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +pub struct StateResponse { + /// Total NTRN incentives share + pub total_incentives_share: Uint128, + /// Vector containing LP addresses for all the supported LP Pools + pub supported_pairs_list: Vec, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct UserInfoResponse { + /// Total NTRN tokens user received as rewards for participation in the lockdrop + pub total_ntrn_rewards: Uint128, + /// NTRN tokens transferred to user + pub ntrn_transferred: bool, + /// Lockup positions + pub lockup_infos: Vec, + /// Tokens receivable as incentives rewards that user can claim + pub claimable_incentives_debt: RestrictedVector, + /// Number of lockup positions the user is having + pub lockup_positions_index: u32, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +pub struct UserInfoWithListResponse { + /// Total NTRN tokens user received as rewards for participation in the lockdrop + pub total_ntrn_rewards: Uint128, + /// NTRN tokens transferred to user + pub ntrn_transferred: bool, + /// Lockup positions + pub lockup_infos: Vec, + /// Number of lockup positions the user is having + pub lockup_positions_index: u32, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +pub struct LockUpInfoSummary { + pub pool_type: PoolType, + pub duration: u64, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct LockUpInfoResponse { + /// Terraswap LP token + pub pool_type: PoolType, + /// Terraswap LP units locked by the user + pub lp_units_locked: Uint128, + /// Boolean value indicating if the user's has withdrawn funds post the only 1 withdrawal limit cutoff + pub withdrawal_flag: bool, + /// NTRN tokens received as rewards for participation in the lockdrop + pub ntrn_rewards: Uint128, + pub duration: u64, + /// incentives tokens lockup received as incentives rewards + pub incentives_debt: RestrictedVector, + /// Tokens receivable as incentives rewards that user can claim + pub claimable_incentives_debt: RestrictedVector, + /// Timestamp beyond which this position can be unlocked + pub unlock_timestamp: u64, + /// User's Astroport LP units, calculated as lp_units_locked (terraswap) / total LP units locked (terraswap) * Astroport LP units minted post migration + pub astroport_lp_units: Option, + pub astroport_lp_token: Addr, + pub astroport_lp_transferred: Option, +} diff --git a/packages/vesting-base/Cargo.toml b/packages/vesting-base/Cargo.toml index ffe8e644..f533e362 100644 --- a/packages/vesting-base/Cargo.toml +++ b/packages/vesting-base/Cargo.toml @@ -13,10 +13,10 @@ backtraces = ["cosmwasm-std/backtraces"] library = [] [dependencies] -cw20 = { workspace = true } +cw20 = { version = "0.15" } cosmwasm-std = { workspace = true } cw-storage-plus = { workspace = true } -astroport = { workspace = true } +astroport = { path = "../../packages/astroport" } thiserror = { workspace = true } # we keep it at 0.15 instead of latest version just for vesting investors contract cw-utils = "0.15" diff --git a/packages/vesting-base/src/error.rs b/packages/vesting-base/src/error.rs index a1859ac0..efee45d3 100644 --- a/packages/vesting-base/src/error.rs +++ b/packages/vesting-base/src/error.rs @@ -20,6 +20,9 @@ pub enum ContractError { #[error("Vesting schedule error on addr: {0}. Should satisfy: (start < end and at_start < total) or (start = end and at_start = total)")] VestingScheduleError(String), + #[error("Vesting schedule error on addr: {0}. No schedule found")] + VestingScheduleExtractError(String), + #[error("Vesting schedule amount error. The total amount should be equal to the CW20 receive amount.")] VestingScheduleAmountError {}, diff --git a/packages/vesting-base/src/ext_historical.rs b/packages/vesting-base/src/ext_historical.rs index d494adf6..fffb3008 100644 --- a/packages/vesting-base/src/ext_historical.rs +++ b/packages/vesting-base/src/ext_historical.rs @@ -3,7 +3,7 @@ use crate::msg::{ExecuteMsgHistorical, QueryMsgHistorical}; use crate::state::{vesting_info, vesting_state, CONFIG}; use crate::types::VestingInfo; use cosmwasm_std::{ - to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, Uint128, + to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, Uint128, }; /// Contains the historical extension check and routing of the message. @@ -35,10 +35,10 @@ pub(crate) fn handle_query_historical_msg( match msg { QueryMsgHistorical::UnclaimedAmountAtHeight { address, height } => { - to_binary(&query_unclaimed_amount_at_height(deps, address, height)?) + to_json_binary(&query_unclaimed_amount_at_height(deps, address, height)?) } QueryMsgHistorical::UnclaimedTotalAmountAtHeight { height } => { - to_binary(&query_total_unclaimed_amount_at_height(deps, height)?) + to_json_binary(&query_total_unclaimed_amount_at_height(deps, height)?) } } } diff --git a/packages/vesting-base/src/ext_with_managers.rs b/packages/vesting-base/src/ext_with_managers.rs index 56573188..6d0f4feb 100644 --- a/packages/vesting-base/src/ext_with_managers.rs +++ b/packages/vesting-base/src/ext_with_managers.rs @@ -2,8 +2,8 @@ use crate::error::{ext_unsupported_err, ContractError}; use crate::msg::{ExecuteMsgWithManagers, QueryMsgWithManagers}; use crate::state::{CONFIG, VESTING_MANAGERS}; use cosmwasm_std::{ - attr, to_binary, Addr, Attribute, Binary, Deps, DepsMut, Env, MessageInfo, Order, Response, - StdError, StdResult, + attr, to_json_binary, Addr, Attribute, Binary, Deps, DepsMut, Env, MessageInfo, Order, + Response, StdError, StdResult, }; /// Contains the with_managers extension check and routing of the message. @@ -40,7 +40,7 @@ pub(crate) fn handle_query_managers_msg( } match msg { - QueryMsgWithManagers::VestingManagers {} => to_binary(&query_vesting_managers(deps)?), + QueryMsgWithManagers::VestingManagers {} => to_json_binary(&query_vesting_managers(deps)?), } } diff --git a/packages/vesting-base/src/handlers.rs b/packages/vesting-base/src/handlers.rs index 7797db28..b05062e1 100644 --- a/packages/vesting-base/src/handlers.rs +++ b/packages/vesting-base/src/handlers.rs @@ -12,7 +12,7 @@ use crate::types::{ use astroport::asset::{addr_opt_validate, token_asset_info, AssetInfo, AssetInfoExt}; use astroport::common::{claim_ownership, drop_ownership_proposal, propose_new_owner}; use cosmwasm_std::{ - attr, from_binary, to_binary, Addr, Binary, Deps, DepsMut, Env, MessageInfo, Response, + attr, from_json, to_json_binary, Addr, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, Storage, SubMsg, Uint128, }; use cw20::Cw20ReceiveMsg; @@ -108,7 +108,7 @@ fn receive_cw20( return Err(ContractError::Unauthorized {}); } - match from_binary(&cw20_msg.msg)? { + match from_json(&cw20_msg.msg)? { Cw20HookMsg::RegisterVestingAccounts { vesting_accounts } => { register_vesting_accounts(deps, vesting_accounts, cw20_msg.amount, env.block.height) } @@ -120,7 +120,7 @@ fn receive_cw20( /// * **vesting_accounts** list of accounts and associated vesting schedules to create. /// /// * **cw20_amount** sets the amount that confirms the total amount of all accounts to register. -fn register_vesting_accounts( +pub fn register_vesting_accounts( deps: DepsMut, vesting_accounts: Vec, amount: Uint128, @@ -275,7 +275,7 @@ pub(crate) fn set_vesting_token( ])) } -pub(crate) fn get_vesting_token(config: &Config) -> Result { +pub fn get_vesting_token(config: &Config) -> Result { config .vesting_token .clone() @@ -285,25 +285,25 @@ pub(crate) fn get_vesting_token(config: &Config) -> Result StdResult { match msg { - QueryMsg::Config {} => Ok(to_binary(&query_config(deps)?)?), + QueryMsg::Config {} => Ok(to_json_binary(&query_config(deps)?)?), QueryMsg::VestingAccount { address } => { - Ok(to_binary(&query_vesting_account(deps, address)?)?) + Ok(to_json_binary(&query_vesting_account(deps, address)?)?) } QueryMsg::VestingAccounts { start_after, limit, order_by, - } => Ok(to_binary(&query_vesting_accounts( + } => Ok(to_json_binary(&query_vesting_accounts( deps, start_after, limit, order_by, )?)?), - QueryMsg::AvailableAmount { address } => Ok(to_binary(&query_vesting_available_amount( - deps, env, address, - )?)?), - QueryMsg::VestingState {} => Ok(to_binary(&query_vesting_state(deps)?)?), - QueryMsg::Timestamp {} => Ok(to_binary(&query_timestamp(env)?)?), + QueryMsg::AvailableAmount { address } => Ok(to_json_binary( + &query_vesting_available_amount(deps, env, address)?, + )?), + QueryMsg::VestingState {} => Ok(to_json_binary(&query_vesting_state(deps)?)?), + QueryMsg::Timestamp {} => Ok(to_json_binary(&query_timestamp(env)?)?), QueryMsg::ManagedExtension { msg } => handle_query_managed_msg(deps, env, msg), QueryMsg::WithManagersExtension { msg } => handle_query_managers_msg(deps, env, msg), QueryMsg::HistoricalExtension { msg } => handle_query_historical_msg(deps, env, msg), @@ -398,7 +398,7 @@ fn is_sender_whitelisted(store: &mut dyn Storage, config: &Config, sender: &Addr /// * **addr** receiver of the vested tokens. /// /// * **vesting_schedules** vesting schedules to validate. -fn assert_vesting_schedules( +pub fn assert_vesting_schedules( addr: &Addr, vesting_schedules: &[VestingSchedule], ) -> Result<(), ContractError> { diff --git a/packages/vesting-base/src/state.rs b/packages/vesting-base/src/state.rs index 978fd8c6..9178f7ca 100644 --- a/packages/vesting-base/src/state.rs +++ b/packages/vesting-base/src/state.rs @@ -3,9 +3,9 @@ use astroport::common::OwnershipProposal; use cosmwasm_std::{Addr, Deps, StdResult}; use cw_storage_plus::{Bound, Item, Map, SnapshotItem, SnapshotMap, Strategy}; -pub(crate) const CONFIG: Item = Item::new("config"); +pub const CONFIG: Item = Item::new("config"); pub(crate) const OWNERSHIP_PROPOSAL: Item = Item::new("ownership_proposal"); -pub(crate) const VESTING_MANAGERS: Map = Map::new("vesting_managers"); +pub const VESTING_MANAGERS: Map = Map::new("vesting_managers"); pub(crate) const VESTING_STATE: SnapshotItem = SnapshotItem::new( "vesting_state", "vesting_state__checkpoints", @@ -31,14 +31,14 @@ pub(crate) const VESTING_INFO_HISTORICAL: SnapshotMap = Snaps Strategy::EveryBlock, ); -pub(crate) fn vesting_state(historical: bool) -> SnapshotItem<'static, VestingState> { +pub fn vesting_state(historical: bool) -> SnapshotItem<'static, VestingState> { if historical { return VESTING_STATE_HISTORICAL; } VESTING_STATE } -pub(crate) fn vesting_info(historical: bool) -> SnapshotMap<'static, Addr, VestingInfo> { +pub fn vesting_info(historical: bool) -> SnapshotMap<'static, Addr, VestingInfo> { if historical { return VESTING_INFO_HISTORICAL; } diff --git a/packages/vesting-base/src/testing.rs b/packages/vesting-base/src/testing.rs index 3d11af41..094ddebe 100644 --- a/packages/vesting-base/src/testing.rs +++ b/packages/vesting-base/src/testing.rs @@ -7,7 +7,7 @@ use crate::msg::{ use crate::types::{Config, Extensions}; use astroport::asset::token_asset_info; use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info}; -use cosmwasm_std::{from_binary, Addr}; +use cosmwasm_std::{from_json, Addr}; #[test] fn set_vesting_token() { @@ -21,7 +21,7 @@ fn set_vesting_token() { // check initialisation assert_eq!( - from_binary::(&query(deps.as_ref(), env.clone(), QueryMsg::Config {}).unwrap()) + from_json::(&query(deps.as_ref(), env.clone(), QueryMsg::Config {}).unwrap()) .unwrap(), Config { owner: Addr::unchecked("owner"), @@ -63,7 +63,7 @@ fn set_vesting_token() { .unwrap(); assert_eq!( - from_binary::(&query(deps.as_ref(), env.clone(), QueryMsg::Config {}).unwrap()) + from_json::(&query(deps.as_ref(), env.clone(), QueryMsg::Config {}).unwrap()) .unwrap(), Config { owner: Addr::unchecked("owner"), @@ -92,7 +92,7 @@ fn set_vesting_token() { ); assert_eq!( - from_binary::(&query(deps.as_ref(), env, QueryMsg::Config {}).unwrap()).unwrap(), + from_json::(&query(deps.as_ref(), env, QueryMsg::Config {}).unwrap()).unwrap(), Config { owner: Addr::unchecked("owner"), token_info_manager: Addr::unchecked(token_info_manager), @@ -119,7 +119,7 @@ fn proper_building_standard() { // check initialisation assert_eq!( - from_binary::(&query(deps.as_ref(), env.clone(), QueryMsg::Config {}).unwrap()) + from_json::(&query(deps.as_ref(), env.clone(), QueryMsg::Config {}).unwrap()) .unwrap(), Config { owner: Addr::unchecked("owner"), @@ -192,7 +192,7 @@ fn proper_building_managers() { // check initialisation assert_eq!( - from_binary::(&query(deps.as_ref(), env.clone(), QueryMsg::Config {}).unwrap()) + from_json::(&query(deps.as_ref(), env.clone(), QueryMsg::Config {}).unwrap()) .unwrap(), Config { owner: Addr::unchecked("owner"), @@ -208,7 +208,7 @@ fn proper_building_managers() { // make sure with_managers extension is enabled assert_eq!( - from_binary::>( + from_json::>( &query( deps.as_ref(), env.clone(), @@ -267,7 +267,7 @@ fn proper_building_historical() { // check initialisation assert_eq!( - from_binary::(&query(deps.as_ref(), env.clone(), QueryMsg::Config {}).unwrap()) + from_json::(&query(deps.as_ref(), env.clone(), QueryMsg::Config {}).unwrap()) .unwrap(), Config { owner: Addr::unchecked("owner"), @@ -335,7 +335,7 @@ fn proper_building_managed() { // check initialisation and set vesting token assert_eq!( - from_binary::(&query(deps.as_ref(), env.clone(), QueryMsg::Config {}).unwrap()) + from_json::(&query(deps.as_ref(), env.clone(), QueryMsg::Config {}).unwrap()) .unwrap(), Config { owner: Addr::unchecked("owner"), @@ -417,7 +417,7 @@ fn proper_building_all_extensions() { // check initialisation and set vesting token assert_eq!( - from_binary::(&query(deps.as_ref(), env.clone(), QueryMsg::Config {}).unwrap()) + from_json::(&query(deps.as_ref(), env.clone(), QueryMsg::Config {}).unwrap()) .unwrap(), Config { owner: Addr::unchecked("owner"), @@ -443,7 +443,7 @@ fn proper_building_all_extensions() { // make sure with_managers extension is enabled assert_eq!( - from_binary::>( + from_json::>( &query( deps.as_ref(), env.clone(), diff --git a/packages/vesting-base/src/types.rs b/packages/vesting-base/src/types.rs index f6081025..6a1378b4 100644 --- a/packages/vesting-base/src/types.rs +++ b/packages/vesting-base/src/types.rs @@ -81,6 +81,15 @@ pub struct VestingAccountResponse { pub info: VestingInfo, } +/// This structure describes a custom struct used to pass the vesting data about a specific vesting target during migration. +#[cw_serde] +pub struct VestingAccountFullInfo { + /// The address that's vesting tokens + pub address: Addr, + /// Vesting information + pub info: VestingInfo, +} + /// This structure describes a custom struct used to return vesting data for multiple vesting targets. #[cw_serde] pub struct VestingAccountsResponse {