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"`
+}