diff --git a/.circleci/config.yml b/.circleci/config.yml index ba74e72..49ecc6f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,7 +6,7 @@ workflows: jobs: - contract_tfi_factory - contract_tfi_pair - - contract_dso_token + - contract_trusted_token - package_tfi build: jobs: @@ -94,10 +94,10 @@ jobs: - target key: cargocache-tfi-pair-rust:1.51.0-{{ checksum "~/project/Cargo.lock" }} - contract_dso_token: + contract_trusted_token: docker: - image: rust:1.51.0 - working_directory: ~/project/contracts/dso-token + working_directory: ~/project/contracts/trusted-token steps: - checkout: path: ~/project @@ -106,7 +106,7 @@ jobs: command: rustc --version; cargo --version; rustup --version - restore_cache: keys: - - cargocache-dso-token-rust:1.51.0-{{ checksum "~/project/Cargo.lock" }} + - cargocache-trusted-token-rust:1.51.0-{{ checksum "~/project/Cargo.lock" }} - run: name: Unit Tests environment: @@ -128,7 +128,7 @@ jobs: paths: - /usr/local/cargo/registry - target - key: cargocache-dso-token-rust:1.51.0-{{ checksum "~/project/Cargo.lock" }} + key: cargocache-trusted-token-rust:1.51.0-{{ checksum "~/project/Cargo.lock" }} package_tfi: docker: diff --git a/Cargo.lock b/Cargo.lock index 4d465b0..b04fae9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -366,26 +366,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "dso-token" -version = "0.2.0" -dependencies = [ - "anyhow", - "cosmwasm-schema", - "cosmwasm-std", - "cw-multi-test", - "cw-storage-plus", - "cw2", - "cw20", - "cw20-base", - "cw4", - "cw4-group", - "derivative", - "schemars", - "serde", - "thiserror", -] - [[package]] name = "dyn-clone" version = "1.0.4" @@ -819,7 +799,7 @@ dependencies = [ [[package]] name = "tfi" -version = "0.2.0" +version = "0.2.1" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -832,7 +812,7 @@ dependencies = [ [[package]] name = "tfi-factory" -version = "0.2.0" +version = "0.2.1" dependencies = [ "anyhow", "cosmwasm-schema", @@ -845,18 +825,18 @@ dependencies = [ "cw4", "cw4-group", "derivative", - "dso-token", "protobuf", "schemars", "serde", "tfi", "tfi-pair", "thiserror", + "trusted-token", ] [[package]] name = "tfi-mocks" -version = "0.2.0" +version = "0.2.1" dependencies = [ "cosmwasm-std", "cosmwasm-storage", @@ -868,7 +848,7 @@ dependencies = [ [[package]] name = "tfi-pair" -version = "0.2.0" +version = "0.2.1" dependencies = [ "anyhow", "cosmwasm-schema", @@ -910,7 +890,7 @@ dependencies = [ [[package]] name = "trusted-circle" -version = "0.2.0" +version = "0.2.1" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -920,6 +900,26 @@ dependencies = [ "serde", ] +[[package]] +name = "trusted-token" +version = "0.2.1" +dependencies = [ + "anyhow", + "cosmwasm-schema", + "cosmwasm-std", + "cw-multi-test", + "cw-storage-plus", + "cw2", + "cw20", + "cw20-base", + "cw4", + "cw4-group", + "derivative", + "schemars", + "serde", + "thiserror", +] + [[package]] name = "typenum" version = "1.13.0" diff --git a/Cargo.toml b/Cargo.toml index 28996fc..766abff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,13 +9,9 @@ incremental = false codegen-units = 1 incremental = false -[profile.release.package.dso-token] -opt-level = 3 -debug = false -debug-assertions = false +[profile.release.package.trusted-token] codegen-units = 1 incremental = false -overflow-checks = true [profile.release] rpath = false diff --git a/USAGE.md b/USAGE.md index 23db7bf..14c0f8a 100644 --- a/USAGE.md +++ b/USAGE.md @@ -25,7 +25,7 @@ Once you have these, upload all three codes and record the code ids. I will call Note that you must use `cw20-base` (or similar) for the token in `TOKEN_ID`, as the [`InstantiateMsg` is fixed](https://github.com/confio/tfi/blob/main/packages/tfi/src/token.rs#L7-L15). -This is used for *liquidity tokens*. You can use any custom (whitelist / dso) token contract for the trading pairs. +This is used for *liquidity tokens*. You can use any custom (whitelist / trusted) token contract for the trading pairs. ## Instantiate the Factory @@ -247,4 +247,4 @@ with this request to the AMM. The final result will work like sending the native "msg": "eyJzd2FwIjp7Im1heF9zcHJlYWQiOiIwLjI1In19Cg" } } -``` \ No newline at end of file +``` diff --git a/contracts/tfi-factory/Cargo.toml b/contracts/tfi-factory/Cargo.toml index 716e5a8..ec36b44 100644 --- a/contracts/tfi-factory/Cargo.toml +++ b/contracts/tfi-factory/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tfi-factory" -version = "0.2.0" +version = "0.2.1" authors = ["Terraform Labs, PTE."] edition = "2018" description = "A tfi factory contract - auto pair contract generator and also directory for all pairs" @@ -23,7 +23,7 @@ crate-type = ["cdylib", "rlib"] backtraces = ["cosmwasm-std/backtraces"] [dependencies] -tfi = { path = "../../packages/tfi", default-features = false, version = "0.2.0"} +tfi = { path = "../../packages/tfi", default-features = false, version = "0.2.1"} cosmwasm-std = "=1.0.0-beta" cw-storage-plus = "=0.10" schemars = "0.8.1" @@ -36,8 +36,8 @@ cosmwasm-schema = "=1.0.0-beta" cosmwasm-storage = "=1.0.0-beta" anyhow = { version = "1", features = ["backtrace"] } cw-multi-test = "=0.10" -tfi-pair = { path = "../tfi-pair", version = "0.2.0" } -dso-token = { path = "../dso-token", version = "0.2.0" } +tfi-pair = { path = "../tfi-pair", version = "0.2.1" } +trusted-token = { path = "../trusted-token", version = "0.2.1" } derivative = "2" cw4-group = { version = "=0.10", features = ["library"] } cw4 = "=0.10" diff --git a/contracts/tfi-factory/src/multitest.rs b/contracts/tfi-factory/src/multitest.rs index a3d0954..53dc1be 100644 --- a/contracts/tfi-factory/src/multitest.rs +++ b/contracts/tfi-factory/src/multitest.rs @@ -85,7 +85,7 @@ fn pair_not_whitelisted() { .provide_liquidity(&pair, &lp, 2000, 6000) .unwrap_err(); - assert_error(err, dso_token::error::ContractError::Unauthorized {}); + assert_error(err, trusted_token::error::ContractError::Unauthorized {}); } /// Failure test showing up, that it is impossible to provide liquidity nor swap with pair by @@ -123,11 +123,11 @@ fn actors_not_whitelisted() { let err = suite .increase_allowance(&cash.addr(), &lp, &pair, 6000) .unwrap_err(); - assert_error(err, dso_token::error::ContractError::Unauthorized {}); + assert_error(err, trusted_token::error::ContractError::Unauthorized {}); // As non-member liquidity provider is not allowed to provide liquidity let err = suite.provide_liquidity(&pair, &lp, 2000, 6000).unwrap_err(); - assert_error(err, dso_token::error::ContractError::Unauthorized {}); + assert_error(err, trusted_token::error::ContractError::Unauthorized {}); // Even if lp is later added, he would need to increase allowance first, as previous attempt // failed @@ -140,8 +140,8 @@ fn actors_not_whitelisted() { // Non whitelisted members has no swap rights let err = suite.swap_btc(&pair, &trader, 1000).unwrap_err(); - assert_error(err, dso_token::error::ContractError::Unauthorized {}); + assert_error(err, trusted_token::error::ContractError::Unauthorized {}); let err = suite.swap_cash(&pair, &trader, 1000).unwrap_err(); - assert_error(err, dso_token::error::ContractError::Unauthorized {}); + assert_error(err, trusted_token::error::ContractError::Unauthorized {}); } diff --git a/contracts/tfi-factory/src/multitest/suite.rs b/contracts/tfi-factory/src/multitest/suite.rs index 469131c..156b55f 100644 --- a/contracts/tfi-factory/src/multitest/suite.rs +++ b/contracts/tfi-factory/src/multitest/suite.rs @@ -59,9 +59,9 @@ fn contract_cw20() -> Box> { fn contract_token() -> Box> { Box::new(ContractWrapper::new( - dso_token::contract::execute, - dso_token::contract::instantiate, - dso_token::contract::query, + trusted_token::contract::execute, + trusted_token::contract::instantiate, + trusted_token::contract::query, )) } @@ -76,7 +76,7 @@ fn contract_group() -> Box> { /// Testing environment with: /// * single native token "btc" /// * single cw4-group used as whitelist -/// * single dso-token "cash" using internal group +/// * single trusted-token "cash" using internal group /// * single tfi-factory /// * number of actors which are just address initialized with some "btc" and "cash" /// @@ -94,7 +94,7 @@ pub struct Suite { pub actors: Vec, /// cw4 whitelist contract address pub whitelist: Cw4Contract, - /// dso-token cash contract address + /// trusted-token cash contract address pub cash: Cw20Contract, /// tfi-factory contract address pub factory: Addr, @@ -414,7 +414,7 @@ impl Config { app.instantiate_contract( cw20_id, owner.clone(), - &dso_token::msg::InstantiateMsg { + &trusted_token::msg::InstantiateMsg { name: "Cash Token".to_owned(), symbol: "CASH".to_owned(), decimals: 9, diff --git a/contracts/tfi-pair/Cargo.toml b/contracts/tfi-pair/Cargo.toml index f0b127b..a33f8a7 100644 --- a/contracts/tfi-pair/Cargo.toml +++ b/contracts/tfi-pair/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tfi-pair" -version = "0.2.0" +version = "0.2.1" authors = ["Terraform Labs, PTE."] edition = "2018" description = "A tfi pair contract" @@ -24,7 +24,7 @@ backtraces = ["cosmwasm-std/backtraces"] [dependencies] integer-sqrt = "0.1.5" -tfi = { path = "../../packages/tfi", default-features = false, version = "0.2.0"} +tfi = { path = "../../packages/tfi", default-features = false, version = "0.2.1"} cw2 = "=0.10" cw20 = "=0.10" cosmwasm-std = "=1.0.0-beta" @@ -38,6 +38,6 @@ cosmwasm-schema = "=1.0.0-beta" cosmwasm-storage = "=1.0.0-beta" cw20-base = { version = "=0.10", features = ["library"] } cw-multi-test = { version = "=0.10" } -tfi-mocks = { path = "../../packages/mocks", version = "0.2.0"} +tfi-mocks = { path = "../../packages/mocks", version = "0.2.1"} derivative = "2" anyhow = { version = "1", features = ["backtrace"] } diff --git a/contracts/dso-token/.cargo/config b/contracts/trusted-token/.cargo/config similarity index 100% rename from contracts/dso-token/.cargo/config rename to contracts/trusted-token/.cargo/config diff --git a/contracts/dso-token/Cargo.toml b/contracts/trusted-token/Cargo.toml similarity index 95% rename from contracts/dso-token/Cargo.toml rename to contracts/trusted-token/Cargo.toml index 73282ce..7710a0c 100644 --- a/contracts/dso-token/Cargo.toml +++ b/contracts/trusted-token/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "dso-token" -version = "0.2.0" +name = "trusted-token" +version = "0.2.1" authors = ["Ethan Frey "] edition = "2018" diff --git a/contracts/dso-token/README.md b/contracts/trusted-token/README.md similarity index 68% rename from contracts/dso-token/README.md rename to contracts/trusted-token/README.md index 3bf4ea7..bef5727 100644 --- a/contracts/dso-token/README.md +++ b/contracts/trusted-token/README.md @@ -1,12 +1,12 @@ -# DSO Token +# Trusted Token -This is a cw20-based token with whitelisting, to be used in the context of a DSO. +This is a cw20-based token with whitelisting, to be used in the context of a Trusted Circle. It can be used to provide one side of a trading pair in an AMM setting. Only whitelisted users will be able to add liquidity to the token, and trade it. -## Differences between standard cw20 and dso-token +## Differences between standard cw20 and trusted-token ### Instantiation @@ -27,6 +27,53 @@ pub struct InstantiateMsg { New field is the address of cw4 group contract. Only addresses being members of this group would be able to trade this token. +### Execution + +We override the `execute` method and check that all addresses (sender, recipient, owner if sending on someone else's behalf) +are members of the whitelist contract before dispatching to the standard `cw20-base` action. This looks like: + +```rust +pub fn execute() { + let res = match msg { + ExecuteMsg::Transfer { recipient, amount } => { + verify_sender_and_addresses_on_whitelist(deps.as_ref(), &info.sender, & [&recipient])?; + cw20_base::contract::execute_transfer(deps, env, info, recipient, amount)? + } + // other variants.... + }; + // rest of code... +} +``` + +The key logic then looks like this: + +```rust +pub(crate) fn verify_sender_and_addresses_on_whitelist( + deps: Deps, + sender: &Addr, + addresses: &[&str], +) -> Result<(), ContractError> { + let whitelist: Cw4Contract = WHITELIST.load(deps.storage)?; + if whitelist.is_member(&deps.querier, sender)?.is_none() { + return Err(ContractError::Unauthorized {}); + } + for address in addresses { + let validated_address = deps.api.addr_validate(address)?; + if whitelist + .is_member(&deps.querier, &validated_address)? + .is_none() + { + return Err(ContractError::Unauthorized {}); + } + } + Ok(()) +} +``` + +Note that it just checks if the member is present in the group contract, it is unimportant what weight it has. +This means that even 0 weight (which will not allow it to vote in voting contracts) is sufficient to pass the whitelist. +It must be fully removed from the group contract to no longer pass the whitelisting check. + ## New messages ### Redeem diff --git a/contracts/dso-token/examples/schema.rs b/contracts/trusted-token/examples/schema.rs similarity index 96% rename from contracts/dso-token/examples/schema.rs rename to contracts/trusted-token/examples/schema.rs index 856cdb3..e248d63 100644 --- a/contracts/dso-token/examples/schema.rs +++ b/contracts/trusted-token/examples/schema.rs @@ -3,7 +3,7 @@ use std::fs::create_dir_all; use cosmwasm_schema::{export_schema, remove_schemas, schema_for}; -use dso_token::msg::{ +use trusted_token::msg::{ AllRedeemsResponse, ExecuteMsg, InstantiateMsg, IsWhitelistedResponse, QueryMsg, RedeemResponse, WhitelistResponse, }; diff --git a/contracts/dso-token/rustfmt.toml b/contracts/trusted-token/rustfmt.toml similarity index 100% rename from contracts/dso-token/rustfmt.toml rename to contracts/trusted-token/rustfmt.toml diff --git a/contracts/dso-token/schema/all_redeems_response.json b/contracts/trusted-token/schema/all_redeems_response.json similarity index 100% rename from contracts/dso-token/schema/all_redeems_response.json rename to contracts/trusted-token/schema/all_redeems_response.json diff --git a/contracts/dso-token/schema/execute_msg.json b/contracts/trusted-token/schema/execute_msg.json similarity index 100% rename from contracts/dso-token/schema/execute_msg.json rename to contracts/trusted-token/schema/execute_msg.json diff --git a/contracts/dso-token/schema/instantiate_msg.json b/contracts/trusted-token/schema/instantiate_msg.json similarity index 100% rename from contracts/dso-token/schema/instantiate_msg.json rename to contracts/trusted-token/schema/instantiate_msg.json diff --git a/contracts/dso-token/schema/is_whitelisted_response.json b/contracts/trusted-token/schema/is_whitelisted_response.json similarity index 100% rename from contracts/dso-token/schema/is_whitelisted_response.json rename to contracts/trusted-token/schema/is_whitelisted_response.json diff --git a/contracts/dso-token/schema/query_msg.json b/contracts/trusted-token/schema/query_msg.json similarity index 100% rename from contracts/dso-token/schema/query_msg.json rename to contracts/trusted-token/schema/query_msg.json diff --git a/contracts/dso-token/schema/redeem_response.json b/contracts/trusted-token/schema/redeem_response.json similarity index 100% rename from contracts/dso-token/schema/redeem_response.json rename to contracts/trusted-token/schema/redeem_response.json diff --git a/contracts/dso-token/schema/whitelist_response.json b/contracts/trusted-token/schema/whitelist_response.json similarity index 100% rename from contracts/dso-token/schema/whitelist_response.json rename to contracts/trusted-token/schema/whitelist_response.json diff --git a/contracts/dso-token/src/contract.rs b/contracts/trusted-token/src/contract.rs similarity index 99% rename from contracts/dso-token/src/contract.rs rename to contracts/trusted-token/src/contract.rs index 072be6b..8ec8448 100644 --- a/contracts/dso-token/src/contract.rs +++ b/contracts/trusted-token/src/contract.rs @@ -21,7 +21,7 @@ use crate::msg::{ use crate::state::{Redeem, REEDEMS, WHITELIST}; // version info for migration info -const CONTRACT_NAME: &str = "crates.io:dso-token"; +const CONTRACT_NAME: &str = "crates.io:trusted-token"; const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); // settings for pagination const MAX_LIMIT: u32 = 30; diff --git a/contracts/dso-token/src/error.rs b/contracts/trusted-token/src/error.rs similarity index 100% rename from contracts/dso-token/src/error.rs rename to contracts/trusted-token/src/error.rs diff --git a/contracts/dso-token/src/lib.rs b/contracts/trusted-token/src/lib.rs similarity index 100% rename from contracts/dso-token/src/lib.rs rename to contracts/trusted-token/src/lib.rs diff --git a/contracts/dso-token/src/msg.rs b/contracts/trusted-token/src/msg.rs similarity index 100% rename from contracts/dso-token/src/msg.rs rename to contracts/trusted-token/src/msg.rs diff --git a/contracts/dso-token/src/multitest.rs b/contracts/trusted-token/src/multitest.rs similarity index 100% rename from contracts/dso-token/src/multitest.rs rename to contracts/trusted-token/src/multitest.rs diff --git a/contracts/dso-token/src/multitest/suite.rs b/contracts/trusted-token/src/multitest/suite.rs similarity index 99% rename from contracts/dso-token/src/multitest/suite.rs rename to contracts/trusted-token/src/multitest/suite.rs index f806a1a..5de2273 100644 --- a/contracts/dso-token/src/multitest/suite.rs +++ b/contracts/trusted-token/src/multitest/suite.rs @@ -127,7 +127,7 @@ fn contract_cw20() -> Box> { Box::new(contract) } -/// Testing environment with dso-token "cash", and configured members +/// Testing environment with trusted-token "cash", and configured members #[derive(Derivative)] #[derivative(Debug)] pub struct Suite { @@ -142,7 +142,7 @@ pub struct Suite { pub minter: Option, /// cw4 whitelist contract address pub whitelist: Cw4Contract, - /// dso-token cash contract address + /// trusted-token cash contract address pub cash: Cw20Contract, } diff --git a/contracts/dso-token/src/state.rs b/contracts/trusted-token/src/state.rs similarity index 100% rename from contracts/dso-token/src/state.rs rename to contracts/trusted-token/src/state.rs diff --git a/packages/mocks/Cargo.toml b/packages/mocks/Cargo.toml index 55be88d..7fd6305 100644 --- a/packages/mocks/Cargo.toml +++ b/packages/mocks/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tfi-mocks" -version = "0.2.0" +version = "0.2.1" authors = ["Ethan Frey "] edition = "2018" description = "Mocks for tfi tests" @@ -11,7 +11,7 @@ homepage = "https://tgrade.finance" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -tfi = { path = "../tfi", version = "0.2.0" } +tfi = { path = "../tfi", version = "0.2.1" } cw20 = "=0.10" cosmwasm-storage = "=1.0.0-beta" cosmwasm-std = "=1.0.0-beta" diff --git a/packages/tfi/Cargo.toml b/packages/tfi/Cargo.toml index e0bf9f0..ac46652 100644 --- a/packages/tfi/Cargo.toml +++ b/packages/tfi/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tfi" -version = "0.2.0" +version = "0.2.1" authors = ["Ethan Frey "] edition = "2018" description = "Common tfi types" @@ -24,5 +24,5 @@ serde = { version = "1.0.103", default-features = false, features = ["derive"] } [dev-dependencies] cosmwasm-schema = "=1.0.0-beta" -tfi-mocks = { path = "../mocks", version = "0.2.0" } +tfi-mocks = { path = "../mocks", version = "0.2.1" } diff --git a/packages/trusted-circle/Cargo.toml b/packages/trusted-circle/Cargo.toml index 412368b..96e8170 100644 --- a/packages/trusted-circle/Cargo.toml +++ b/packages/trusted-circle/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "trusted-circle" -version = "0.2.0" +version = "0.2.1" authors = ["Ethan Frey "] edition = "2018" description = "Public API to call into the trusted-circle contracts"