diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 000000000..6a82f4e8f --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,10 @@ +{ + "overrides": [ + { + "files": "*.md", + "options": { + "proseWrap": "always" + } + } + ] +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..2967f9b5c --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,11 @@ +# Contributing Guidelines + +We're happily accepting bugfixes, style improvements, good refactors and enhancements to documentation. + +For the specs, their APIs are considered final and immutable. We do not accept API-breaking changes. + +It is possible to propose a new protocol instead. In that case, please open an issue for discussion first, including +some motivating use cases. + +The contracts are not expected to be packed with features. They're expected to be minimal, reference implementations of +the specifications. We do not therefore accept enhancements. diff --git a/README.md b/README.md index 8d3fd6b68..ae6b28e80 100644 --- a/README.md +++ b/README.md @@ -2,19 +2,20 @@ [![CircleCI](https://circleci.com/gh/CosmWasm/cw-plus/tree/main.svg?style=shield)](https://circleci.com/gh/CosmWasm/cw-plus/tree/main) -| Specification | Crates.io | Docs | Coverage | -|---------------|-------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------| -| cw1 | [![cw1 on crates.io](https://img.shields.io/crates/v/cw1.svg)](https://crates.io/crates/cw1) | [![Docs](https://docs.rs/cw1/badge.svg)](https://docs.rs/cw1) | [![codecov](https://codecov.io/gh/CosmWasm/cw-plus/branch/main/graph/badge.svg?token=IYY72ZVS3X)](https://codecov.io/gh/CosmWasm/cw-plus) | -| cw2 | [![cw2 on crates.io](https://img.shields.io/crates/v/cw2.svg)](https://crates.io/crates/cw2) | [![Docs](https://docs.rs/cw2/badge.svg)](https://docs.rs/cw2) | [![codecov](https://codecov.io/gh/CosmWasm/cw-plus/branch/main/graph/badge.svg?token=IYY72ZVS3X)](https://codecov.io/gh/CosmWasm/cw-plus) | -| cw3 | [![cw3 on crates.io](https://img.shields.io/crates/v/cw3.svg)](https://crates.io/crates/cw3) | [![Docs](https://docs.rs/cw3/badge.svg)](https://docs.rs/cw3) | [![codecov](https://codecov.io/gh/CosmWasm/cw-plus/branch/main/graph/badge.svg?token=IYY72ZVS3X)](https://codecov.io/gh/CosmWasm/cw-plus) | -| cw4 | [![cw4 on crates.io](https://img.shields.io/crates/v/cw4.svg)](https://crates.io/crates/cw4) | [![Docs](https://docs.rs/cw4/badge.svg)](https://docs.rs/cw4) | [![codecov](https://codecov.io/gh/CosmWasm/cw-plus/branch/main/graph/badge.svg?token=IYY72ZVS3X)](https://codecov.io/gh/CosmWasm/cw-plus) | -| cw20 | [![cw20 on crates.io](https://img.shields.io/crates/v/cw20.svg)](https://crates.io/crates/cw20) | [![Docs](https://docs.rs/cw20/badge.svg)](https://docs.rs/cw20) | [![codecov](https://codecov.io/gh/CosmWasm/cw-plus/branch/main/graph/badge.svg?token=IYY72ZVS3X)](https://codecov.io/gh/CosmWasm/cw-plus) | - -| Utilities | Crates.io | Docs | Coverage | -|-----------------|----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------| -| cw-controllers | [![cw-controllers on crates.io](https://img.shields.io/crates/v/cw-controllers.svg)](https://crates.io/crates/cw-controllers) | [![Docs](https://docs.rs/cw-controllers/badge.svg)](https://docs.rs/cw-controllers) | [![codecov](https://codecov.io/gh/CosmWasm/cw-plus/branch/main/graph/badge.svg?token=IYY72ZVS3X)](https://codecov.io/gh/CosmWasm/cw-plus) | +| Specification | Crates.io | Docs | Coverage | +| ------------- | ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| cw1 | [![cw1 on crates.io](https://img.shields.io/crates/v/cw1.svg)](https://crates.io/crates/cw1) | [![Docs](https://docs.rs/cw1/badge.svg)](https://docs.rs/cw1) | [![codecov](https://codecov.io/gh/CosmWasm/cw-plus/branch/main/graph/badge.svg?token=IYY72ZVS3X)](https://codecov.io/gh/CosmWasm/cw-plus) | +| cw2 | [![cw2 on crates.io](https://img.shields.io/crates/v/cw2.svg)](https://crates.io/crates/cw2) | [![Docs](https://docs.rs/cw2/badge.svg)](https://docs.rs/cw2) | [![codecov](https://codecov.io/gh/CosmWasm/cw-plus/branch/main/graph/badge.svg?token=IYY72ZVS3X)](https://codecov.io/gh/CosmWasm/cw-plus) | +| cw3 | [![cw3 on crates.io](https://img.shields.io/crates/v/cw3.svg)](https://crates.io/crates/cw3) | [![Docs](https://docs.rs/cw3/badge.svg)](https://docs.rs/cw3) | [![codecov](https://codecov.io/gh/CosmWasm/cw-plus/branch/main/graph/badge.svg?token=IYY72ZVS3X)](https://codecov.io/gh/CosmWasm/cw-plus) | +| cw4 | [![cw4 on crates.io](https://img.shields.io/crates/v/cw4.svg)](https://crates.io/crates/cw4) | [![Docs](https://docs.rs/cw4/badge.svg)](https://docs.rs/cw4) | [![codecov](https://codecov.io/gh/CosmWasm/cw-plus/branch/main/graph/badge.svg?token=IYY72ZVS3X)](https://codecov.io/gh/CosmWasm/cw-plus) | +| cw20 | [![cw20 on crates.io](https://img.shields.io/crates/v/cw20.svg)](https://crates.io/crates/cw20) | [![Docs](https://docs.rs/cw20/badge.svg)](https://docs.rs/cw20) | [![codecov](https://codecov.io/gh/CosmWasm/cw-plus/branch/main/graph/badge.svg?token=IYY72ZVS3X)](https://codecov.io/gh/CosmWasm/cw-plus) | + +| Utilities | Crates.io | Docs | Coverage | +| -------------- | ----------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| cw-controllers | [![cw-controllers on crates.io](https://img.shields.io/crates/v/cw-controllers.svg)](https://crates.io/crates/cw-controllers) | [![Docs](https://docs.rs/cw-controllers/badge.svg)](https://docs.rs/cw-controllers) | [![codecov](https://codecov.io/gh/CosmWasm/cw-plus/branch/main/graph/badge.svg?token=IYY72ZVS3X)](https://codecov.io/gh/CosmWasm/cw-plus) | + | Contracts | Download | Docs | Coverage | -|--------------------|----------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------| +| ------------------ | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | | cw1-subkeys | [Release v0.13.4](https://github.com/CosmWasm/cw-plus/releases/download/v0.13.4/cw1_subkeys.wasm) | [![Docs](https://docs.rs/cw1-subkeys/badge.svg)](https://docs.rs/cw1-subkeys) | [![codecov](https://codecov.io/gh/CosmWasm/cw-plus/branch/main/graph/badge.svg?token=IYY72ZVS3X)](https://codecov.io/gh/CosmWasm/cw-plus) | | cw1-whitelist | [Release v0.13.4](https://github.com/CosmWasm/cw-plus/releases/download/v0.13.4/cw1_whitelist.wasm) | [![Docs](https://docs.rs/cw1-whitelist/badge.svg)](https://docs.rs/cw1-whitelist) | [![codecov](https://codecov.io/gh/CosmWasm/cw-plus/branch/main/graph/badge.svg?token=IYY72ZVS3X)](https://codecov.io/gh/CosmWasm/cw-plus) | | cw3-fixed-multisig | [Release v0.13.4](https://github.com/CosmWasm/cw-plus/releases/download/v0.13.4/cw3_fixed_multisig.wasm) | [![Docs](https://docs.rs/cw3-fixed-multisig/badge.svg)](https://docs.rs/cw3-fixed-multisig) | [![codecov](https://codecov.io/gh/CosmWasm/cw-plus/branch/main/graph/badge.svg?token=IYY72ZVS3X)](https://codecov.io/gh/CosmWasm/cw-plus) | @@ -24,102 +25,76 @@ | cw20-base | [Release v0.13.4](https://github.com/CosmWasm/cw-plus/releases/download/v0.13.4/cw20_base.wasm) | [![Docs](https://docs.rs/cw20-base/badge.svg)](https://docs.rs/cw20-base) | [![codecov](https://codecov.io/gh/CosmWasm/cw-plus/branch/main/graph/badge.svg?token=IYY72ZVS3X)](https://codecov.io/gh/CosmWasm/cw-plus) | | cw20-ics20 | [Release v0.13.4](https://github.com/CosmWasm/cw-plus/releases/download/v0.13.4/cw20_ics20.wasm) | [![Docs](https://docs.rs/cw20-ics20/badge.svg)](https://docs.rs/cw20-ics20) | [![codecov](https://codecov.io/gh/CosmWasm/cw-plus/branch/main/graph/badge.svg?token=IYY72ZVS3X)](https://codecov.io/gh/CosmWasm/cw-plus) | -Note: `cw721` and `cw721-base` have moved to the new [`cw-nfts` repo](https://github.com/CosmWasm/cw-nfts) -and can be followed there. - -Note: most of the `cw20-*` contracts besides `cw20-base` have moved to the new [`cw-tokens` repo](https://github.com/CosmWasm/cw-tokens) -and can be followed there. +Note: `cw721` and `cw721-base` have moved to the new [`cw-nfts` repo](https://github.com/CosmWasm/cw-nfts) and can be +followed there. -This is a collection of specification and contracts designed for -use on real networks. They are designed not just as examples, but to -solve real-world use cases, and to provide a reusable basis to build -many custom contracts. +Note: most of the `cw20-*` contracts besides `cw20-base` have moved to the new +[`cw-tokens` repo](https://github.com/CosmWasm/cw-tokens) and can be followed there. -If you don't know what CosmWasm is, please check out -[our homepage](https://cosmwasm.com) and -[our documentation](https://docs.cosmwasm.com) to get more background. -We are running [public testnets](https://github.com/CosmWasm/testnets#running) -you can use to test out any contracts. +This is a collection of specification and contracts designed for use on real networks. They are designed not just as +examples, but to solve real-world use cases, and to provide a reusable basis to build many custom contracts. -**Warning** None of these contracts have been audited and no liability is -assumed for the use of this code. They are provided to turbo-start -your projects. +If you don't know what CosmWasm is, please check out [our homepage](https://cosmwasm.com) and +[our documentation](https://docs.cosmwasm.com) to get more background. We are running +[public testnets](https://github.com/CosmWasm/testnets#running) you can use to test out any contracts. -**Note** All code in pre-1.0 packages is in "draft" form, meaning it may -undergo minor changes and additions until 1.0. For example between 0.1 and -0.2 we adjusted the `Expiration` type to make the JSON representation -cleaner (before: `expires: {at_height: {height: 12345}}` after -`expires: {at_height: 12345}`) +**Warning** None of these contracts have been audited and no liability is assumed for the use of this code. They are +provided to turbo-start your projects. ## Specifications -The most reusable components are the various cwXYZ specifications under -`packages`. Each one defines a standard interface for different domains, -e.g. [cw20](./packages/cw20/README.md) for fungible tokens, +The most reusable components are the various cwXYZ specifications under `packages`. Each one defines a standard +interface for different domains, e.g. [cw20](./packages/cw20/README.md) for fungible tokens, [cw721](https://github.com/CosmWasm/cw-nfts/blob/main/packages/cw721/README.md) for non-fungible tokens, -[cw1](./packages/cw1/README.md) for "proxy contracts", etc. -The interface comes with a human description in the READMEs, as well -as Rust types that can be imported. +[cw1](./packages/cw1/README.md) for "proxy contracts", etc. The interface comes with a human description in the READMEs, +as well as Rust types that can be imported. -They contain no logic, but specify an interface. It shows what you -need to implement to create a compatible contracts, as well as what -interface we guarantee to any consumer of such contracts. This is -the real bonus of specifications, we can create an escrow contract that -can handle many different fungible tokens, as long as they all adhere to -the cw20 specification. +They contain no logic, but specify an interface. It shows what you need to implement to create a compatible contracts, +as well as what interface we guarantee to any consumer of such contracts. This is the real bonus of specifications, we +can create an escrow contract that can handle many different fungible tokens, as long as they all adhere to the cw20 +specification. -If you have ideas for new specifications or want to make enhancements to -existing spec, please [raise an issue](https://github.com/CosmWasm/cw-plus/issues) -or [create a pull request](https://github.com/CosmWasm/cw-plus/pulls) on this repo. +If you have ideas for new specifications , please [raise an issue](https://github.com/CosmWasm/cw-plus/issues) or +[create a pull request](https://github.com/CosmWasm/cw-plus/pulls) on this repo. ## Contracts -We provide sample contracts that either implement or consume these -specifications to both provide examples, and provide a basis -for code you can extend for more custom contacts, without worrying -about reinventing the wheel each time. -For example [`cw20-base`](./contracts/cw20-base) is a basic implementation -of a `cw20` compatible contract that can be imported in any custom -contract you want to build on it. +We provide sample contracts that either implement or consume these specifications to both provide examples, and provide +a basis for code you can extend for more custom contacts, without worrying about reinventing the wheel each time. For +example [`cw20-base`](./contracts/cw20-base) is a basic implementation of a `cw20` compatible contract that can be +imported in any custom contract you want to build on it. CW1 Proxy Contracts: -* [`cw1-whitelist`](./contracts/cw1-whitelist) a minimal implementation of `cw1` -mainly designed for reference. -* [`cw1-subkeys`](./contracts/cw1-subkeys) a simple, but useful implementation, -which lets us use a proxy contract to provide "allowances" for native tokens -without modifying the `bank` module. +- [`cw1-whitelist`](./contracts/cw1-whitelist) a minimal implementation of `cw1` mainly designed for reference. +- [`cw1-subkeys`](./contracts/cw1-subkeys) a simple, but useful implementation, which lets us use a proxy contract to + provide "allowances" for native tokens without modifying the `bank` module. CW3 Multisig: -* [`cw3-fixed-multisig`](./contracts/cw3-fixed-multisig) a simple implementation of the -[cw3 spec](./packages/cw3/README.md). It is a multisig with a fixed set of addresses, -created upon initialization. -Each address may have the same weight (K of N), or some may have extra voting -power. This works much like the native Cosmos SDK multisig, except that rather -than aggregating the signatures off chain and submitting the final result, -we aggregate the approvals on-chain. -* [`cw3-flex-multisig`](./contracts/cw3-flex-multisig) builds on cw3-fixed-multisig, -with a more powerful implementation of the cw3 spec. It's a multisig contract -backed by a cw4 (group) contract, which independently maintains the voter set. +- [`cw3-fixed-multisig`](./contracts/cw3-fixed-multisig) a simple implementation of the + [cw3 spec](./packages/cw3/README.md). It is a multisig with a fixed set of addresses, created upon initialization. + Each address may have the same weight (K of N), or some may have extra voting power. This works much like the native + Cosmos SDK multisig, except that rather than aggregating the signatures off chain and submitting the final result, we + aggregate the approvals on-chain. +- [`cw3-flex-multisig`](./contracts/cw3-flex-multisig) builds on cw3-fixed-multisig, with a more powerful implementation + of the cw3 spec. It's a multisig contract backed by a cw4 (group) contract, which independently maintains the voter + set. CW4 Group: -* [`cw4-group`](./contracts/cw4-group) a basic implementation of the -[cw4 spec](./packages/cw4/README.md). It handles elected membership, by admin or multisig. -It fulfills all elements of the spec, including raw query lookups, -and is designed to be used as a backing storage for [cw3 compliant contracts](./packages/cw3/README.md). -* [`cw4-stake`](./contracts/cw4-stake) a second implementation of the -[cw4 spec](./packages/cw4/README.md). It fulfills all elements of the spec, including raw query lookups, -and is designed to be used as a backing storage for [cw3 compliant contracts](./packages/cw3/README.md). -It provides a similar API to [`cw4-group`], but rather than appointing members, -their membership and weight are based on the number of staked tokens they have. +- [`cw4-group`](./contracts/cw4-group) a basic implementation of the [cw4 spec](./packages/cw4/README.md). It handles + elected membership, by admin or multisig. It fulfills all elements of the spec, including raw query lookups, and is + designed to be used as a backing storage for [cw3 compliant contracts](./packages/cw3/README.md). +- [`cw4-stake`](./contracts/cw4-stake) a second implementation of the [cw4 spec](./packages/cw4/README.md). It fulfills + all elements of the spec, including raw query lookups, and is designed to be used as a backing storage for + [cw3 compliant contracts](./packages/cw3/README.md). It provides a similar API to [`cw4-group`], but rather than + appointing members, their membership and weight are based on the number of staked tokens they have. CW20 Fungible Tokens: -* [`cw20-base`](./contracts/cw20-base) a straightforward, but complete -implementation of the cw20 spec along with all extensions. Can be deployed -as-is, or imported by other contracts. +- [`cw20-base`](./contracts/cw20-base) a straightforward, but complete implementation of the cw20 spec along with all + extensions. Can be deployed as-is, or imported by other contracts. ## Compiling @@ -129,32 +104,27 @@ To compile all the contracts, run the following in the repo root: 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 \ - cosmwasm/workspace-optimizer:0.12.6 + cosmwasm/workspace-optimizer:0.12.9 ``` -This will compile all packages in the `contracts` directory and output the -stripped and optimized wasm code under the `artifacts` directory as output, -along with a `checksums.txt` file. +This will compile all packages in the `contracts` directory and output the stripped and optimized wasm code under the +`artifacts` directory as output, along with a `checksums.txt` file. -If you hit any issues there and want to debug, you can try to run the -following in each contract dir: +If you hit any issues there and want to debug, you can try to run the following in each contract dir: `RUSTFLAGS="-C link-arg=-s" cargo build --release --target=wasm32-unknown-unknown --locked` ## Quality Control -One of the basic metrics of assurance over code quality is how much is covered by -unit tests. There are several tools available for Rust to do such analysis and -we will describe one below. This should be used as a baseline metric to give some -confidence in the code. +One of the basic metrics of assurance over code quality is how much is covered by unit tests. There are several tools +available for Rust to do such analysis and we will describe one below. This should be used as a baseline metric to give +some confidence in the code. -Beyond code coverage metrics, just having a robust PR review process with a few -more trained eyes looking for bugs is very helpful in detecting paths the original -coder was not aware of. This is more subjective, but looking at the relevant PRs -and depth of discussion can give an idea how much review was present. +Beyond code coverage metrics, just having a robust PR review process with a few more trained eyes looking for bugs is +very helpful in detecting paths the original coder was not aware of. This is more subjective, but looking at the +relevant PRs and depth of discussion can give an idea how much review was present. -After that, fuzzing it (ideally with an intelligent fuzzer that understands the domain) -can be valuable. And beyond that formal verification can provide even more assurance -(but is very time-consuming and expensive). +After that, fuzzing it (ideally with an intelligent fuzzer that understands the domain) can be valuable. And beyond that +formal verification can provide even more assurance (but is very time-consuming and expensive). ### Code Coverage @@ -162,20 +132,24 @@ I recommend the use of [tarpaulin](https://github.com/xd009642/tarpaulin): `carg To get some nice interactive charts, you can go to the root directory and run: -`cargo tarpaulin -o html` -and then `xdg-open tarpaulin-report.html` (or just `open` on MacOS). +`cargo tarpaulin -o html` and then `xdg-open tarpaulin-report.html` (or just `open` on MacOS). -Once you find a package that you want to improve, you can do the following to just -analyze this package, which gives much faster turn-around: +Once you find a package that you want to improve, you can do the following to just analyze this package, which gives +much faster turn-around: `cargo tarpaulin -o html --packages cw3-fixed-multisig` -Note that it will produce a code coverage report for the entire project, but only the coverage in that -package is the real value. If does give quick feedback for you if you unit test writing was successful. +Note that it will produce a code coverage report for the entire project, but only the coverage in that package is the +real value. If does give quick feedback for you if you unit test writing was successful. + +## Contributing + +See our [Contributing Guidelines](CONTRIBUTING.md). ## Generating changelog -To generate a changelog we decided to use [github-changelog-generator](https://github.com/github-changelog-generator/github-changelog-generator). +To generate a changelog we decided to use +[github-changelog-generator](https://github.com/github-changelog-generator/github-changelog-generator). To install tool you need Ruby's `gem` package manager. @@ -191,18 +165,16 @@ Appending next releases could be done adding `--base` flag: $ github_changelog_generator -u CosmWasm -p cw-plus --base CHANGELOG.md -If you hit GitHub's 50 requests/hour limit, please follow [this](https://github.com/github-changelog-generator/github-changelog-generator#github-token) -guide to create a token key which you can pass using `--token` flag. +If you hit GitHub's 50 requests/hour limit, please follow +[this](https://github.com/github-changelog-generator/github-changelog-generator#github-token) guide to create a token +key which you can pass using `--token` flag. -There's also a convenience `scripts/update_changelog.sh`, which can take a ---since-tag parameter (to avoid processing the entire history). It can also -auto-detect the latest version tag for you, with --latest-tag. +There's also a convenience `scripts/update_changelog.sh`, which can take a --since-tag parameter (to avoid processing +the entire history). It can also auto-detect the latest version tag for you, with --latest-tag. ## Licenses This repo is licensed under [Apache 2.0](./LICENSE). -All *specifications* will always be Apache-2.0. All contracts that are -meant to be *building blocks* will also be Apache-2.0. This is along -the lines of Open Zeppelin or other public references. - +All _specifications_ will always be Apache-2.0. All contracts that are meant to be _building blocks_ will also be +Apache-2.0. This is along the lines of Open Zeppelin or other public references.