diff --git a/Cargo.lock b/Cargo.lock index 92b7c230..812354ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,6 +19,27 @@ version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +[[package]] +name = "astroport" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcea351626899d205aab091c891fc878fc9b3c930585fd3ef6222de028d8a7a" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 0.15.1", + "cw-utils 0.15.1", + "cw20", + "itertools", + "uint", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "base16ct" version = "0.1.1" @@ -31,12 +52,24 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "base64" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5" + [[package]] name = "base64ct" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + [[package]] name = "block-buffer" version = "0.9.0" @@ -66,6 +99,9 @@ name = "bytes" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +dependencies = [ + "serde", +] [[package]] name = "cfg-if" @@ -79,11 +115,33 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" +[[package]] +name = "cosmos-sdk-proto" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20b42021d8488665b1a0d9748f1f81df7235362d194f44481e2e61bf376b77b4" +dependencies = [ + "prost 0.11.9", + "prost-types", + "tendermint-proto 0.23.9", +] + +[[package]] +name = "cosmos-sdk-proto" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4776e787b24d9568dd61d3237eeb4eb321d622fb881b858c7b82806420e87d4" +dependencies = [ + "prost 0.11.9", + "prost-types", + "tendermint-proto 0.27.0", +] + [[package]] name = "cosmwasm-crypto" -version = "1.2.5" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75836a10cb9654c54e77ee56da94d592923092a10b369cdb0dbd56acefc16340" +checksum = "41c0e41be7e6c7d7ab3c61cdc32fcfaa14f948491a401cbc1c74bb33b6f4b851" dependencies = [ "digest 0.10.7", "ed25519-zebra", @@ -94,18 +152,18 @@ dependencies = [ [[package]] name = "cosmwasm-derive" -version = "1.2.5" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c9f7f0e51bfc7295f7b2664fe8513c966428642aa765dad8a74acdab5e0c773" +checksum = "3a7ee2798c92c00dd17bebb4210f81d5f647e5e92d847959b7977e0fd29a3500" dependencies = [ "syn 1.0.109", ] [[package]] name = "cosmwasm-schema" -version = "1.2.5" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f00b363610218eea83f24bbab09e1a7c3920b79f068334fdfcc62f6129ef9fc" +checksum = "407aca6f1671a08b60db8167f03bb7cb6b2378f0ddd9a030367b66ba33c2fd41" dependencies = [ "cosmwasm-schema-derive", "schemars", @@ -116,9 +174,9 @@ dependencies = [ [[package]] name = "cosmwasm-schema-derive" -version = "1.2.5" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae38f909b2822d32b275c9e2db9728497aa33ffe67dd463bc67c6a3b7092785c" +checksum = "e6d1e00b8fd27ff923c10303023626358e23a6f9079f8ebec23a8b4b0bfcd4b3" dependencies = [ "proc-macro2", "quote", @@ -127,11 +185,11 @@ dependencies = [ [[package]] name = "cosmwasm-std" -version = "1.2.5" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a49b85345e811c8e80ec55d0d091e4fcb4f00f97ab058f9be5f614c444a730cb" +checksum = "92d5fdfd112b070055f068fad079d490117c8e905a588b92a5a7c9276d029930" dependencies = [ - "base64", + "base64 0.13.1", "cosmwasm-crypto", "cosmwasm-derive", "derivative", @@ -139,15 +197,15 @@ dependencies = [ "hex", "schemars", "serde", - "serde-json-wasm", - "sha2 0.10.6", + "serde-json-wasm 0.5.1", + "sha2 0.10.7", "thiserror", "uint", ] [[package]] name = "covenant-clock" -version = "0.1.0" +version = "1.0.0" dependencies = [ "anyhow", "cosmwasm-schema", @@ -156,8 +214,8 @@ dependencies = [ "covenant-clock-tester", "cw-fifo", "cw-multi-test", - "cw-storage-plus", - "cw2", + "cw-storage-plus 1.1.0", + "cw2 1.0.1", "serde", "thiserror", ] @@ -173,20 +231,71 @@ dependencies = [ [[package]] name = "covenant-clock-tester" -version = "0.1.0" +version = "1.0.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 1.1.0", + "cw2 1.0.1", + "thiserror", +] + +[[package]] +name = "covenant-depositor" +version = "1.0.0" dependencies = [ + "anyhow", + "base64 0.13.1", + "bech32", + "cosmos-sdk-proto 0.14.0", "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus", - "cw2", + "cw-multi-test", + "cw-storage-plus 1.1.0", + "cw-utils 1.0.1", + "cw2 1.0.1", + "neutron-sdk", + "prost 0.11.9", + "prost-types", + "protobuf", + "schemars", + "serde", + "serde-json-wasm 0.4.1", + "sha2 0.10.7", + "thiserror", +] + +[[package]] +name = "covenant-lper" +version = "1.0.0" +dependencies = [ + "astroport", + "base64 0.13.1", + "bech32", + "cosmos-sdk-proto 0.14.0", + "cosmwasm-schema", + "cosmwasm-std", + "cw-multi-test", + "cw-storage-plus 1.1.0", + "cw-utils 1.0.1", + "cw2 1.0.1", + "cw20", + "neutron-sdk", + "prost 0.11.9", + "prost-types", + "protobuf", + "schemars", + "serde", + "serde-json-wasm 0.4.1", + "sha2 0.10.7", "thiserror", ] [[package]] name = "cpufeatures" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" +checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" dependencies = [ "libc", ] @@ -238,24 +347,24 @@ version = "0.0.1" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus", + "cw-storage-plus 1.1.0", "serde", ] [[package]] name = "cw-multi-test" -version = "0.16.4" +version = "0.16.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a18afd2e201221c6d72a57f0886ef2a22151bbc9e6db7af276fde8a91081042" +checksum = "127c7bb95853b8e828bdab97065c81cb5ddc20f7339180b61b2300565aaa99d1" dependencies = [ "anyhow", "cosmwasm-std", - "cw-storage-plus", - "cw-utils", + "cw-storage-plus 1.1.0", + "cw-utils 1.0.1", "derivative", "itertools", "k256", - "prost", + "prost 0.9.0", "schemars", "serde", "thiserror", @@ -263,13 +372,39 @@ dependencies = [ [[package]] name = "cw-storage-plus" -version = "1.0.1" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6cf70ef7686e2da9ad7b067c5942cd3e88dd9453f7af42f54557f8af300fb0" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + +[[package]] +name = "cw-storage-plus" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f0e92a069d62067f3472c62e30adedb4cab1754725c0f2a682b3128d2bf3c79" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + +[[package]] +name = "cw-utils" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053a5083c258acd68386734f428a5a171b29f7d733151ae83090c6fcc9417ffa" +checksum = "0ae0b69fa7679de78825b4edeeec045066aa2b2c4b6e063d80042e565bb4da5c" dependencies = [ + "cosmwasm-schema", "cosmwasm-std", + "cw2 0.15.1", "schemars", + "semver", "serde", + "thiserror", ] [[package]] @@ -280,13 +415,26 @@ checksum = "c80e93d1deccb8588db03945016a292c3c631e6325d349ebb35d2db6f4f946f7" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw2", + "cw2 1.0.1", "schemars", "semver", "serde", "thiserror", ] +[[package]] +name = "cw2" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5abb8ecea72e09afff830252963cb60faf945ce6cef2c20a43814516082653da" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 0.15.1", + "schemars", + "serde", +] + [[package]] name = "cw2" version = "1.0.1" @@ -295,7 +443,20 @@ checksum = "8fb70cee2cf0b4a8ff7253e6bc6647107905e8eb37208f87d54f67810faa62f8" dependencies = [ "cosmwasm-schema", "cosmwasm-std", - "cw-storage-plus", + "cw-storage-plus 1.1.0", + "schemars", + "serde", +] + +[[package]] +name = "cw20" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6025276fb6e603e974c21f3e4606982cdc646080e8fba3198816605505e1d9a" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils 0.15.1", "schemars", "serde", ] @@ -410,6 +571,15 @@ dependencies = [ "subtle", ] +[[package]] +name = "flex-error" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c606d892c9de11507fa0dcffc116434f94e105d0bbdc4e405b61519464c49d7b" +dependencies = [ + "paste", +] + [[package]] name = "forward_ref" version = "1.0.0" @@ -428,9 +598,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", @@ -496,20 +666,69 @@ dependencies = [ "cfg-if", "ecdsa", "elliptic-curve", - "sha2 0.10.6", + "sha2 0.10.7", ] [[package]] name = "libc" -version = "0.2.144" +version = "0.2.146" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" + +[[package]] +name = "neutron-sdk" +version = "0.5.0" +source = "git+https://github.com/neutron-org/neutron-sdk#dd253066f673f88aac4495876592afcfb4f8d527" +dependencies = [ + "base64 0.20.0", + "bech32", + "cosmos-sdk-proto 0.16.0", + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 1.1.0", + "prost 0.11.9", + "protobuf", + "schemars", + "serde", + "serde-json-wasm 0.4.1", + "serde_json", + "thiserror", +] + +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] [[package]] name = "once_cell" -version = "1.17.2" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "opaque-debug" @@ -517,6 +736,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "paste" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" + [[package]] name = "pkcs8" version = "0.9.0" @@ -529,9 +754,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" +checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" dependencies = [ "unicode-ident", ] @@ -543,7 +768,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" dependencies = [ "bytes", - "prost-derive", + "prost-derive 0.9.0", +] + +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes", + "prost-derive 0.11.9", ] [[package]] @@ -559,6 +794,49 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "prost-types" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +dependencies = [ + "prost 0.11.9", +] + +[[package]] +name = "protobuf" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55bad9126f378a853655831eb7363b7b01b81d19f8cb1218861086ca4a1a61e" +dependencies = [ + "bytes", + "once_cell", + "protobuf-support", + "thiserror", +] + +[[package]] +name = "protobuf-support" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d4d7b8601c814cfb36bcebb79f0e61e45e1e93640cf778837833bbed05c372" +dependencies = [ + "thiserror", +] + [[package]] name = "quote" version = "1.0.28" @@ -646,13 +924,22 @@ checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" [[package]] name = "serde" -version = "1.0.163" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" dependencies = [ "serde_derive", ] +[[package]] +name = "serde-json-wasm" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479b4dbc401ca13ee8ce902851b834893251404c4f3c65370a49e047a6be09a5" +dependencies = [ + "serde", +] + [[package]] name = "serde-json-wasm" version = "0.5.1" @@ -662,11 +949,20 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_bytes" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416bda436f9aab92e02c8e10d49a15ddd339cea90b6e340fe51ed97abb548294" +dependencies = [ + "serde", +] + [[package]] name = "serde_derive" -version = "1.0.163" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" dependencies = [ "proc-macro2", "quote", @@ -686,9 +982,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "bdf3bf93142acad5821c99197022e170842cdbc1c30482b98750c688c640842a" dependencies = [ "itoa", "ryu", @@ -710,9 +1006,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" dependencies = [ "cfg-if", "cpufeatures", @@ -751,6 +1047,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +[[package]] +name = "subtle-encoding" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcb1ed7b8330c5eed5441052651dd7a12c75e2ed88f2ec024ae1fa3a5e59945" +dependencies = [ + "zeroize", +] + [[package]] name = "syn" version = "1.0.109" @@ -773,6 +1078,42 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tendermint-proto" +version = "0.23.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ce80bf536476db81ecc9ebab834dc329c9c1509a694f211a73858814bfe023" +dependencies = [ + "bytes", + "flex-error", + "num-derive", + "num-traits", + "prost 0.11.9", + "prost-types", + "serde", + "serde_bytes", + "subtle-encoding", + "time", +] + +[[package]] +name = "tendermint-proto" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5895470f28c530f8ae8c4071bf8190304ce00bd131d25e81730453124a3375c" +dependencies = [ + "bytes", + "flex-error", + "num-derive", + "num-traits", + "prost 0.11.9", + "prost-types", + "serde", + "serde_bytes", + "subtle-encoding", + "time", +] + [[package]] name = "thiserror" version = "1.0.40" @@ -793,6 +1134,23 @@ dependencies = [ "syn 2.0.18", ] +[[package]] +name = "time" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217" +dependencies = [ + "libc", + "num_threads", + "time-macros", +] + +[[package]] +name = "time-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" + [[package]] name = "typenum" version = "1.16.0" diff --git a/Cargo.toml b/Cargo.toml index 6d3cb373..31c80fed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,8 +7,10 @@ members = [ [workspace.package] edition = "2021" license = "BSD-3" +version = "1.0.0" +repository = "https://github.com/timewave-computer/covenants/stride-covenant" + rust-version = "1.66" -version = "0.1.0" [profile.release] codegen-units = 1 @@ -22,28 +24,39 @@ panic = 'abort' rpath = false [workspace.dependencies] -cosmwasm-schema = "1.2" -cosmwasm-std = { version = "1.2", features = ["ibc3"] } -cw-storage-plus = "1.0" -cw-utils = "1.0" -cw2 = "1.0" +covenant-depositor = { path = "./packages/depositor", version = "*" } +covenant-lper = { path = "./packages/lper", version = "*" } +covenant-clock = { path = "contracts/clock" } +covenant-clock-tester = { path = "contracts/clock-tester" } +covenant-lp = { path = "contracts/lper" } +covenant-clock-derive = { path = "packages/clock-derive" } +cw-fifo = { path = "packages/cw-fifo" } + -serde = { version = "1", default-features = false, features = ["derive"] } -thiserror = "1" # the sha2 version here is the same as the one used by # cosmwasm-std. when bumping cosmwasm-std, this should also be # updated. to find cosmwasm_std's sha function: # ```cargo tree --package cosmwasm-std``` sha2 = "0.10.6" - -covenant-clock-derive = { path = "packages/clock-derive" } -cw-fifo = { path = "packages/cw-fifo" } - -covenant-clock = { path = "contracts/clock" } -covenant-clock-tester = { path = "contracts/clock-tester" } -covenant-depositor = { path = "contracts/depositor" } +neutron-sdk = { git = "https://github.com/neutron-org/neutron-sdk", default-features = false, version = "0.5.0" } +cosmos-sdk-proto = { version = "0.14.0", default-features = false } +protobuf = { version = "3.2.0", features = ["with-bytes"] } +serde-json-wasm = { version = "0.4.1" } +base64 = "0.13.0" +prost = "0.11" +prost-types = "0.11" +bech32 = "0.9.0" +cosmwasm-schema = "1.2.1" +cosmwasm-std = { version = "1.2.4", features = ["ibc3"] } +cw-storage-plus = "1.0.1" +cw-utils = "1.0.1" +cw2 = "1.0.1" +serde = { version = "1.0.145", default-features = false, features = ["derive"] } +thiserror = "1.0.31" +schemars = "0.8.10" # dev-dependencies -cw-multi-test = "0.16" -anyhow = "1" \ No newline at end of file +cw-multi-test = "0.16.2" +anyhow = { version = "1.0.51" } + diff --git a/contracts/depositor/.cargo/config b/contracts/depositor/.cargo/config index 1e91742c..5f6aa466 100644 --- a/contracts/depositor/.cargo/config +++ b/contracts/depositor/.cargo/config @@ -1,6 +1,3 @@ [alias] -wasm = "build --release --target wasm32-unknown-unknown" -wasm-debug = "build --target wasm32-unknown-unknown" -unit-test = "test --lib --features backtraces" -integration-test = "test --test integration" -schema = "run --example schema" \ No newline at end of file +wasm = "build --release --lib --target wasm32-unknown-unknown" +schema = "run --bin schema" diff --git a/contracts/depositor/Cargo.toml b/contracts/depositor/Cargo.toml index 33472dbe..f45e7c75 100644 --- a/contracts/depositor/Cargo.toml +++ b/contracts/depositor/Cargo.toml @@ -1,19 +1,28 @@ [package] -name = "stride-depositor" -version = "0.0.1" -edition = "2021" +name = "covenant-depositor" +edition = { workspace = true } authors = ["benskey bekauz@protonmail.com"] description = "Depositor module for stride covenant" -license = "BSD-3" +license = { workspace = true } +repository = { workspace = true } +version = { workspace = true } exclude = [ "contract.wasm", "hash.txt", ] + [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 = [] + [profile.release] opt-level = 3 debug = true @@ -25,59 +34,25 @@ panic = 'abort' incremental = false overflow-checks = true -[features] -# for more explicit tests, cargo test --features=backtraces -backtraces = ["cosmwasm-std/backtraces"] -library = [] - [dependencies] -cosmwasm-schema = "1.2.1" -cosmwasm-std = { version = "1.2.4", features = ["ibc3"] } -cw-storage-plus = "1.0.1" -cw-utils = "1.0.1" -cw2 = "1.0.1" -serde = { version = "1.0.145", default-features = false, features = ["derive"] } -thiserror = "1.0.31" -# the sha2 version here is the same as the one used by -# cosmwasm-std. when bumping cosmwasm-std, this should also be -# updated. to find cosmwasm_std's sha function: -# ```cargo tree --package cosmwasm-std``` -sha2 = "0.10.6" -neutron-sdk = { git = "https://github.com/neutron-org/neutron-sdk", default-features = false, version = "0.5.0" } -cosmos-sdk-proto = { version = "0.14.0", default-features = false } -protobuf = { version = "3.2.0", features = ["with-bytes"] } -schemars = "0.8.10" -serde-json-wasm = { version = "0.4.1" } -base64 = "0.13.0" -prost = "0.11" -prost-types = "0.11" -bech32 = "0.9.0" - -# cosmwasm-schema = { workspace = true } -# cosmwasm-std = { workspace = true } -# cw-storage-plus = { workspace = true } -# serde = { workspace = true } -# cw2 = { workspace = true } -# thiserror = { workspace = true } -# cw-multi-test = { workspace = true } -# neutron-sdk = { workspace = true } -# cosmos-sdk-proto = { workspace = true } -# protobuf = { workspace = true } -# schemars = { workspace = true } -# prost = { workspace = true } -# prost-types = { workspace = true } -# serde-json-wasm = { workspace = true } - - -# # the sha2 version here is the same as the one used by -# # cosmwasm-std. when bumping cosmwasm-std, this should also be -# # updated. to find cosmwasm_std's sha function: -# # ```cargo tree --package cosmwasm-std``` -# sha2 = { workspace = true } +cosmwasm-schema = { workspace = true } +cosmwasm-std = { workspace = true } +cw-storage-plus = { workspace = true } +cw-utils = { workspace = true } +cw2 = { workspace = true } +serde = { workspace = true } +thiserror = { workspace = true } +sha2 = { workspace = true } +neutron-sdk = { workspace = true } +cosmos-sdk-proto = { workspace = true } +protobuf = { workspace = true } +schemars = { workspace = true } +serde-json-wasm = { workspace = true } +base64 = { workspace = true } +prost = { workspace = true } +prost-types = { workspace = true } +bech32 ={ workspace = true } -# dev-dependencies [dev-dependencies] -cw-multi-test = "0.16.2" -anyhow = { version = "1.0.51" } -# cw-multi-test = { workspace = true } -# anyhow = { workspace = true } +cw-multi-test = { workspace = true } +anyhow = { workspace = true } diff --git a/contracts/depositor/examples/schema.rs b/contracts/depositor/examples/schema.rs index 29d4265e..ad4ece29 100644 --- a/contracts/depositor/examples/schema.rs +++ b/contracts/depositor/examples/schema.rs @@ -1,5 +1,5 @@ use cosmwasm_schema::{export_schema, remove_schemas, schema_for}; -use stride_depositor::msg::{InstantiateMsg, ExecuteMsg, QueryMsg}; +use covenant_depositor::msg::{InstantiateMsg, ExecuteMsg, QueryMsg}; use neutron_sdk::bindings::query::QueryInterchainAccountAddressResponse; use neutron_sdk::sudo::msg::SudoMsg; use std::env::current_dir; diff --git a/contracts/depositor/src/contract.rs b/contracts/depositor/src/contract.rs index 5da9ecf2..1afec7e4 100644 --- a/contracts/depositor/src/contract.rs +++ b/contracts/depositor/src/contract.rs @@ -46,7 +46,7 @@ const ICS_CONNECTION_ID: &str = "connection-1"; const INTERCHAIN_ACCOUNT_ID: &str = "test"; const TRANSFER_PORT: &str = "transfer"; -const CONTRACT_NAME: &str = "crates.io:stride-depositor"; +const CONTRACT_NAME: &str = "crates.io:covenant-depositor"; const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] diff --git a/contracts/lper/.cargo/config b/contracts/lper/.cargo/config new file mode 100644 index 00000000..6a6f2852 --- /dev/null +++ b/contracts/lper/.cargo/config @@ -0,0 +1,3 @@ +[alias] +wasm = "build --release --lib --target wasm32-unknown-unknown" +schema = "run --bin schema" \ No newline at end of file diff --git a/contracts/lper/Cargo.toml b/contracts/lper/Cargo.toml new file mode 100644 index 00000000..16228450 --- /dev/null +++ b/contracts/lper/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "covenant-lper" +authors = ["benskey bekauz@protonmail.com"] +description = "LP module for stride covenant" +license = { workspace = true } +repository = { workspace = true } +version = { workspace = true } +edition = { workspace = true } + +[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] +cosmwasm-schema = { workspace = true } +cosmwasm-std = { workspace = true } +cw-storage-plus = { workspace = true } +cw-utils = { workspace = true } +cw2 = { workspace = true } +serde = { workspace = true } +thiserror = { workspace = true } +# the sha2 version here is the same as the one used by +# cosmwasm-std. when bumping cosmwasm-std, this should also be +# updated. to find cosmwasm_std's sha function: +# ```cargo tree --package cosmwasm-std``` +sha2 = { workspace = true } +neutron-sdk = { workspace = true } +cosmos-sdk-proto = { workspace = true } +protobuf = { workspace = true } +schemars = { workspace = true } +serde-json-wasm = { workspace = true } +base64 = { workspace = true } +prost = { workspace = true } +prost-types = { workspace = true } +bech32 ={ workspace = true } +astroport = "2.8.0" +cw20 = { version = "0.15" } + +# dev-dependencies +[dev-dependencies] +cw-multi-test = { workspace = true } diff --git a/stride-covenant/LICENSE b/contracts/lper/LICENSE similarity index 100% rename from stride-covenant/LICENSE rename to contracts/lper/LICENSE diff --git a/contracts/lper/examples/schema.rs b/contracts/lper/examples/schema.rs new file mode 100644 index 00000000..0ff69930 --- /dev/null +++ b/contracts/lper/examples/schema.rs @@ -0,0 +1,15 @@ +use cosmwasm_schema::{export_schema, remove_schemas, schema_for}; +use covenant_lper::msg::{InstantiateMsg, ExecuteMsg, QueryMsg}; +use std::env::current_dir; +use std::fs::create_dir_all; + +fn main() { + let mut out_dir = current_dir().unwrap(); + out_dir.push("schema"); + create_dir_all(&out_dir).unwrap(); + remove_schemas(&out_dir).unwrap(); + + export_schema(&schema_for!(InstantiateMsg), &out_dir); + export_schema(&schema_for!(QueryMsg), &out_dir); + export_schema(&schema_for!(ExecuteMsg), &out_dir); +} \ No newline at end of file diff --git a/contracts/lper/src/contract.rs b/contracts/lper/src/contract.rs new file mode 100644 index 00000000..8acae8c6 --- /dev/null +++ b/contracts/lper/src/contract.rs @@ -0,0 +1,166 @@ +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; +use cosmwasm_std::{MessageInfo, Response, + StdResult, Addr, DepsMut, Env, Binary, Deps, to_binary, SubMsg, WasmMsg, CosmosMsg, Coin, Uint128, Reply, +}; +use cw2::set_contract_version; + +use astroport::{pair::{ExecuteMsg::ProvideLiquidity, Cw20HookMsg}, asset::{Asset, AssetInfo}}; +use cw20::Cw20ReceiveMsg; + +use crate::{msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}, state::{HOLDER_ADDRESS, LP_POSITION}}; + +use neutron_sdk::{ + bindings::{ + msg::{NeutronMsg}, + query::{NeutronQuery}, + }, + NeutronResult, +}; + +use crate::state::{ + CLOCK_ADDRESS, CONTRACT_STATE, ContractState, +}; + + +const CONTRACT_NAME: &str = "crates.io:covenant-lper"; +const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + deps: DepsMut, + _env: Env, + _info: MessageInfo, + msg: InstantiateMsg, +) -> NeutronResult<Response<NeutronMsg>> { + deps.api.debug("WASMDEBUG: instantiate"); + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + + // TODO: validations + CLOCK_ADDRESS.save(deps.storage, &Addr::unchecked(msg.clock_address))?; + CONTRACT_STATE.save(deps.storage, &ContractState::Instantiated)?; + LP_POSITION.save(deps.storage, &msg.lp_position)?; + HOLDER_ADDRESS.save(deps.storage, &msg.holder_address)?; + + Ok(Response::default()) +} + +#[entry_point] +pub fn execute( + mut deps: DepsMut, + env: Env, + info: MessageInfo, + msg: ExecuteMsg, +) -> NeutronResult<Response<NeutronMsg>> { + deps.api + .debug(format!("WASMDEBUG: execute: received msg: {:?}", msg).as_str()); + match msg { + ExecuteMsg::Tick {} => try_tick(deps, env, info), + ExecuteMsg::WithdrawRewards {} => try_withdraw(deps, env, info), + } +} + + +fn try_tick(deps: DepsMut, env: Env, info: MessageInfo) -> NeutronResult<Response<NeutronMsg>> { + let current_state = CONTRACT_STATE.load(deps.storage)?; + + match current_state { + ContractState::Instantiated => try_enter_lp_position(deps, env, info), + ContractState::LpPositionEntered => no_op(), + ContractState::LpPositionExited => no_op(), + ContractState::WithdrawComplete => no_op(), + } +} + +fn no_op() -> NeutronResult<Response<NeutronMsg>> { + Ok(Response::default()) +} + +fn try_enter_lp_position( + deps: DepsMut, + env: Env, + info: MessageInfo, +) -> NeutronResult<Response<NeutronMsg>> { + let pool_address = LP_POSITION.load(deps.storage)?; + + // get balances of uatom and statom + let balances: Vec<Coin> = deps.querier.query_all_balances(env.contract.address)? + .into_iter() + .filter(|coin| coin.denom == "uatom" || coin.denom == "statom") + .collect(); + + // generate astroport Assets from balances + let assets: Vec<Asset> = balances.clone().into_iter() + .map(|bal| Asset { + info: AssetInfo::NativeToken { + denom: bal.denom, + }, + amount: bal.amount, + }) + .collect(); + + let provide_liquidity_msg = ProvideLiquidity { + assets, + slippage_tolerance: None, + auto_stake: Some(true), + receiver: None, + }; + + Ok(Response::default().add_message( + CosmosMsg::Wasm(WasmMsg::Execute { + contract_addr: pool_address.addr, + msg: to_binary(&provide_liquidity_msg)?, + funds: balances, + }) + )) + +} + +fn try_withdraw( + deps: DepsMut, + env: Env, + info: MessageInfo, +) -> NeutronResult<Response<NeutronMsg>> { + let pool_address = LP_POSITION.load(deps.storage)?; + // todo + let withdraw_liquidity_msg = Cw20HookMsg::WithdrawLiquidity { + assets: vec![ + + ], + }; + + let cw20_receive_msg = Cw20ReceiveMsg { + sender: env.contract.address.to_string(), + amount: Uint128::new(1), + msg: to_binary(&withdraw_liquidity_msg)?, + }; + + let msg = WasmMsg::Execute { + contract_addr: pool_address.addr, + msg: to_binary(&astroport::pair::ExecuteMsg::Receive(cw20_receive_msg))?, + funds: vec![], + }; + + Ok(Response::default().add_message( + CosmosMsg::Wasm(msg) + )) + +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps<NeutronQuery>, env: Env, msg: QueryMsg) -> NeutronResult<Binary> { + match msg { + QueryMsg::ClockAddress {} => Ok( + to_binary(&CLOCK_ADDRESS.may_load(deps.storage)?)? + ), + QueryMsg::LpPosition {} => Ok( + to_binary(&LP_POSITION.may_load(deps.storage)?)? + ) + } +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn migrate(deps: DepsMut, _env: Env, _msg: MigrateMsg) -> StdResult<Response> { + deps.api.debug("WASMDEBUG: migrate"); + Ok(Response::default()) +} diff --git a/contracts/lper/src/lib.rs b/contracts/lper/src/lib.rs new file mode 100644 index 00000000..cb0f31b4 --- /dev/null +++ b/contracts/lper/src/lib.rs @@ -0,0 +1,7 @@ +#![warn(clippy::unwrap_used, clippy::expect_used)] + +extern crate core; + +pub mod contract; +pub mod msg; +pub mod state; diff --git a/contracts/lper/src/msg.rs b/contracts/lper/src/msg.rs new file mode 100644 index 00000000..7ed30b5f --- /dev/null +++ b/contracts/lper/src/msg.rs @@ -0,0 +1,34 @@ +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub struct InstantiateMsg { + pub lp_position: LPInfo, + pub clock_address: String, + pub holder_address: String, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub struct LPInfo { + pub addr: String, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum ExecuteMsg { + Tick {}, + WithdrawRewards {}, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum QueryMsg { + LpPosition {}, + ClockAddress {}, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +pub struct MigrateMsg { +} diff --git a/contracts/lper/src/state.rs b/contracts/lper/src/state.rs new file mode 100644 index 00000000..85edbbfa --- /dev/null +++ b/contracts/lper/src/state.rs @@ -0,0 +1,24 @@ + +use cosmwasm_std::Addr; +use cw_storage_plus::{Item}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use crate::msg::LPInfo; + + +// store the clock address to verify calls +pub const CLOCK_ADDRESS: Item<Addr> = Item::new("clock_address"); +pub const LP_POSITION: Item<LPInfo> = Item::new("lp_position"); +pub const HOLDER_ADDRESS: Item<String> = Item::new("holder_address"); +pub const CONTRACT_STATE: Item<ContractState> = Item::new("contract_state"); + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum ContractState { + Instantiated, + LpPositionEntered, + LpPositionExited, + WithdrawComplete, +} + diff --git a/stride-covenant/.gitignore b/stride-covenant/.gitignore deleted file mode 100644 index 0894b8ee..00000000 --- a/stride-covenant/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -# macOS -.DS_Store - -# Text file backups -**/*.rs.bk - -# Build results -target/ - -# IDEs -.vscode/ -.idea/ -*.iml -**/.editorconfig - -# Auto-gen -.cargo-ok - -# Build artifacts -*.wasm -hash.txt -contracts.txt -artifacts/ - -# code coverage -tarpaulin-report.* - -# integration tests -gas_reports/ -ci/configs/cosm-orc/local.yaml - -contracts/**/Cargo.lock -packages/**/Cargo.lock \ No newline at end of file diff --git a/stride-covenant/astroport/astroport_factory.wasm b/stride-covenant/astroport/astroport_factory.wasm new file mode 100644 index 00000000..32215872 Binary files /dev/null and b/stride-covenant/astroport/astroport_factory.wasm differ diff --git a/stride-covenant/astroport/astroport_native_coin_registry.wasm b/stride-covenant/astroport/astroport_native_coin_registry.wasm new file mode 100644 index 00000000..b3e79d9c Binary files /dev/null and b/stride-covenant/astroport/astroport_native_coin_registry.wasm differ diff --git a/stride-covenant/astroport/astroport_pair.wasm b/stride-covenant/astroport/astroport_pair.wasm new file mode 100644 index 00000000..5d98eb87 Binary files /dev/null and b/stride-covenant/astroport/astroport_pair.wasm differ diff --git a/stride-covenant/astroport/astroport_pair_stable.wasm b/stride-covenant/astroport/astroport_pair_stable.wasm new file mode 100644 index 00000000..47caf760 Binary files /dev/null and b/stride-covenant/astroport/astroport_pair_stable.wasm differ diff --git a/stride-covenant/astroport/astroport_token.wasm b/stride-covenant/astroport/astroport_token.wasm new file mode 100644 index 00000000..6663163a Binary files /dev/null and b/stride-covenant/astroport/astroport_token.wasm differ diff --git a/stride-covenant/astroport/astroport_whitelist.wasm b/stride-covenant/astroport/astroport_whitelist.wasm new file mode 100644 index 00000000..0d6fadf8 Binary files /dev/null and b/stride-covenant/astroport/astroport_whitelist.wasm differ diff --git a/stride-covenant/justfile b/stride-covenant/justfile index 8c671ef9..dde0c9a1 100644 --- a/stride-covenant/justfile +++ b/stride-covenant/justfile @@ -21,6 +21,13 @@ optimize: ./optimize.sh simtest: optimize + if [[ $(uname -m) =~ "arm64" ]]; then \ + mv ./../artifacts/covenant_depositor-aarch64.wasm ./../artifacts/covenant_depositor.wasm && \ + mv ./../artifacts/covenant_lper-aarch64.wasm ./../artifacts/covenant_lper.wasm \ + ;fi + + cp ./astroport/*.wasm ./../artifacts + mkdir -p tests/interchaintest/wasms cp -R ./../artifacts/*.wasm tests/interchaintest/wasms diff --git a/stride-covenant/tests/interchaintest/genesis_helpers.go b/stride-covenant/tests/interchaintest/genesis_helpers.go new file mode 100644 index 00000000..c29afb1c --- /dev/null +++ b/stride-covenant/tests/interchaintest/genesis_helpers.go @@ -0,0 +1,104 @@ +package ibc_test + +import ( + "encoding/json" + "fmt" + + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/icza/dyno" + "github.com/strangelove-ventures/interchaintest/v3/ibc" +) + +// Sets custom fields for the Neutron genesis file that interchaintest isn't aware of by default. +// +// soft_opt_out_threshold - the bottom `soft_opt_out_threshold` +// percentage of validators may opt out of running a Neutron +// node [^1]. +// +// reward_denoms - the reward denominations allowed to be sent to the +// provider (atom) from the consumer (neutron) [^2]. +// +// provider_reward_denoms - the reward denominations allowed to be +// sent to the consumer by the provider [^2]. +// +// [^1]: https://docs.neutron.org/neutron/consumer-chain-launch#relevant-parameters +// [^2]: https://github.com/cosmos/interchain-security/blob/54e9852d3c89a2513cd0170a56c6eec894fc878d/proto/interchain_security/ccv/consumer/v1/consumer.proto#L61-L66 +func setupNeutronGenesis( + soft_opt_out_threshold string, + reward_denoms []string, + provider_reward_denoms []string) func(ibc.ChainConfig, []byte) ([]byte, error) { + return func(chainConfig ibc.ChainConfig, genbz []byte) ([]byte, error) { + g := make(map[string]interface{}) + if err := json.Unmarshal(genbz, &g); err != nil { + return nil, fmt.Errorf("failed to unmarshal genesis file: %w", err) + } + + if err := dyno.Set(g, soft_opt_out_threshold, "app_state", "ccvconsumer", "params", "soft_opt_out_threshold"); err != nil { + return nil, fmt.Errorf("failed to set soft_opt_out_threshold in genesis json: %w", err) + } + + if err := dyno.Set(g, reward_denoms, "app_state", "ccvconsumer", "params", "reward_denoms"); err != nil { + return nil, fmt.Errorf("failed to set reward_denoms in genesis json: %w", err) + } + + if err := dyno.Set(g, provider_reward_denoms, "app_state", "ccvconsumer", "params", "provider_reward_denoms"); err != nil { + return nil, fmt.Errorf("failed to set provider_reward_denoms in genesis json: %w", err) + } + + out, err := json.Marshal(g) + + if err != nil { + return nil, fmt.Errorf("failed to marshal genesis bytes to json: %w", err) + } + return out, nil + } +} + +// Sets custom fields for the Gaia genesis file that interchaintest isn't aware of by default. +// +// allowed_messages - explicitly allowed messages to be accepted by the the interchainaccounts section +func setupGaiaGenesis(allowed_messages []string) func(ibc.ChainConfig, []byte) ([]byte, error) { + return func(chainConfig ibc.ChainConfig, genbz []byte) ([]byte, error) { + g := make(map[string]interface{}) + if err := json.Unmarshal(genbz, &g); err != nil { + return nil, fmt.Errorf("failed to unmarshal genesis file: %w", err) + } + + if err := dyno.Set(g, allowed_messages, "app_state", "interchainaccounts", "host_genesis_state", "params", "allow_messages"); err != nil { + return nil, fmt.Errorf("failed to set allow_messages for interchainaccount host in genesis json: %w", err) + } + + out, err := json.Marshal(g) + if err != nil { + return nil, fmt.Errorf("failed to marshal genesis bytes to json: %w", err) + } + return out, nil + } +} + +func getCreateValidatorCmd(chain ibc.Chain) []string { + // Before receiving a validator set change (VSC) packet, + // consumer chains disallow bank transfers. To trigger a VSC + // packet, this creates a validator (from a random public key) + // that will never do anything, triggering a VSC + // packet. Eventually this validator will become jailed, + // triggering another one. + cmd := []string{"gaiad", "tx", "staking", "create-validator", + "--amount", "1000000uatom", + "--pubkey", `{"@type":"/cosmos.crypto.ed25519.PubKey","key":"qwrYHaJ7sNHfYBR1nzDr851+wT4ed6p8BbwTeVhaHoA="}`, + "--moniker", "a", + "--commission-rate", "0.1", + "--commission-max-rate", "0.2", + "--commission-max-change-rate", "0.01", + "--min-self-delegation", "1000000", + "--node", chain.GetRPCAddress(), + "--home", chain.HomeDir(), + "--chain-id", chain.Config().ChainID, + "--from", "faucet", + "--fees", "20000uatom", + "--keyring-backend", keyring.BackendTest, + "-y", + } + + return cmd +} diff --git a/stride-covenant/tests/interchaintest/go.mod b/stride-covenant/tests/interchaintest/go.mod index a87621a6..80b7e639 100644 --- a/stride-covenant/tests/interchaintest/go.mod +++ b/stride-covenant/tests/interchaintest/go.mod @@ -14,6 +14,7 @@ replace ( require ( github.com/cosmos/cosmos-sdk v0.45.15 + github.com/cosmos/ibc-go/v3 v3.4.0 github.com/icza/dyno v0.0.0-20220812133438-f0b6f8a18845 github.com/strangelove-ventures/interchaintest/v3 v3.0.0-20230424185430-002b69e57bc7 github.com/stretchr/testify v1.8.2 @@ -43,7 +44,6 @@ require ( github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gorocksdb v1.2.0 // indirect github.com/cosmos/iavl v0.19.4 // indirect - github.com/cosmos/ibc-go/v3 v3.4.0 // indirect github.com/cosmos/interchain-security v1.0.0-rc2 // indirect github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect github.com/cosmos/ledger-go v0.9.3 // indirect diff --git a/stride-covenant/tests/interchaintest/ics_test.go b/stride-covenant/tests/interchaintest/ics_test.go index e190cfb9..7e1af7ed 100644 --- a/stride-covenant/tests/interchaintest/ics_test.go +++ b/stride-covenant/tests/interchaintest/ics_test.go @@ -4,12 +4,12 @@ import ( "context" "encoding/json" "fmt" + "strconv" "testing" "time" "github.com/cosmos/cosmos-sdk/crypto/keyring" transfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" - "github.com/icza/dyno" ibctest "github.com/strangelove-ventures/interchaintest/v3" "github.com/strangelove-ventures/interchaintest/v3/chain/cosmos" "github.com/strangelove-ventures/interchaintest/v3/ibc" @@ -22,148 +22,6 @@ import ( "go.uber.org/zap/zaptest" ) -type InstantiateMsg struct { - StAtomReceiver WeightedReceiver `json:"st_atom_receiver"` - AtomReceiver WeightedReceiver `json:"atom_receiver"` - ClockAddress string `json:"clock_address,string"` - GaiaNeutronIBCTransferChannelId string `json:"gaia_neutron_ibc_transfer_channel_id"` -} - -type WeightedReceiver struct { - Amount int64 `json:"amount"` - Address string `json:"address,string"` -} - -// A query against the Neutron example contract. Note the usage of -// `omitempty` on fields. This means that if that field has no value, -// it will not have a key in the serialized representaiton of the -// struct, thus mimicing the serialization of Rust enums. -type IcaExampleContractQuery struct { - InterchainAccountAddress InterchainAccountAddressQuery `json:"interchain_account_address,omitempty"` -} - -type InterchainAccountAddressQuery struct { - InterchainAccountId string `json:"interchain_account_id"` - ConnectionId string `json:"connection_id"` -} - -type QueryResponse struct { - Data InterchainAccountAddressQueryResponse `json:"data"` -} - -type ICAQueryResponse struct { - Data DepositorInterchainAccountAddressQueryResponse `json:"data"` -} - -type InterchainAccountAddressQueryResponse struct { - InterchainAccountAddress string `json:"interchain_account_address"` -} - -type DepositorICAAddressQuery struct { - DepositorInterchainAccountAddress DepositorInterchainAccountAddressQuery `json:"depositor_interchain_account_address"` -} - -type DepositorContractQuery struct { - ClockAddress ClockAddressQuery `json:"clock_address"` -} - -type StAtomWeightedReceiverQuery struct { - StAtomReceiver StAtomReceiverQuery `json:"st_atom_receiver"` -} - -type AtomWeightedReceiverQuery struct { - AtomReceiver AtomReceiverQuery `json:"atom_receiver"` -} - -type ClockAddressQuery struct{} -type StAtomReceiverQuery struct{} -type AtomReceiverQuery struct{} -type DepositorInterchainAccountAddressQuery struct{} - -type WeightedReceiverResponse struct { - Data WeightedReceiver `json:"data"` -} - -type ClockQueryResponse struct { - Data string `json:"data"` -} - -// A query response from the Neutron contract. Note that when -// interchaintest returns query responses, it does so in the form -// `{"data": <RESPONSE>}`, so we need this outer data key, which is -// not present in the neutron contract, to properly deserialze. - -type DepositorInterchainAccountAddressQueryResponse struct { - DepositorInterchainAccountAddress string `json:"depositor_interchain_account_address"` -} - -// Sets custom fields for the Neutron genesis file that interchaintest isn't aware of by default. -// -// soft_opt_out_threshold - the bottom `soft_opt_out_threshold` -// percentage of validators may opt out of running a Neutron -// node [^1]. -// -// reward_denoms - the reward denominations allowed to be sent to the -// provider (atom) from the consumer (neutron) [^2]. -// -// provider_reward_denoms - the reward denominations allowed to be -// sent to the consumer by the provider [^2]. -// -// [^1]: https://docs.neutron.org/neutron/consumer-chain-launch#relevant-parameters -// [^2]: https://github.com/cosmos/interchain-security/blob/54e9852d3c89a2513cd0170a56c6eec894fc878d/proto/interchain_security/ccv/consumer/v1/consumer.proto#L61-L66 -func setupNeutronGenesis( - soft_opt_out_threshold string, - reward_denoms []string, - provider_reward_denoms []string) func(ibc.ChainConfig, []byte) ([]byte, error) { - return func(chainConfig ibc.ChainConfig, genbz []byte) ([]byte, error) { - g := make(map[string]interface{}) - if err := json.Unmarshal(genbz, &g); err != nil { - return nil, fmt.Errorf("failed to unmarshal genesis file: %w", err) - } - - if err := dyno.Set(g, soft_opt_out_threshold, "app_state", "ccvconsumer", "params", "soft_opt_out_threshold"); err != nil { - return nil, fmt.Errorf("failed to set soft_opt_out_threshold in genesis json: %w", err) - } - - if err := dyno.Set(g, reward_denoms, "app_state", "ccvconsumer", "params", "reward_denoms"); err != nil { - return nil, fmt.Errorf("failed to set reward_denoms in genesis json: %w", err) - } - - if err := dyno.Set(g, provider_reward_denoms, "app_state", "ccvconsumer", "params", "provider_reward_denoms"); err != nil { - return nil, fmt.Errorf("failed to set provider_reward_denoms in genesis json: %w", err) - } - - out, err := json.Marshal(g) - - if err != nil { - return nil, fmt.Errorf("failed to marshal genesis bytes to json: %w", err) - } - return out, nil - } -} - -// Sets custom fields for the Gaia genesis file that interchaintest isn't aware of by default. -// -// allowed_messages - explicitly allowed messages to be accepted by the the interchainaccounts section -func setupGaiaGenesis(allowed_messages []string) func(ibc.ChainConfig, []byte) ([]byte, error) { - return func(chainConfig ibc.ChainConfig, genbz []byte) ([]byte, error) { - g := make(map[string]interface{}) - if err := json.Unmarshal(genbz, &g); err != nil { - return nil, fmt.Errorf("failed to unmarshal genesis file: %w", err) - } - - if err := dyno.Set(g, allowed_messages, "app_state", "interchainaccounts", "host_genesis_state", "params", "allow_messages"); err != nil { - return nil, fmt.Errorf("failed to set allow_messages for interchainaccount host in genesis json: %w", err) - } - - out, err := json.Marshal(g) - if err != nil { - return nil, fmt.Errorf("failed to marshal genesis bytes to json: %w", err) - } - return out, nil - } -} - // This tests Cosmos Interchain Security, spinning up gaia, neutron, and stride func TestICS(t *testing.T) { if testing.Short() { @@ -254,7 +112,6 @@ func TestICS(t *testing.T) { relayer.RelayerOptionExtraStartFlags{Flags: []string{"-d", "--log-format", "console"}}, ).Build(t, client, network) - const clockContractAddress = "clock_contract_address" const icaAccountId = "test" var icaAccountAddress string // Prep Interchain @@ -332,28 +189,7 @@ func TestICS(t *testing.T) { } } - // Before receiving a validator set change (VSC) packet, - // consumer chains disallow bank transfers. To trigger a VSC - // packet, this creates a validator (from a random public key) - // that will never do anything, triggering a VSC - // packet. Eventually this validator will become jailed, - // triggering another one. - cmd := []string{"gaiad", "tx", "staking", "create-validator", - "--amount", "1000000uatom", - "--pubkey", `{"@type":"/cosmos.crypto.ed25519.PubKey","key":"qwrYHaJ7sNHfYBR1nzDr851+wT4ed6p8BbwTeVhaHoA="}`, - "--moniker", "a", - "--commission-rate", "0.1", - "--commission-max-rate", "0.2", - "--commission-max-change-rate", "0.01", - "--min-self-delegation", "1000000", - "--node", atom.GetRPCAddress(), - "--home", atom.HomeDir(), - "--chain-id", atom.Config().ChainID, - "--from", "faucet", - "--fees", "20000uatom", - "--keyring-backend", keyring.BackendTest, - "-y", - } + cmd := getCreateValidatorCmd(atom) _, _, err = atom.Exec(ctx, cmd, nil) require.NoError(t, err) @@ -387,84 +223,355 @@ func TestICS(t *testing.T) { } } // find the ibc transfer channel to gaia (same connection hops) + print("\n neutron channels:\n") for _, s := range neutronChannelInfo { + channelJson, _ := json.Marshal(s) + print("\n", string(channelJson), "\n") if s.State == "STATE_OPEN" && s.Ordering == "ORDER_UNORDERED" && s.PortID == "transfer" { if len(s.Counterparty.ChannelID) > 5 && s.Counterparty.PortID == "transfer" && s.ConnectionHops[0] == neutronGaiaICSChannel.ConnectionHops[0] { neutronGaiaIBCChannel = s } } } + gaiaNeutronIBCChannel := neutronGaiaIBCChannel.Counterparty - neutronGaiaIBCChannelId := neutronGaiaIBCChannel.ChannelID - gaiaNeutronIBCChannelId := gaiaNeutronIBCChannel.ChannelID - gaiaNeutronICSChannelId := neutronGaiaICSChannel.Counterparty.ChannelID - neutronGaiaICSChannelId := neutronGaiaICSChannel.ChannelID - _, _ = gaiaNeutronICSChannelId, neutronGaiaICSChannelId - - t.Run("instantiate depositor", func(t *testing.T) { - // Store and instantiate the Neutron ICA example contract. The - // wasm file is placed in `wasms/` by the `just test` command. - codeId, err := cosmosNeutron.StoreContract(ctx, neutronUser.KeyName, "wasms/stride_depositor.wasm") - require.NoError(t, err, "failed to store neutron ICA contract") - - stAtomWeightedReceiver := WeightedReceiver{ - Amount: int64(10), - Address: "neutron1ud6resqzgewt92njs826m5st98n9r6kkjnurup", - } - atomWeightedReceiver := WeightedReceiver{ - Amount: int64(10), - Address: "neutron1ud6resqzgewt92njs826m5st98n9r6kkjnurup", - } - msg := InstantiateMsg{ - StAtomReceiver: stAtomWeightedReceiver, - AtomReceiver: atomWeightedReceiver, - ClockAddress: clockContractAddress, - GaiaNeutronIBCTransferChannelId: gaiaNeutronIBCChannelId, - } - str, err := json.Marshal(msg) - require.NoError(t, err, "Failed to marshall instantiateMsg") + print("\n gaia channels:\n") + gaiaChannelInfo, _ := r.GetChannels(ctx, eRep, atom.Config().ChainID) + for _, s := range gaiaChannelInfo { + channelJson, _ := json.Marshal(s) + print("\n", string(channelJson), "\n") + } - address, err := cosmosNeutron.InstantiateContract(ctx, neutronUser.KeyName, codeId, string(str), true) - require.NoError(t, err, "failed to instantiate depositor contract: ", err) + t.Run("stride covenant tests", func(t *testing.T) { + const clockContractAddress = "clock_contract_address" + const holderContractAddress = "holder_contract_address" + + var lperContractAddress string + var depositorContractAddress string + var stAtomWeightedReceiver WeightedReceiver + var atomWeightedReceiver WeightedReceiver neutronSrcDenomTrace := transfertypes.ParseDenomTrace( transfertypes.GetPrefixedDenom("transfer", - neutronGaiaIBCChannelId, + neutronGaiaIBCChannel.ChannelID, atom.Config().Denom)) neutronDstIbcDenom := neutronSrcDenomTrace.IBCDenom() - t.Run("query instantiated clock", func(t *testing.T) { - var response ClockQueryResponse - err = cosmosNeutron.QueryContract(ctx, address, DepositorContractQuery{ - ClockAddress: ClockAddressQuery{}, - }, &response) - require.NoError(t, err, "failed to query clock address") - expectedAddrJson, _ := json.Marshal(clockContractAddress) - require.Equal(t, string(expectedAddrJson), response.Data) + var coinRegistryAddress string + var factoryAddress string + var stableswapAddress string + var tokenAddress string + var whitelistAddress string + _, _ = tokenAddress, whitelistAddress + + t.Run("deploy astroport contracts", func(t *testing.T) { + stablePairCodeIdStr, err := cosmosNeutron.StoreContract(ctx, neutronUser.KeyName, "wasms/astroport_pair_stable.wasm") + require.NoError(t, err, "failed to store astroport stableswap contract") + stablePairCodeId, err := strconv.ParseUint(stablePairCodeIdStr, 10, 64) + require.NoError(t, err, "failed to parse codeId into uint64") + + factoryCodeIdStr, err := cosmosNeutron.StoreContract(ctx, neutronUser.KeyName, "wasms/astroport_factory.wasm") + require.NoError(t, err, "failed to store astroport factory contract") + // factoryCodeId, err := strconv.ParseUint(factoryCodeIdStr, 10, 64) + // require.NoError(t, err, "failed to parse codeId into uint64") + + whitelistCodeIdStr, err := cosmosNeutron.StoreContract(ctx, neutronUser.KeyName, "wasms/astroport_whitelist.wasm") + require.NoError(t, err, "failed to store astroport whitelist contract") + whitelistCodeId, err := strconv.ParseUint(whitelistCodeIdStr, 10, 64) + require.NoError(t, err, "failed to parse codeId into uint64") + + tokenCodeIdStr, err := cosmosNeutron.StoreContract(ctx, neutronUser.KeyName, "wasms/astroport_token.wasm") + require.NoError(t, err, "failed to store astroport token contract") + tokenCodeId, err := strconv.ParseUint(tokenCodeIdStr, 10, 64) + require.NoError(t, err, "failed to parse codeId into uint64") + + t.Run("astroport token", func(t *testing.T) { + + // cap := uint64(1) + msg := NativeTokenInstantiateMsg{ + Name: "nativetoken", + Symbol: "ntk", + Decimals: 5, + InitialBalances: []Cw20Coin{ + // Cw20Coin{ + // Address: neutronUser.Bech32Address(neutron.Config().Bech32Prefix), + // Amount: 1, + // }, + }, + // Mint: &MinterResponse{ + // Minter: depositorContractAddress, + // Cap: &cap, + // }, + Mint: nil, + Marketing: nil, + } + + str, err := json.Marshal(msg) + require.NoError(t, err, "Failed to marshall NativeTokenInstantiateMsg") + + tokenAddress, err = cosmosNeutron.InstantiateContract(ctx, neutronUser.KeyName, tokenCodeIdStr, string(str), true) + require.NoError(t, err, "Failed to instantiate Native Token") + err = testutil.WaitForBlocks(ctx, 2, atom, neutron, stride) + require.NoError(t, err, "failed to wait for blocks") + }) + + t.Run("whitelist", func(t *testing.T) { + + admins := []string{neutronUser.Bech32Address(neutron.Config().Bech32Prefix)} + + msg := WhitelistInstantiateMsg{ + Admins: admins, + Mutable: false, + } + + str, err := json.Marshal(msg) + require.NoError(t, err, "Failed to marshall WhitelistInstantiateMsg") + + whitelistAddress, err = cosmosNeutron.InstantiateContract( + ctx, neutronUser.KeyName, whitelistCodeIdStr, string(str), true) + require.NoError(t, err, "Failed to instantiate Whitelist") + + err = testutil.WaitForBlocks(ctx, 2, atom, neutron, stride) + require.NoError(t, err, "failed to wait for blocks") + }) + + t.Run("native coins registry", func(t *testing.T) { + coinRegistryCodeId, err := cosmosNeutron.StoreContract( + ctx, neutronUser.KeyName, "wasms/astroport_native_coin_registry.wasm") + require.NoError(t, err, "failed to store astroport native coin registry contract") + + msg := NativeCoinRegistryInstantiateMsg{ + Owner: neutronUser.Bech32Address(neutron.Config().Bech32Prefix), + } + str, err := json.Marshal(msg) + require.NoError(t, err, "Failed to marshall NativeCoinRegistryInstantiateMsg") + + nativeCoinRegistryAddress, err := cosmosNeutron.InstantiateContract( + ctx, neutronUser.KeyName, coinRegistryCodeId, string(str), true) + require.NoError(t, err, "Failed to instantiate NativeCoinRegistry") + coinRegistryAddress = nativeCoinRegistryAddress + err = testutil.WaitForBlocks(ctx, 2, atom, neutron, stride) + require.NoError(t, err, "failed to wait for blocks") + }) + + t.Run("add coins to registry", func(t *testing.T) { + // no clue how to marshall go struct fields into rust Vec<(String, u8)> + // so passing as a string for now + addMessage := `{"add":{"native_coins":[["statom",10],["uatom",10]]}}` + addCmd := []string{"neutrond", "tx", "wasm", "execute", + coinRegistryAddress, + addMessage, + "--from", neutronUser.KeyName, + "--gas-prices", "0.0untrn", + "--gas-adjustment", `1.5`, + "--output", "json", + "--home", "/var/cosmos-chain/neutron-2", + "--node", neutron.GetRPCAddress(), + "--home", neutron.HomeDir(), + "--chain-id", neutron.Config().ChainID, + "--from", neutronUser.KeyName, + "--gas", "auto", + "--keyring-backend", keyring.BackendTest, + "-y", + } + _, _, err = cosmosNeutron.Exec(ctx, addCmd, nil) + require.NoError(t, err, err) + + err = testutil.WaitForBlocks(ctx, 2, atom, neutron, stride) + require.NoError(t, err, "failed to wait for blocks") + }) + + t.Run("factory", func(t *testing.T) { + pairConfigs := []PairConfig{ + PairConfig{ + CodeId: stablePairCodeId, + PairType: PairType{ + Stable: struct{}{}, + }, + TotalFeeBps: 0, + MakerFeeBps: 0, + IsDisabled: false, + IsGeneratorDisabled: true, + }, + } + + msg := FactoryInstantiateMsg{ + PairConfigs: pairConfigs, + TokenCodeId: tokenCodeId, + FeeAddress: nil, + GeneratorAddress: nil, + Owner: neutronUser.Bech32Address(neutron.Config().Bech32Prefix), + WhitelistCodeId: whitelistCodeId, + CoinRegistryAddress: coinRegistryAddress, + } + + str, err := json.Marshal(msg) + require.NoError(t, err, "Failed to marshall FactoryInstantiateMsg") + + factoryAddr, err := cosmosNeutron.InstantiateContract( + ctx, neutronUser.KeyName, factoryCodeIdStr, string(str), true) + require.NoError(t, err, "Failed to instantiate Factory") + factoryAddress = factoryAddr + + err = testutil.WaitForBlocks(ctx, 2, atom, neutron, stride) + require.NoError(t, err, "failed to wait for blocks") + }) + + t.Run("stableswap", func(t *testing.T) { + + initParams := StablePoolParams{ + Amp: 9001, + Owner: nil, + } + binaryData, err := json.Marshal(initParams) + require.NoError(t, err, "error encoding stable pool params to binary") + + stAtom := NativeToken{ + Denom: "statom", + } + nativeAtom := NativeToken{ + Denom: atom.Config().Denom, + } + assetInfos := []AssetInfo{ + { + NativeToken: &stAtom, + }, + { + NativeToken: &nativeAtom, + }, + } + + msg := StableswapInstantiateMsg{ + TokenCodeId: tokenCodeId, + FactoryAddr: factoryAddress, + AssetInfos: assetInfos, + InitParams: binaryData, + } + + str, err := json.Marshal(msg) + require.NoError(t, err, "Failed to marshall DepositorInstantiateMsg") + + stableswapAddr, err := cosmosNeutron.InstantiateContract( + ctx, neutronUser.KeyName, stablePairCodeIdStr, string(str), true, + "--label", "stableswap", + "--gas-prices", "0.0untrn", + "--gas-adjustment", `1.5`, + "--output", "json", + "--node", neutron.GetRPCAddress(), + "--home", neutron.HomeDir(), + "--chain-id", neutron.Config().ChainID, + "--gas", "auto", + "--keyring-backend", keyring.BackendTest, + "-y", + ) + require.NoError(t, err, "Failed to instantiate stableswap") + stableswapAddress = stableswapAddr + + err = testutil.WaitForBlocks(ctx, 2, atom, neutron, stride) + require.NoError(t, err, "failed to wait for blocks") + }) + }) - t.Run("query instantiated weighted receivers", func(t *testing.T) { - var stAtomReceiver WeightedReceiverResponse - err = cosmosNeutron.QueryContract(ctx, address, StAtomWeightedReceiverQuery{ - StAtomReceiver: StAtomReceiverQuery{}, - }, &stAtomReceiver) - require.NoError(t, err, "failed to query stAtom weighted receiver") - require.Equal(t, stAtomWeightedReceiver, stAtomReceiver.Data) - - var atomReceiver WeightedReceiverResponse - err = cosmosNeutron.QueryContract(ctx, address, AtomWeightedReceiverQuery{ - AtomReceiver: AtomReceiverQuery{}, - }, &atomReceiver) - require.NoError(t, err, "failed to query atom weighted receiver") - require.Equal(t, int64(10), atomReceiver.Data.Amount) - require.Equal(t, "neutron1ud6resqzgewt92njs826m5st98n9r6kkjnurup", atomReceiver.Data.Address) + t.Run("instantiate lper contract", func(t *testing.T) { + codeId, err := cosmosNeutron.StoreContract(ctx, neutronUser.KeyName, "wasms/stride_lper.wasm") + require.NoError(t, err, "failed to store neutron ICA contract") + lpInfo := LpInfo{ + Addr: stableswapAddress, + } + + lpMsg := LPerInstantiateMsg{ + LpPosition: lpInfo, + ClockAddress: clockContractAddress, + HolderAddress: holderContractAddress, + } + + str, err := json.Marshal(lpMsg) + require.NoError(t, err, "Failed to marshall LPerInstantiateMsg") + + lperContractAddress, err = cosmosNeutron.InstantiateContract(ctx, neutronUser.KeyName, codeId, string(str), true) + require.NoError(t, err, "failed to instantiate lper contract: ", err) + + t.Run("query instantiated clock", func(t *testing.T) { + var response ClockQueryResponse + err = cosmosNeutron.QueryContract(ctx, lperContractAddress, LPContractQuery{ + ClockAddress: ClockAddressQuery{}, + }, &response) + require.NoError(t, err, "failed to query clock address") + expectedAddrJson, _ := json.Marshal(clockContractAddress) + require.Equal(t, string(expectedAddrJson), response.Data) + }) + + t.Run("query lp position", func(t *testing.T) { + var response LpPositionQueryResponse + err := cosmosNeutron.QueryContract(ctx, lperContractAddress, LPPositionQuery{ + LpPosition: LpPositionQuery{}, + }, &response) + require.NoError(t, err, "failed to query lp position address") + require.Equal(t, stableswapAddress, response.Data.Addr) + }) + }) + + t.Run("instantiate depositor contract", func(t *testing.T) { + codeId, err := cosmosNeutron.StoreContract(ctx, neutronUser.KeyName, "wasms/stride_depositor.wasm") + require.NoError(t, err, "failed to store neutron ICA contract") + + stAtomWeightedReceiver = WeightedReceiver{ + Amount: int64(10), + Address: lperContractAddress, + } + + atomWeightedReceiver = WeightedReceiver{ + Amount: int64(10), + Address: lperContractAddress, + } + + msg := DepositorInstantiateMsg{ + StAtomReceiver: stAtomWeightedReceiver, + AtomReceiver: atomWeightedReceiver, + ClockAddress: clockContractAddress, + GaiaNeutronIBCTransferChannelId: gaiaNeutronIBCChannel.ChannelID, + } + + str, err := json.Marshal(msg) + require.NoError(t, err, "Failed to marshall DepositorInstantiateMsg") + + depositorContractAddress, err = cosmosNeutron.InstantiateContract(ctx, neutronUser.KeyName, codeId, string(str), true) + require.NoError(t, err, "failed to instantiate depositor contract: ", err) + + t.Run("query instantiated clock", func(t *testing.T) { + var response ClockQueryResponse + err = cosmosNeutron.QueryContract(ctx, depositorContractAddress, DepositorContractQuery{ + ClockAddress: ClockAddressQuery{}, + }, &response) + require.NoError(t, err, "failed to query clock address") + expectedAddrJson, _ := json.Marshal(clockContractAddress) + require.Equal(t, string(expectedAddrJson), response.Data) + }) + + t.Run("query instantiated weighted receivers", func(t *testing.T) { + var stAtomReceiver WeightedReceiverResponse + err = cosmosNeutron.QueryContract(ctx, depositorContractAddress, StAtomWeightedReceiverQuery{ + StAtomReceiver: StAtomReceiverQuery{}, + }, &stAtomReceiver) + require.NoError(t, err, "failed to query stAtom weighted receiver") + require.Equal(t, stAtomWeightedReceiver, stAtomReceiver.Data) + + var atomReceiver WeightedReceiverResponse + err = cosmosNeutron.QueryContract(ctx, depositorContractAddress, AtomWeightedReceiverQuery{ + AtomReceiver: AtomReceiverQuery{}, + }, &atomReceiver) + require.NoError(t, err, "failed to query atom weighted receiver") + require.Equal(t, int64(10), atomReceiver.Data.Amount) + require.Equal(t, lperContractAddress, atomReceiver.Data.Address) + }) }) var addrResponse QueryResponse t.Run("first tick instantiates ICA", func(t *testing.T) { // should remain constant - cmd = []string{"neutrond", "tx", "wasm", "execute", address, + cmd = []string{"neutrond", "tx", "wasm", "execute", depositorContractAddress, `{"tick":{}}`, "--from", neutronUser.KeyName, "--gas-prices", "0.0untrn", @@ -487,7 +594,7 @@ func TestICS(t *testing.T) { require.NoError(t, err, "failed to wait for blocks") var response QueryResponse - err = cosmosNeutron.QueryContract(ctx, address, IcaExampleContractQuery{ + err = cosmosNeutron.QueryContract(ctx, depositorContractAddress, IcaExampleContractQuery{ InterchainAccountAddress: InterchainAccountAddressQuery{ InterchainAccountId: icaAccountId, ConnectionId: neutronIcsConnectionId, @@ -496,7 +603,7 @@ func TestICS(t *testing.T) { require.NoError(t, err, "failed to query ICA account address") require.NotEmpty(t, response.Data.InterchainAccountAddress) icaAccountAddress = response.Data.InterchainAccountAddress - err = cosmosNeutron.QueryContract(ctx, address, DepositorICAAddressQuery{ + err = cosmosNeutron.QueryContract(ctx, depositorContractAddress, DepositorICAAddressQuery{ DepositorInterchainAccountAddress: DepositorInterchainAccountAddressQuery{}, }, &addrResponse) require.NoError(t, err, "failed to query ICA account address") @@ -508,6 +615,8 @@ func TestICS(t *testing.T) { response.Data.InterchainAccountAddress, icaAccountAddress, ) + + print("\ndepositor ICA instantiated with address ", icaAccountAddress, "\n") }) t.Run("multisig transfers atom to ICA account", func(t *testing.T) { @@ -529,7 +638,7 @@ func TestICS(t *testing.T) { t.Run("fund depositor contract with some neutron", func(t *testing.T) { err := neutron.SendFunds(ctx, neutronUser.KeyName, ibc.WalletAmount{ - Address: address, + Address: depositorContractAddress, Amount: 500001, Denom: neutron.Config().Denom, }) @@ -538,7 +647,7 @@ func TestICS(t *testing.T) { err = testutil.WaitForBlocks(ctx, 10, atom, neutron) require.NoError(t, err, "failed to wait for blocks") - neutronBal, err := neutron.GetBalance(ctx, address, neutron.Config().Denom) + neutronBal, err := neutron.GetBalance(ctx, depositorContractAddress, neutron.Config().Denom) require.NoError(t, err, "failed to get depositor neutron balance") require.EqualValues(t, 500001, neutronBal) }) @@ -548,7 +657,7 @@ func TestICS(t *testing.T) { require.NoError(t, err, "failed to get ICA balance") require.EqualValues(t, 20, atomBal) - cmd = []string{"neutrond", "tx", "wasm", "execute", address, + cmd = []string{"neutrond", "tx", "wasm", "execute", depositorContractAddress, `{"tick":{}}`, "--from", neutronUser.KeyName, "--gas-adjustment", `1.3`, @@ -566,7 +675,7 @@ func TestICS(t *testing.T) { _, _, err = neutron.Exec(ctx, cmd, nil) require.NoError(t, err) - err = testutil.WaitForBlocks(ctx, 50, atom, neutron) + err = testutil.WaitForBlocks(ctx, 20, atom, neutron) require.NoError(t, err, "failed to wait for blocks") atomICABal, err := atom.GetBalance(ctx, icaAccountAddress, atom.Config().Denom) @@ -575,14 +684,16 @@ func TestICS(t *testing.T) { neutronUserBalNew, err := neutron.GetBalance( ctx, - address, + depositorContractAddress, neutronDstIbcDenom) require.NoError(t, err, "failed to query depositor contract atom balance") require.Equal(t, int64(10), neutronUserBalNew) }) + // to keep docker containers alive for debugging + // err = testutil.WaitForBlocks(ctx, 200, atom, neutron) t.Run("subsequent ticks do nothing", func(t *testing.T) { - cmd = []string{"neutrond", "tx", "wasm", "execute", address, + cmd = []string{"neutrond", "tx", "wasm", "execute", depositorContractAddress, `{"tick":{}}`, "--from", neutronUser.KeyName, "--gas-prices", "0.0untrn", @@ -604,6 +715,7 @@ func TestICS(t *testing.T) { err = testutil.WaitForBlocks(ctx, 10, atom, neutron) require.NoError(t, err, "failed to wait for blocks") }) + }) } diff --git a/stride-covenant/tests/interchaintest/types.go b/stride-covenant/tests/interchaintest/types.go new file mode 100644 index 00000000..09b999c1 --- /dev/null +++ b/stride-covenant/tests/interchaintest/types.go @@ -0,0 +1,209 @@ +package ibc_test + +type DepositorInstantiateMsg struct { + StAtomReceiver WeightedReceiver `json:"st_atom_receiver"` + AtomReceiver WeightedReceiver `json:"atom_receiver"` + ClockAddress string `json:"clock_address,string"` + GaiaNeutronIBCTransferChannelId string `json:"gaia_neutron_ibc_transfer_channel_id"` +} + +type LPerInstantiateMsg struct { + LpPosition LpInfo `json:"lp_position"` + ClockAddress string `json:"clock_address,string"` + HolderAddress string `json:"holder_address,string"` +} + +type LpInfo struct { + Addr string `json:"addr,string"` +} + +type WeightedReceiver struct { + Amount int64 `json:"amount"` + Address string `json:"address,string"` +} + +// A query against the Neutron example contract. Note the usage of +// `omitempty` on fields. This means that if that field has no value, +// it will not have a key in the serialized representaiton of the +// struct, thus mimicing the serialization of Rust enums. +type IcaExampleContractQuery struct { + InterchainAccountAddress InterchainAccountAddressQuery `json:"interchain_account_address,omitempty"` +} + +type InterchainAccountAddressQuery struct { + InterchainAccountId string `json:"interchain_account_id"` + ConnectionId string `json:"connection_id"` +} + +type QueryResponse struct { + Data InterchainAccountAddressQueryResponse `json:"data"` +} + +type ICAQueryResponse struct { + Data DepositorInterchainAccountAddressQueryResponse `json:"data"` +} + +type InterchainAccountAddressQueryResponse struct { + InterchainAccountAddress string `json:"interchain_account_address"` +} + +type DepositorICAAddressQuery struct { + DepositorInterchainAccountAddress DepositorInterchainAccountAddressQuery `json:"depositor_interchain_account_address"` +} + +type DepositorContractQuery struct { + ClockAddress ClockAddressQuery `json:"clock_address"` +} + +type LPContractQuery struct { + ClockAddress ClockAddressQuery `json:"clock_address"` +} + +type LPPositionQuery struct { + LpPosition LpPositionQuery `json:"lp_position"` +} + +type StAtomWeightedReceiverQuery struct { + StAtomReceiver StAtomReceiverQuery `json:"st_atom_receiver"` +} + +type AtomWeightedReceiverQuery struct { + AtomReceiver AtomReceiverQuery `json:"atom_receiver"` +} + +type ClockAddressQuery struct{} +type StAtomReceiverQuery struct{} +type AtomReceiverQuery struct{} +type DepositorInterchainAccountAddressQuery struct{} +type LpPositionQuery struct{} + +type WeightedReceiverResponse struct { + Data WeightedReceiver `json:"data"` +} + +type ClockQueryResponse struct { + Data string `json:"data"` +} + +type LpPositionQueryResponse struct { + Data LpInfo `json:"data"` +} + +// A query response from the Neutron contract. Note that when +// interchaintest returns query responses, it does so in the form +// `{"data": <RESPONSE>}`, so we need this outer data key, which is +// not present in the neutron contract, to properly deserialze. + +type DepositorInterchainAccountAddressQueryResponse struct { + DepositorInterchainAccountAddress string `json:"depositor_interchain_account_address"` +} + +// astroport stableswap +type StableswapInstantiateMsg struct { + TokenCodeId uint64 `json:"token_code_id"` + FactoryAddr string `json:"factory_addr"` + AssetInfos []AssetInfo `json:"asset_infos"` + InitParams []byte `json:"init_params"` +} + +type AssetInfo struct { + Token *Token `json:"token,omitempty"` + NativeToken *NativeToken `json:"native_token,omitempty"` +} + +type StablePoolParams struct { + Amp uint64 `json:"amp"` + Owner *string `json:"owner"` +} + +type Token struct { + ContractAddr string `json:"contract_addr"` +} + +type NativeToken struct { + Denom string `json:"denom"` +} + +// astroport factory +type FactoryInstantiateMsg struct { + PairConfigs []PairConfig `json:"pair_configs"` + TokenCodeId uint64 `json:"token_code_id"` + FeeAddress *string `json:"fee_address"` + GeneratorAddress *string `json:"generator_address"` + Owner string `json:"owner"` + WhitelistCodeId uint64 `json:"whitelist_code_id"` + CoinRegistryAddress string `json:"coin_registry_address"` +} + +type PairConfig struct { + CodeId uint64 `json:"code_id"` + PairType PairType `json:"pair_type"` + TotalFeeBps uint64 `json:"total_fee_bps"` + MakerFeeBps uint64 `json:"maker_fee_bps"` + IsDisabled bool `json:"is_disabled"` + IsGeneratorDisabled bool `json:"is_generator_disabled"` +} + +type PairType struct { + // Xyk struct{} `json:"xyk,omitempty"` + Stable struct{} `json:"stable,omitempty"` + // Custom struct{} `json:"custom,omitempty"` +} + +// astroport native coin registry + +type NativeCoinRegistryInstantiateMsg struct { + Owner string `json:"owner"` +} + +type AddExecuteMsg struct { + Add Add `json:"add"` +} + +type Add struct { + NativeCoins []NativeCoin `json:"native_coins"` +} + +type NativeCoin struct { + Name string `json:"name"` + Value uint8 `json:"value"` +} + +// Add { native_coins: Vec<(String, u8)> }, + +// astroport native token +type NativeTokenInstantiateMsg struct { + Name string `json:"name"` + Symbol string `json:"symbol"` + Decimals uint8 `json:"decimals"` + InitialBalances []Cw20Coin `json:"initial_balances"` + Mint *MinterResponse `json:"mint"` + Marketing *InstantiateMarketingInfo `json:"marketing"` +} + +type Cw20Coin struct { + Address string `json:"address"` + Amount uint64 `json:"amount"` +} + +type MinterResponse struct { + Minter string `json:"minter"` + Cap *uint64 `json:"cap,omitempty"` +} + +type InstantiateMarketingInfo struct { + Project string `json:"project"` + Description string `json:"description"` + Marketing string `json:"marketing"` + Logo Logo `json:"logo"` +} + +type Logo struct { + Url string `json:"url"` +} + +// astroport whitelist +type WhitelistInstantiateMsg struct { + Admins []string `json:"admins"` + Mutable bool `json:"mutable"` +}