Repository: DA0-DA0/dao-contracts
Pull request #447 (2022-08-11 07:16:55)

Whiskey/stakerslist queries
issue #422 . corrected cw-paginate generic w/ @ezekiiel and fixed bug with order desc

onewhiskeypls: @ezekiiel updated with suggestion and cargo fmt'd. i was p drunk the night of working on the test cases for this so sorry if it is nonsensical hah
onewhiskeypls: > This looks great. Looks like you'll just need to update the `test_list_items` test in `cw-core` and regenerate schemas with `bash scripts/schema.sh`. Your code is working, the test is wrong. :)

most recent commit expands test and adds clarifying note

Patch:
diff --git a/.cargo/config b/.cargo/config
index 71deaf22..e857f471 100644
--- a/.cargo/config
+++ b/.cargo/config
@@ -1,4 +1,5 @@
 [alias]
 wasm = "build --release --target wasm32-unknown-unknown"
 wasm-debug = "build --target wasm32-unknown-unknown"
-unit-test = "test --lib"
+t = "test --workspace --exclude integration_tests"
+unit-test = "test --workspace --exclude integration_tests"
\ No newline at end of file
diff --git a/.github/workflows/basic.yml b/.github/workflows/basic.yml
index 4fe3b6a1..ee347565 100644
--- a/.github/workflows/basic.yml
+++ b/.github/workflows/basic.yml
@@ -24,7 +24,7 @@ jobs:
         uses: actions-rs/cargo@v1
         with:
           toolchain: nightly
-          command: test
+          command: unit-test
           args: --locked
         env:
           RUST_BACKTRACE: 1
diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml
index 9b3d3a12..b2547b17 100644
--- a/.github/workflows/codecov.yml
+++ b/.github/workflows/codecov.yml
@@ -13,7 +13,7 @@ jobs:
         uses: actions/checkout@v2
       - name: Generate code coverage
         run: >
-          cargo +nightly tarpaulin --verbose --workspace --out Xml --exclude-files debug/* *test*.rs packages/testing/* packages/cw-core-macros/* legacy/*
+          cargo +nightly tarpaulin --verbose --workspace --out Xml --exclude integration_tests --exclude-files debug/* *test*.rs packages/testing/* packages/cw-core-macros/* legacy/* ci/*
       - name: Upload to codecov.io
         uses: codecov/codecov-action@v3
         with:
diff --git a/.gitignore b/.gitignore
index ca8ada31..6cf19d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,3 +24,6 @@ artifacts/
 
 # code coverage
 tarpaulin-report.*
+
+# integration tests
+gas_reports/
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index 5276e3ce..9da9951a 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -1,4 +1,4 @@
-# Code of conduct
+# Code of conduct 
 
 Be kind to one another.
 
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f170b65c..f2eb8547 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,58 +1,163 @@
-# Welcome to the DAO DAO contributing guide <!-- omit in toc -->
+# Contributing to DAO DAO
 
-Thank you for investing your time in contributing to our project!
+Thanks for your interest in contributing. We're excited to welcome you
+into our community. :)
 
-Read our [Code of Conduct](./CODE_OF_CONDUCT.md) to keep our community approachable and respectable.
+We value kindness, humility, and low-ego communication. You can read
+our [Code of Conduct](./CODE_OF_CONDUCT.md) for a poetic version of
+this.
 
-All contributions will fall under our [our open-source license agreement](./LICENSE).
+There are many ways you can contribute.
 
-In this guide you will get an overview of the contribution workflow from opening an issue, creating a PR, reviewing, and merging the PR.
+- If you're interested in doing smart contract work, you're in the
+  right place.
+- If you want to work on our UI, check out the [dao-dao-ui
+  repo](https://github.com/DA0-DA0/dao-dao-ui).
+- If you want to contribute documentation, check out our [docs
+  repo](https://github.com/DA0-DA0/docs).
 
-## New contributor guide
+Getting started contributing to an open source project can be
+daunting. A great place to ask questions is the [DAO DAO
+Discord](https://discord.gg/sAaGuyW3D2).
 
-To get an overview of the project, read the [README](README.md). Here are some resources to help you get started with open source contributions:
+## Getting started
 
-- [Finding ways to contribute to open source on GitHub](https://docs.github.com/en/get-started/exploring-projects-on-github/finding-ways-to-contribute-to-open-source-on-github)
-- [Set up Git](https://docs.github.com/en/get-started/quickstart/set-up-git)
-- [GitHub flow](https://docs.github.com/en/get-started/quickstart/github-flow)
-- [Collaborating with pull requests](https://docs.github.com/en/github/collaborating-with-pull-requests)
+To work on the DAO DAO smart contracts you'll need a reasonable
+understanding of the Rust programming language. The [Rust
+book](https://doc.rust-lang.org/book/) is a really good place to pick
+this up.
 
-### Issues
+Before picking up any issues, you may also want to read our [design
+wiki
+page](https://github.com/DA0-DA0/dao-contracts/wiki/DAO-DAO-Contracts-Design)
+which gives an overview of how all of the DAO DAO smart contracts fit
+together.
 
-#### Create a new issue
+Our development workflow is just like a regular Rust project:
 
-If you spot a problem, [search if an issue already exists](https://docs.github.com/en/github/searching-for-information-on-github/searching-on-github/searching-issues-and-pull-requests#search-by-the-title-body-or-comments). If a related issue doesn't exist, you can open a new issue using a relevant [issue form](https://github.com/DA0-DA0/dao-contracts/issues/new/choose).
+- `cargo build` from the repository root to build the contracts.
+- `cargo test` from the repository root to test the contracts.
 
-#### Solve an issue
+To build WASM files for deploying on a blockchain, run:
 
-Scan through our [existing issues](https://github.com/DA0-DA0/dao-contracts/issues) to find one that interests you. You can narrow down the search using `labels` as filters. See [Labels](/contributing/how-to-use-labels.md) for more information. As a general rule, we don’t assign issues to anyone. If you find an issue to work on, you are welcome to open a PR with a fix.
+```
+docker run --rm -v "$(pwd)":/code \
+  --mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \
+  --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
+  --platform linux/amd64 \
+  cosmwasm/workspace-optimizer:0.12.6
+```
 
-### Make Changes
+From the repository root.
 
-#### Make changes in the UI
+## Getting ready to make a PR
 
-1. [Install Git LFS](https://docs.github.com/en/github/managing-large-files/versioning-large-files/installing-git-large-file-storage).
+Before making a PR, you'll need to do two things to get CI passing:
 
-2. Fork the repository.
+1. Generate schema files for the contracts.
+2. Generate Typescript interfaces from those schemas.
 
-3. Create a working branch and start with your changes!
+### Generating schema files
 
-### Commit your update
+We generate JSON schema files for all of our contracts' query and
+execute messages. We use those schema files to generate Typescript
+code for interacting with those contracts via
+[ts-codegen](https://github.com/CosmWasm/ts-codegen). This generated
+Typescript code is then [used in the
+UI](https://github.com/DA0-DA0/dao-dao-ui/tree/40f3cbfe676a98bf7b9db7b646e74e5b2dae4502/packages/state/clients)
+to interact with our contracts. Generating this code means that
+frontend developers don't have to manually write query and execute
+messages for each method on our contracts.
 
-Commit the changes once you are happy with them. See [Atom's contributing guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md#git-commit-messages) to know how to use emoji for commit messages.
+To make sure these files are generated correctly, make sure to add any
+new data types used in contract messages to `examples/schema.rs`.
 
-### Pull Request
+If you are adding a new query, ts-codegen expects:
 
-When you're finished with the changes, create a pull request, also known as a PR.
+1. There is a corresponding query response type exported from
+   `examples/schema.rs` for that contract.
+2. The query response has a name in the form `<queryName>Response`.
 
-- Don't forget to [link the PR to an issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) if you are solving one.
-  Once you submit your PR, a team member will review your proposal. We may ask questions or request for additional information.
-- We may ask for changes to be made before a PR can be merged, either using [suggested changes](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/incorporating-feedback-in-your-pull-request) or pull request comments. You can apply suggested changes directly through the UI. You can make any other changes in your fork, then commit them to your branch.
-- As you update your PR and apply changes, mark each conversation as [resolved](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/commenting-on-a-pull-request#resolving-conversations).
-- If you run into any merge issues, checkout this [git tutorial](https://lab.github.com/githubtraining/managing-merge-conflicts) to help you resolve merge conflicts and other issues.
+For example, if you added a `ListStakers {}` query, you'd also need to
+make sure to export a type from the schema file called
+`ListStakersResponse`.
 
-### Your PR is merged!
+Most of the time, this will just be a struct with the same
+name. Occasionally though you may have queries that return types like
+`Vec<Addr>`. In these cases you'll still need to export a type from
+the schema file for this. You can do so with:
 
-Congratulations :tada::tada: DAO DAO thanks you :sparkles:.
+```rust
+export_schema_with_title(&schema_for!(Vec<Addr>), &out_dir, "Cw20TokenListResponse");
+```
 
-Once your PR is merged, your contributions will be publicly visible.
+Once you have exported these types, you can generate schema files for
+all the contracts by running:
+
+```
+bash scripts/schema.sh
+```
+
+### Generating the Typescript interface
+
+To generate the Typescript interface, after generating the schema
+files, run:
+
+```
+rm -rf types/contracts # Clear out any old or invalid state.
+yarn --cwd ./types install --frozen-lockfile
+yarn --cwd ./types build
+yarn --cwd ./types codegen
+```
+
+To do this you'll need [yarn](https://yarnpkg.com/) installed.
+
+If you get errors complaining about a missing query response type it
+is likely because you forgot to export that type from
+`examples/schema.rs` for that contract.
+
+## Deploying in a development environment
+
+Build and deploy the contracts to a local chain running in Docker with:
+
+```sh
+bash scripts/deploy_local.sh juno10j9gpw9t4jsz47qgnkvl5n3zlm2fz72k67rxsg
+```
+
+> Note: This Wasm account is from the [default
+> account](default-account.txt), which you can use for testing (DO NOT
+> store any real funds with this account). You can pass in any wasm
+> account address you want to use.
+
+This will run a chain locally in a docker container, then build and
+deploy the contracts to that chain.
+
+The script will output something like:
+
+```sh
+NEXT_PUBLIC_CW20_CODE_ID=1
+NEXT_PUBLIC_CW4GROUP_CODE_ID=2
+NEXT_PUBLIC_CWCORE_CODE_ID=7
+NEXT_PUBLIC_CWPROPOSALSINGLE_CODE_ID=11
+NEXT_PUBLIC_CW4VOTING_CODE_ID=5
+NEXT_PUBLIC_CW20STAKEDBALANCEVOTING_CODE_ID=4
+NEXT_PUBLIC_STAKECW20_CODE_ID=13
+NEXT_PUBLIC_DAO_CONTRACT_ADDRESS=juno1zlmaky7753d2fneyhduwz0rn3u9ns8rse3tudhze8rc2g54w9ysqgjt23l
+NEXT_PUBLIC_V1_FACTORY_CONTRACT_ADDRESS=juno1pvrwmjuusn9wh34j7y520g8gumuy9xtl3gvprlljfdpwju3x7ucssml9ug
+```
+
+This output can be directly copy and pased into a `.env` file in the
+[DAO DAO UI](https://github.com/DA0-DA0/dao-dao-ui) for local
+development.
+
+Note, to send commands to the docker container:
+
+```sh
+docker exec -i cosmwasm junod status
+```
+
+Some commands require a password which defaults to `xxxxxxxxx`. You can use them like so:
+
+```sh
+echo xxxxxxxxx | docker exec -i cosmwasm  junod keys show validator -a
+```
diff --git a/Cargo.lock b/Cargo.lock
index 866aeae5..18e0ed17 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,11 +2,95 @@
 # It is not intended for manual editing.
 version = 3
 
+[[package]]
+name = "addr2line"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "ahash"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
+dependencies = [
+ "getrandom 0.2.7",
+ "once_cell",
+ "version_check",
+]
+
+[[package]]
+name = "aho-corasick"
+version = "0.7.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
+dependencies = [
+ "memchr",
+]
+
 [[package]]
 name = "anyhow"
-version = "1.0.58"
+version = "1.0.59"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c91f1f46651137be86f3a2b9a8359f9ab421d04d941c62b5982e1ca21113adf9"
+
+[[package]]
+name = "assert_matches"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9"
+
+[[package]]
+name = "async-stream"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e"
+dependencies = [
+ "async-stream-impl",
+ "futures-core",
+]
+
+[[package]]
+name = "async-stream-impl"
+version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704"
+checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "async-trait"
+version = "0.1.57"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
 
 [[package]]
 name = "autocfg"
@@ -14,6 +98,64 @@ version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 
+[[package]]
+name = "axum"
+version = "0.5.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b9496f0c1d1afb7a2af4338bbe1d969cddfead41d87a9fb3aaa6d0bbc7af648"
+dependencies = [
+ "async-trait",
+ "axum-core",
+ "bitflags",
+ "bytes",
+ "futures-util",
+ "http",
+ "http-body",
+ "hyper",
+ "itoa",
+ "matchit",
+ "memchr",
+ "mime",
+ "percent-encoding",
+ "pin-project-lite",
+ "serde",
+ "sync_wrapper",
+ "tokio",
+ "tower",
+ "tower-http",
+ "tower-layer",
+ "tower-service",
+]
+
+[[package]]
+name = "axum-core"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4f44a0e6200e9d11a1cdc989e4b358f6e3d354fbf48478f345a17f4e43f8635"
+dependencies = [
+ "async-trait",
+ "bytes",
+ "futures-util",
+ "http",
+ "http-body",
+ "mime",
+]
+
+[[package]]
+name = "backtrace"
+version = "0.3.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7"
+dependencies = [
+ "addr2line",
+ "cc",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+]
+
 [[package]]
 name = "base16ct"
 version = "0.1.1"
@@ -32,15 +174,70 @@ version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3bdca834647821e0b13d9539a8634eb62d3501b6b6c2cec1722786ee6671b851"
 
+[[package]]
+name = "bip32"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "873faa4363bfc54c36a48321da034c92a0645a363eed34d948683ffc1706e37f"
+dependencies = [
+ "bs58",
+ "hmac",
+ "k256",
+ "once_cell",
+ "pbkdf2",
+ "rand_core 0.6.3",
+ "ripemd160",
+ "sha2",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
 [[package]]
 name = "block-buffer"
 version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
 dependencies = [
+ "block-padding",
  "generic-array",
 ]
 
+[[package]]
+name = "block-buffer"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "block-padding"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
+
+[[package]]
+name = "bs58"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3"
+dependencies = [
+ "sha2",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3"
+
 [[package]]
 name = "byteorder"
 version = "1.4.3"
@@ -49,9 +246,15 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
 
 [[package]]
 name = "bytes"
-version = "1.2.0"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db"
+
+[[package]]
+name = "cc"
+version = "1.0.73"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0b3de4a0c5e67e16066a0715723abd91edc2f9001d09c46e1dca929351e130e"
+checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
 
 [[package]]
 name = "cfg-if"
@@ -59,19 +262,108 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
+[[package]]
+name = "config"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11f1667b8320afa80d69d8bbe40830df2c8a06003d86f73d8e003b2c48df416d"
+dependencies = [
+ "async-trait",
+ "json5",
+ "lazy_static",
+ "nom",
+ "pathdiff",
+ "ron",
+ "rust-ini",
+ "serde",
+ "serde_json",
+ "toml",
+ "yaml-rust",
+]
+
 [[package]]
 name = "const-oid"
 version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3"
 
+[[package]]
+name = "core-foundation"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
+
+[[package]]
+name = "cosm-orc"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "718327a8f492823d82433323f1f62290c041e98faf3cf670ae8bc2e658faf1e7"
+dependencies = [
+ "backtrace",
+ "config",
+ "cosmos-sdk-proto",
+ "cosmrs",
+ "log",
+ "prost 0.10.4",
+ "serde",
+ "serde_json",
+ "tendermint-rpc",
+ "thiserror",
+ "tokio",
+]
+
+[[package]]
+name = "cosmos-sdk-proto"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24ca04d3795c18023c221a2143b29de9c70668ecb22d17783bc02ee780c6c404"
+dependencies = [
+ "prost 0.10.4",
+ "prost-types",
+ "tendermint-proto",
+ "tonic",
+]
+
+[[package]]
+name = "cosmrs"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6989fdb6267eccb52762530b79ce0b385f4eaeb8b786522a95512e9bebb268c2"
+dependencies = [
+ "bip32",
+ "cosmos-sdk-proto",
+ "ecdsa",
+ "eyre",
+ "getrandom 0.2.7",
+ "k256",
+ "prost 0.10.4",
+ "prost-types",
+ "rand_core 0.6.3",
+ "serde",
+ "serde_json",
+ "subtle-encoding",
+ "tendermint",
+ "tendermint-rpc",
+ "thiserror",
+]
+
 [[package]]
 name = "cosmwasm-crypto"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5eb0afef2325df81aadbf9be1233f522ed8f6e91df870c764bc44cca2b1415bd"
 dependencies = [
- "digest",
+ "digest 0.9.0",
  "ed25519-zebra",
  "k256",
  "rand_core 0.6.3",
@@ -151,6 +443,16 @@ dependencies = [
  "zeroize",
 ]
 
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
 [[package]]
 name = "crypto-mac"
 version = "0.11.1"
@@ -161,6 +463,25 @@ dependencies = [
  "subtle",
 ]
 
+[[package]]
+name = "ct-logs"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1a816186fa68d9e426e3cb4ae4dff1fcd8e4a2c34b781bf7a822574a0d0aac8"
+dependencies = [
+ "sct",
+]
+
+[[package]]
+name = "ctor"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdffe87e1d521a10f9696f833fe502293ea446d7f256c06128293a4119bdf4cb"
+dependencies = [
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "curve25519-dalek"
 version = "3.2.1"
@@ -168,7 +489,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0"
 dependencies = [
  "byteorder",
- "digest",
+ "digest 0.9.0",
  "rand_core 0.5.1",
  "subtle",
  "zeroize",
@@ -268,7 +589,7 @@ dependencies = [
  "cw-utils 0.13.4",
  "derivative",
  "itertools",
- "prost",
+ "prost 0.9.0",
  "schemars",
  "serde",
  "thiserror",
@@ -277,7 +598,7 @@ dependencies = [
 [[package]]
 name = "cw-multi-test"
 version = "0.14.0"
-source = "git+https://github.com/CosmWasm/cw-plus?branch=main#d67face967d2a7f0f59ed4c29b5bbf8f00ce1523"
+source = "git+https://github.com/CosmWasm/cw-plus?branch=main#0a3f52dc2c8b5bdc79be7077a8a877a6c495604e"
 dependencies = [
  "anyhow",
  "cosmwasm-std",
@@ -286,7 +607,7 @@ dependencies = [
  "cw-utils 0.14.0",
  "derivative",
  "itertools",
- "prost",
+ "prost 0.9.0",
  "schemars",
  "serde",
  "thiserror",
@@ -337,6 +658,7 @@ dependencies = [
  "cw-core-interface",
  "cw-core-macros",
  "cw-multi-test 0.13.4",
+ "cw-paginate",
  "cw-storage-plus 0.13.4",
  "cw-utils 0.13.4",
  "cw2 0.13.4",
@@ -466,7 +788,7 @@ dependencies = [
 [[package]]
 name = "cw-storage-plus"
 version = "0.14.0"
-source = "git+https://github.com/CosmWasm/cw-plus?branch=main#d67face967d2a7f0f59ed4c29b5bbf8f00ce1523"
+source = "git+https://github.com/CosmWasm/cw-plus?branch=main#0a3f52dc2c8b5bdc79be7077a8a877a6c495604e"
 dependencies = [
  "cosmwasm-std",
  "schemars",
@@ -518,7 +840,7 @@ dependencies = [
 [[package]]
 name = "cw-utils"
 version = "0.14.0"
-source = "git+https://github.com/CosmWasm/cw-plus?branch=main#d67face967d2a7f0f59ed4c29b5bbf8f00ce1523"
+source = "git+https://github.com/CosmWasm/cw-plus?branch=main#0a3f52dc2c8b5bdc79be7077a8a877a6c495604e"
 dependencies = [
  "cosmwasm-std",
  "cw2 0.14.0",
@@ -543,7 +865,7 @@ dependencies = [
 [[package]]
 name = "cw2"
 version = "0.14.0"
-source = "git+https://github.com/CosmWasm/cw-plus?branch=main#d67face967d2a7f0f59ed4c29b5bbf8f00ce1523"
+source = "git+https://github.com/CosmWasm/cw-plus?branch=main#0a3f52dc2c8b5bdc79be7077a8a877a6c495604e"
 dependencies = [
  "cosmwasm-std",
  "cw-storage-plus 0.14.0",
@@ -621,6 +943,7 @@ dependencies = [
  "cosmwasm-storage",
  "cw-controllers",
  "cw-multi-test 0.13.4",
+ "cw-paginate",
  "cw-storage-plus 0.13.4",
  "cw-utils 0.13.4",
  "cw2 0.13.4",
@@ -806,11 +1129,27 @@ dependencies = [
  "generic-array",
 ]
 
+[[package]]
+name = "digest"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
+dependencies = [
+ "block-buffer 0.10.2",
+ "crypto-common",
+]
+
+[[package]]
+name = "dlv-list"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257"
+
 [[package]]
 name = "dyn-clone"
-version = "1.0.8"
+version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d07a982d1fb29db01e5a59b1918e03da4df7297eaeee7686ac45542fd4e59c8"
+checksum = "4f94fa09c2aeea5b8839e414b7b841bf429fd25b9c522116ac97ee87856d88b2"
 
 [[package]]
 name = "ecdsa"
@@ -824,6 +1163,27 @@ dependencies = [
  "signature",
 ]
 
+[[package]]
+name = "ed25519"
+version = "1.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369"
+dependencies = [
+ "signature",
+]
+
+[[package]]
+name = "ed25519-dalek"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d"
+dependencies = [
+ "curve25519-dalek",
+ "ed25519",
+ "sha2",
+ "zeroize",
+]
+
 [[package]]
 name = "ed25519-zebra"
 version = "3.0.0"
@@ -863,6 +1223,29 @@ dependencies = [
  "zeroize",
 ]
 
+[[package]]
+name = "env_logger"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
+dependencies = [
+ "atty",
+ "humantime",
+ "log",
+ "regex",
+ "termcolor",
+]
+
+[[package]]
+name = "eyre"
+version = "0.6.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb"
+dependencies = [
+ "indenter",
+ "once_cell",
+]
+
 [[package]]
 name = "ff"
 version = "0.11.1"
@@ -873,6 +1256,32 @@ dependencies = [
  "subtle",
 ]
 
+[[package]]
+name = "flex-error"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c606d892c9de11507fa0dcffc116434f94e105d0bbdc4e405b61519464c49d7b"
+dependencies = [
+ "eyre",
+ "paste",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
+dependencies = [
+ "matches",
+ "percent-encoding",
+]
+
 [[package]]
 name = "forward_ref"
 version = "1.0.0"
@@ -880,348 +1289,1673 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e"
 
 [[package]]
-name = "generic-array"
-version = "0.14.5"
+name = "futures"
+version = "0.3.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803"
+checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e"
 dependencies = [
- "typenum",
- "version_check",
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
 ]
 
 [[package]]
-name = "getrandom"
-version = "0.1.16"
+name = "futures-channel"
+version = "0.3.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
+checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
 dependencies = [
- "cfg-if",
- "libc",
- "wasi 0.9.0+wasi-snapshot-preview1",
+ "futures-core",
+ "futures-sink",
 ]
 
 [[package]]
-name = "getrandom"
-version = "0.2.7"
+name = "futures-core"
+version = "0.3.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi 0.11.0+wasi-snapshot-preview1",
-]
+checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
 
 [[package]]
-name = "group"
-version = "0.11.0"
+name = "futures-executor"
+version = "0.3.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89"
+checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6"
 dependencies = [
- "ff",
- "rand_core 0.6.3",
- "subtle",
+ "futures-core",
+ "futures-task",
+ "futures-util",
 ]
 
 [[package]]
-name = "hashbrown"
-version = "0.12.3"
+name = "futures-io"
+version = "0.3.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
 
 [[package]]
-name = "hex"
-version = "0.4.3"
+name = "futures-macro"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
+
+[[package]]
+name = "futures-task"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
+
+[[package]]
+name = "futures-util"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-macro",
+ "futures-sink",
+ "futures-task",
+ "memchr",
+ "pin-project-lite",
+ "pin-utils",
+ "slab",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi 0.9.0+wasi-snapshot-preview1",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "libc",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "gimli"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
+
+[[package]]
+name = "group"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89"
+dependencies = [
+ "ff",
+ "rand_core 0.6.3",
+ "subtle",
+]
+
+[[package]]
+name = "h2"
+version = "0.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57"
+dependencies = [
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http",
+ "indexmap",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tracing",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+dependencies = [
+ "ahash",
+]
+
+[[package]]
+name = "headers"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cff78e5788be1e0ab65b04d306b2ed5092c815ec97ec70f4ebd5aee158aa55d"
+dependencies = [
+ "base64",
+ "bitflags",
+ "bytes",
+ "headers-core",
+ "http",
+ "httpdate",
+ "mime",
+ "sha-1",
+]
+
+[[package]]
+name = "headers-core"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429"
+dependencies = [
+ "http",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "hex"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
 
 [[package]]
-name = "hmac"
-version = "0.11.0"
+name = "hmac"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
+dependencies = [
+ "crypto-mac",
+ "digest 0.9.0",
+]
+
+[[package]]
+name = "http"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "http-body"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
+dependencies = [
+ "bytes",
+ "http",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "http-range-header"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29"
+
+[[package]]
+name = "httparse"
+version = "1.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c"
+
+[[package]]
+name = "httpdate"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
+
+[[package]]
+name = "humantime"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+
+[[package]]
+name = "hyper"
+version = "0.14.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "hyper-proxy"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca815a891b24fdfb243fa3239c86154392b0953ee584aa1a2a1f66d20cbe75cc"
+dependencies = [
+ "bytes",
+ "futures",
+ "headers",
+ "http",
+ "hyper",
+ "hyper-rustls",
+ "rustls-native-certs",
+ "tokio",
+ "tokio-rustls",
+ "tower-service",
+ "webpki",
+]
+
+[[package]]
+name = "hyper-rustls"
+version = "0.22.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64"
+dependencies = [
+ "ct-logs",
+ "futures-util",
+ "hyper",
+ "log",
+ "rustls",
+ "rustls-native-certs",
+ "tokio",
+ "tokio-rustls",
+ "webpki",
+ "webpki-roots",
+]
+
+[[package]]
+name = "hyper-timeout"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
+dependencies = [
+ "hyper",
+ "pin-project-lite",
+ "tokio",
+ "tokio-io-timeout",
+]
+
+[[package]]
+name = "idna"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
+dependencies = [
+ "matches",
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "indenter"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
+
+[[package]]
+name = "indexable-hooks"
+version = "0.1.0"
+dependencies = [
+ "cosmwasm-std",
+ "cw-storage-plus 0.13.4",
+ "schemars",
+ "serde",
+ "thiserror",
+]
+
+[[package]]
+name = "indexmap"
+version = "1.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+ "serde",
+]
+
+[[package]]
+name = "integration_tests"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "assert_matches",
+ "cosm-orc",
+ "cosmwasm-std",
+ "ctor",
+ "cw-core",
+ "cw-core-interface",
+ "cw-proposal-single",
+ "cw-utils 0.13.4",
+ "cw20 0.13.4",
+ "cw20-base",
+ "cw20-stake",
+ "cw20-staked-balance-voting",
+ "env_logger",
+ "once_cell",
+ "rand",
+ "serde",
+ "serde_json",
+ "test-context",
+ "voting",
+]
+
+[[package]]
+name = "itertools"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
+
+[[package]]
+name = "js-sys"
+version = "0.3.59"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "json5"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1"
+dependencies = [
+ "pest",
+ "pest_derive",
+ "serde",
+]
+
+[[package]]
+name = "k256"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d"
+dependencies = [
+ "cfg-if",
+ "ecdsa",
+ "elliptic-curve",
+ "sec1",
+ "sha2",
+ "sha3",
+]
+
+[[package]]
+name = "keccak"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.127"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b"
+
+[[package]]
+name = "linked-hash-map"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
+
+[[package]]
+name = "lock_api"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "matches"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
+
+[[package]]
+name = "matchit"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb"
+
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
+[[package]]
+name = "mime"
+version = "0.3.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "mio"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
+dependencies = [
+ "libc",
+ "log",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+ "windows-sys",
+]
+
+[[package]]
+name = "nom"
+version = "7.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
+[[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",
+]
+
+[[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_cpus"
+version = "1.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "num_threads"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "object"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
+
+[[package]]
+name = "opaque-debug"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
+
+[[package]]
+name = "openssl-probe"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
+
+[[package]]
+name = "ordered-multimap"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a"
+dependencies = [
+ "dlv-list",
+ "hashbrown",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-sys",
+]
+
+[[package]]
+name = "paste"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9423e2b32f7a043629287a536f21951e8c6a82482d0acb1eeebfc90bc2225b22"
+
+[[package]]
+name = "pathdiff"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
+
+[[package]]
+name = "pbkdf2"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f05894bce6a1ba4be299d0c5f29563e08af2bc18bb7d48313113bed71e904739"
+dependencies = [
+ "crypto-mac",
+]
+
+[[package]]
+name = "peg"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07c0b841ea54f523f7aa556956fbd293bcbe06f2e67d2eb732b7278aaf1d166a"
+dependencies = [
+ "peg-macros",
+ "peg-runtime",
+]
+
+[[package]]
+name = "peg-macros"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5aa52829b8decbef693af90202711348ab001456803ba2a98eb4ec8fb70844c"
+dependencies = [
+ "peg-runtime",
+ "proc-macro2",
+ "quote",
+]
+
+[[package]]
+name = "peg-runtime"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c719dcf55f09a3a7e764c6649ab594c18a177e3599c467983cdf644bfc0a4088"
+
+[[package]]
+name = "percent-encoding"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
+
+[[package]]
+name = "pest"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69486e2b8c2d2aeb9762db7b4e00b0331156393555cff467f4163ff06821eef8"
+dependencies = [
+ "thiserror",
+ "ucd-trie",
+]
+
+[[package]]
+name = "pest_derive"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b13570633aff33c6d22ce47dd566b10a3b9122c2fe9d8e7501895905be532b91"
+dependencies = [
+ "pest",
+ "pest_generator",
+]
+
+[[package]]
+name = "pest_generator"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3c567e5702efdc79fb18859ea74c3eb36e14c43da7b8c1f098a4ed6514ec7a0"
+dependencies = [
+ "pest",
+ "pest_meta",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "pest_meta"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5eb32be5ee3bbdafa8c7a18b0a8a8d962b66cfa2ceee4037f49267a50ee821fe"
+dependencies = [
+ "once_cell",
+ "pest",
+ "sha-1",
+]
+
+[[package]]
+name = "pin-project"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78203e83c48cffbe01e4a2d35d566ca4de445d79a85372fc64e378bfc812a260"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "710faf75e1b33345361201d36d04e98ac1ed8909151a017ed384700836104c74"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "pkcs8"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0"
+dependencies = [
+ "der",
+ "spki",
+ "zeroize",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "proposal-hooks"
+version = "0.1.0"
+dependencies = [
+ "cosmwasm-std",
+ "indexable-hooks",
+ "schemars",
+ "serde",
+ "voting",
+]
+
+[[package]]
+name = "proposal-hooks-counter"
+version = "0.1.0"
+dependencies = [
+ "cosmwasm-schema",
+ "cosmwasm-std",
+ "cosmwasm-storage",
+ "cw-core",
+ "cw-multi-test 0.13.4",
+ "cw-proposal-single",
+ "cw-storage-plus 0.13.4",
+ "cw-utils 0.13.4",
+ "cw2 0.13.4",
+ "cw20 0.13.4",
+ "cw20-balance-voting",
+ "cw20-base",
+ "indexable-hooks",
+ "proposal-hooks",
+ "schemars",
+ "serde",
+ "thiserror",
+ "vote-hooks",
+ "voting",
+]
+
+[[package]]
+name = "prost"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001"
+dependencies = [
+ "bytes",
+ "prost-derive 0.9.0",
+]
+
+[[package]]
+name = "prost"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71adf41db68aa0daaefc69bb30bcd68ded9b9abaad5d1fbb6304c4fb390e083e"
+dependencies = [
+ "bytes",
+ "prost-derive 0.10.1",
+]
+
+[[package]]
+name = "prost-derive"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe"
+dependencies = [
+ "anyhow",
+ "itertools",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "prost-derive"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b670f45da57fb8542ebdbb6105a925fe571b67f9e7ed9f47a06a84e72b4e7cc"
+dependencies = [
+ "anyhow",
+ "itertools",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "prost-types"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d0a014229361011dc8e69c8a1ec6c2e8d0f2af7c91e3ea3f5b2170298461e68"
+dependencies = [
+ "bytes",
+ "prost 0.10.4",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core 0.6.3",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.6.3",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+dependencies = [
+ "getrandom 0.1.16",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
+dependencies = [
+ "getrandom 0.2.7",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "regex"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
+
+[[package]]
+name = "rfc6979"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525"
+dependencies = [
+ "crypto-bigint",
+ "hmac",
+ "zeroize",
+]
+
+[[package]]
+name = "ring"
+version = "0.16.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
+dependencies = [
+ "cc",
+ "libc",
+ "once_cell",
+ "spin",
+ "untrusted",
+ "web-sys",
+ "winapi",
+]
+
+[[package]]
+name = "ripemd160"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2eca4ecc81b7f313189bf73ce724400a07da2a6dac19588b03c8bd76a2dcc251"
+dependencies = [
+ "block-buffer 0.9.0",
+ "digest 0.9.0",
+ "opaque-debug",
+]
+
+[[package]]
+name = "ron"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a"
+dependencies = [
+ "base64",
+ "bitflags",
+ "serde",
+]
+
+[[package]]
+name = "rust-ini"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df"
+dependencies = [
+ "cfg-if",
+ "ordered-multimap",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
+
+[[package]]
+name = "rustls"
+version = "0.19.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7"
+dependencies = [
+ "base64",
+ "log",
+ "ring",
+ "sct",
+ "webpki",
+]
+
+[[package]]
+name = "rustls-native-certs"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092"
+dependencies = [
+ "openssl-probe",
+ "rustls",
+ "schannel",
+ "security-framework",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "schannel"
+version = "0.1.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2"
+dependencies = [
+ "lazy_static",
+ "windows-sys",
+]
+
+[[package]]
+name = "schemars"
+version = "0.8.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1847b767a3d62d95cbf3d8a9f0e421cf57a0d8aa4f411d4b16525afb0284d4ed"
+dependencies = [
+ "dyn-clone",
+ "schemars_derive",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "schemars_derive"
+version = "0.8.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af4d7e1b012cb3d9129567661a63755ea4b8a7386d339dc945ae187e403c6743"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "serde_derive_internals",
+ "syn",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "sct"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
+[[package]]
+name = "sec1"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1"
+dependencies = [
+ "der",
+ "generic-array",
+ "pkcs8",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "security-framework"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc"
+dependencies = [
+ "bitflags",
+ "core-foundation",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework-sys"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "semver"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711"
+
+[[package]]
+name = "serde"
+version = "1.0.142"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e590c437916fb6b221e1d00df6e3294f3fccd70ca7e92541c475d6ed6ef5fee2"
+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_bytes"
+version = "0.11.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.142"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34b5b8d809babe02f538c2cfec6f2c1ed10804c0e5a6a041a049a4f5588ccc2e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_derive_internals"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.83"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
+checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7"
 dependencies = [
- "crypto-mac",
- "digest",
+ "itoa",
+ "ryu",
+ "serde",
 ]
 
 [[package]]
-name = "indexable-hooks"
-version = "0.1.0"
+name = "serde_repr"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca"
 dependencies = [
- "cosmwasm-std",
- "cw-storage-plus 0.13.4",
- "schemars",
- "serde",
- "thiserror",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
-name = "indexmap"
-version = "1.9.1"
+name = "sha-1"
+version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
+checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
 dependencies = [
- "autocfg",
- "hashbrown",
- "serde",
+ "cfg-if",
+ "cpufeatures",
+ "digest 0.10.3",
 ]
 
 [[package]]
-name = "itertools"
-version = "0.10.3"
+name = "sha2"
+version = "0.9.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
+checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
 dependencies = [
- "either",
+ "block-buffer 0.9.0",
+ "cfg-if",
+ "cpufeatures",
+ "digest 0.9.0",
+ "opaque-debug",
 ]
 
 [[package]]
-name = "itoa"
-version = "1.0.2"
+name = "sha3"
+version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
+checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809"
+dependencies = [
+ "block-buffer 0.9.0",
+ "digest 0.9.0",
+ "keccak",
+ "opaque-debug",
+]
 
 [[package]]
-name = "k256"
-version = "0.10.4"
+name = "signal-hook-registry"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d"
+checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
 dependencies = [
- "cfg-if",
- "ecdsa",
- "elliptic-curve",
- "sec1",
- "sha2",
+ "libc",
 ]
 
 [[package]]
-name = "libc"
-version = "0.2.126"
+name = "signature"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
+checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788"
+dependencies = [
+ "digest 0.9.0",
+ "rand_core 0.6.3",
+]
 
 [[package]]
-name = "opaque-debug"
-version = "0.3.0"
+name = "slab"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
+checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
+dependencies = [
+ "autocfg",
+]
 
 [[package]]
-name = "pkcs8"
-version = "0.8.0"
+name = "smallvec"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0"
+checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
+
+[[package]]
+name = "socket2"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
 dependencies = [
- "der",
- "spki",
- "zeroize",
+ "libc",
+ "winapi",
 ]
 
 [[package]]
-name = "ppv-lite86"
-version = "0.2.16"
+name = "spin"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
 
 [[package]]
-name = "proc-macro2"
-version = "1.0.42"
+name = "spki"
+version = "0.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c278e965f1d8cf32d6e0e96de3d3e79712178ae67986d9cf9151f51e95aac89b"
+checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27"
 dependencies = [
- "unicode-ident",
+ "base64ct",
+ "der",
 ]
 
 [[package]]
-name = "proposal-hooks"
-version = "0.1.0"
+name = "stake-cw20-external-rewards"
+version = "0.2.6"
 dependencies = [
+ "anyhow",
+ "cosmwasm-schema",
  "cosmwasm-std",
- "indexable-hooks",
+ "cosmwasm-storage",
+ "cw-controllers",
+ "cw-multi-test 0.13.4",
+ "cw-storage-plus 0.13.4",
+ "cw-utils 0.13.4",
+ "cw2 0.13.4",
+ "cw20 0.13.4",
+ "cw20-base",
+ "cw20-stake",
  "schemars",
  "serde",
- "voting",
+ "thiserror",
 ]
 
 [[package]]
-name = "proposal-hooks-counter"
+name = "stake-cw20-reward-distributor"
 version = "0.1.0"
 dependencies = [
  "cosmwasm-schema",
  "cosmwasm-std",
  "cosmwasm-storage",
- "cw-core",
  "cw-multi-test 0.13.4",
- "cw-proposal-single",
  "cw-storage-plus 0.13.4",
  "cw-utils 0.13.4",
  "cw2 0.13.4",
  "cw20 0.13.4",
- "cw20-balance-voting",
  "cw20-base",
- "indexable-hooks",
- "proposal-hooks",
+ "cw20-stake",
  "schemars",
  "serde",
  "thiserror",
- "vote-hooks",
- "voting",
 ]
 
 [[package]]
-name = "prost"
-version = "0.9.0"
+name = "static_assertions"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "subtle"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
+
+[[package]]
+name = "subtle-encoding"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dcb1ed7b8330c5eed5441052651dd7a12c75e2ed88f2ec024ae1fa3a5e59945"
 dependencies = [
- "bytes",
- "prost-derive",
+ "zeroize",
 ]
 
 [[package]]
-name = "prost-derive"
-version = "0.9.0"
+name = "syn"
+version = "1.0.99"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe"
+checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
 dependencies = [
- "anyhow",
- "itertools",
  "proc-macro2",
  "quote",
- "syn",
+ "unicode-ident",
 ]
 
 [[package]]
-name = "quote"
-version = "1.0.20"
+name = "sync_wrapper"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8"
+
+[[package]]
+name = "synstructure"
+version = "0.12.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
+checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
 dependencies = [
  "proc-macro2",
+ "quote",
+ "syn",
+ "unicode-xid",
 ]
 
 [[package]]
-name = "rand"
-version = "0.8.5"
+name = "tendermint"
+version = "0.23.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+checksum = "3ca881fa4dedd2b46334f13be7fbc8cc1549ba4be5a833fe4e73d1a1baaf7949"
 dependencies = [
- "libc",
- "rand_chacha",
- "rand_core 0.6.3",
+ "async-trait",
+ "bytes",
+ "ed25519",
+ "ed25519-dalek",
+ "flex-error",
+ "futures",
+ "k256",
+ "num-traits",
+ "once_cell",
+ "prost 0.10.4",
+ "prost-types",
+ "ripemd160",
+ "serde",
+ "serde_bytes",
+ "serde_json",
+ "serde_repr",
+ "sha2",
+ "signature",
+ "subtle",
+ "subtle-encoding",
+ "tendermint-proto",
+ "time",
+ "zeroize",
 ]
 
 [[package]]
-name = "rand_chacha"
-version = "0.3.1"
+name = "tendermint-config"
+version = "0.23.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+checksum = "f6c56ee93f4e9b7e7daba86d171f44572e91b741084384d0ae00df7991873dfd"
 dependencies = [
- "ppv-lite86",
- "rand_core 0.6.3",
+ "flex-error",
+ "serde",
+ "serde_json",
+ "tendermint",
+ "toml",
+ "url",
 ]
 
 [[package]]
-name = "rand_core"
-version = "0.5.1"
+name = "tendermint-proto"
+version = "0.23.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+checksum = "b71f925d74903f4abbdc4af0110635a307b3cb05b175fdff4a7247c14a4d0874"
 dependencies = [
- "getrandom 0.1.16",
+ "bytes",
+ "flex-error",
+ "num-derive",
+ "num-traits",
+ "prost 0.10.4",
+ "prost-types",
+ "serde",
+ "serde_bytes",
+ "subtle-encoding",
+ "time",
 ]
 
 [[package]]
-name = "rand_core"
-version = "0.6.3"
+name = "tendermint-rpc"
+version = "0.23.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
+checksum = "a13e63f57ee05a1e927887191c76d1b139de9fa40c180b9f8727ee44377242a6"
 dependencies = [
+ "async-trait",
+ "bytes",
+ "flex-error",
+ "futures",
  "getrandom 0.2.7",
+ "http",
+ "hyper",
+ "hyper-proxy",
+ "hyper-rustls",
+ "peg",
+ "pin-project",
+ "serde",
+ "serde_bytes",
+ "serde_json",
+ "subtle-encoding",
+ "tendermint",
+ "tendermint-config",
+ "tendermint-proto",
+ "thiserror",
+ "time",
+ "tokio",
+ "tracing",
+ "url",
+ "uuid",
+ "walkdir",
 ]
 
 [[package]]
-name = "rfc6979"
-version = "0.1.0"
+name = "termcolor"
+version = "1.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525"
+checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
 dependencies = [
- "crypto-bigint",
- "hmac",
- "zeroize",
+ "winapi-util",
 ]
 
 [[package]]
-name = "ryu"
-version = "1.0.10"
+name = "test-context"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
+checksum = "055831a02a4f5aa28fede67f2902014273eb8c21b958ac5ebbd59b71ef30dbc3"
+dependencies = [
+ "async-trait",
+ "futures",
+ "test-context-macros",
+]
 
 [[package]]
-name = "schemars"
-version = "0.8.10"
+name = "test-context-macros"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1847b767a3d62d95cbf3d8a9f0e421cf57a0d8aa4f411d4b16525afb0284d4ed"
+checksum = "8901a55b0a7a06ebc4a674dcca925170da8e613fa3b163a1df804ed10afb154d"
 dependencies = [
- "dyn-clone",
- "schemars_derive",
- "serde",
- "serde_json",
+ "quote",
+ "syn",
 ]
 
 [[package]]
-name = "schemars_derive"
-version = "0.8.10"
+name = "testing"
+version = "0.1.0"
+dependencies = [
+ "cosmwasm-schema",
+ "cosmwasm-std",
+ "cw-core",
+ "cw-core-interface",
+ "cw-multi-test 0.13.4",
+ "cw-utils 0.13.4",
+ "cw2 0.13.4",
+ "cw20 0.13.4",
+ "cw20-balance-voting",
+ "cw20-base",
+ "cw20-stake",
+ "cw20-staked-balance-voting",
+ "cw4",
+ "cw4-group",
+ "cw4-voting",
+ "indexable-hooks",
+ "rand",
+ "voting",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af4d7e1b012cb3d9129567661a63755ea4b8a7386d339dc945ae187e403c6743"
+checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21"
 dependencies = [
  "proc-macro2",
  "quote",
- "serde_derive_internals",
  "syn",
 ]
 
 [[package]]
-name = "sec1"
-version = "0.2.1"
+name = "time"
+version = "0.3.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1"
+checksum = "74b7cc93fc23ba97fde84f7eea56c55d1ba183f495c6715defdfc7b9cb8c870f"
 dependencies = [
- "der",
- "generic-array",
- "pkcs8",
- "subtle",
- "zeroize",
+ "js-sys",
+ "libc",
+ "num_threads",
+ "time-macros",
 ]
 
 [[package]]
-name = "semver"
-version = "1.0.12"
+name = "time-macros"
+version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2333e6df6d6598f2b1974829f853c2b4c5f4a6e503c10af918081aa6f8564e1"
+checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792"
 
 [[package]]
-name = "serde"
-version = "1.0.140"
+name = "tinyvec"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
+
+[[package]]
+name = "tokio"
+version = "1.20.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03"
+checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581"
 dependencies = [
- "serde_derive",
+ "autocfg",
+ "bytes",
+ "libc",
+ "memchr",
+ "mio",
+ "num_cpus",
+ "once_cell",
+ "parking_lot",
+ "pin-project-lite",
+ "signal-hook-registry",
+ "socket2",
+ "tokio-macros",
+ "winapi",
 ]
 
 [[package]]
-name = "serde-json-wasm"
-version = "0.4.1"
+name = "tokio-io-timeout"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "479b4dbc401ca13ee8ce902851b834893251404c4f3c65370a49e047a6be09a5"
+checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf"
 dependencies = [
- "serde",
+ "pin-project-lite",
+ "tokio",
 ]
 
 [[package]]
-name = "serde_derive"
-version = "1.0.140"
+name = "tokio-macros"
+version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f2122636b9fe3b81f1cb25099fcf2d3f542cdb1d45940d56c713158884a05da"
+checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1229,166 +2963,181 @@ dependencies = [
 ]
 
 [[package]]
-name = "serde_derive_internals"
-version = "0.26.0"
+name = "tokio-rustls"
+version = "0.22.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c"
+checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6"
 dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "rustls",
+ "tokio",
+ "webpki",
 ]
 
 [[package]]
-name = "serde_json"
-version = "1.0.82"
+name = "tokio-stream"
+version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7"
+checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9"
 dependencies = [
- "itoa",
- "ryu",
- "serde",
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
 ]
 
 [[package]]
-name = "sha2"
-version = "0.9.9"
+name = "tokio-util"
+version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
+checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45"
 dependencies = [
- "block-buffer",
- "cfg-if",
- "cpufeatures",
- "digest",
- "opaque-debug",
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "pin-project-lite",
+ "tokio",
+ "tracing",
 ]
 
 [[package]]
-name = "signature"
-version = "1.4.0"
+name = "toml"
+version = "0.5.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788"
+checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
 dependencies = [
- "digest",
- "rand_core 0.6.3",
+ "serde",
 ]
 
 [[package]]
-name = "spki"
-version = "0.5.4"
+name = "tonic"
+version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27"
+checksum = "5be9d60db39854b30b835107500cf0aca0b0d14d6e1c3de124217c23a29c2ddb"
 dependencies = [
- "base64ct",
- "der",
+ "async-stream",
+ "async-trait",
+ "axum",
+ "base64",
+ "bytes",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-timeout",
+ "percent-encoding",
+ "pin-project",
+ "prost 0.10.4",
+ "prost-derive 0.10.1",
+ "tokio",
+ "tokio-stream",
+ "tokio-util",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+ "tracing-futures",
+]
+
+[[package]]
+name = "tower"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "indexmap",
+ "pin-project",
+ "pin-project-lite",
+ "rand",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tower-layer",
+ "tower-service",
+ "tracing",
 ]
 
 [[package]]
-name = "stake-cw20-external-rewards"
-version = "0.2.6"
+name = "tower-http"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c530c8675c1dbf98facee631536fa116b5fb6382d7dd6dc1b118d970eafe3ba"
 dependencies = [
- "anyhow",
- "cosmwasm-schema",
- "cosmwasm-std",
- "cosmwasm-storage",
- "cw-controllers",
- "cw-multi-test 0.13.4",
- "cw-storage-plus 0.13.4",
- "cw-utils 0.13.4",
- "cw2 0.13.4",
- "cw20 0.13.4",
- "cw20-base",
- "cw20-stake",
- "schemars",
- "serde",
- "thiserror",
+ "bitflags",
+ "bytes",
+ "futures-core",
+ "futures-util",
+ "http",
+ "http-body",
+ "http-range-header",
+ "pin-project-lite",
+ "tower",
+ "tower-layer",
+ "tower-service",
 ]
 
 [[package]]
-name = "stake-cw20-reward-distributor"
-version = "0.1.0"
-dependencies = [
- "cosmwasm-schema",
- "cosmwasm-std",
- "cosmwasm-storage",
- "cw-multi-test 0.13.4",
- "cw-storage-plus 0.13.4",
- "cw-utils 0.13.4",
- "cw2 0.13.4",
- "cw20 0.13.4",
- "cw20-base",
- "cw20-stake",
- "schemars",
- "serde",
- "thiserror",
-]
+name = "tower-layer"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62"
 
 [[package]]
-name = "static_assertions"
-version = "1.1.0"
+name = "tower-service"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
 
 [[package]]
-name = "subtle"
-version = "2.4.1"
+name = "tracing"
+version = "0.1.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
+checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307"
+dependencies = [
+ "cfg-if",
+ "log",
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
 
 [[package]]
-name = "syn"
-version = "1.0.98"
+name = "tracing-attributes"
+version = "0.1.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
+checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2"
 dependencies = [
  "proc-macro2",
  "quote",
- "unicode-ident",
+ "syn",
 ]
 
 [[package]]
-name = "testing"
-version = "0.1.0"
+name = "tracing-core"
+version = "0.1.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7"
 dependencies = [
- "cosmwasm-schema",
- "cosmwasm-std",
- "cw-core",
- "cw-core-interface",
- "cw-multi-test 0.13.4",
- "cw-utils 0.13.4",
- "cw2 0.13.4",
- "cw20 0.13.4",
- "cw20-balance-voting",
- "cw20-base",
- "cw20-stake",
- "cw20-staked-balance-voting",
- "cw4",
- "cw4-group",
- "cw4-voting",
- "indexable-hooks",
- "rand",
- "voting",
+ "once_cell",
 ]
 
 [[package]]
-name = "thiserror"
-version = "1.0.31"
+name = "tracing-futures"
+version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
+checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
 dependencies = [
- "thiserror-impl",
+ "pin-project",
+ "tracing",
 ]
 
 [[package]]
-name = "thiserror-impl"
-version = "1.0.31"
+name = "try-lock"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
+checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
 
 [[package]]
 name = "typenum"
@@ -1396,6 +3145,12 @@ version = "1.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
 
+[[package]]
+name = "ucd-trie"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89570599c4fe5585de2b388aab47e99f7fa4e9238a1399f707a02e356058141c"
+
 [[package]]
 name = "uint"
 version = "0.9.3"
@@ -1408,11 +3163,56 @@ dependencies = [
  "static_assertions",
 ]
 
+[[package]]
+name = "unicode-bidi"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
+
 [[package]]
 name = "unicode-ident"
-version = "1.0.2"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7"
+checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
+
+[[package]]
+name = "untrusted"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
+
+[[package]]
+name = "url"
+version = "2.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "matches",
+ "percent-encoding",
+]
+
+[[package]]
+name = "uuid"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
 
 [[package]]
 name = "version_check"
@@ -1446,6 +3246,27 @@ dependencies = [
  "thiserror",
 ]
 
+[[package]]
+name = "walkdir"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
+dependencies = [
+ "same-file",
+ "winapi",
+ "winapi-util",
+]
+
+[[package]]
+name = "want"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
+dependencies = [
+ "log",
+ "try-lock",
+]
+
 [[package]]
 name = "wasi"
 version = "0.9.0+wasi-snapshot-preview1"
@@ -1458,8 +3279,189 @@ version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.82"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.82"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.82"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.82"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.82"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a"
+
+[[package]]
+name = "web-sys"
+version = "0.3.59"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "webpki"
+version = "0.21.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
+[[package]]
+name = "webpki-roots"
+version = "0.21.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940"
+dependencies = [
+ "webpki",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-sys"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
+dependencies = [
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
+
+[[package]]
+name = "yaml-rust"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
+dependencies = [
+ "linked-hash-map",
+]
+
 [[package]]
 name = "zeroize"
 version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd"
+dependencies = [
+ "zeroize_derive",
+]
+
+[[package]]
+name = "zeroize_derive"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
diff --git a/Cargo.toml b/Cargo.toml
index 64f2b8ea..66e6faeb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,5 +1,5 @@
 [workspace]
-members = ["contracts/*", "packages/*", "debug/*"]
+members = ["contracts/*", "packages/*", "debug/*", "ci/*"]
 
 
 [profile.release.package.stake-cw20-external-rewards]
diff --git a/README.md b/README.md
index 7f5c22dc..6770996f 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,13 @@
 # DAO DAO Contracts
+
 [![codecov](https://codecov.io/gh/DA0-DA0/dao-contracts/branch/main/graph/badge.svg?token=SCKOIPYZPV)](https://codecov.io/gh/DA0-DA0/dao-contracts)
 
+This is a collection for smart contracts for building composable,
+modular, and upgradable DAOs.
+
+For an overview of our contract design, see [our
+wiki](https://github.com/DA0-DA0/dao-contracts/wiki/DAO-DAO-Contracts-Design).
+
 | Audited contracts                                                        | Description                                                |
 | :----------------------------------------------------------------------- | :--------------------------------------------------------- |
 | [cw-core](contracts/cw-core)                                             | The core module for a DAO DAO DAO.                         |
@@ -8,75 +15,46 @@
 | [cw20-staked-balance-voting](contracts/cw20-staked-balance-voting)       | A voting power module for staked governance tokens.        |
 | [cw4-voting](contracts/cw4-voting)                                       | A voting power module for multisig-style voting.           |
 | [cw20-stake](contracts/cw20-stake)                                       | A contract for staking cw20 tokens.                        |
+| [stake-external-rewards](contracts/cw20-stake-external-rewards)          | A contract for providing external stakinig rewards.        |
+| [cw20-stake-reward-distributor](contracts/cw20-stake-external-rewards)   | A contract for distributing rewards via stake-cw20.        |
 
 
 | Unaudited contracts                                                      | Description                                                |
 | :----------------------------------------------------------------------- | :--------------------------------------------------------- |
 | [cw-named-groups](contracts/cw-named-groups)                             | A contract for managing named groups of addresses.         |
-| [cw-proposal-sudo](contracts/cw-proposal-sudo)                           | A proposal module that allows an admin to control a DAO.   |
-| [cw20-balance-voting](contracts/cw20-balance-voting)                     | TESTING ONLY - a voting module based on cw20 balances.     |
-| [proposal-hooks-counter](contracts/proposal-hooks-counter)               | TESTING ONLY - a contract for testing proposal hooks.      |
-| [stake-external-rewards](contracts/cw20-stake-external-rewards)          | A contract for providing external stakinig rewards.        |
-| [cw20-stake-reward-distributor](contracts/cw20-stake-external-rewards)   | A contract for distributing rewards via stake-cw20.        |
 | [cw-proposal-multiple](contracts/cw-proposal-multiple)                   | A proposal module for multiple choice proposals.           |
-Audited contracts have completed [an
-audit](https://github.com/securityDAO/audits/blob/7bb8e4910baaea89fddfc025591658f44adbc27c/cosmwasm/dao-contracts/v0.3%20DAO%20DAO%20audit.pdf)
-by security DAO. A second audit is forthcoming.
-
-## Contributing
-
-Interested in contributing to DAO DAO? Check out [CONTRIBUTING.md](./CONTRIBUTING.md).
-
-## Deploying in a development environment
-
-_Note: this will deploy the legacy version of the contracts currently
-running at [daodao.zone](https://daodao.zone)._
-
-Build and deploy the contracts to a local chain running in Docker with:
-
-```sh
-bash scripts/deploy_local.sh juno10j9gpw9t4jsz47qgnkvl5n3zlm2fz72k67rxsg
-```
-
-> Note: This Wasm account is from the [default account](default-account.txt), which you can use for testing (DO NOT store any real funds with this account). You can pass in any wasm account address you want to use.
 
-This will run a chain locally in a docker container, then build and deploy the contracts to that chain.
+Audited contracts have completed audits by
+[securityDAO](https://github.com/securityDAO/audits/blob/7bb8e4910baaea89fddfc025591658f44adbc27c/cosmwasm/dao-contracts/v0.3%20DAO%20DAO%20audit.pdf)
+and [Oak
+Security](https://github.com/oak-security/audit-reports/blob/2377ba8cfcfd505283c789d706311b06771d6db4/DAO%20DAO/2022-06-22%20Audit%20Report%20-%20DAO%20DAO%20v1.0.pdf).
 
-The script will output something like:
+## Developers
 
-```sh
-NEXT_PUBLIC_CW20_CODE_ID=1
-NEXT_PUBLIC_CW4GROUP_CODE_ID=2
-NEXT_PUBLIC_CWCORE_CODE_ID=7
-NEXT_PUBLIC_CWPROPOSALSINGLE_CODE_ID=11
-NEXT_PUBLIC_CW4VOTING_CODE_ID=5
-NEXT_PUBLIC_CW20STAKEDBALANCEVOTING_CODE_ID=4
-NEXT_PUBLIC_STAKECW20_CODE_ID=13
-NEXT_PUBLIC_DAO_CONTRACT_ADDRESS=juno1zlmaky7753d2fneyhduwz0rn3u9ns8rse3tudhze8rc2g54w9ysqgjt23l
-NEXT_PUBLIC_V1_FACTORY_CONTRACT_ADDRESS=juno1pvrwmjuusn9wh34j7y520g8gumuy9xtl3gvprlljfdpwju3x7ucssml9ug
-```
+Information about our development workflow and how to contribute can
+be found in [CONTRIBUTING.md](./CONTRIBUTING.md).
 
-You can then instantiate and interact with contracts.
+## Testing
 
-Note, to send commands to the docker container:
+### Unit tests
 
-```sh
-docker exec -i cosmwasm junod status
-```
+Run `cargo t` or `cargo unit-test` from the project root to run the unit tests.
 
-Some commands require a password which defaults to `xxxxxxxxx`. You can use them like so:
+### Integration tests
 
-```sh
-echo xxxxxxxxx | docker exec -i cosmwasm  junod keys show validator -a
-```
+* `./scripts/deploy_local.sh juno10j9gpw9t4jsz47qgnkvl5n3zlm2fz72k67rxsg`
+* `cd ci/integration_tests`
+* `CONTRACT_DIR="../../artifacts" GAS_OUT_DIR="gas_reports" CONFIG="configs/local.yaml" cargo t`
 
-## Generating schema for all contracts
-As we have a workflow to check schema differences on commit, to quickly run `cargo schema` against all contracts
-simply run the following from the repo root:
-```sh
-./scripts/schema.sh
-```
+See [ci/integration_tests/README.md](ci/integration_tests/README.md) for more information.
 
 ## Disclaimer
 
-DAO DAO TOOLING IS PROVIDED “AS IS”, AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND. No developer or entity involved in creating the DAO DAO UI or smart contracts will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of DAO DAO tooling, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value.
+DAO DAO TOOLING IS PROVIDED “AS IS”, AT YOUR OWN RISK, AND WITHOUT
+WARRANTIES OF ANY KIND. No developer or entity involved in creating
+the DAO DAO UI or smart contracts will be liable for any claims or
+damages whatsoever associated with your use, inability to use, or your
+interaction with other users of DAO DAO tooling, including any direct,
+indirect, incidental, special, exemplary, punitive or consequential
+damages, or loss of profits, cryptocurrencies, tokens, or anything
+else of value.
diff --git a/contracts/cw-native-staked-balance-voting/Cargo.toml b/contracts/cw-native-staked-balance-voting/Cargo.toml
index 4e225522..99c56981 100644
--- a/contracts/cw-native-staked-balance-voting/Cargo.toml
+++ b/contracts/cw-native-staked-balance-voting/Cargo.toml
@@ -33,6 +33,7 @@ serde = { version = "1.0", default-features = false, features = ["derive"] }
 thiserror = { version = "1.0" }
 cw-core-macros = { version = "*", path = "../../packages/cw-core-macros" }
 cw-core-interface = { version = "*", path = "../../packages/cw-core-interface" }
+cw-paginate = { version = "0.1.0", path = "../../packages/cw-paginate" }
 
 [dev-dependencies]
 cosmwasm-schema = { version = "1.0.0" }
diff --git a/contracts/cw-native-staked-balance-voting/examples/schema.rs b/contracts/cw-native-staked-balance-voting/examples/schema.rs
index 3779e062..0b908322 100644
--- a/contracts/cw-native-staked-balance-voting/examples/schema.rs
+++ b/contracts/cw-native-staked-balance-voting/examples/schema.rs
@@ -8,7 +8,7 @@ use cw_core_interface::voting::{
     InfoResponse, IsActiveResponse, TotalPowerAtHeightResponse, VotingPowerAtHeightResponse,
 };
 use cw_native_staked_balance_voting::msg::{
-    ExecuteMsg, InstantiateMsg, MigrateMsg, Owner, QueryMsg,
+    ExecuteMsg, InstantiateMsg, ListStakersResponse, MigrateMsg, Owner, QueryMsg,
 };
 use cw_native_staked_balance_voting::state::Config;
 
@@ -29,6 +29,7 @@ fn main() {
     export_schema(&schema_for!(VotingPowerAtHeightResponse), &out_dir);
     export_schema(&schema_for!(IsActiveResponse), &out_dir);
     export_schema(&schema_for!(ClaimsResponse), &out_dir);
+    export_schema(&schema_for!(ListStakersResponse), &out_dir);
 
     // Auto TS code generation expects the query return type as QueryNameResponse
     // Here we map query resonses to the correct name
diff --git a/contracts/cw-native-staked-balance-voting/schema/list_stakers_response.json b/contracts/cw-native-staked-balance-voting/schema/list_stakers_response.json
new file mode 100644
index 00000000..e48d91d9
--- /dev/null
+++ b/contracts/cw-native-staked-balance-voting/schema/list_stakers_response.json
@@ -0,0 +1,37 @@
+{
+  "$schema": "http://json-schema.org/draft-07/schema#",
+  "title": "ListStakersResponse",
+  "type": "object",
+  "required": [
+    "stakers"
+  ],
+  "properties": {
+    "stakers": {
+      "type": "array",
+      "items": {
+        "$ref": "#/definitions/StakerBalanceResponse"
+      }
+    }
+  },
+  "definitions": {
+    "StakerBalanceResponse": {
+      "type": "object",
+      "required": [
+        "address",
+        "balance"
+      ],
+      "properties": {
+        "address": {
+          "type": "string"
+        },
+        "balance": {
+          "$ref": "#/definitions/Uint128"
+        }
+      }
+    },
+    "Uint128": {
+      "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
+      "type": "string"
+    }
+  }
+}
diff --git a/contracts/cw-native-staked-balance-voting/schema/query_msg.json b/contracts/cw-native-staked-balance-voting/schema/query_msg.json
index e2f561a5..0ce22a82 100644
--- a/contracts/cw-native-staked-balance-voting/schema/query_msg.json
+++ b/contracts/cw-native-staked-balance-voting/schema/query_msg.json
@@ -46,6 +46,34 @@
       },
       "additionalProperties": false
     },
+    {
+      "type": "object",
+      "required": [
+        "list_stakers"
+      ],
+      "properties": {
+        "list_stakers": {
+          "type": "object",
+          "properties": {
+            "limit": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint32",
+              "minimum": 0.0
+            },
+            "start_after": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        }
+      },
+      "additionalProperties": false
+    },
     {
       "type": "object",
       "required": [
diff --git a/contracts/cw-native-staked-balance-voting/src/contract.rs b/contracts/cw-native-staked-balance-voting/src/contract.rs
index 12aac50d..079e1130 100644
--- a/contracts/cw-native-staked-balance-voting/src/contract.rs
+++ b/contracts/cw-native-staked-balance-voting/src/contract.rs
@@ -10,7 +10,10 @@ use cw_core_interface::voting::{TotalPowerAtHeightResponse, VotingPowerAtHeightR
 use cw_utils::{must_pay, Duration};
 
 use crate::error::ContractError;
-use crate::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, Owner, QueryMsg};
+use crate::msg::{
+    ExecuteMsg, InstantiateMsg, ListStakersResponse, MigrateMsg, Owner, QueryMsg,
+    StakerBalanceResponse,
+};
 use crate::state::{Config, CLAIMS, CONFIG, DAO, MAX_CLAIMS, STAKED_BALANCES, STAKED_TOTAL};
 
 const CONTRACT_NAME: &str = "crates.io:cw-native-staked-balance-voting";
@@ -280,6 +283,9 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
         QueryMsg::Dao {} => query_dao(deps),
         QueryMsg::Claims { address } => to_binary(&query_claims(deps, address)?),
         QueryMsg::GetConfig {} => to_binary(&CONFIG.load(deps.storage)?),
+        QueryMsg::ListStakers { start_after, limit } => {
+            query_list_stakers(deps, start_after, limit)
+        }
     }
 }
 
@@ -323,6 +329,34 @@ pub fn query_claims(deps: Deps, address: String) -> StdResult<ClaimsResponse> {
     CLAIMS.query_claims(deps, &deps.api.addr_validate(&address)?)
 }
 
+pub fn query_list_stakers(
+    deps: Deps,
+    start_after: Option<String>,
+    limit: Option<u32>,
+) -> StdResult<Binary> {
+    let start_at = start_after
+        .map(|addr| deps.api.addr_validate(&addr))
+        .transpose()?;
+
+    let stakers = cw_paginate::paginate_snapshot_map(
+        deps,
+        &STAKED_BALANCES,
+        start_at.as_ref(),
+        limit,
+        cosmwasm_std::Order::Ascending,
+    )?;
+
+    let stakers = stakers
+        .into_iter()
+        .map(|(address, balance)| StakerBalanceResponse {
+            address: address.into_string(),
+            balance,
+        })
+        .collect();
+
+    to_binary(&ListStakersResponse { stakers })
+}
+
 #[cfg_attr(not(feature = "library"), entry_point)]
 pub fn migrate(_deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result<Response, ContractError> {
     // Don't do any state migrations.
diff --git a/contracts/cw-native-staked-balance-voting/src/msg.rs b/contracts/cw-native-staked-balance-voting/src/msg.rs
index 5daf16cc..18e5b9a3 100644
--- a/contracts/cw-native-staked-balance-voting/src/msg.rs
+++ b/contracts/cw-native-staked-balance-voting/src/msg.rs
@@ -49,8 +49,27 @@ pub enum ExecuteMsg {
 pub enum QueryMsg {
     Dao {},
     GetConfig {},
-    Claims { address: String },
+    Claims {
+        address: String,
+    },
+    ListStakers {
+        start_after: Option<String>,
+        limit: Option<u32>,
+    },
 }
 
 #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
 pub struct MigrateMsg {}
+
+#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
+#[serde(rename_all = "snake_case")]
+pub struct ListStakersResponse {
+    pub stakers: Vec<StakerBalanceResponse>,
+}
+
+#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
+#[serde(rename_all = "snake_case")]
+pub struct StakerBalanceResponse {
+    pub address: String,
+    pub balance: Uint128,
+}
diff --git a/contracts/cw20-stake/Cargo.toml b/contracts/cw20-stake/Cargo.toml
index 54e3311c..64710a17 100644
--- a/contracts/cw20-stake/Cargo.toml
+++ b/contracts/cw20-stake/Cargo.toml
@@ -27,6 +27,7 @@ cw2 = "0.13"
 schemars = "0.8.8"
 serde = { version = "1.0.132", default-features = false, features = ["derive"] }
 thiserror = { version = "1.0.30" }
+cw-paginate = { version = "0.1.0", path = "../../packages/cw-paginate" }
 
 [dev-dependencies]
 cosmwasm-schema = { version = "1.0.0" }
diff --git a/contracts/cw20-stake/examples/schema.rs b/contracts/cw20-stake/examples/schema.rs
index ad360754..5db33a63 100644
--- a/contracts/cw20-stake/examples/schema.rs
+++ b/contracts/cw20-stake/examples/schema.rs
@@ -8,7 +8,7 @@ use cw20::{
     TokenInfoResponse,
 };
 use cw20_stake::msg::{
-    ClaimsResponse, ExecuteMsg, GetHooksResponse, InstantiateMsg, QueryMsg,
+    ClaimsResponse, ExecuteMsg, GetHooksResponse, InstantiateMsg, ListStakersResponse, QueryMsg,
     StakedBalanceAtHeightResponse, StakedValueResponse, TotalStakedAtHeightResponse,
     TotalValueResponse,
 };
@@ -34,6 +34,7 @@ fn main() {
     export_schema(&schema_for!(TokenInfoResponse), &out_dir);
     export_schema(&schema_for!(AllAllowancesResponse), &out_dir);
     export_schema(&schema_for!(AllAccountsResponse), &out_dir);
+    export_schema(&schema_for!(ListStakersResponse), &out_dir);
 
     // Need to rename so it matches the TS pattern
     export_schema_with_title(&schema_for!(Config), &out_dir, "GetConfigResponse");
diff --git a/contracts/cw20-stake/schema/list_stakers_response.json b/contracts/cw20-stake/schema/list_stakers_response.json
new file mode 100644
index 00000000..e48d91d9
--- /dev/null
+++ b/contracts/cw20-stake/schema/list_stakers_response.json
@@ -0,0 +1,37 @@
+{
+  "$schema": "http://json-schema.org/draft-07/schema#",
+  "title": "ListStakersResponse",
+  "type": "object",
+  "required": [
+    "stakers"
+  ],
+  "properties": {
+    "stakers": {
+      "type": "array",
+      "items": {
+        "$ref": "#/definitions/StakerBalanceResponse"
+      }
+    }
+  },
+  "definitions": {
+    "StakerBalanceResponse": {
+      "type": "object",
+      "required": [
+        "address",
+        "balance"
+      ],
+      "properties": {
+        "address": {
+          "type": "string"
+        },
+        "balance": {
+          "$ref": "#/definitions/Uint128"
+        }
+      }
+    },
+    "Uint128": {
+      "description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
+      "type": "string"
+    }
+  }
+}
diff --git a/contracts/cw20-stake/schema/query_msg.json b/contracts/cw20-stake/schema/query_msg.json
index 60ae2172..f4d9193b 100644
--- a/contracts/cw20-stake/schema/query_msg.json
+++ b/contracts/cw20-stake/schema/query_msg.json
@@ -127,6 +127,34 @@
         }
       },
       "additionalProperties": false
+    },
+    {
+      "type": "object",
+      "required": [
+        "list_stakers"
+      ],
+      "properties": {
+        "list_stakers": {
+          "type": "object",
+          "properties": {
+            "limit": {
+              "type": [
+                "integer",
+                "null"
+              ],
+              "format": "uint32",
+              "minimum": 0.0
+            },
+            "start_after": {
+              "type": [
+                "string",
+                "null"
+              ]
+            }
+          }
+        }
+      },
+      "additionalProperties": false
     }
   ]
 }
diff --git a/contracts/cw20-stake/src/contract.rs b/contracts/cw20-stake/src/contract.rs
index 84bd49c5..3527ed89 100644
--- a/contracts/cw20-stake/src/contract.rs
+++ b/contracts/cw20-stake/src/contract.rs
@@ -10,9 +10,9 @@ use cw20::Cw20ReceiveMsg;
 
 use crate::hooks::{stake_hook_msgs, unstake_hook_msgs};
 use crate::msg::{
-    ExecuteMsg, GetHooksResponse, InstantiateMsg, MigrateMsg, QueryMsg, ReceiveMsg,
-    StakedBalanceAtHeightResponse, StakedValueResponse, TotalStakedAtHeightResponse,
-    TotalValueResponse,
+    ExecuteMsg, GetHooksResponse, InstantiateMsg, ListStakersResponse, MigrateMsg, QueryMsg,
+    ReceiveMsg, StakedBalanceAtHeightResponse, StakedValueResponse, StakerBalanceResponse,
+    TotalStakedAtHeightResponse, TotalValueResponse,
 };
 use crate::state::{
     Config, BALANCE, CLAIMS, CONFIG, HOOKS, MAX_CLAIMS, STAKED_BALANCES, STAKED_TOTAL,
@@ -388,6 +388,9 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
         QueryMsg::TotalValue {} => to_binary(&query_total_value(deps, env)?),
         QueryMsg::Claims { address } => to_binary(&query_claims(deps, address)?),
         QueryMsg::GetHooks {} => to_binary(&query_hooks(deps)?),
+        QueryMsg::ListStakers { start_after, limit } => {
+            query_list_stakers(deps, start_after, limit)
+        }
     }
 }
 
@@ -462,6 +465,34 @@ pub fn query_hooks(deps: Deps) -> StdResult<GetHooksResponse> {
     })
 }
 
+pub fn query_list_stakers(
+    deps: Deps,
+    start_after: Option<String>,
+    limit: Option<u32>,
+) -> StdResult<Binary> {
+    let start_at = start_after
+        .map(|addr| deps.api.addr_validate(&addr))
+        .transpose()?;
+
+    let stakers = cw_paginate::paginate_snapshot_map(
+        deps,
+        &STAKED_BALANCES,
+        start_at.as_ref(),
+        limit,
+        cosmwasm_std::Order::Ascending,
+    )?;
+
+    let stakers = stakers
+        .into_iter()
+        .map(|(address, balance)| StakerBalanceResponse {
+            address: address.into_string(),
+            balance,
+        })
+        .collect();
+
+    to_binary(&ListStakersResponse { stakers })
+}
+
 #[cfg_attr(not(feature = "library"), entry_point)]
 pub fn migrate(deps: DepsMut, _env: Env, msg: MigrateMsg) -> Result<Response, ContractError> {
     use serde::{Deserialize, Serialize};
diff --git a/contracts/cw20-stake/src/msg.rs b/contracts/cw20-stake/src/msg.rs
index 64f8f8f8..d4ac7790 100644
--- a/contracts/cw20-stake/src/msg.rs
+++ b/contracts/cw20-stake/src/msg.rs
@@ -64,6 +64,10 @@ pub enum QueryMsg {
         address: String,
     },
     GetHooks {},
+    ListStakers {
+        start_after: Option<String>,
+        limit: Option<u32>,
+    },
 }
 
 #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
@@ -104,3 +108,16 @@ pub struct TotalValueResponse {
 pub struct GetHooksResponse {
     pub hooks: Vec<String>,
 }
+
+#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
+#[serde(rename_all = "snake_case")]
+pub struct ListStakersResponse {
+    pub stakers: Vec<StakerBalanceResponse>,
+}
+
+#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
+#[serde(rename_all = "snake_case")]
+pub struct StakerBalanceResponse {
+    pub address: String,
+    pub balance: Uint128,
+}
diff --git a/default-account.txt b/default-account.txt
index 49a0cd34..5119a576 100644
--- a/default-account.txt
+++ b/default-account.txt
@@ -8,4 +8,4 @@
 **Important** write this mnemonic phrase in a safe place.
 It is the only way to recover your account if you ever forget your password.
 
-siren window salt bullet cream letter huge satoshi fade shiver permit offer happy immense wage fitness goose usual aim hammer clap about super trend
\ No newline at end of file
+siren window salt bullet cream letter huge satoshi fade shiver permit offer happy immense wage fitness goose usual aim hammer clap about super trend
diff --git a/packages/cw-paginate/src/lib.rs b/packages/cw-paginate/src/lib.rs
index 7806056b..e0d438f4 100644
--- a/packages/cw-paginate/src/lib.rs
+++ b/packages/cw-paginate/src/lib.rs
@@ -40,7 +40,9 @@
 //!  ```
 
 use cosmwasm_std::{Deps, Order, StdResult};
-use cw_storage_plus::{Bound, Bounder, KeyDeserialize, Map, SnapshotMap};
+
+#[allow(unused_imports)]
+use cw_storage_plus::{Bound, Bounder, KeyDeserialize, Map, SnapshotMap, Strategy};
 
 /// Generic function for paginating a list of (K, V) pairs in a
 /// CosmWasm Map.
@@ -55,7 +57,12 @@ where
     K: Bounder<'a> + KeyDeserialize<Output = K> + 'static,
     V: serde::de::DeserializeOwned + serde::Serialize,
 {
-    let items = map.range(deps.storage, start_after.map(Bound::exclusive), None, order);
+    let (range_min, range_max) = match order {
+        Order::Ascending => (start_after.map(Bound::exclusive), None),
+        Order::Descending => (None, start_after.map(Bound::exclusive)),
+    };
+
+    let items = map.range(deps.storage, range_min, range_max, order);
     match limit {
         Some(limit) => Ok(items
             .take(limit.try_into().unwrap())
@@ -76,7 +83,38 @@ where
     K: Bounder<'a> + KeyDeserialize<Output = K> + 'static,
     V: serde::de::DeserializeOwned + serde::Serialize,
 {
-    let items = map.keys(deps.storage, start_after.map(Bound::exclusive), None, order);
+    let (range_min, range_max) = match order {
+        Order::Ascending => (start_after.map(Bound::exclusive), None),
+        Order::Descending => (None, start_after.map(Bound::exclusive)),
+    };
+
+    let items = map.keys(deps.storage, range_min, range_max, order);
+    match limit {
+        Some(limit) => Ok(items
+            .take(limit.try_into().unwrap())
+            .collect::<StdResult<_>>()?),
+        None => Ok(items.collect::<StdResult<_>>()?),
+    }
+}
+
+/// Same as `paginate_map` but for use with `SnapshotMap`.
+pub fn paginate_snapshot_map<'a, 'b, K, V, R: 'static>(
+    deps: Deps,
+    map: &SnapshotMap<'a, K, V>,
+    start_after: Option<K>,
+    limit: Option<u32>,
+    order: Order,
+) -> StdResult<Vec<(R, V)>>
+where
+    K: Bounder<'a> + KeyDeserialize<Output = R> + 'b,
+    V: serde::de::DeserializeOwned + serde::Serialize,
+{
+    let (range_min, range_max) = match order {
+        Order::Ascending => (start_after.map(Bound::exclusive), None),
+        Order::Descending => (None, start_after.map(Bound::exclusive)),
+    };
+
+    let items = map.range(deps.storage, range_min, range_max, order);
     match limit {
         Some(limit) => Ok(items
             .take(limit.try_into().unwrap())
@@ -87,18 +125,23 @@ where
 
 /// Same as `paginate_map` but only returns the keys. For use with
 /// `SnaphotMap`.
-pub fn paginate_snapshot_map_keys<'a, K, V>(
+pub fn paginate_snapshot_map_keys<'a, 'b, K, V, R: 'static>(
     deps: Deps,
     map: &SnapshotMap<'a, K, V>,
     start_after: Option<K>,
     limit: Option<u32>,
     order: Order,
-) -> StdResult<Vec<K>>
+) -> StdResult<Vec<R>>
 where
-    K: Bounder<'a> + KeyDeserialize<Output = K> + 'static,
+    K: Bounder<'a> + KeyDeserialize<Output = R> + 'b,
     V: serde::de::DeserializeOwned + serde::Serialize,
 {
-    let items = map.keys(deps.storage, start_after.map(Bound::exclusive), None, order);
+    let (range_min, range_max) = match order {
+        Order::Ascending => (start_after.map(Bound::exclusive), None),
+        Order::Descending => (None, start_after.map(Bound::exclusive)),
+    };
+
+    let items = map.keys(deps.storage, range_min, range_max, order);
     match limit {
         Some(limit) => Ok(items
             .take(limit.try_into().unwrap())
@@ -110,7 +153,8 @@ where
 #[cfg(test)]
 mod tests {
     use super::*;
-    use cosmwasm_std::testing::mock_dependencies;
+    use cosmwasm_std::testing::{mock_dependencies, mock_env};
+    use cosmwasm_std::{Addr, Uint128};
 
     #[test]
     fn pagination() {
@@ -184,4 +228,212 @@ mod tests {
             paginate_map_keys(deps.as_ref(), &map, None, Some(1), Order::Ascending).unwrap();
         assert_eq!(items, vec!["1".to_string()]);
     }
+
+    // this test will double check the descending keys with the rewrite
+    #[test]
+    fn key_pagination_test2() {
+        let mut deps = mock_dependencies();
+        let map: Map<u32, String> = Map::new("items");
+
+        for num in 1u32..=10 {
+            map.save(&mut deps.storage, num, &(num * 2).to_string())
+                .unwrap();
+        }
+
+        let items = paginate_map_keys(deps.as_ref(), &map, None, None, Order::Descending).unwrap();
+        assert_eq!(items, vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 1]);
+
+        let items = paginate_map_keys(deps.as_ref(), &map, None, None, Order::Ascending).unwrap();
+        assert_eq!(items, vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+
+        let items =
+            paginate_map_keys(deps.as_ref(), &map, Some(3), Some(3), Order::Ascending).unwrap();
+        assert_eq!(items, vec![4, 5, 6]);
+
+        let items =
+            paginate_map_keys(deps.as_ref(), &map, Some(7), Some(4), Order::Descending).unwrap();
+        assert_eq!(items, vec![6, 5, 4, 3]);
+    }
+
+    #[test]
+    fn snapshot_pagination() {
+        let mut deps = mock_dependencies();
+        let env = mock_env();
+
+        let map: SnapshotMap<&Addr, Uint128> = SnapshotMap::new(
+            "items",
+            "items__checkpoints",
+            "items__changelog",
+            Strategy::EveryBlock,
+        );
+
+        for ctr in 1..100 {
+            let addr = Addr::unchecked(format!("test_addr{:0>3}", ctr.clone()));
+            map.save(
+                &mut deps.storage,
+                &addr,
+                &Uint128::new(ctr),
+                env.block.height,
+            )
+            .unwrap();
+        }
+
+        // grab first 10 items
+        let items =
+            paginate_snapshot_map(deps.as_ref(), &map, None, Some(10), Order::Ascending).unwrap();
+
+        assert_eq!(items.len(), 10);
+
+        let mut test_vec: Vec<(Addr, Uint128)> = vec![];
+        for ctr in 1..=10 {
+            let addr = Addr::unchecked(format!("test_addr{:0>3}", ctr.clone()));
+
+            test_vec.push((addr, Uint128::new(ctr)));
+        }
+        assert_eq!(items, test_vec);
+
+        // using the last result of the last item (10), grab the next one
+        let items = paginate_snapshot_map(
+            deps.as_ref(),
+            &map,
+            Some(&items[items.len() - 1].0),
+            Some(10),
+            Order::Ascending,
+        )
+        .unwrap();
+
+        // should be the 11th item
+        assert_eq!(items[0].0, Addr::unchecked("test_addr011".to_string()));
+        assert_eq!(items[0].1, Uint128::new(11));
+
+        let items =
+            paginate_snapshot_map(deps.as_ref(), &map, None, None, Order::Descending).unwrap();
+
+        // 20th item (19 index) should be 80
+        assert_eq!(items[19].0, Addr::unchecked("test_addr080".to_string()));
+        assert_eq!(items[19].1, Uint128::new(80));
+    }
+
+    // this test will encapsulate the generic changes for &Addr
+    #[test]
+    fn snapshot_pagination_keys_new_generic() {
+        let mut deps = mock_dependencies();
+        let env = mock_env();
+
+        let map: SnapshotMap<&Addr, Uint128> = SnapshotMap::new(
+            "items",
+            "items__checkpoints",
+            "items__changelog",
+            Strategy::EveryBlock,
+        );
+
+        for ctr in 1..100 {
+            let addr = Addr::unchecked(format!("test_addr{:0>3}", ctr.clone()));
+            map.save(
+                &mut deps.storage,
+                &addr,
+                &Uint128::new(ctr),
+                env.block.height,
+            )
+            .unwrap();
+        }
+
+        // grab first 10 items
+        let items =
+            paginate_snapshot_map_keys(deps.as_ref(), &map, None, Some(10), Order::Ascending)
+                .unwrap();
+
+        assert_eq!(items.len(), 10);
+
+        let mut test_vec: Vec<Addr> = vec![];
+        for ctr in 1..=10 {
+            let addr = Addr::unchecked(format!("test_addr{:0>3}", ctr.clone()));
+
+            test_vec.push(addr);
+        }
+        assert_eq!(items, test_vec);
+
+        // max item from before was the 10th, so it'll go backwards from 9->1
+        let items = paginate_snapshot_map_keys(
+            deps.as_ref(),
+            &map,
+            Some(&items[items.len() - 1]),
+            None,
+            Order::Descending,
+        )
+        .unwrap();
+
+        // 3rd item in vec should be 006
+        assert_eq!(items[3], Addr::unchecked("test_addr006".to_string()));
+
+        let items =
+            paginate_snapshot_map_keys(deps.as_ref(), &map, None, None, Order::Descending).unwrap();
+
+        // 20th item (19 index) should be 80
+        assert_eq!(items[19], Addr::unchecked("test_addr080".to_string()));
+    }
+
+    #[test]
+    fn snapshot_pagination_keys() {
+        let mut deps = mock_dependencies();
+        let env = mock_env();
+
+        let map: SnapshotMap<u32, Uint128> = SnapshotMap::new(
+            "items",
+            "items__checkpoints",
+            "items__changelog",
+            Strategy::EveryBlock,
+        );
+
+        for ctr in 1..=100 {
+            map.save(
+                &mut deps.storage,
+                ctr,
+                &Uint128::new(ctr.try_into().unwrap()),
+                env.block.height,
+            )
+            .unwrap();
+        }
+
+        // grab first 10 items
+        let items =
+            paginate_snapshot_map_keys(deps.as_ref(), &map, None, Some(10), Order::Ascending)
+                .unwrap();
+
+        assert_eq!(items.len(), 10);
+        assert_eq!(items, vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+
+        let items =
+            paginate_snapshot_map_keys(deps.as_ref(), &map, Some(50), Some(10), Order::Ascending)
+                .unwrap();
+
+        assert_eq!(items, vec![51, 52, 53, 54, 55, 56, 57, 58, 59, 60]);
+
+        let items =
+            paginate_snapshot_map_keys(deps.as_ref(), &map, Some(50), Some(10), Order::Descending)
+                .unwrap();
+
+        assert_eq!(items, vec![49, 48, 47, 46, 45, 44, 43, 42, 41, 40]);
+    }
+
+    #[test]
+    fn pagination_order_desc_tests() {
+        let mut deps = mock_dependencies();
+        let map: Map<u32, u32> = Map::new("items");
+
+        map.save(&mut deps.storage, 1, &40).unwrap();
+        map.save(&mut deps.storage, 2, &22).unwrap();
+        map.save(&mut deps.storage, 3, &77).unwrap();
+        map.save(&mut deps.storage, 4, &66).unwrap();
+        map.save(&mut deps.storage, 5, &0).unwrap();
+
+        let items = paginate_map(deps.as_ref(), &map, None, None, Order::Descending).unwrap();
+        assert_eq!(items, vec![(5, 0), (4, 66), (3, 77), (2, 22), (1, 40)]);
+
+        let items = paginate_map(deps.as_ref(), &map, Some(3), None, Order::Descending).unwrap();
+        assert_eq!(items, vec![(2, 22), (1, 40)]);
+
+        let items = paginate_map(deps.as_ref(), &map, Some(1), None, Order::Descending).unwrap();
+        assert_eq!(items, vec![]);
+    }
 }
diff --git a/types/contracts/cw-native-staked-balance-voting/CwNativeStakedBalanceVotingContract.ts b/types/contracts/cw-native-staked-balance-voting/CwNativeStakedBalanceVotingContract.ts
index e1772ce9..112eefa0 100644
--- a/types/contracts/cw-native-staked-balance-voting/CwNativeStakedBalanceVotingContract.ts
+++ b/types/contracts/cw-native-staked-balance-voting/CwNativeStakedBalanceVotingContract.ts
@@ -89,6 +89,15 @@ export interface IsActiveResponse {
   active: boolean;
   [k: string]: unknown;
 }
+export interface ListStakersResponse {
+  stakers: StakerBalanceResponse[];
+  [k: string]: unknown;
+}
+export interface StakerBalanceResponse {
+  address: string;
+  balance: Uint128;
+  [k: string]: unknown;
+}
 export interface MigrateMsg {
   [k: string]: unknown;
 }
@@ -105,6 +114,12 @@ export type QueryMsg = {
     address: string;
     [k: string]: unknown;
   };
+} | {
+  list_stakers: {
+    limit?: number | null;
+    start_after?: string | null;
+    [k: string]: unknown;
+  };
 } | {
   voting_power_at_height: {
     address: string;
@@ -140,6 +155,13 @@ export interface CwNativeStakedBalanceVotingReadOnlyInterface {
   }: {
     address: string;
   }) => Promise<ClaimsResponse>;
+  listStakers: ({
+    limit,
+    startAfter
+  }: {
+    limit?: number;
+    startAfter?: string;
+  }) => Promise<ListStakersResponse>;
   votingPowerAtHeight: ({
     address,
     height
@@ -164,6 +186,7 @@ export class CwNativeStakedBalanceVotingQueryClient implements CwNativeStakedBal
     this.dao = this.dao.bind(this);
     this.getConfig = this.getConfig.bind(this);
     this.claims = this.claims.bind(this);
+    this.listStakers = this.listStakers.bind(this);
     this.votingPowerAtHeight = this.votingPowerAtHeight.bind(this);
     this.totalPowerAtHeight = this.totalPowerAtHeight.bind(this);
     this.info = this.info.bind(this);
@@ -190,6 +213,20 @@ export class CwNativeStakedBalanceVotingQueryClient implements CwNativeStakedBal
       }
     });
   };
+  listStakers = async ({
+    limit,
+    startAfter
+  }: {
+    limit?: number;
+    startAfter?: string;
+  }): Promise<ListStakersResponse> => {
+    return this.client.queryContractSmart(this.contractAddress, {
+      list_stakers: {
+        limit,
+        start_after: startAfter
+      }
+    });
+  };
   votingPowerAtHeight = async ({
     address,
     height
diff --git a/types/contracts/cw20-stake/Cw20StakeContract.ts b/types/contracts/cw20-stake/Cw20StakeContract.ts
index 0c00f282..e9b16f1b 100644
--- a/types/contracts/cw20-stake/Cw20StakeContract.ts
+++ b/types/contracts/cw20-stake/Cw20StakeContract.ts
@@ -110,6 +110,15 @@ export interface InstantiateMsg {
   unstaking_duration?: Duration | null;
   [k: string]: unknown;
 }
+export interface ListStakersResponse {
+  stakers: StakerBalanceResponse[];
+  [k: string]: unknown;
+}
+export interface StakerBalanceResponse {
+  address: string;
+  balance: Uint128;
+  [k: string]: unknown;
+}
 export type QueryMsg = {
   staked_balance_at_height: {
     address: string;
@@ -143,6 +152,12 @@ export type QueryMsg = {
   get_hooks: {
     [k: string]: unknown;
   };
+} | {
+  list_stakers: {
+    limit?: number | null;
+    start_after?: string | null;
+    [k: string]: unknown;
+  };
 };
 export interface StakedBalanceAtHeightResponse {
   balance: Uint128;
@@ -196,6 +211,13 @@ export interface Cw20StakeReadOnlyInterface {
     address: string;
   }) => Promise<ClaimsResponse>;
   getHooks: () => Promise<GetHooksResponse>;
+  listStakers: ({
+    limit,
+    startAfter
+  }: {
+    limit?: number;
+    startAfter?: string;
+  }) => Promise<ListStakersResponse>;
 }
 export class Cw20StakeQueryClient implements Cw20StakeReadOnlyInterface {
   client: CosmWasmClient;
@@ -211,6 +233,7 @@ export class Cw20StakeQueryClient implements Cw20StakeReadOnlyInterface {
     this.getConfig = this.getConfig.bind(this);
     this.claims = this.claims.bind(this);
     this.getHooks = this.getHooks.bind(this);
+    this.listStakers = this.listStakers.bind(this);
   }
 
   stakedBalanceAtHeight = async ({
@@ -275,6 +298,20 @@ export class Cw20StakeQueryClient implements Cw20StakeReadOnlyInterface {
       get_hooks: {}
     });
   };
+  listStakers = async ({
+    limit,
+    startAfter
+  }: {
+    limit?: number;
+    startAfter?: string;
+  }): Promise<ListStakersResponse> => {
+    return this.client.queryContractSmart(this.contractAddress, {
+      list_stakers: {
+        limit,
+        start_after: startAfter
+      }
+    });
+  };
 }
 export interface Cw20StakeInterface extends Cw20StakeReadOnlyInterface {
   contractAddress: string;


Test patch:
diff --git a/.github/workflows/integration_tests.yml b/.github/workflows/integration_tests.yml
new file mode 100644
index 00000000..8a9f3d46
--- /dev/null
+++ b/.github/workflows/integration_tests.yml
@@ -0,0 +1,111 @@
+name: Integration Tests
+
+on:
+  pull_request:
+  push:
+    branches:
+      - main
+
+jobs:
+  compile-contracts:
+    name: Compile contracts using optimized rust compiler
+    runs-on: ubuntu-latest
+    container:
+      image: cosmwasm/workspace-optimizer:0.12.6
+    steps:
+      - name: Checkout sources
+        uses: actions/checkout@v3
+      - name: Install tar for cache upload
+        run: apk add --no-cache tar
+      - name: Rust Dependencies Cache
+        uses: actions/cache@v3
+        with:
+          path: |
+            ~/.cargo/bin/
+            ~/.cargo/registry/index/
+            ~/.cargo/registry/cache/
+            ~/.cargo/git/db/
+            target/
+          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
+      - name: Optimize
+        run: optimize_workspace.sh
+      - name: Upload contracts
+        uses: actions/upload-artifact@v3
+        with:
+          name: dao-dao-contract-artifacts-${{ github.event.number }}
+          path: artifacts
+          retention-days: 1
+
+  test:
+    name: Run integration tests against local juno node
+    runs-on: ubuntu-latest
+    needs: compile-contracts
+    env:
+      ADMIN_ADDR: juno10j9gpw9t4jsz47qgnkvl5n3zlm2fz72k67rxsg
+      GAS_OUT_DIR: gas_reports
+      CONFIG: configs/ci.yaml
+      CONTRACT_DIR: artifacts
+    steps:
+      - name: Checkout sources
+        uses: actions/checkout@v3
+
+      - name: Run Local Juno Node
+        run: |
+          docker run --rm -d --name juno \
+            -e PASSWORD=xxxxxxxxx \
+            -e STAKE_TOKEN=ujunox \
+            -e GAS_LIMIT=100000000 \
+            -e MAX_BYTES=22020096 \
+            -e UNSAFE_CORS=true \
+            -p 1317:1317 \
+            -p 26656:26656 \
+            -p 26657:26657 \
+            ghcr.io/cosmoscontracts/juno:v9.0.0 /opt/setup_and_run.sh $ADMIN_ADDR
+
+      - name: Let Juno catch up
+        run: sleep 30
+
+      - name: Restore optimized contracts
+        uses: actions/download-artifact@v3
+        with:
+          name: dao-dao-contract-artifacts-${{ github.event.number }}
+          path: ci/integration_tests/artifacts
+
+      - name: Download smart contract dependencies
+        run: |
+          wget https://github.com/CosmWasm/cw-plus/releases/download/v0.11.1/cw20_base.wasm \
+            -O ci/integration_tests/artifacts/cw20_base.wasm
+          wget https://github.com/CosmWasm/cw-plus/releases/download/v0.11.1/cw4_group.wasm \
+            -O ci/integration_tests/artifacts/cw4_group.wasm
+
+      - name: Rust Dependencies Cache
+        uses: actions/cache@v3
+        with:
+          path: |
+            ~/.cargo/bin/
+            ~/.cargo/registry/index/
+            ~/.cargo/registry/cache/
+            ~/.cargo/git/db/
+            target/
+          key: ${{ runner.os }}-cargo-integration-${{ hashFiles('ci/integration_tests/Cargo.lock') }}
+
+      - name: Run Integration Tests
+        run: cd ci/integration_tests/ && cargo t
+
+      - name: Combine Test Gas Reports
+        run: cd ci/integration_tests/ && jq -rs 'reduce .[] as $item ({}; . * $item)' gas_reports/*.json > gas_report.json
+
+      - name: Raw Gas Report
+        run: cat ci/integration_tests/gas_report.json
+
+      - name: Set GIT_BRANCH
+        run: echo "GIT_BRANCH=$(echo ${{ github.ref }} | sed 's|/|-|g')" >> $GITHUB_ENV
+
+      - name: Upload Gas Report
+        uses: actions/upload-artifact@v3
+        with:
+          name: dao-dao-gas-report-${{ env.GIT_BRANCH }}
+          path: ci/integration_tests/gas_report.json
+          retention-days: 90
+
+      # TODO: Download main's gas_report artifact and diff
diff --git a/ci/integration_tests/.cargo/config b/ci/integration_tests/.cargo/config
new file mode 100644
index 00000000..2c55b254
--- /dev/null
+++ b/ci/integration_tests/.cargo/config
@@ -0,0 +1,3 @@
+[alias]
+c = "check --tests"
+t = "test -- --test-threads 1"
\ No newline at end of file
diff --git a/ci/integration_tests/Cargo.lock b/ci/integration_tests/Cargo.lock
new file mode 100644
index 00000000..caa29a35
--- /dev/null
+++ b/ci/integration_tests/Cargo.lock
@@ -0,0 +1,1577 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "addr2line"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "ahash"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
+dependencies = [
+ "getrandom 0.2.7",
+ "once_cell",
+ "version_check",
+]
+
+[[package]]
+name = "aho-corasick"
+version = "0.7.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.58"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704"
+
+[[package]]
+name = "async-trait"
+version = "0.1.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "backtrace"
+version = "0.3.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7"
+dependencies = [
+ "addr2line",
+ "cc",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+]
+
+[[package]]
+name = "base16ct"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce"
+
+[[package]]
+name = "base64"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
+
+[[package]]
+name = "base64ct"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3bdca834647821e0b13d9539a8634eb62d3501b6b6c2cec1722786ee6671b851"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "block-buffer"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
+dependencies = [
+ "block-padding",
+ "byte-tools",
+ "byteorder",
+ "generic-array 0.12.4",
+]
+
+[[package]]
+name = "block-buffer"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
+dependencies = [
+ "generic-array 0.14.5",
+]
+
+[[package]]
+name = "block-padding"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
+dependencies = [
+ "byte-tools",
+]
+
+[[package]]
+name = "byte-tools"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "cc"
+version = "1.0.73"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "config"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ea917b74b6edfb5024e3b55d3c8f710b5f4ed92646429601a42e96f0812b31b"
+dependencies = [
+ "async-trait",
+ "json5",
+ "lazy_static",
+ "nom",
+ "pathdiff",
+ "ron",
+ "rust-ini",
+ "serde",
+ "serde_json",
+ "toml",
+ "yaml-rust",
+]
+
+[[package]]
+name = "const-oid"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3"
+
+[[package]]
+name = "cosm-orc"
+version = "0.5.8"
+dependencies = [
+ "anyhow",
+ "backtrace",
+ "config",
+ "log",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "cosmwasm-crypto"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5eb0afef2325df81aadbf9be1233f522ed8f6e91df870c764bc44cca2b1415bd"
+dependencies = [
+ "digest 0.9.0",
+ "ed25519-zebra",
+ "k256",
+ "rand_core 0.6.3",
+ "thiserror",
+]
+
+[[package]]
+name = "cosmwasm-derive"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b36e527620a2a3e00e46b6e731ab6c9b68d11069c986f7d7be8eba79ef081a4"
+dependencies = [
+ "syn",
+]
+
+[[package]]
+name = "cosmwasm-std"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "875994993c2082a6fcd406937bf0fca21c349e4a624f3810253a14fa83a3a195"
+dependencies = [
+ "base64",
+ "cosmwasm-crypto",
+ "cosmwasm-derive",
+ "forward_ref",
+ "schemars",
+ "serde",
+ "serde-json-wasm",
+ "thiserror",
+ "uint",
+]
+
+[[package]]
+name = "cosmwasm-storage"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d18403b07304d15d304dad11040d45bbcaf78d603b4be3fb5e2685c16f9229b5"
+dependencies = [
+ "cosmwasm-std",
+ "serde",
+]
+
+[[package]]
+name = "cpufeatures"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crunchy"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
+
+[[package]]
+name = "crypto-bigint"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21"
+dependencies = [
+ "generic-array 0.14.5",
+ "rand_core 0.6.3",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "crypto-mac"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714"
+dependencies = [
+ "generic-array 0.14.5",
+ "subtle",
+]
+
+[[package]]
+name = "ctor"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c"
+dependencies = [
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "curve25519-dalek"
+version = "3.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0"
+dependencies = [
+ "byteorder",
+ "digest 0.9.0",
+ "rand_core 0.5.1",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "cw-controllers"
+version = "0.13.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4f0bc6019b4d3d81e11f5c384bcce7173e2210bd654d75c6c9668e12cca05dfa"
+dependencies = [
+ "cosmwasm-std",
+ "cw-storage-plus 0.13.4",
+ "cw-utils 0.13.4",
+ "schemars",
+ "serde",
+ "thiserror",
+]
+
+[[package]]
+name = "cw-core"
+version = "0.1.0"
+dependencies = [
+ "cosmwasm-std",
+ "cosmwasm-storage",
+ "cw-core-interface",
+ "cw-core-macros",
+ "cw-paginate",
+ "cw-storage-plus 0.13.4",
+ "cw-utils 0.13.4",
+ "cw2",
+ "cw20 0.13.4",
+ "cw721",
+ "schemars",
+ "serde",
+ "thiserror",
+]
+
+[[package]]
+name = "cw-core-interface"
+version = "0.1.0"
+dependencies = [
+ "cosmwasm-std",
+ "cw-core-macros",
+ "cw2",
+ "schemars",
+ "serde",
+]
+
+[[package]]
+name = "cw-core-macros"
+version = "0.1.0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "cw-paginate"
+version = "0.1.0"
+dependencies = [
+ "cosmwasm-std",
+ "cosmwasm-storage",
+ "cw-storage-plus 0.13.4",
+ "serde",
+]
+
+[[package]]
+name = "cw-proposal-single"
+version = "0.1.0"
+dependencies = [
+ "cosmwasm-std",
+ "cosmwasm-storage",
+ "cw-core",
+ "cw-core-interface",
+ "cw-core-macros",
+ "cw-storage-plus 0.13.4",
+ "cw-utils 0.13.4",
+ "cw2",
+ "cw20 0.13.4",
+ "cw3",
+ "indexable-hooks",
+ "proposal-hooks",
+ "schemars",
+ "serde",
+ "thiserror",
+ "vote-hooks",
+ "voting",
+]
+
+[[package]]
+name = "cw-storage-plus"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c087ff98fb0475db4c2b5298a5fd12b2848d2854b39d1115d930ee6da24d1eed"
+dependencies = [
+ "cosmwasm-std",
+ "schemars",
+ "serde",
+]
+
+[[package]]
+name = "cw-storage-plus"
+version = "0.13.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "648b1507290bbc03a8d88463d7cd9b04b1fa0155e5eef366c4fa052b9caaac7a"
+dependencies = [
+ "cosmwasm-std",
+ "schemars",
+ "serde",
+]
+
+[[package]]
+name = "cw-utils"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3396c7aff5a0e3fb6dcc6cc89f56862c1d212b40d93ed725a6962955b1887ff"
+dependencies = [
+ "cosmwasm-std",
+ "schemars",
+ "serde",
+ "thiserror",
+]
+
+[[package]]
+name = "cw-utils"
+version = "0.13.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9dbaecb78c8e8abfd6b4258c7f4fbeb5c49a5e45ee4d910d3240ee8e1d714e1b"
+dependencies = [
+ "cosmwasm-std",
+ "schemars",
+ "serde",
+ "thiserror",
+]
+
+[[package]]
+name = "cw2"
+version = "0.13.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04cf4639517490dd36b333bbd6c4fbd92e325fd0acf4683b41753bc5eb63bfc1"
+dependencies = [
+ "cosmwasm-std",
+ "cw-storage-plus 0.13.4",
+ "schemars",
+ "serde",
+]
+
+[[package]]
+name = "cw20"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "413911037f6b0106ae37ca82352f9131939ccc995aade435df47a5baf2c815f2"
+dependencies = [
+ "cosmwasm-std",
+ "cw-utils 0.12.1",
+ "schemars",
+ "serde",
+]
+
+[[package]]
+name = "cw20"
+version = "0.13.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cb782b8f110819a4eb5dbbcfed25ffba49ec16bbe32b4ad8da50a5ce68fec05"
+dependencies = [
+ "cosmwasm-std",
+ "cw-utils 0.13.4",
+ "schemars",
+ "serde",
+]
+
+[[package]]
+name = "cw20-base"
+version = "0.13.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0306e606581f4fb45e82bcbb7f0333179ed53dd949c6523f01a99b4bfc1475a0"
+dependencies = [
+ "cosmwasm-std",
+ "cw-storage-plus 0.13.4",
+ "cw-utils 0.13.4",
+ "cw2",
+ "cw20 0.13.4",
+ "schemars",
+ "serde",
+ "thiserror",
+]
+
+[[package]]
+name = "cw20-stake"
+version = "0.2.6"
+dependencies = [
+ "cosmwasm-std",
+ "cosmwasm-storage",
+ "cw-controllers",
+ "cw-storage-plus 0.13.4",
+ "cw-utils 0.13.4",
+ "cw2",
+ "cw20 0.13.4",
+ "cw20-base",
+ "schemars",
+ "serde",
+ "thiserror",
+]
+
+[[package]]
+name = "cw20-staked-balance-voting"
+version = "0.1.0"
+dependencies = [
+ "cosmwasm-std",
+ "cosmwasm-storage",
+ "cw-core-interface",
+ "cw-core-macros",
+ "cw-storage-plus 0.13.4",
+ "cw-utils 0.13.4",
+ "cw2",
+ "cw20 0.13.4",
+ "cw20-base",
+ "cw20-stake",
+ "schemars",
+ "serde",
+ "thiserror",
+]
+
+[[package]]
+name = "cw3"
+version = "0.13.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe19462a7f644ba60c19d3443cb90d00c50d9b6b3b0a3a7fca93df8261af979b"
+dependencies = [
+ "cosmwasm-std",
+ "cw-utils 0.13.4",
+ "schemars",
+ "serde",
+]
+
+[[package]]
+name = "cw721"
+version = "0.13.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "035818368a74c07dd9ed5c5a93340199ba251530162010b9f34c3809e3b97df1"
+dependencies = [
+ "cosmwasm-std",
+ "cw-utils 0.13.4",
+ "schemars",
+ "serde",
+]
+
+[[package]]
+name = "der"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c"
+dependencies = [
+ "const-oid",
+]
+
+[[package]]
+name = "digest"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
+dependencies = [
+ "generic-array 0.12.4",
+]
+
+[[package]]
+name = "digest"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
+dependencies = [
+ "generic-array 0.14.5",
+]
+
+[[package]]
+name = "dlv-list"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257"
+
+[[package]]
+name = "dyn-clone"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d07a982d1fb29db01e5a59b1918e03da4df7297eaeee7686ac45542fd4e59c8"
+
+[[package]]
+name = "ecdsa"
+version = "0.13.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9"
+dependencies = [
+ "der",
+ "elliptic-curve",
+ "rfc6979",
+ "signature",
+]
+
+[[package]]
+name = "ed25519-zebra"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "403ef3e961ab98f0ba902771d29f842058578bb1ce7e3c59dad5a6a93e784c69"
+dependencies = [
+ "curve25519-dalek",
+ "hex",
+ "rand_core 0.6.3",
+ "serde",
+ "sha2",
+ "thiserror",
+ "zeroize",
+]
+
+[[package]]
+name = "elliptic-curve"
+version = "0.11.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6"
+dependencies = [
+ "base16ct",
+ "crypto-bigint",
+ "der",
+ "ff",
+ "generic-array 0.14.5",
+ "group",
+ "rand_core 0.6.3",
+ "sec1",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
+dependencies = [
+ "atty",
+ "humantime",
+ "log",
+ "regex",
+ "termcolor",
+]
+
+[[package]]
+name = "fake-simd"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
+
+[[package]]
+name = "ff"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "131655483be284720a17d74ff97592b8e76576dc25563148601df2d7c9080924"
+dependencies = [
+ "rand_core 0.6.3",
+ "subtle",
+]
+
+[[package]]
+name = "forward_ref"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e"
+
+[[package]]
+name = "futures"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
+
+[[package]]
+name = "futures-executor"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-io"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
+
+[[package]]
+name = "futures-macro"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
+
+[[package]]
+name = "futures-task"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
+
+[[package]]
+name = "futures-util"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-macro",
+ "futures-sink",
+ "futures-task",
+ "memchr",
+ "pin-project-lite",
+ "pin-utils",
+ "slab",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
+dependencies = [
+ "typenum",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi 0.9.0+wasi-snapshot-preview1",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+]
+
+[[package]]
+name = "gimli"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
+
+[[package]]
+name = "group"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89"
+dependencies = [
+ "ff",
+ "rand_core 0.6.3",
+ "subtle",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+dependencies = [
+ "ahash",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
+name = "hmac"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
+dependencies = [
+ "crypto-mac",
+ "digest 0.9.0",
+]
+
+[[package]]
+name = "humantime"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+
+[[package]]
+name = "indexable-hooks"
+version = "0.1.0"
+dependencies = [
+ "cosmwasm-std",
+ "cw-storage-plus 0.13.4",
+ "schemars",
+ "serde",
+ "thiserror",
+]
+
+[[package]]
+name = "integration_tests"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "cosm-orc",
+ "cosmwasm-std",
+ "ctor",
+ "cw-core",
+ "cw-core-interface",
+ "cw-proposal-single",
+ "cw-utils 0.13.4",
+ "cw20 0.13.4",
+ "cw20-base",
+ "cw20-stake",
+ "cw20-staked-balance-voting",
+ "env_logger",
+ "once_cell",
+ "rand",
+ "serde",
+ "serde_json",
+ "test-context",
+ "voting",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
+
+[[package]]
+name = "json5"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1"
+dependencies = [
+ "pest",
+ "pest_derive",
+ "serde",
+]
+
+[[package]]
+name = "k256"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d"
+dependencies = [
+ "cfg-if",
+ "ecdsa",
+ "elliptic-curve",
+ "sec1",
+ "sha2",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.126"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
+
+[[package]]
+name = "linked-hash-map"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
+
+[[package]]
+name = "log"
+version = "0.4.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "maplit"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
+
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "nom"
+version = "7.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
+[[package]]
+name = "object"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
+
+[[package]]
+name = "opaque-debug"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
+
+[[package]]
+name = "opaque-debug"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
+
+[[package]]
+name = "ordered-multimap"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a"
+dependencies = [
+ "dlv-list",
+ "hashbrown",
+]
+
+[[package]]
+name = "pathdiff"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
+
+[[package]]
+name = "pest"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
+dependencies = [
+ "ucd-trie",
+]
+
+[[package]]
+name = "pest_derive"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
+dependencies = [
+ "pest",
+ "pest_generator",
+]
+
+[[package]]
+name = "pest_generator"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
+dependencies = [
+ "pest",
+ "pest_meta",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "pest_meta"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
+dependencies = [
+ "maplit",
+ "pest",
+ "sha-1",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "pkcs8"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0"
+dependencies = [
+ "der",
+ "spki",
+ "zeroize",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c278e965f1d8cf32d6e0e96de3d3e79712178ae67986d9cf9151f51e95aac89b"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "proposal-hooks"
+version = "0.1.0"
+dependencies = [
+ "cosmwasm-std",
+ "indexable-hooks",
+ "schemars",
+ "serde",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core 0.6.3",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.6.3",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+dependencies = [
+ "getrandom 0.1.16",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
+dependencies = [
+ "getrandom 0.2.7",
+]
+
+[[package]]
+name = "regex"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
+
+[[package]]
+name = "rfc6979"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525"
+dependencies = [
+ "crypto-bigint",
+ "hmac",
+ "zeroize",
+]
+
+[[package]]
+name = "ron"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a"
+dependencies = [
+ "base64",
+ "bitflags",
+ "serde",
+]
+
+[[package]]
+name = "rust-ini"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df"
+dependencies = [
+ "cfg-if",
+ "ordered-multimap",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
+
+[[package]]
+name = "ryu"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
+
+[[package]]
+name = "schemars"
+version = "0.8.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1847b767a3d62d95cbf3d8a9f0e421cf57a0d8aa4f411d4b16525afb0284d4ed"
+dependencies = [
+ "dyn-clone",
+ "schemars_derive",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "schemars_derive"
+version = "0.8.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af4d7e1b012cb3d9129567661a63755ea4b8a7386d339dc945ae187e403c6743"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "serde_derive_internals",
+ "syn",
+]
+
+[[package]]
+name = "sec1"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1"
+dependencies = [
+ "der",
+ "generic-array 0.14.5",
+ "pkcs8",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.140"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03"
+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_derive"
+version = "1.0.140"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f2122636b9fe3b81f1cb25099fcf2d3f542cdb1d45940d56c713158884a05da"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_derive_internals"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.82"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "sha-1"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
+dependencies = [
+ "block-buffer 0.7.3",
+ "digest 0.8.1",
+ "fake-simd",
+ "opaque-debug 0.2.3",
+]
+
+[[package]]
+name = "sha2"
+version = "0.9.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
+dependencies = [
+ "block-buffer 0.9.0",
+ "cfg-if",
+ "cpufeatures",
+ "digest 0.9.0",
+ "opaque-debug 0.3.0",
+]
+
+[[package]]
+name = "signature"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788"
+dependencies = [
+ "digest 0.9.0",
+ "rand_core 0.6.3",
+]
+
+[[package]]
+name = "slab"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "spki"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27"
+dependencies = [
+ "base64ct",
+ "der",
+]
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "subtle"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
+
+[[package]]
+name = "syn"
+version = "1.0.98"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "termcolor"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "test-context"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "055831a02a4f5aa28fede67f2902014273eb8c21b958ac5ebbd59b71ef30dbc3"
+dependencies = [
+ "async-trait",
+ "futures",
+ "test-context-macros",
+]
+
+[[package]]
+name = "test-context-macros"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8901a55b0a7a06ebc4a674dcca925170da8e613fa3b163a1df804ed10afb154d"
+dependencies = [
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "toml"
+version = "0.5.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "typenum"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
+
+[[package]]
+name = "ucd-trie"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89570599c4fe5585de2b388aab47e99f7fa4e9238a1399f707a02e356058141c"
+
+[[package]]
+name = "uint"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12f03af7ccf01dd611cc450a0d10dbc9b745770d096473e2faf0ca6e2d66d1e0"
+dependencies = [
+ "byteorder",
+ "crunchy",
+ "hex",
+ "static_assertions",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7"
+
+[[package]]
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+
+[[package]]
+name = "vote-hooks"
+version = "0.1.0"
+dependencies = [
+ "cosmwasm-std",
+ "indexable-hooks",
+ "schemars",
+ "serde",
+]
+
+[[package]]
+name = "voting"
+version = "0.1.0"
+dependencies = [
+ "cosmwasm-std",
+ "cw-core",
+ "cw-core-interface",
+ "cw-storage-plus 0.12.1",
+ "cw-utils 0.13.4",
+ "cw20 0.12.1",
+ "schemars",
+ "serde",
+ "thiserror",
+]
+
+[[package]]
+name = "wasi"
+version = "0.9.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "yaml-rust"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
+dependencies = [
+ "linked-hash-map",
+]
+
+[[package]]
+name = "zeroize"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd"
diff --git a/ci/integration_tests/Cargo.toml b/ci/integration_tests/Cargo.toml
new file mode 100644
index 00000000..b99abf9a
--- /dev/null
+++ b/ci/integration_tests/Cargo.toml
@@ -0,0 +1,33 @@
+[package]
+name = "integration_tests"
+version = "0.1.0"
+edition = "2021"
+
+# This crate depends on rand. These are not features in
+# wasm builds of cosmwasm. Despite this crate only being used as a dev
+# dependency, because it is part of the workspace it will always be
+# compiled. There is no good way to remove a member from a workspace
+# conditionally. As such, we don't compile anything here if we're
+# targeting wasm.
+[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
+cosm-orc = { version = "1.3.2" }
+cw20 = "0.13"
+cw20-base = "0.13"
+cw-utils = "0.13"
+cosmwasm-std = { version = "1.0.0", features = ["ibc3"] }
+cw-core = { version = "0.1.0", path = "../../contracts/cw-core" }
+cw20-stake = { version = "*", path = "../../contracts/cw20-stake" }
+cw20-staked-balance-voting = { version = "0.1.0", path = "../../contracts/cw20-staked-balance-voting" }
+cw-proposal-single = { version = "0.1.0", path = "../../contracts/cw-proposal-single" }
+cw-core-interface = { version = "0.1.0", path = "../../packages/cw-core-interface" }
+voting = { version = "*", path = "../../packages/voting" }
+
+assert_matches = "1.5"
+anyhow = { version = "1.0.51"}
+serde = { version = "1.0", default-features = false, features = ["derive"] }
+serde_json = "1.0"
+once_cell = "1.13.0"
+env_logger = "0.9.0"
+test-context = "0.1.4"
+ctor = "0.1.22"
+rand = "0.8.5"
diff --git a/ci/integration_tests/README.md b/ci/integration_tests/README.md
new file mode 100644
index 00000000..10dbf6a6
--- /dev/null
+++ b/ci/integration_tests/README.md
@@ -0,0 +1,68 @@
+# Dao Dao Integration Tests
+
+Dao Dao e2e integration tests with gas profiling.
+
+`cd ci/integration_tests && cargo t` to run all tests.
+
+`cargo t fn_test_name` to run individual integration tests.
+
+## Running Locally
+
+### Hitting Local Juno
+
+* `./scripts/deploy_local.sh juno10j9gpw9t4jsz47qgnkvl5n3zlm2fz72k67rxsg`
+* `cd ci/integration_tests`
+* `CONTRACT_DIR="../../artifacts" GAS_OUT_DIR="gas_reports" CONFIG="configs/local.yaml" cargo t`
+
+### Hitting Testnet
+
+* `cd ci/integration_tests`
+* Change `src/helpers/chain.rs::test_account()` with your testnet account
+* `CONTRACT_DIR="../../artifacts" GAS_OUT_DIR="gas_reports" CONFIG="configs/testnet.yaml" cargo t`
+
+
+### Skipping Contract Storage
+
+By default all of the smart contracts are stored on-chain once before all of the tests are run. 
+This is time consuming when writing tests. If you want to skip this step you can use the `SKIP_CONTRACT_STORE=true` flag like so:
+
+`SKIP_CONTRACT_STORE=true GAS_OUT_DIR="gas_reports" CONFIG="configs/local.yaml" cargo t`
+
+This requires the `code ids` stored in [`configs/local.yaml`](configs/local.yaml) to be set to the correct, up to date value.
+For now you can see the output from `scripts/deploy_local.sh` and manually copy them over.
+These values change as contracts are added, so this is likely out of date, and a more robust solution for this is needed.
+
+
+## Adding New Integration Tests
+
+Add new tests in `src/tests`:
+```rust
+#[test_context(Chain)]
+#[test]
+fn new_dao_has_no_items(chain: &mut Chain) {
+    let res = create_dao(
+        chain, 
+        Some(chain.user.addr.clone()),
+        "ex_create_dao", 
+       chain.user.addr.clone()
+    );
+    let dao = res.unwrap();
+
+    // use the native rust types to interact with the contract
+     let res = chain
+        .orc
+        .query(
+            "cw_core",
+            "exc_items_get",
+            &cw_core::msg::QueryMsg::GetItem {
+                key: "meme".to_string(),
+            },
+        )
+        .unwrap();
+    let res: GetItemResponse = res.data().unwrap();
+
+    assert_eq!(res.item, None);
+}
+```
+
+Run `cargo c` to compile the tests.
diff --git a/ci/integration_tests/configs/ci.yaml b/ci/integration_tests/configs/ci.yaml
new file mode 100644
index 00000000..2cc4c6a1
--- /dev/null
+++ b/ci/integration_tests/configs/ci.yaml
@@ -0,0 +1,7 @@
+chain_cfg: 
+  denom: "ujunox"
+  prefix: "juno"
+  chain_id: "testing"
+  rpc_endpoint: "http://localhost:26657/"
+  gas_prices: 0.1
+  gas_adjustment: 1.5
diff --git a/ci/integration_tests/configs/local.yaml b/ci/integration_tests/configs/local.yaml
new file mode 100644
index 00000000..3a3f01e9
--- /dev/null
+++ b/ci/integration_tests/configs/local.yaml
@@ -0,0 +1,20 @@
+chain_cfg: 
+  denom: "ujunox"
+  prefix: "juno"
+  chain_id: "testing"
+  rpc_endpoint: "http://localhost:26657/"
+  gas_prices: 0.1
+  gas_adjustment: 1.5
+
+# Add code ids if you dont need to store them:
+code_ids:
+  "cw20_base": 1
+  "cw4_group": 2
+  # NOTE: If you are using `SKIP_CONTRACT_STORE` you will need to put the up-to-date
+  # code ids for the contracts you need here.
+  # Something like this:
+  # "cw_core": 9
+  # "cw_proposal_single": 14
+  # "cw4_voting": 6
+  # "cw20_staked_balance_voting": 5
+  # "cw20_stake": 4
\ No newline at end of file
diff --git a/ci/integration_tests/configs/testnet.yaml b/ci/integration_tests/configs/testnet.yaml
new file mode 100644
index 00000000..dd6c1089
--- /dev/null
+++ b/ci/integration_tests/configs/testnet.yaml
@@ -0,0 +1,12 @@
+chain_cfg: 
+  denom: "ujunox"
+  prefix: "juno"
+  chain_id: "uni-3"
+  rpc_endpoint: "https://rpc.uni.juno.deuslabs.fi:443"
+  gas_prices: 0.1
+  gas_adjustment: 1.5
+
+# Add code ids if you dont need to store them:
+code_ids:
+  "cw20_base": 77
+  "cw4_group": 78
\ No newline at end of file
diff --git a/ci/integration_tests/src/helpers/chain.rs b/ci/integration_tests/src/helpers/chain.rs
new file mode 100644
index 00000000..f5a60b63
--- /dev/null
+++ b/ci/integration_tests/src/helpers/chain.rs
@@ -0,0 +1,117 @@
+use cosm_orc::config::key::Key;
+use cosm_orc::orchestrator::cosm_orc::CosmOrc;
+use cosm_orc::{
+    config::cfg::Config, config::key::SigningKey, profilers::gas_profiler::GasProfiler,
+};
+use ctor::ctor;
+use once_cell::sync::OnceCell;
+use rand::Rng;
+use serde_json::Value;
+use std::env;
+use std::fs;
+use std::path::Path;
+use test_context::TestContext;
+
+static CONFIG: OnceCell<Cfg> = OnceCell::new();
+
+#[derive(Debug)]
+pub struct Cfg {
+    cfg: Config,
+    gas_report_dir: String,
+}
+
+pub struct Chain {
+    pub cfg: Config,
+    pub orc: CosmOrc,
+    pub user: Account,
+}
+
+pub struct Account {
+    pub addr: String,
+    pub key: SigningKey,
+}
+
+// NOTE: we have to run the integration tests in one thread right now.
+// We get `account sequence mismatch` CosmosSDK error when we run in parallel.
+// We could either serialize the `account.sequence` per key, or use a different key per test.
+
+impl TestContext for Chain {
+    fn setup() -> Self {
+        let cfg = CONFIG.get().unwrap().cfg.clone();
+        let orc = CosmOrc::new(cfg.clone())
+            .unwrap()
+            .add_profiler(Box::new(GasProfiler::new()));
+
+        let user = test_account(&cfg.chain_cfg.prefix);
+
+        Self { cfg, orc, user }
+    }
+
+    fn teardown(self) {
+        let cfg = CONFIG.get().unwrap();
+        save_gas_report(&self.orc, &cfg.gas_report_dir);
+    }
+}
+
+fn test_account(prefix: &str) -> Account {
+    // TODO: Make this configurable + bootstrap the local env with many test accounts
+    let key = SigningKey {
+        name: "localval".to_string(),
+        key: Key::Mnemonic("siren window salt bullet cream letter huge satoshi fade shiver permit offer happy immense wage fitness goose usual aim hammer clap about super trend".to_string()),
+    };
+    let addr = key.to_account(prefix).unwrap().to_string();
+
+    Account { addr, key }
+}
+
+// global_setup() runs once before anything else
+#[ctor]
+fn global_setup() {
+    env_logger::init();
+    let config = env::var("CONFIG").expect("missing yaml CONFIG env var");
+    let gas_report_dir = env::var("GAS_OUT_DIR").expect("missing GAS_OUT_DIR env var");
+
+    let mut cfg = Config::from_yaml(&config).unwrap();
+    let mut orc = CosmOrc::new(cfg.clone())
+        .unwrap()
+        .add_profiler(Box::new(GasProfiler::new()));
+
+    let account = test_account(&cfg.chain_cfg.prefix);
+
+    let skip_storage = env::var("SKIP_CONTRACT_STORE").unwrap_or_else(|_| "false".to_string());
+    if !skip_storage.parse::<bool>().unwrap() {
+        let contract_dir = env::var("CONTRACT_DIR").expect("missing CONTRACT_DIR env var");
+        orc.store_contracts(&contract_dir, &account.key).unwrap();
+        save_gas_report(&orc, &gas_report_dir);
+        // persist stored code_ids in CONFIG, so we can reuse for all tests
+        cfg.code_ids = orc
+            .contract_map
+            .deploy_info()
+            .iter()
+            .map(|(k, v)| (k.clone(), v.code_id))
+            .collect();
+    }
+
+    let config = Cfg {
+        cfg,
+        gas_report_dir,
+    };
+    CONFIG.set(config).expect("error initializing Config");
+}
+
+fn save_gas_report(orc: &CosmOrc, gas_report_dir: &str) {
+    let reports = orc
+        .profiler_reports()
+        .expect("error fetching profile reports");
+
+    let j: Value = serde_json::from_slice(&reports[0].json_data).unwrap();
+
+    let p = Path::new(gas_report_dir);
+    if !p.exists() {
+        fs::create_dir(p).unwrap();
+    }
+
+    let mut rng = rand::thread_rng();
+    let file_name = format!("test-{}.json", rng.gen::<u32>());
+    fs::write(p.join(file_name), j.to_string()).unwrap();
+}
diff --git a/ci/integration_tests/src/helpers/helper.rs b/ci/integration_tests/src/helpers/helper.rs
new file mode 100644
index 00000000..ece3a0a6
--- /dev/null
+++ b/ci/integration_tests/src/helpers/helper.rs
@@ -0,0 +1,96 @@
+use super::chain::Chain;
+use anyhow::Result;
+use cosmwasm_std::{to_binary, Decimal, Uint128};
+use cw20::Cw20Coin;
+use cw_core::{
+    msg::{Admin, ModuleInstantiateInfo},
+    query::DumpStateResponse,
+};
+use cw_utils::Duration;
+use voting::{
+    deposit::DepositInfo, deposit::DepositToken, threshold::PercentageThreshold,
+    threshold::Threshold,
+};
+
+#[derive(Debug)]
+pub struct DaoState {
+    pub addr: String,
+    pub state: DumpStateResponse,
+}
+
+pub fn create_dao(
+    chain: &mut Chain,
+    admin: Option<String>,
+    op_name: &str,
+    user_addr: String,
+) -> Result<DaoState> {
+    let msg = cw_core::msg::InstantiateMsg {
+        admin,
+        name: "DAO DAO".to_string(),
+        description: "A DAO that makes DAO tooling".to_string(),
+        image_url: None,
+        automatically_add_cw20s: false,
+        automatically_add_cw721s: false,
+        voting_module_instantiate_info: ModuleInstantiateInfo {
+            code_id: chain
+                .orc
+                .contract_map
+                .code_id("cw20_staked_balance_voting")?,
+            msg: to_binary(&cw20_staked_balance_voting::msg::InstantiateMsg {
+                token_info: cw20_staked_balance_voting::msg::TokenInfo::New {
+                    code_id: chain.orc.contract_map.code_id("cw20_base")?,
+                    label: "DAO DAO Gov token".to_string(),
+                    name: "DAO".to_string(),
+                    symbol: "DAO".to_string(),
+                    decimals: 6,
+                    initial_balances: vec![Cw20Coin {
+                        address: user_addr,
+                        amount: Uint128::new(100_000_000),
+                    }],
+                    marketing: None,
+                    staking_code_id: chain.orc.contract_map.code_id("cw20_stake")?,
+                    unstaking_duration: Some(Duration::Time(1209600)),
+                    initial_dao_balance: None,
+                },
+                active_threshold: None,
+            })?,
+            admin: Admin::CoreContract {},
+            label: "DAO DAO Voting Module".to_string(),
+        },
+        proposal_modules_instantiate_info: vec![ModuleInstantiateInfo {
+            code_id: chain.orc.contract_map.code_id("cw_proposal_single")?,
+            msg: to_binary(&cw_proposal_single::msg::InstantiateMsg {
+                min_voting_period: None,
+                threshold: Threshold::ThresholdQuorum {
+                    threshold: PercentageThreshold::Majority {},
+                    quorum: PercentageThreshold::Percent(Decimal::percent(35)),
+                },
+                max_voting_period: Duration::Time(432000),
+                allow_revoting: false,
+                only_members_execute: true,
+                deposit_info: Some(DepositInfo {
+                    token: DepositToken::VotingModuleToken {},
+                    deposit: Uint128::new(1000000000),
+                    refund_failed_proposals: true,
+                }),
+                close_proposal_on_execution_failure: false,
+            })?,
+            admin: Admin::CoreContract {},
+            label: "DAO DAO Proposal Module".to_string(),
+        }],
+        initial_items: None,
+    };
+
+    chain
+        .orc
+        .instantiate("cw_core", op_name, &msg, &chain.user.key)?;
+
+    let res = chain
+        .orc
+        .query("cw_core", op_name, &cw_core::msg::QueryMsg::DumpState {})?;
+
+    Ok(DaoState {
+        addr: chain.orc.contract_map.address("cw_core")?,
+        state: res.data()?,
+    })
+}
diff --git a/ci/integration_tests/src/helpers/mod.rs b/ci/integration_tests/src/helpers/mod.rs
new file mode 100644
index 00000000..5cc5aff6
--- /dev/null
+++ b/ci/integration_tests/src/helpers/mod.rs
@@ -0,0 +1,3 @@
+pub mod helper;
+
+pub mod chain;
diff --git a/ci/integration_tests/src/lib.rs b/ci/integration_tests/src/lib.rs
new file mode 100644
index 00000000..3d559812
--- /dev/null
+++ b/ci/integration_tests/src/lib.rs
@@ -0,0 +1,7 @@
+#![allow(dead_code)]
+
+#[cfg(not(target_arch = "wasm32"))]
+mod tests;
+
+#[cfg(not(target_arch = "wasm32"))]
+mod helpers;
diff --git a/ci/integration_tests/src/tests/cw20_stake_test.rs b/ci/integration_tests/src/tests/cw20_stake_test.rs
new file mode 100644
index 00000000..4d2ecc93
--- /dev/null
+++ b/ci/integration_tests/src/tests/cw20_stake_test.rs
@@ -0,0 +1,118 @@
+use core::time;
+use std::thread;
+
+use crate::helpers::{chain::Chain, helper::create_dao};
+use cosmwasm_std::{to_binary, Uint128};
+use cw20_stake::{msg::StakedValueResponse, state::Config};
+use cw_core_interface::voting::VotingPowerAtHeightResponse;
+use test_context::test_context;
+
+// #### ExecuteMsg #####
+
+#[test_context(Chain)]
+#[test]
+fn execute_stake_tokens(chain: &mut Chain) {
+    let voting_contract = "cw20_staked_balance_voting";
+
+    let res = create_dao(chain, None, "exc_stake_create_dao", chain.user.addr.clone());
+    let dao = res.unwrap();
+
+    let voting_addr = dao.state.voting_module.as_str();
+
+    // stake dao tokens:
+    chain
+        .orc
+        .contract_map
+        .add_address(voting_contract, voting_addr)
+        .unwrap();
+    let staking_addr: String = chain
+        .orc
+        .query(
+            voting_contract,
+            "exc_stake_q_stake",
+            &cw20_staked_balance_voting::msg::QueryMsg::StakingContract {},
+        )
+        .unwrap()
+        .data()
+        .unwrap();
+
+    chain
+        .orc
+        .contract_map
+        .add_address("cw20_stake", staking_addr.to_string())
+        .unwrap();
+    let res = chain
+        .orc
+        .query(
+            "cw20_stake",
+            "exc_stake_q_staked_value",
+            &cw20_stake::msg::QueryMsg::StakedValue {
+                address: chain.user.addr.clone(),
+            },
+        )
+        .unwrap();
+    let staked_value: StakedValueResponse = res.data().unwrap();
+
+    assert_eq!(staked_value.value, Uint128::new(0));
+
+    let res = chain
+        .orc
+        .query(
+            "cw20_stake",
+            "exc_stake_q_cfg",
+            &cw20_stake::msg::QueryMsg::GetConfig {},
+        )
+        .unwrap();
+    let config: Config = res.data().unwrap();
+
+    chain
+        .orc
+        .contract_map
+        .add_address("cw20_base", config.token_address.as_str())
+        .unwrap();
+    chain
+        .orc
+        .execute(
+            "cw20_base",
+            "exc_stake_stake_tokens",
+            &cw20_base::msg::ExecuteMsg::Send {
+                contract: staking_addr,
+                amount: Uint128::new(100),
+                msg: to_binary(&cw20_stake::msg::ReceiveMsg::Stake {}).unwrap(),
+            },
+            &chain.user.key,
+        )
+        .unwrap();
+
+    let res = chain
+        .orc
+        .query(
+            "cw20_stake",
+            "exc_stake_q_stake",
+            &cw20_stake::msg::QueryMsg::StakedValue {
+                address: chain.user.addr.clone(),
+            },
+        )
+        .unwrap();
+    let staked_value: StakedValueResponse = res.data().unwrap();
+
+    assert_eq!(staked_value.value, Uint128::new(100));
+
+    // Sleep to let staking block process, so we have voting power:
+    thread::sleep(time::Duration::from_millis(5000));
+
+    let res = chain
+        .orc
+        .query(
+            "cw_core",
+            "exc_stake_q_power",
+            &cw_core::msg::QueryMsg::VotingPowerAtHeight {
+                address: chain.user.addr.clone(),
+                height: None,
+            },
+        )
+        .unwrap();
+    let power: VotingPowerAtHeightResponse = res.data().unwrap();
+
+    assert_eq!(power.power, Uint128::new(100));
+}
diff --git a/ci/integration_tests/src/tests/cw_core_test.rs b/ci/integration_tests/src/tests/cw_core_test.rs
new file mode 100644
index 00000000..6c103a85
--- /dev/null
+++ b/ci/integration_tests/src/tests/cw_core_test.rs
@@ -0,0 +1,367 @@
+use crate::helpers::chain::Chain;
+use crate::helpers::helper::create_dao;
+use assert_matches::assert_matches;
+use cosm_orc::client::error::ClientError;
+use cosm_orc::orchestrator::error::ProcessError;
+use cosmwasm_std::{to_binary, Addr, CosmosMsg, Decimal, Uint128};
+use cw20_stake::msg::{StakedValueResponse, TotalValueResponse};
+use cw_core::query::{GetItemResponse, PauseInfoResponse};
+use cw_utils::Duration;
+use test_context::test_context;
+use voting::{deposit::CheckedDepositInfo, threshold::PercentageThreshold, threshold::Threshold};
+
+// #### ExecuteMsg #####
+
+// TODO: Add tests for all cw-core execute msgs
+
+#[test_context(Chain)]
+#[test]
+fn execute_execute_admin_msgs(chain: &mut Chain) {
+    // if you are not the admin, you cant execute admin msgs:
+    let res = create_dao(
+        chain,
+        None,
+        "exc_admin_msgs_create_dao",
+        chain.user.addr.clone(),
+    );
+    let dao = res.unwrap();
+
+    let res = chain.orc.execute(
+        "cw_core",
+        "exc_admin_msgs_pause_dao_fail",
+        &cw_core::msg::ExecuteMsg::ExecuteAdminMsgs {
+            msgs: vec![CosmosMsg::Wasm(cosmwasm_std::WasmMsg::Execute {
+                contract_addr: dao.addr,
+                msg: to_binary(&cw_core::msg::ExecuteMsg::Pause {
+                    duration: Duration::Time(100),
+                })
+                .unwrap(),
+                funds: vec![],
+            })],
+        },
+        &chain.user.key,
+    );
+
+    assert_matches!(
+        res.unwrap_err(),
+        ProcessError::ClientError(ClientError::CosmosSdk { .. })
+    );
+
+    let res = chain
+        .orc
+        .query(
+            "cw_core",
+            "exc_admin_msgs_pause_dao_query",
+            &cw_core::msg::QueryMsg::PauseInfo {},
+        )
+        .unwrap();
+    let res: PauseInfoResponse = res.data().unwrap();
+
+    assert_eq!(res, PauseInfoResponse::Unpaused {});
+
+    // if you are the admin you can execute admin msgs:
+    let res = create_dao(
+        chain,
+        Some(chain.user.addr.clone()),
+        "exc_admin_msgs_create_dao_with_admin",
+        chain.user.addr.clone(),
+    );
+    let dao = res.unwrap();
+
+    chain
+        .orc
+        .execute(
+            "cw_core",
+            "exc_admin_msgs_pause_dao",
+            &cw_core::msg::ExecuteMsg::ExecuteAdminMsgs {
+                msgs: vec![CosmosMsg::Wasm(cosmwasm_std::WasmMsg::Execute {
+                    contract_addr: dao.addr,
+                    msg: to_binary(&cw_core::msg::ExecuteMsg::Pause {
+                        duration: Duration::Height(100),
+                    })
+                    .unwrap(),
+                    funds: vec![],
+                })],
+            },
+            &chain.user.key,
+        )
+        .unwrap();
+
+    let res = chain
+        .orc
+        .query(
+            "cw_core",
+            "exc_admin_msgs_pause_dao",
+            &cw_core::msg::QueryMsg::PauseInfo {},
+        )
+        .unwrap();
+
+    let res: PauseInfoResponse = res.data().unwrap();
+    assert_ne!(res, PauseInfoResponse::Unpaused {});
+}
+
+#[test_context(Chain)]
+#[test]
+fn execute_items(chain: &mut Chain) {
+    // add item:
+    let res = create_dao(
+        chain,
+        Some(chain.user.addr.clone()),
+        "exc_items_create_dao",
+        chain.user.addr.clone(),
+    );
+
+    let dao = res.unwrap();
+
+    let res = chain
+        .orc
+        .query(
+            "cw_core",
+            "exc_items_get",
+            &cw_core::msg::QueryMsg::GetItem {
+                key: "meme".to_string(),
+            },
+        )
+        .unwrap();
+    let res: GetItemResponse = res.data().unwrap();
+
+    assert_eq!(res.item, None);
+
+    chain
+        .orc
+        .execute(
+            "cw_core",
+            "exc_items_set",
+            &cw_core::msg::ExecuteMsg::ExecuteAdminMsgs {
+                msgs: vec![CosmosMsg::Wasm(cosmwasm_std::WasmMsg::Execute {
+                    contract_addr: dao.addr.clone(),
+                    msg: to_binary(&cw_core::msg::ExecuteMsg::SetItem {
+                        key: "meme".to_string(),
+                        addr: "foobar".to_string(),
+                    })
+                    .unwrap(),
+                    funds: vec![],
+                })],
+            },
+            &chain.user.key,
+        )
+        .unwrap();
+
+    let res = chain
+        .orc
+        .query(
+            "cw_core",
+            "exc_items_set",
+            &cw_core::msg::QueryMsg::GetItem {
+                key: "meme".to_string(),
+            },
+        )
+        .unwrap();
+    let res: GetItemResponse = res.data().unwrap();
+
+    assert_eq!(res.item, Some("foobar".to_string()));
+
+    // remove item:
+    chain
+        .orc
+        .execute(
+            "cw_core",
+            "exc_items_rm",
+            &cw_core::msg::ExecuteMsg::ExecuteAdminMsgs {
+                msgs: vec![CosmosMsg::Wasm(cosmwasm_std::WasmMsg::Execute {
+                    contract_addr: dao.addr,
+                    msg: to_binary(&cw_core::msg::ExecuteMsg::RemoveItem {
+                        key: "meme".to_string(),
+                    })
+                    .unwrap(),
+                    funds: vec![],
+                })],
+            },
+            &chain.user.key,
+        )
+        .unwrap();
+
+    let res = chain
+        .orc
+        .query(
+            "cw_core",
+            "exc_items_rm",
+            &cw_core::msg::QueryMsg::GetItem {
+                key: "meme".to_string(),
+            },
+        )
+        .unwrap();
+    let res: GetItemResponse = res.data().unwrap();
+
+    assert_eq!(res.item, None);
+}
+
+// #### InstantiateMsg #####
+
+#[test_context(Chain)]
+#[test]
+fn instantiate_with_no_admin(chain: &mut Chain) {
+    let res = create_dao(chain, None, "inst_dao_no_admin", chain.user.addr.clone());
+    let dao = res.unwrap();
+
+    // ensure the dao is the admin:
+    assert_eq!(dao.state.admin, dao.addr);
+    assert_eq!(dao.state.pause_info, PauseInfoResponse::Unpaused {});
+    assert_eq!(
+        dao.state.config,
+        cw_core::state::Config {
+            name: "DAO DAO".to_string(),
+            description: "A DAO that makes DAO tooling".to_string(),
+            image_url: None,
+            automatically_add_cw20s: false,
+            automatically_add_cw721s: false
+        }
+    );
+}
+
+#[test_context(Chain)]
+#[test]
+fn instantiate_with_admin(chain: &mut Chain) {
+    let voting_contract = "cw20_staked_balance_voting";
+    let proposal_contract = "cw_proposal_single";
+
+    let res = create_dao(
+        chain,
+        Some(chain.user.addr.clone()),
+        "inst_admin_create_dao",
+        chain.user.addr.clone(),
+    );
+    let dao = res.unwrap();
+
+    // general dao info is valid:
+    assert_eq!(dao.state.admin, chain.user.addr);
+    assert_eq!(dao.state.pause_info, PauseInfoResponse::Unpaused {});
+    assert_eq!(
+        dao.state.config,
+        cw_core::state::Config {
+            name: "DAO DAO".to_string(),
+            description: "A DAO that makes DAO tooling".to_string(),
+            image_url: None,
+            automatically_add_cw20s: false,
+            automatically_add_cw721s: false
+        }
+    );
+
+    let voting_addr = dao.state.voting_module.as_str();
+    let prop_addr = dao.state.proposal_modules[0].as_str();
+
+    // voting module config is valid:
+    chain
+        .orc
+        .contract_map
+        .add_address(voting_contract, voting_addr)
+        .unwrap();
+    let res = &chain
+        .orc
+        .query(
+            voting_contract,
+            "inst_admin_q_stake",
+            &cw20_staked_balance_voting::msg::QueryMsg::StakingContract {},
+        )
+        .unwrap();
+    let staking_addr: &str = res.data().unwrap();
+
+    chain
+        .orc
+        .contract_map
+        .add_address("cw20_stake", staking_addr)
+        .unwrap();
+    let res = chain
+        .orc
+        .query(
+            "cw20_stake",
+            "inst_admin_q_val",
+            &cw20_stake::msg::QueryMsg::StakedValue {
+                address: chain.user.addr.clone(),
+            },
+        )
+        .unwrap();
+    let staked_res: StakedValueResponse = res.data().unwrap();
+    assert_eq!(staked_res.value, Uint128::new(0));
+
+    let res = chain
+        .orc
+        .query(
+            "cw20_stake",
+            "inst_admin_q_cfg",
+            &cw20_stake::msg::QueryMsg::GetConfig {},
+        )
+        .unwrap();
+    let config_res: cw20_stake::state::Config = res.data().unwrap();
+    assert_eq!(
+        config_res.owner,
+        Some(Addr::unchecked(
+            chain.orc.contract_map.address("cw_core").unwrap()
+        ))
+    );
+    assert_eq!(config_res.manager, None);
+
+    let res = &chain
+        .orc
+        .query(
+            voting_contract,
+            "inst_admin_q_tok",
+            &cw20_staked_balance_voting::msg::QueryMsg::TokenContract {},
+        )
+        .unwrap();
+    let token_addr: &str = res.data().unwrap();
+    assert_eq!(config_res.token_address, token_addr);
+
+    assert_eq!(config_res.unstaking_duration, Some(Duration::Time(1209600)));
+
+    let res = chain
+        .orc
+        .query(
+            "cw20_stake",
+            "inst_admin_q_val",
+            &cw20_stake::msg::QueryMsg::TotalValue {},
+        )
+        .unwrap();
+    let total_res: TotalValueResponse = res.data().unwrap();
+    assert_eq!(total_res.total, Uint128::new(0));
+
+    // proposal module config is valid:
+    chain
+        .orc
+        .contract_map
+        .add_address(proposal_contract, prop_addr)
+        .unwrap();
+    let res = chain
+        .orc
+        .query(
+            proposal_contract,
+            "inst_admin_q_cfg",
+            &cw_proposal_single::msg::QueryMsg::Config {},
+        )
+        .unwrap();
+    let config_res: cw_proposal_single::state::Config = res.data().unwrap();
+
+    assert_eq!(config_res.min_voting_period, None);
+    assert_eq!(config_res.max_voting_period, Duration::Time(432000));
+    assert!(!config_res.allow_revoting);
+    assert!(config_res.only_members_execute);
+    assert_eq!(
+        config_res.deposit_info,
+        Some(CheckedDepositInfo {
+            token: Addr::unchecked(token_addr),
+            deposit: Uint128::new(1000000000),
+            refund_failed_proposals: true,
+        })
+    );
+    assert_eq!(
+        config_res.threshold,
+        Threshold::ThresholdQuorum {
+            threshold: PercentageThreshold::Majority {},
+            quorum: PercentageThreshold::Percent(Decimal::percent(35)),
+        }
+    );
+    assert_eq!(
+        config_res.dao,
+        chain.orc.contract_map.address("cw_core").unwrap()
+    );
+}
diff --git a/ci/integration_tests/src/tests/mod.rs b/ci/integration_tests/src/tests/mod.rs
new file mode 100644
index 00000000..758582f3
--- /dev/null
+++ b/ci/integration_tests/src/tests/mod.rs
@@ -0,0 +1,3 @@
+pub mod cw_core_test;
+
+pub mod cw20_stake_test;
diff --git a/contracts/cw-core/src/tests.rs b/contracts/cw-core/src/tests.rs
index 37ef94e2..242a0ba8 100644
--- a/contracts/cw-core/src/tests.rs
+++ b/contracts/cw-core/src/tests.rs
@@ -1438,23 +1438,48 @@ fn test_list_items() {
         "barkey".to_string(),
         "baraddr".to_string(),
     );
+    set_item(
+        &mut app,
+        gov_addr.clone(),
+        "loremkey".to_string(),
+        "loremaddr".to_string(),
+    );
+    set_item(
+        &mut app,
+        gov_addr.clone(),
+        "ipsumkey".to_string(),
+        "ipsumaddr".to_string(),
+    );
 
     // Foo returned as we are only getting one item and items are in
     // decending order.
     let first_item = list_items(&mut app, gov_addr.clone(), None, Some(1));
     assert_eq!(first_item.len(), 1);
-    assert_eq!(first_item[0], ("fookey".to_string(), "fooaddr".to_string()));
+    assert_eq!(
+        first_item[0],
+        ("loremkey".to_string(), "loremaddr".to_string())
+    );
 
     let no_items = list_items(&mut app, gov_addr.clone(), None, Some(0));
     assert_eq!(no_items.len(), 0);
 
     // Items are retreived in decending order so asking for foo with
-    // no limit ought to give us a single item.
-    let second_item = list_items(&mut app, gov_addr, Some("foo".to_string()), None);
-    assert_eq!(second_item.len(), 1);
+    // no limit ought to give us the barkey k/v. this will be the last item
+    // note: the paginate map bound is exclusive, so fookey will be starting point
+    let last_item = list_items(&mut app, gov_addr.clone(), Some("foo".to_string()), None);
+    assert_eq!(last_item.len(), 1);
+    assert_eq!(last_item[0], ("barkey".to_string(), "baraddr".to_string()));
+
+    // Items are retreived in decending order so asking for ipsum with
+    // 4 limit ought to give us the fookey and barkey k/vs.
+    let after_foo_list = list_items(&mut app, gov_addr, Some("ipsum".to_string()), Some(4));
+    assert_eq!(after_foo_list.len(), 2);
     assert_eq!(
-        second_item[0],
-        ("fookey".to_string(), "fooaddr".to_string())
+        after_foo_list,
+        vec![
+            ("fookey".to_string(), "fooaddr".to_string()),
+            ("barkey".to_string(), "baraddr".to_string())
+        ]
     );
 }
 
diff --git a/contracts/cw-native-staked-balance-voting/src/tests.rs b/contracts/cw-native-staked-balance-voting/src/tests.rs
index 2f73081d..ec1961dc 100644
--- a/contracts/cw-native-staked-balance-voting/src/tests.rs
+++ b/contracts/cw-native-staked-balance-voting/src/tests.rs
@@ -1,4 +1,6 @@
-use crate::msg::{ExecuteMsg, InstantiateMsg, Owner, QueryMsg};
+use crate::msg::{
+    ExecuteMsg, InstantiateMsg, ListStakersResponse, Owner, QueryMsg, StakerBalanceResponse,
+};
 use crate::state::Config;
 use cosmwasm_std::{coins, Addr, Coin, Empty, Uint128};
 use cw_controllers::ClaimsResponse;
@@ -884,3 +886,87 @@ fn test_voting_power_queries() {
     let resp = get_voting_power_at_height(&mut app, addr, ADDR2.to_string(), None);
     assert_eq!(resp.power, Uint128::new(50));
 }
+
+#[test]
+fn test_query_list_stakers() {
+    let mut app = mock_app();
+    let staking_id = app.store_code(staking_contract());
+    let addr = instantiate_staking(
+        &mut app,
+        staking_id,
+        InstantiateMsg {
+            owner: Some(Owner::Addr(DAO_ADDR.to_string())),
+            manager: Some(ADDR1.to_string()),
+            denom: DENOM.to_string(),
+            unstaking_duration: Some(Duration::Height(5)),
+        },
+    );
+
+    // ADDR1 stakes
+    stake_tokens(&mut app, addr.clone(), ADDR1, 100, DENOM).unwrap();
+
+    // ADDR2 stakes
+    stake_tokens(&mut app, addr.clone(), ADDR2, 50, DENOM).unwrap();
+
+    // check entire result set
+    let stakers: ListStakersResponse = app
+        .wrap()
+        .query_wasm_smart(
+            addr.clone(),
+            &QueryMsg::ListStakers {
+                start_after: None,
+                limit: None,
+            },
+        )
+        .unwrap();
+
+    let test_res = ListStakersResponse {
+        stakers: vec![
+            StakerBalanceResponse {
+                address: ADDR1.to_string(),
+                balance: Uint128::new(100),
+            },
+            StakerBalanceResponse {
+                address: ADDR2.to_string(),
+                balance: Uint128::new(50),
+            },
+        ],
+    };
+
+    assert_eq!(stakers, test_res);
+
+    // skipped 1, check result
+    let stakers: ListStakersResponse = app
+        .wrap()
+        .query_wasm_smart(
+            addr.clone(),
+            &QueryMsg::ListStakers {
+                start_after: Some(ADDR1.to_string()),
+                limit: None,
+            },
+        )
+        .unwrap();
+
+    let test_res = ListStakersResponse {
+        stakers: vec![StakerBalanceResponse {
+            address: ADDR2.to_string(),
+            balance: Uint128::new(50),
+        }],
+    };
+
+    assert_eq!(stakers, test_res);
+
+    // skipped 2, check result. should be nothing
+    let stakers: ListStakersResponse = app
+        .wrap()
+        .query_wasm_smart(
+            addr,
+            &QueryMsg::ListStakers {
+                start_after: Some(ADDR2.to_string()),
+                limit: None,
+            },
+        )
+        .unwrap();
+
+    assert_eq!(stakers, ListStakersResponse { stakers: vec![] });
+}
diff --git a/contracts/cw20-stake/src/tests.rs b/contracts/cw20-stake/src/tests.rs
index 49a632a0..c5b5b5e8 100644
--- a/contracts/cw20-stake/src/tests.rs
+++ b/contracts/cw20-stake/src/tests.rs
@@ -1,8 +1,8 @@
 use std::borrow::BorrowMut;
 
 use crate::msg::{
-    ExecuteMsg, QueryMsg, ReceiveMsg, StakedBalanceAtHeightResponse, StakedValueResponse,
-    TotalStakedAtHeightResponse, TotalValueResponse,
+    ExecuteMsg, ListStakersResponse, QueryMsg, ReceiveMsg, StakedBalanceAtHeightResponse,
+    StakedValueResponse, StakerBalanceResponse, TotalStakedAtHeightResponse, TotalValueResponse,
 };
 use crate::state::{Config, MAX_CLAIMS};
 use crate::ContractError;
@@ -1044,3 +1044,121 @@ fn test_double_unstake_at_height() {
 
     assert_eq!(balance.balance, Uint128::zero())
 }
+
+#[test]
+fn test_query_list_stakers() {
+    let mut app = App::default();
+
+    let (staking_addr, cw20_addr) = setup_test_case(
+        &mut app,
+        vec![
+            Cw20Coin {
+                address: "ekez1".to_string(),
+                amount: Uint128::new(10),
+            },
+            Cw20Coin {
+                address: "ekez2".to_string(),
+                amount: Uint128::new(20),
+            },
+            Cw20Coin {
+                address: "ekez3".to_string(),
+                amount: Uint128::new(30),
+            },
+            Cw20Coin {
+                address: "ekez4".to_string(),
+                amount: Uint128::new(40),
+            },
+        ],
+        None,
+    );
+
+    stake_tokens(
+        &mut app,
+        &staking_addr,
+        &cw20_addr,
+        mock_info("ekez1", &[]),
+        Uint128::new(10),
+    )
+    .unwrap();
+
+    stake_tokens(
+        &mut app,
+        &staking_addr,
+        &cw20_addr,
+        mock_info("ekez2", &[]),
+        Uint128::new(20),
+    )
+    .unwrap();
+
+    stake_tokens(
+        &mut app,
+        &staking_addr,
+        &cw20_addr,
+        mock_info("ekez3", &[]),
+        Uint128::new(30),
+    )
+    .unwrap();
+
+    stake_tokens(
+        &mut app,
+        &staking_addr,
+        &cw20_addr,
+        mock_info("ekez4", &[]),
+        Uint128::new(40),
+    )
+    .unwrap();
+
+    // check first 2
+    let stakers: ListStakersResponse = app
+        .wrap()
+        .query_wasm_smart(
+            staking_addr.clone(),
+            &QueryMsg::ListStakers {
+                start_after: None,
+                limit: Some(2),
+            },
+        )
+        .unwrap();
+
+    let test_res = ListStakersResponse {
+        stakers: vec![
+            StakerBalanceResponse {
+                address: "ekez1".to_string(),
+                balance: Uint128::new(10),
+            },
+            StakerBalanceResponse {
+                address: "ekez2".to_string(),
+                balance: Uint128::new(20),
+            },
+        ],
+    };
+
+    assert_eq!(stakers, test_res);
+
+    // skip first and grab 2
+    let stakers: ListStakersResponse = app
+        .wrap()
+        .query_wasm_smart(
+            staking_addr,
+            &QueryMsg::ListStakers {
+                start_after: Some("ekez1".to_string()),
+                limit: Some(2),
+            },
+        )
+        .unwrap();
+
+    let test_res = ListStakersResponse {
+        stakers: vec![
+            StakerBalanceResponse {
+                address: "ekez2".to_string(),
+                balance: Uint128::new(20),
+            },
+            StakerBalanceResponse {
+                address: "ekez3".to_string(),
+                balance: Uint128::new(30),
+            },
+        ],
+    };
+
+    assert_eq!(stakers, test_res)
+}