From f8f9071895e24b96fd2a209ab836ca6251a7417a Mon Sep 17 00:00:00 2001 From: Noah Saso Date: Mon, 18 Dec 2023 00:31:01 -0800 Subject: [PATCH] Support both osmosis and cosmwasm tokenfactory msg standards via feature flags. --- Cargo.lock | 63 ++-- Cargo.toml | 8 +- .../cw-tokenfactory-issuer/Cargo.toml | 20 +- .../cw-tokenfactory-issuer/src/contract.rs | 26 +- .../cw-tokenfactory-issuer/src/execute.rs | 103 +++---- .../cw-tokenfactory-issuer/src/msg.rs | 6 +- .../tests/cases/allowlist.rs | 4 + .../tests/cases/beforesend.rs | 5 + .../tests/cases/contract_owner.rs | 1 + .../tests/cases/denylist.rs | 5 + .../tests/cases/force_transfer.rs | 1 + .../tests/cases/freeze.rs | 2 + .../tests/cases/mint.rs | 1 + .../tests/cases/set_before_send_hook.rs | 4 + .../cw-tokenfactory-issuer/tests/test_env.rs | 7 +- .../dao-voting-token-staked/src/contract.rs | 2 +- packages/cw-tokenfactory-types/Cargo.toml | 27 ++ packages/cw-tokenfactory-types/README.md | 12 + .../cw-tokenfactory-types/src/cosmwasm.rs | 281 ++++++++++++++++++ packages/cw-tokenfactory-types/src/lib.rs | 8 + packages/cw-tokenfactory-types/src/msg.rs | 190 ++++++++++++ packages/cw-tokenfactory-types/src/shim.rs | 88 ++++++ packages/dao-testing/Cargo.toml | 1 - 23 files changed, 761 insertions(+), 104 deletions(-) create mode 100644 packages/cw-tokenfactory-types/Cargo.toml create mode 100644 packages/cw-tokenfactory-types/README.md create mode 100644 packages/cw-tokenfactory-types/src/cosmwasm.rs create mode 100644 packages/cw-tokenfactory-types/src/lib.rs create mode 100644 packages/cw-tokenfactory-types/src/msg.rs create mode 100644 packages/cw-tokenfactory-types/src/shim.rs diff --git a/Cargo.lock b/Cargo.lock index 26d684f7b..324ceafc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -438,7 +438,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20b42021d8488665b1a0d9748f1f81df7235362d194f44481e2e61bf376b77b4" dependencies = [ "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", "tendermint-proto 0.23.9", ] @@ -449,7 +449,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673d31bd830c0772d78545de20d975129b6ab2f7db4e4e9313c3b8777d319194" dependencies = [ "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", "tendermint-proto 0.26.0", "tonic 0.8.3", ] @@ -461,7 +461,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73c9d2043a9e617b0d602fbc0a0ecd621568edbf3a9774890a6d562389bd8e1c" dependencies = [ "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", "tendermint-proto 0.32.2", "tonic 0.9.2", ] @@ -1020,15 +1020,32 @@ dependencies = [ "cw-multi-test", "cw-ownable", "cw-storage-plus 1.2.0", + "cw-tokenfactory-types", "cw2 1.1.2", + "dao-interface", "osmosis-std", "osmosis-test-tube", - "prost 0.11.9", + "prost 0.12.3", "schemars", "serde", "serde_json", "thiserror", - "token-bindings", +] + +[[package]] +name = "cw-tokenfactory-types" +version = "2.4.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "dao-interface", + "osmosis-std", + "osmosis-std-derive", + "prost 0.12.3", + "prost-types 0.12.3", + "schemars", + "serde", + "serde-cw-value", ] [[package]] @@ -2004,7 +2021,6 @@ dependencies = [ "serde", "serde_json", "stake-cw20", - "token-bindings", ] [[package]] @@ -3154,7 +3170,7 @@ dependencies = [ "cosmwasm-std", "osmosis-std-derive", "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", "schemars", "serde", "serde-cw-value", @@ -3168,7 +3184,7 @@ checksum = "c5ebdfd1bc8ed04db596e110c6baa9b174b04f6ed1ec22c666ddc5cb3fa91bd7" dependencies = [ "itertools 0.10.5", "proc-macro2", - "prost-types", + "prost-types 0.11.9", "quote", "syn 1.0.109", ] @@ -3440,6 +3456,15 @@ dependencies = [ "prost 0.11.9", ] +[[package]] +name = "prost-types" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" +dependencies = [ + "prost 0.12.3", +] + [[package]] name = "quote" version = "1.0.33" @@ -4104,7 +4129,7 @@ dependencies = [ "num-traits", "once_cell", "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", "ripemd160", "serde", "serde_bytes", @@ -4135,7 +4160,7 @@ dependencies = [ "num-traits", "once_cell", "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", "ripemd160", "serde", "serde_bytes", @@ -4189,7 +4214,7 @@ dependencies = [ "num-derive", "num-traits", "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", "serde", "serde_bytes", "subtle-encoding", @@ -4207,7 +4232,7 @@ dependencies = [ "num-derive", "num-traits", "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", "serde", "serde_bytes", "subtle-encoding", @@ -4225,7 +4250,7 @@ dependencies = [ "num-derive", "num-traits", "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", "serde", "serde_bytes", "subtle-encoding", @@ -4397,18 +4422,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" -[[package]] -name = "token-bindings" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be1c893c90d2993320d9722516ece705460f464616313a62edadb9e71df4502" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "schemars", - "serde", -] - [[package]] name = "tokio" version = "1.34.0" diff --git a/Cargo.toml b/Cargo.toml index 3bf5781db..dcdf1b5c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ members = [ "packages/*", "ci/*", ] +resolver = "2" [workspace.package] edition = "2021" @@ -55,13 +56,16 @@ cw721-base = "0.18" env_logger = "0.10" once_cell = "1.18" osmosis-std = "0.20.1" +osmosis-std-derive = "0.20.1" osmosis-test-tube = "20.1.1" proc-macro2 = "1.0" -prost = "0.11" +prost = { version = "0.12.3", features = ["prost-derive"] } +prost-types = { version = "0.12.3", default-features = false } quote = "1.0" rand = "0.8" schemars = "0.8" serde = { version = "1.0", default-features = false, features = ["derive"] } +serde-cw-value = "0.7" serde_json = "1.0" serde_yaml = "0.9" sg-multi-test = "3.1.0" @@ -71,7 +75,6 @@ sg721-base = "3.1.0" syn = { version = "1.0", features = ["derive"] } test-context = "0.1" thiserror = { version = "1.0" } -token-bindings = "0.11.0" wynd-utils = "0.4" # One commit ahead of version 0.3.0. Allows initialization with an @@ -85,6 +88,7 @@ cw-paginate-storage = { path = "./packages/cw-paginate-storage", version = "2.4. cw-payroll-factory = { path = "./contracts/external/cw-payroll-factory", version = "2.4.0" } cw-stake-tracker = { path = "./packages/cw-stake-tracker", version = "2.4.0" } cw-tokenfactory-issuer = { path = "./contracts/external/cw-tokenfactory-issuer", version = "2.4.0" } +cw-tokenfactory-types = { path = "./packages/cw-tokenfactory-types", version = "2.4.0", default-features = false } cw-vesting = { path = "./contracts/external/cw-vesting", version = "2.4.0" } cw-wormhole = { path = "./packages/cw-wormhole", version = "2.4.0" } cw20-stake = { path = "./contracts/staking/cw20-stake", version = "2.4.0" } diff --git a/contracts/external/cw-tokenfactory-issuer/Cargo.toml b/contracts/external/cw-tokenfactory-issuer/Cargo.toml index 66fc81ada..41bcc89ac 100644 --- a/contracts/external/cw-tokenfactory-issuer/Cargo.toml +++ b/contracts/external/cw-tokenfactory-issuer/Cargo.toml @@ -1,5 +1,9 @@ [package] -authors = ["Maurits Bos ", "Sunny Aggarwal ", "Jake Hartnell "] +authors = [ + "Maurits Bos ", + "Sunny Aggarwal ", + "Jake Hartnell ", +] name = "cw-tokenfactory-issuer" description = "A CosmWasm contract that issues new Token Factory tokens on supported chains." version = { workspace = true } @@ -23,15 +27,18 @@ exclude = [ crate-type = ["cdylib", "rlib"] [features] +default = ["osmosis_tokenfactory"] # for more explicit tests, cargo test --features=backtraces backtraces = ["cosmwasm-std/backtraces"] # use library feature to disable all instantiate/execute/query exports library = [] # use test tube feature to enable test-tube integration tests, for example # cargo test --features "test-tube" -test-tube = [] -# when writing tests you may wish to enable test-tube as a default feature -# default = ["test-tube"] +test-tube = ["osmosis_tokenfactory"] +# different tokenfactory cosmos sdk module standards. enable corresponding +# standard in types library +osmosis_tokenfactory = ["cw-tokenfactory-types/osmosis_tokenfactory"] +cosmwasm_tokenfactory = ["cw-tokenfactory-types/cosmwasm_tokenfactory"] [dependencies] cosmwasm-schema = { workspace = true } @@ -40,12 +47,13 @@ cosmwasm-storage = { workspace = true } cw2 = { workspace = true } cw-ownable = { workspace = true } cw-storage-plus = { workspace = true } +cw-tokenfactory-types = { workspace = true, default-features = false } +dao-interface = { workspace = true } osmosis-std = { workspace = true } prost = { workspace = true } schemars = { workspace = true } -serde = { workspace = true, default-features = false, features = ["derive"]} +serde = { workspace = true, default-features = false, features = ["derive"] } thiserror = { workspace = true } -token-bindings = { workspace = true } [dev-dependencies] cosmwasm-schema = { workspace = true } diff --git a/contracts/external/cw-tokenfactory-issuer/src/contract.rs b/contracts/external/cw-tokenfactory-issuer/src/contract.rs index 1879a52a6..1eb6ece16 100644 --- a/contracts/external/cw-tokenfactory-issuer/src/contract.rs +++ b/contracts/external/cw-tokenfactory-issuer/src/contract.rs @@ -3,12 +3,10 @@ use std::convert::TryInto; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult, SubMsg, + to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, StdResult, SubMsg, }; -use cosmwasm_std::{CosmosMsg, Reply}; use cw2::{get_contract_version, set_contract_version, ContractVersion}; -use osmosis_std::types::osmosis::tokenfactory::v1beta1::{MsgCreateDenom, MsgCreateDenomResponse}; -use token_bindings::TokenFactoryMsg; +use cw_tokenfactory_types::msg::{msg_create_denom, MsgCreateDenomResponse}; use crate::error::ContractError; use crate::execute; @@ -29,7 +27,7 @@ pub fn instantiate( env: Env, info: MessageInfo, msg: InstantiateMsg, -) -> Result, ContractError> { +) -> Result { set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; // Owner is the sender of the initial InstantiateMsg @@ -54,10 +52,7 @@ pub fn instantiate( .add_submessage( // Create new denom, denom info is saved in the reply SubMsg::reply_on_success( - >::from(MsgCreateDenom { - sender: env.contract.address.to_string(), - subdenom, - }), + msg_create_denom(env.contract.address.to_string(), subdenom), CREATE_DENOM_REPLY_ID, ), )) @@ -79,7 +74,7 @@ pub fn execute( env: Env, info: MessageInfo, msg: ExecuteMsg, -) -> Result, ContractError> { +) -> Result { match msg { // Executive Functions ExecuteMsg::Mint { to_address, amount } => { @@ -92,6 +87,8 @@ pub fn execute( ExecuteMsg::Deny { address, status } => execute::deny(deps, env, info, address, status), ExecuteMsg::Allow { address, status } => execute::allow(deps, info, address, status), ExecuteMsg::Freeze { status } => execute::freeze(deps, env, info, status), + + #[cfg(feature = "osmosis_tokenfactory")] ExecuteMsg::ForceTransfer { amount, from_address, @@ -100,7 +97,7 @@ pub fn execute( // Admin functions ExecuteMsg::UpdateTokenFactoryAdmin { new_admin } => { - execute::update_tokenfactory_admin(deps, info, new_admin) + execute::update_tokenfactory_admin(deps, env, info, new_admin) } ExecuteMsg::UpdateOwnership(action) => { execute::update_contract_owner(deps, env, info, action) @@ -111,6 +108,7 @@ pub fn execute( ExecuteMsg::SetBurnerAllowance { address, allowance } => { execute::set_burner(deps, info, address, allowance) } + #[cfg(feature = "osmosis_tokenfactory")] ExecuteMsg::SetBeforeSendHook { cosmwasm_address } => { execute::set_before_send_hook(deps, env, info, cosmwasm_address) } @@ -177,11 +175,7 @@ pub fn migrate(deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result Result, ContractError> { +pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> Result { match msg.id { CREATE_DENOM_REPLY_ID => { let MsgCreateDenomResponse { new_token_denom } = msg.result.try_into()?; diff --git a/contracts/external/cw-tokenfactory-issuer/src/execute.rs b/contracts/external/cw-tokenfactory-issuer/src/execute.rs index 09a84f248..064af7ffd 100644 --- a/contracts/external/cw-tokenfactory-issuer/src/execute.rs +++ b/contracts/external/cw-tokenfactory-issuer/src/execute.rs @@ -1,16 +1,17 @@ -use cosmwasm_std::{coins, BankMsg, Coin, CosmosMsg, DepsMut, Env, MessageInfo, Response, Uint128}; -use osmosis_std::types::cosmos::bank::v1beta1::Metadata; -use osmosis_std::types::osmosis::tokenfactory::v1beta1::{ - MsgBurn, MsgForceTransfer, MsgSetBeforeSendHook, MsgSetDenomMetadata, -}; -use token_bindings::TokenFactoryMsg; +use cosmwasm_std::{coins, BankMsg, CosmosMsg, DepsMut, Env, MessageInfo, Response, Uint128}; + +use cw_tokenfactory_types::msg::{msg_burn, msg_change_admin, msg_mint, msg_set_denom_metadata}; +#[cfg(feature = "osmosis_tokenfactory")] +use cw_tokenfactory_types::msg::{msg_force_transfer, msg_set_before_send_hook}; + +use dao_interface::token::Metadata; use crate::error::ContractError; use crate::helpers::{check_before_send_hook_features_enabled, check_is_not_frozen}; -use crate::state::{ - BeforeSendHookInfo, ALLOWLIST, BEFORE_SEND_HOOK_INFO, BURNER_ALLOWANCES, DENOM, DENYLIST, - IS_FROZEN, MINTER_ALLOWANCES, -}; + +#[cfg(feature = "osmosis_tokenfactory")] +use crate::state::{BeforeSendHookInfo, BEFORE_SEND_HOOK_INFO}; +use crate::state::{ALLOWLIST, BURNER_ALLOWANCES, DENOM, DENYLIST, IS_FROZEN, MINTER_ALLOWANCES}; /// Mints new tokens. To mint new tokens, the address calling this method must /// have an allowance of tokens to mint. This allowance is set by the contract through @@ -21,7 +22,7 @@ pub fn mint( info: MessageInfo, to_address: String, amount: Uint128, -) -> Result, ContractError> { +) -> Result { // Validate that to_address is a valid address deps.api.addr_validate(&to_address)?; @@ -54,10 +55,10 @@ pub fn mint( check_is_not_frozen(deps.as_ref(), info.sender.as_str(), &to_address, &denom)?; // Create tokenfactory MsgMint which mints coins to the contract address - let mint_tokens_msg = TokenFactoryMsg::mint_contract_tokens( + let mint_tokens_msg = msg_mint( + env.contract.address.to_string(), + amount.u128(), denom.clone(), - amount, - env.contract.address.into_string(), ); // Send newly minted coins from contract to designated recipient @@ -85,7 +86,7 @@ pub fn burn( info: MessageInfo, amount: Uint128, address: String, -) -> Result, ContractError> { +) -> Result { // Don't allow burning of 0 coins if amount.is_zero() { return Err(ContractError::ZeroAmount {}); @@ -114,11 +115,12 @@ pub fn burn( // Create tokenfactory MsgBurn which burns coins from the contract address // NOTE: this requires the contract to own the tokens already let burn_from_address = deps.api.addr_validate(&address)?; - let burn_tokens_msg: cosmwasm_std::CosmosMsg = MsgBurn { - sender: env.contract.address.to_string(), - amount: Some(Coin::new(amount.u128(), denom).into()), - burn_from_address: burn_from_address.to_string(), - } + let burn_tokens_msg: CosmosMsg = msg_burn( + env.contract.address.to_string(), + amount.u128(), + denom, + burn_from_address.to_string(), + ) .into(); Ok(Response::new() @@ -136,7 +138,7 @@ pub fn update_contract_owner( env: Env, info: MessageInfo, action: cw_ownable::Action, -) -> Result, ContractError> { +) -> Result { // cw-ownable performs all validation and ownership checks for us let ownership = cw_ownable::update_ownership(deps, &env.block, &info.sender, action)?; Ok(Response::default().add_attributes(ownership.into_attributes())) @@ -149,9 +151,10 @@ pub fn update_contract_owner( /// Must be the contract owner to call this method. pub fn update_tokenfactory_admin( deps: DepsMut, + env: Env, info: MessageInfo, new_admin: String, -) -> Result, ContractError> { +) -> Result { // Only allow current contract owner to change tokenfactory admin cw_ownable::assert_owner(deps.storage, &info.sender)?; @@ -159,10 +162,11 @@ pub fn update_tokenfactory_admin( let new_admin_addr = deps.api.addr_validate(&new_admin)?; // Construct tokenfactory change admin msg - let update_admin_msg = TokenFactoryMsg::ChangeAdmin { - denom: DENOM.load(deps.storage)?, - new_admin_address: new_admin_addr.into(), - }; + let update_admin_msg = msg_change_admin( + env.contract.address.to_string(), + DENOM.load(deps.storage)?, + new_admin_addr.into(), + ); Ok(Response::new() .add_message(update_admin_msg) @@ -178,16 +182,16 @@ pub fn set_denom_metadata( env: Env, info: MessageInfo, metadata: Metadata, -) -> Result, ContractError> { +) -> Result { // Only allow current contract owner to set denom metadata cw_ownable::assert_owner(deps.storage, &info.sender)?; Ok(Response::new() .add_attribute("action", "set_denom_metadata") - .add_message(MsgSetDenomMetadata { - sender: env.contract.address.to_string(), - metadata: Some(metadata), - })) + .add_message(msg_set_denom_metadata( + env.contract.address.to_string(), + metadata, + ))) } /// Calls `MsgSetBeforeSendHook` and enables BeforeSendHook related features. @@ -199,12 +203,13 @@ pub fn set_denom_metadata( /// is intended to be called should chains add this feature at a later date. /// /// Must be the contract owner to call this method. +#[cfg(feature = "osmosis_tokenfactory")] pub fn set_before_send_hook( deps: DepsMut, env: Env, info: MessageInfo, cosmwasm_address: String, -) -> Result, ContractError> { +) -> Result { // Only allow current contract owner cw_ownable::assert_owner(deps.storage, &info.sender)?; @@ -247,12 +252,8 @@ pub fn set_before_send_hook( // SetBeforeSendHook to this contract. // This will trigger sudo endpoint before any bank send, // which makes denylisting / freezing possible. - let msg_set_beforesend_hook: CosmosMsg = MsgSetBeforeSendHook { - sender: env.contract.address.to_string(), - denom, - cosmwasm_address, - } - .into(); + let msg_set_beforesend_hook: CosmosMsg = + msg_set_before_send_hook(env.contract.address.to_string(), denom, cosmwasm_address).into(); Ok(Response::new() .add_attribute("action", "set_before_send_hook") @@ -268,7 +269,7 @@ pub fn set_burner( info: MessageInfo, address: String, allowance: Uint128, -) -> Result, ContractError> { +) -> Result { // Only allow current contract owner to set burner allowance cw_ownable::assert_owner(deps.storage, &info.sender)?; @@ -297,7 +298,7 @@ pub fn set_minter( info: MessageInfo, address: String, allowance: Uint128, -) -> Result, ContractError> { +) -> Result { // Only allow current contract owner to set minter allowance cw_ownable::assert_owner(deps.storage, &info.sender)?; @@ -337,7 +338,7 @@ pub fn freeze( env: Env, info: MessageInfo, status: bool, -) -> Result, ContractError> { +) -> Result { check_before_send_hook_features_enabled(deps.as_ref())?; // Only allow current contract owner to call this method @@ -371,7 +372,7 @@ pub fn deny( info: MessageInfo, address: String, status: bool, -) -> Result, ContractError> { +) -> Result { check_before_send_hook_features_enabled(deps.as_ref())?; // Only allow current contract owner to call this method @@ -411,7 +412,7 @@ pub fn allow( info: MessageInfo, address: String, status: bool, -) -> Result, ContractError> { +) -> Result { check_before_send_hook_features_enabled(deps.as_ref())?; // Only allow current contract owner to call this method @@ -439,6 +440,7 @@ pub fn allow( /// admin to be a null address or the address of the bank module. /// /// Must be the contract owner to call this method. +#[cfg(feature = "osmosis_tokenfactory")] pub fn force_transfer( deps: DepsMut, env: Env, @@ -446,7 +448,7 @@ pub fn force_transfer( amount: Uint128, from_address: String, to_address: String, -) -> Result, ContractError> { +) -> Result { // Only allow current contract owner to change owner cw_ownable::assert_owner(deps.storage, &info.sender)?; @@ -454,12 +456,13 @@ pub fn force_transfer( let denom = DENOM.load(deps.storage)?; // Force transfer tokens - let force_transfer_msg: CosmosMsg = MsgForceTransfer { - transfer_from_address: from_address.clone(), - transfer_to_address: to_address.clone(), - amount: Some(Coin::new(amount.u128(), denom).into()), - sender: env.contract.address.to_string(), - } + let force_transfer_msg: CosmosMsg = msg_force_transfer( + env.contract.address.to_string(), + amount.u128(), + denom, + from_address.clone(), + to_address.clone(), + ) .into(); Ok(Response::new() diff --git a/contracts/external/cw-tokenfactory-issuer/src/msg.rs b/contracts/external/cw-tokenfactory-issuer/src/msg.rs index 3c874e584..4587a0ea5 100644 --- a/contracts/external/cw-tokenfactory-issuer/src/msg.rs +++ b/contracts/external/cw-tokenfactory-issuer/src/msg.rs @@ -1,8 +1,8 @@ +use crate::state::BeforeSendHookInfo; use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::{Coin, Uint128}; -pub use osmosis_std::types::cosmos::bank::v1beta1::{DenomUnit, Metadata}; -use crate::state::BeforeSendHookInfo; +pub use dao_interface::token::{DenomUnit, Metadata}; /// The message used to create a new instance of this smart contract. #[cw_serde] @@ -52,6 +52,7 @@ pub enum ExecuteMsg { Freeze { status: bool }, /// Force transfer token from one address to another. + #[cfg(feature = "osmosis_tokenfactory")] ForceTransfer { amount: Uint128, from_address: String, @@ -70,6 +71,7 @@ pub enum ExecuteMsg { /// Setting the address to an empty string will remove the SetBeforeSendHook. /// /// This method can only be called by the contract owner. + #[cfg(feature = "osmosis_tokenfactory")] SetBeforeSendHook { cosmwasm_address: String }, /// Grant/revoke burn allowance. diff --git a/contracts/external/cw-tokenfactory-issuer/tests/cases/allowlist.rs b/contracts/external/cw-tokenfactory-issuer/tests/cases/allowlist.rs index 9d1da91d8..c9737fc62 100644 --- a/contracts/external/cw-tokenfactory-issuer/tests/cases/allowlist.rs +++ b/contracts/external/cw-tokenfactory-issuer/tests/cases/allowlist.rs @@ -5,6 +5,7 @@ use crate::test_env::{ test_query_over_default_limit, test_query_within_default_limit, TestEnv, TokenfactoryIssuer, }; +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn allowlist_by_owner_should_pass() { let env = TestEnv::default(); @@ -41,6 +42,7 @@ fn allowlist_by_owner_should_pass() { ); } +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn allowlist_by_non_owern_should_fail() { let env = TestEnv::default(); @@ -67,6 +69,7 @@ fn allowlist_by_non_owern_should_fail() { ); } +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn query_allowlist_within_default_limit() { test_query_within_default_limit::( @@ -100,6 +103,7 @@ fn query_allowlist_within_default_limit() { ); } +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn query_allowlist_over_default_limit() { test_query_over_default_limit::( diff --git a/contracts/external/cw-tokenfactory-issuer/tests/cases/beforesend.rs b/contracts/external/cw-tokenfactory-issuer/tests/cases/beforesend.rs index 49320bed8..1e15e567b 100644 --- a/contracts/external/cw-tokenfactory-issuer/tests/cases/beforesend.rs +++ b/contracts/external/cw-tokenfactory-issuer/tests/cases/beforesend.rs @@ -22,6 +22,7 @@ fn before_send_should_not_block_anything_by_default() { .unwrap(); } +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn before_send_should_block_on_frozen() { let env = TestEnv::default(); @@ -48,6 +49,7 @@ fn before_send_should_block_on_frozen() { assert_eq!(err, RunnerError::ExecuteError { msg: format!("failed to execute message; message index: 0: failed to call before send hook for denom {denom}: The contract is frozen for denom \"{denom}\". Addresses need to be added to the allowlist to enable transfers to or from an account.: execute wasm contract failed") }); } +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn allowlisted_addresses_can_transfer_when_token_frozen() { let env = TestEnv::default(); @@ -95,6 +97,7 @@ fn allowlisted_addresses_can_transfer_when_token_frozen() { .unwrap(); } +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn non_allowlisted_accounts_can_transfer_to_allowlisted_address_frozen() { let env = TestEnv::default(); @@ -129,6 +132,7 @@ fn non_allowlisted_accounts_can_transfer_to_allowlisted_address_frozen() { .unwrap(); } +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn before_send_should_block_sending_from_denylist_address() { let env = TestEnv::default(); @@ -167,6 +171,7 @@ fn before_send_should_block_sending_from_denylist_address() { assert_eq!(err, RunnerError::ExecuteError { msg: format!("failed to execute message; message index: 0: failed to call before send hook for denom {denom}: The address '{denylistee_addr}' is denied transfer abilities: execute wasm contract failed") }); } +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn before_send_should_block_sending_to_denylist_address() { let env = TestEnv::default(); diff --git a/contracts/external/cw-tokenfactory-issuer/tests/cases/contract_owner.rs b/contracts/external/cw-tokenfactory-issuer/tests/cases/contract_owner.rs index f7cc5491f..b5af63eb1 100644 --- a/contracts/external/cw-tokenfactory-issuer/tests/cases/contract_owner.rs +++ b/contracts/external/cw-tokenfactory-issuer/tests/cases/contract_owner.rs @@ -53,6 +53,7 @@ fn change_owner_by_non_owner_should_fail() { ); } +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn renounce_ownership() { let env = TestEnv::default(); diff --git a/contracts/external/cw-tokenfactory-issuer/tests/cases/denylist.rs b/contracts/external/cw-tokenfactory-issuer/tests/cases/denylist.rs index b15de2f22..4adc6d164 100644 --- a/contracts/external/cw-tokenfactory-issuer/tests/cases/denylist.rs +++ b/contracts/external/cw-tokenfactory-issuer/tests/cases/denylist.rs @@ -5,6 +5,7 @@ use crate::test_env::{ test_query_over_default_limit, test_query_within_default_limit, TestEnv, TokenfactoryIssuer, }; +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn denylist_by_owner_should_pass() { let env = TestEnv::default(); @@ -41,6 +42,7 @@ fn denylist_by_owner_should_pass() { ); } +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn denylist_by_non_owner_should_fail() { let env = TestEnv::default(); @@ -67,6 +69,7 @@ fn denylist_by_non_owner_should_fail() { ); } +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn set_denylist_to_issuer_itself_fails() { let env = TestEnv::default(); @@ -89,6 +92,7 @@ fn set_denylist_to_issuer_itself_fails() { ); } +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn query_denylist_within_default_limit() { test_query_within_default_limit::( @@ -122,6 +126,7 @@ fn query_denylist_within_default_limit() { ); } +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn query_denylist_over_default_limit() { test_query_over_default_limit::( diff --git a/contracts/external/cw-tokenfactory-issuer/tests/cases/force_transfer.rs b/contracts/external/cw-tokenfactory-issuer/tests/cases/force_transfer.rs index a02bafce9..56fc70f6c 100644 --- a/contracts/external/cw-tokenfactory-issuer/tests/cases/force_transfer.rs +++ b/contracts/external/cw-tokenfactory-issuer/tests/cases/force_transfer.rs @@ -4,6 +4,7 @@ use osmosis_test_tube::Account; use crate::test_env::{TestEnv, TokenfactoryIssuer}; +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn test_force_transfer() { let env = TestEnv::default(); diff --git a/contracts/external/cw-tokenfactory-issuer/tests/cases/freeze.rs b/contracts/external/cw-tokenfactory-issuer/tests/cases/freeze.rs index 8a9963c73..c0f67e5c9 100644 --- a/contracts/external/cw-tokenfactory-issuer/tests/cases/freeze.rs +++ b/contracts/external/cw-tokenfactory-issuer/tests/cases/freeze.rs @@ -2,6 +2,7 @@ use cw_tokenfactory_issuer::ContractError; use crate::test_env::{TestEnv, TokenfactoryIssuer}; +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn freeze_by_owener_should_pass() { let env = TestEnv::default(); @@ -33,6 +34,7 @@ fn freeze_by_owener_should_pass() { ); } +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn freeze_by_non_owner_should_fail() { let env = TestEnv::default(); diff --git a/contracts/external/cw-tokenfactory-issuer/tests/cases/mint.rs b/contracts/external/cw-tokenfactory-issuer/tests/cases/mint.rs index 594a07f4c..59f896ddd 100644 --- a/contracts/external/cw-tokenfactory-issuer/tests/cases/mint.rs +++ b/contracts/external/cw-tokenfactory-issuer/tests/cases/mint.rs @@ -102,6 +102,7 @@ fn used_up_allowance_should_be_removed_from_storage() { ); } +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn granular_minting_permissions_when_frozen() { let env = TestEnv::default(); diff --git a/contracts/external/cw-tokenfactory-issuer/tests/cases/set_before_send_hook.rs b/contracts/external/cw-tokenfactory-issuer/tests/cases/set_before_send_hook.rs index 74810986d..7caf883b4 100644 --- a/contracts/external/cw-tokenfactory-issuer/tests/cases/set_before_send_hook.rs +++ b/contracts/external/cw-tokenfactory-issuer/tests/cases/set_before_send_hook.rs @@ -5,6 +5,7 @@ use osmosis_test_tube::{Account, RunnerError}; use crate::test_env::{TestEnv, TokenfactoryIssuer}; +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn test_set_before_send_hook() { let env = TestEnv::default(); @@ -37,6 +38,7 @@ fn test_set_before_send_hook() { assert!(info.advanced_features_enabled); } +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn test_set_before_send_hook_nil() { let env = TestEnv::default(); @@ -55,6 +57,7 @@ fn test_set_before_send_hook_nil() { assert!(!info.advanced_features_enabled); } +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn test_set_before_send_hook_invalid_address_fails() { let env = TestEnv::default(); @@ -72,6 +75,7 @@ fn test_set_before_send_hook_invalid_address_fails() { ); } +#[cfg(feature = "osmosis_tokenfactory")] #[test] fn test_set_before_send_hook_to_a_different_contract() { let env = TestEnv::default(); diff --git a/contracts/external/cw-tokenfactory-issuer/tests/test_env.rs b/contracts/external/cw-tokenfactory-issuer/tests/test_env.rs index f6f4b3d1e..e997ac208 100644 --- a/contracts/external/cw-tokenfactory-issuer/tests/test_env.rs +++ b/contracts/external/cw-tokenfactory-issuer/tests/test_env.rs @@ -2,7 +2,10 @@ // see https://github.com/rust-lang/rust/issues/46379 #![allow(dead_code)] -use cosmwasm_std::{Addr, Coin, Uint128}; +#[cfg(feature = "osmosis_tokenfactory")] +use cosmwasm_std::Uint128; +use cosmwasm_std::{Addr, Coin}; + use cw_tokenfactory_issuer::msg::{AllowlistResponse, DenylistResponse, Metadata, MigrateMsg}; use cw_tokenfactory_issuer::{ msg::{ @@ -272,6 +275,7 @@ impl TokenfactoryIssuer { ) } + #[cfg(feature = "osmosis_tokenfactory")] pub fn set_before_send_hook( &self, cosmwasm_address: String, @@ -284,6 +288,7 @@ impl TokenfactoryIssuer { ) } + #[cfg(feature = "osmosis_tokenfactory")] pub fn force_transfer( &self, signer: &SigningAccount, diff --git a/contracts/voting/dao-voting-token-staked/src/contract.rs b/contracts/voting/dao-voting-token-staked/src/contract.rs index ffcba6902..8a68522ef 100644 --- a/contracts/voting/dao-voting-token-staked/src/contract.rs +++ b/contracts/voting/dao-voting-token-staked/src/contract.rs @@ -106,7 +106,7 @@ pub fn instantiate( // Save new token info for use in reply TOKEN_INSTANTIATION_INFO.save(deps.storage, &msg.token_info)?; - // Tnstantiate cw-token-factory-issuer contract + // Instantiate cw-token-factory-issuer contract // DAO (sender) is set as contract admin let issuer_instantiate_msg = SubMsg::reply_on_success( WasmMsg::Instantiate { diff --git a/packages/cw-tokenfactory-types/Cargo.toml b/packages/cw-tokenfactory-types/Cargo.toml new file mode 100644 index 000000000..67f2e1085 --- /dev/null +++ b/packages/cw-tokenfactory-types/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "cw-tokenfactory-types" +authors = ["Noah Saso "] +description = "A package for the handling of variou tokenfactory types." +edition = { workspace = true } +license = { workspace = true } +repository = { workspace = true } +version = { workspace = true } + +[features] +default = ["osmosis_tokenfactory"] +# use the /cosmwasm.tokenfactory... msg types +cosmwasm_tokenfactory = [] +# use the /osmosis.tokenfactory... msg types +osmosis_tokenfactory = [] + +[dependencies] +cosmwasm-std = { workspace = true } +cosmwasm-schema = { workspace = true } +dao-interface = { workspace = true } +osmosis-std = { workspace = true } +osmosis-std-derive = { workspace = true } +prost = { workspace = true } +prost-types = { workspace = true } +schemars = { workspace = true } +serde = { workspace = true } +serde-cw-value = { workspace = true } diff --git a/packages/cw-tokenfactory-types/README.md b/packages/cw-tokenfactory-types/README.md new file mode 100644 index 000000000..c4043b951 --- /dev/null +++ b/packages/cw-tokenfactory-types/README.md @@ -0,0 +1,12 @@ +# cw-tokenfactory-types + +This package supports contracts that depend on varying tokenfactory standards, +which use very similar or identical Cosmos SDK msgs with different type URLs: + +- `/cosmwasm.tokenfactory...` +- `/osmosis.tokenfactory...` + +Enabling the `cosmwasm_tokenfactory` build feature will use the +`/cosmwasm.tokenfactory...` msg type URLs, whereas enabling the +`osmosis_tokenfactory` build feature will use the `/osmosis.tokenfactory...` msg +type URLs. `osmosis_tokenfactory` is enabled by default. diff --git a/packages/cw-tokenfactory-types/src/cosmwasm.rs b/packages/cw-tokenfactory-types/src/cosmwasm.rs new file mode 100644 index 000000000..1c294dceb --- /dev/null +++ b/packages/cw-tokenfactory-types/src/cosmwasm.rs @@ -0,0 +1,281 @@ +use std::convert::TryFrom; +use std::convert::TryInto; + +use osmosis_std_derive::CosmwasmExt; + +// see https://github.com/notional-labs/wasmd/blob/v0.30.0-sdk469.4/proto/cosmwasm/tokenfactory/v1beta1/tx.proto + +/// Coin defines a token with a denomination and an amount. +/// +/// NOTE: The amount field is an Int which implements the custom method +/// signatures required by gogoproto. +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/cosmos.base.v1beta1.Coin")] +pub struct Coin { + #[prost(string, tag = "1")] + pub denom: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub amount: ::prost::alloc::string::String, +} + +/// DenomUnit represents a struct that describes a given +/// denomination unit of the basic token. +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/cosmos.bank.v1beta1.DenomUnit")] +pub struct DenomUnit { + /// denom represents the string name of the given denom unit (e.g uatom). + #[prost(string, tag = "1")] + pub denom: ::prost::alloc::string::String, + /// exponent represents power of 10 exponent that one must + /// raise the base_denom to in order to equal the given DenomUnit's denom + /// 1 denom = 1^exponent base_denom + /// (e.g. with a base_denom of uatom, one can create a DenomUnit of 'atom' with + /// exponent = 6, thus: 1 atom = 10^6 uatom). + #[prost(uint32, tag = "2")] + #[serde( + serialize_with = "crate::shim::as_str::serialize", + deserialize_with = "crate::shim::as_str::deserialize" + )] + pub exponent: u32, + /// aliases is a list of string aliases for the given denom + #[prost(string, repeated, tag = "3")] + pub aliases: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +/// Metadata represents a struct that describes +/// a basic token. +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/cosmos.bank.v1beta1.Metadata")] +pub struct Metadata { + #[prost(string, tag = "1")] + pub description: ::prost::alloc::string::String, + /// denom_units represents the list of DenomUnit's for a given coin + #[prost(message, repeated, tag = "2")] + pub denom_units: ::prost::alloc::vec::Vec, + /// base represents the base denom (should be the DenomUnit with exponent = 0). + #[prost(string, tag = "3")] + pub base: ::prost::alloc::string::String, + /// display indicates the suggested denom that should be + /// displayed in clients. + #[prost(string, tag = "4")] + pub display: ::prost::alloc::string::String, + /// name defines the name of the token (eg: Cosmos Atom) + /// + /// Since: cosmos-sdk 0.43 + #[prost(string, tag = "5")] + pub name: ::prost::alloc::string::String, + /// symbol is the token symbol usually shown on exchanges (eg: ATOM). This can + /// be the same as the display. + /// + /// Since: cosmos-sdk 0.43 + #[prost(string, tag = "6")] + pub symbol: ::prost::alloc::string::String, +} + +/// MsgCreateDenom defines the message structure for the CreateDenom gRPC service +/// method. It allows an account to create a new denom. It requires a sender +/// address and a sub denomination. The (sender_address, sub_denomination) tuple +/// must be unique and cannot be re-used. +/// +/// The resulting denom created is defined as +/// . The resulting denom's admin is +/// originally set to be the creator, but this can be changed later. The token +/// denom does not indicate the current admin. +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + serde::Serialize, + serde::Deserialize, + schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/cosmwasm.tokenfactory.v1beta1.MsgCreateDenom")] +pub struct MsgCreateDenom { + #[prost(string, tag = "1")] + pub sender: ::prost::alloc::string::String, + /// subdenom can be up to 44 "alphanumeric" characters long. + #[prost(string, tag = "2")] + pub subdenom: ::prost::alloc::string::String, +} + +/// MsgCreateDenomResponse is the return value of MsgCreateDenom +/// It returns the full string of the newly created denom +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + serde::Serialize, + serde::Deserialize, + schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/cosmwasm.tokenfactory.v1beta1.MsgCreateDenomResponse")] +pub struct MsgCreateDenomResponse { + #[prost(string, tag = "1")] + pub new_token_denom: ::prost::alloc::string::String, +} + +/// MsgMint is the sdk.Msg type for allowing an admin account to mint +/// more of a token. For now, we only support minting to the sender account +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + serde::Serialize, + serde::Deserialize, + schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/cosmwasm.tokenfactory.v1beta1.MsgMint")] +pub struct MsgMint { + #[prost(string, tag = "1")] + pub sender: ::prost::alloc::string::String, + #[prost(message, optional, tag = "2")] + pub amount: ::core::option::Option, +} + +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + serde::Serialize, + serde::Deserialize, + schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/cosmwasm.tokenfactory.v1beta1.MsgMintResponse")] +pub struct MsgMintResponse {} + +/// MsgBurn is the sdk.Msg type for allowing an admin account to burn +/// a token. For now, we only support burning from the sender account. +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + serde::Serialize, + serde::Deserialize, + schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/cosmwasm.tokenfactory.v1beta1.MsgBurn")] +pub struct MsgBurn { + #[prost(string, tag = "1")] + pub sender: ::prost::alloc::string::String, + #[prost(message, optional, tag = "2")] + pub amount: ::core::option::Option, +} + +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + serde::Serialize, + serde::Deserialize, + schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/cosmwasm.tokenfactory.v1beta1.MsgBurnResponse")] +pub struct MsgBurnResponse {} + +/// MsgSetDenomMetadata is the sdk.Msg type for allowing an admin account to set +/// the denom's bank metadata +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/cosmwasm.tokenfactory.v1beta1.MsgSetDenomMetadata")] +pub struct MsgSetDenomMetadata { + #[prost(string, tag = "1")] + pub sender: ::prost::alloc::string::String, + #[prost(message, optional, tag = "2")] + pub metadata: ::core::option::Option, +} +/// MsgSetDenomMetadataResponse defines the response structure for an executed +/// MsgSetDenomMetadata message. +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/cosmwasm.tokenfactory.v1beta1.MsgSetDenomMetadataResponse")] +pub struct MsgSetDenomMetadataResponse {} + +// MsgChangeAdmin is the sdk.Msg type for allowing an admin account to reassign +// adminship of a denom to a new account +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/cosmwasm.tokenfactory.v1beta1.MsgChangeAdmin")] +pub struct MsgChangeAdmin { + #[prost(string, tag = "1")] + pub sender: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub denom: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub new_admin: ::prost::alloc::string::String, +} +// MsgChangeAdminResponse defines the response structure for an executed +// MsgChangeAdmin message. +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/cosmwasm.tokenfactory.v1beta1.MsgChangeAdminResponse")] +pub struct MsgChangeAdminResponse {} diff --git a/packages/cw-tokenfactory-types/src/lib.rs b/packages/cw-tokenfactory-types/src/lib.rs new file mode 100644 index 000000000..d829f8d88 --- /dev/null +++ b/packages/cw-tokenfactory-types/src/lib.rs @@ -0,0 +1,8 @@ +pub mod msg; + +pub mod cosmwasm; +pub use osmosis_std::types::osmosis::tokenfactory::v1beta1 as osmosis; + +// helpers for both osmosis types (osmosis_std crate) and cosmwasm types. it +// needs to be named `shim` because osmosis_std assumes it exists. +mod shim; diff --git a/packages/cw-tokenfactory-types/src/msg.rs b/packages/cw-tokenfactory-types/src/msg.rs new file mode 100644 index 000000000..0c5925641 --- /dev/null +++ b/packages/cw-tokenfactory-types/src/msg.rs @@ -0,0 +1,190 @@ +#[cfg(feature = "cosmwasm_tokenfactory")] +mod tokenfactory_msg { + use crate::cosmwasm::{ + Coin, DenomUnit as CosmwasmDenomUnit, Metadata as CosmwasmMetadata, MsgBurn, + MsgChangeAdmin, MsgCreateDenom, MsgMint, MsgSetDenomMetadata, + }; + use dao_interface::token::Metadata; + + pub use crate::cosmwasm::MsgCreateDenomResponse; + + pub fn msg_create_denom(sender: String, subdenom: String) -> MsgCreateDenom { + MsgCreateDenom { sender, subdenom } + } + + pub fn msg_mint(sender: String, amount: u128, denom: String) -> MsgMint { + MsgMint { + sender, + amount: Some(Coin { + amount: amount.to_string(), + denom, + }), + } + } + + // TODO figure out if it is problematic to not have burn_from_address here (ie check if it works the same as osmosis' message or not) + pub fn msg_burn( + sender: String, + amount: u128, + denom: String, + _burn_from_address: String, + ) -> MsgBurn { + MsgBurn { + sender, + amount: Some(Coin { + amount: amount.to_string(), + denom, + }), + } + } + + pub fn msg_set_denom_metadata(sender: String, metadata: Metadata) -> MsgSetDenomMetadata { + MsgSetDenomMetadata { + sender, + metadata: Some(CosmwasmMetadata { + description: metadata.description, + denom_units: metadata + .denom_units + .into_iter() + .map(|denom_unit| CosmwasmDenomUnit { + denom: denom_unit.denom, + exponent: denom_unit.exponent, + aliases: denom_unit.aliases, + }) + .collect(), + base: metadata.base, + display: metadata.display, + name: metadata.name, + symbol: metadata.symbol, + }), + } + } + + pub fn msg_change_admin(sender: String, denom: String, new_admin: String) -> MsgChangeAdmin { + MsgChangeAdmin { + sender, + denom, + new_admin, + } + } +} + +#[cfg(feature = "osmosis_tokenfactory")] +mod tokenfactory_msg { + use crate::osmosis::{ + MsgBurn, MsgChangeAdmin, MsgCreateDenom, MsgForceTransfer, MsgMint, MsgSetBeforeSendHook, + MsgSetDenomMetadata, + }; + use dao_interface::token::Metadata; + use osmosis_std::types::cosmos::{ + bank::v1beta1::{DenomUnit as OsmosisDenomUnit, Metadata as OsmosisMetadata}, + base::v1beta1::Coin, + }; + + pub use crate::osmosis::MsgCreateDenomResponse; + + pub fn msg_create_denom(sender: String, subdenom: String) -> MsgCreateDenom { + MsgCreateDenom { sender, subdenom } + } + + pub fn msg_mint(sender: String, amount: u128, denom: String) -> MsgMint { + MsgMint { + sender: sender.clone(), + amount: Some(Coin { + amount: amount.to_string(), + denom, + }), + mint_to_address: sender, + } + } + + pub fn msg_burn( + sender: String, + amount: u128, + denom: String, + burn_from_address: String, + ) -> MsgBurn { + MsgBurn { + sender, + amount: Some(Coin { + amount: amount.to_string(), + denom, + }), + burn_from_address, + } + } + + pub fn msg_set_denom_metadata(sender: String, metadata: Metadata) -> MsgSetDenomMetadata { + MsgSetDenomMetadata { + sender, + metadata: Some(OsmosisMetadata { + description: metadata.description, + denom_units: metadata + .denom_units + .into_iter() + .map(|denom_unit| OsmosisDenomUnit { + denom: denom_unit.denom, + exponent: denom_unit.exponent, + aliases: denom_unit.aliases, + }) + .collect(), + base: metadata.base, + display: metadata.display, + name: metadata.name, + symbol: metadata.symbol, + }), + } + } + + pub fn msg_change_admin(sender: String, denom: String, new_admin: String) -> MsgChangeAdmin { + MsgChangeAdmin { + sender, + denom, + new_admin, + } + } + + pub fn msg_force_transfer( + sender: String, + amount: u128, + denom: String, + transfer_from_address: String, + transfer_to_address: String, + ) -> MsgForceTransfer { + MsgForceTransfer { + sender, + amount: Some(Coin { + amount: amount.to_string(), + denom, + }), + transfer_from_address, + transfer_to_address, + } + } + + pub fn msg_set_before_send_hook( + sender: String, + denom: String, + cosmwasm_address: String, + ) -> MsgSetBeforeSendHook { + MsgSetBeforeSendHook { + sender, + denom, + cosmwasm_address, + } + } +} + +// re-export chosen tokenfactory standard +#[cfg(any(feature = "cosmwasm_tokenfactory", feature = "osmosis_tokenfactory"))] +pub use tokenfactory_msg::*; + +// require one tokenfactory standard to be chosen +#[cfg(not(any(feature = "cosmwasm_tokenfactory", feature = "osmosis_tokenfactory")))] +compile_error!( + "feature \"cosmwasm_tokenfactory\" or feature \"osmosis_tokenfactory\" must be enabled" +); + +// prevent more than one tokenfactory standard from being chosen +#[cfg(all(feature = "cosmwasm_tokenfactory", feature = "osmosis_tokenfactory"))] +compile_error!("feature \"cosmwasm_tokenfactory\" and feature \"osmosis_tokenfactory\" cannot be enabled at the same time"); diff --git a/packages/cw-tokenfactory-types/src/shim.rs b/packages/cw-tokenfactory-types/src/shim.rs new file mode 100644 index 000000000..b5bf14e85 --- /dev/null +++ b/packages/cw-tokenfactory-types/src/shim.rs @@ -0,0 +1,88 @@ +#[derive(Clone, PartialEq, Eq, ::prost::Message, schemars::JsonSchema)] + +// depended on by osmosis_std +pub struct Any { + /// A URL/resource name that uniquely identifies the type of the serialized + /// protocol buffer message. This string must contain at least + /// one "/" character. The last segment of the URL's path must represent + /// the fully qualified name of the type (as in + /// `path/google.protobuf.Duration`). The name should be in a canonical form + /// (e.g., leading "." is not accepted). + /// + /// In practice, teams usually precompile into the binary all types that they + /// expect it to use in the context of Any. However, for URLs which use the + /// scheme `http`, `https`, or no scheme, one can optionally set up a type + /// server that maps type URLs to message definitions as follows: + /// + /// * If no scheme is provided, `https` is assumed. + /// * An HTTP GET on the URL must yield a \[google.protobuf.Type][\] + /// value in binary format, or produce an error. + /// * Applications are allowed to cache lookup results based on the + /// URL, or have them precompiled into a binary to avoid any + /// lookup. Therefore, binary compatibility needs to be preserved + /// on changes to types. (Use versioned type names to manage + /// breaking changes.) + /// + /// Note: this functionality is not currently available in the official + /// protobuf release, and it is not used for type URLs beginning with + /// type.googleapis.com. + /// + /// Schemes other than `http`, `https` (or the empty scheme) might be + /// used with implementation specific semantics. + /// + #[prost(string, tag = "1")] + pub type_url: ::prost::alloc::string::String, + /// Must be a valid serialized protocol buffer of the above specified type. + #[prost(bytes = "vec", tag = "2")] + pub value: ::prost::alloc::vec::Vec, +} + +macro_rules! impl_prost_types_exact_conversion { + ($t:ident | $($arg:ident),*) => { + impl From<$t> for prost_types::$t { + fn from(src: $t) -> Self { + prost_types::$t { + $( + $arg: src.$arg, + )* + } + } + } + + impl From for $t { + fn from(src: prost_types::$t) -> Self { + $t { + $( + $arg: src.$arg, + )* + } + } + } + }; +} + +impl_prost_types_exact_conversion! { Any | type_url, value } + +// depended on by cosmwasm.rs +pub mod as_str { + use serde::{de, Deserialize, Deserializer, Serializer}; + use std::{fmt::Display, str::FromStr}; + + pub fn deserialize<'de, T, D>(deserializer: D) -> Result + where + T: FromStr, + T::Err: Display, + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + T::from_str(&s).map_err(de::Error::custom) + } + + pub fn serialize(value: &T, serializer: S) -> Result + where + S: Serializer, + T: Display, + { + serializer.serialize_str(&value.to_string()) + } +} diff --git a/packages/dao-testing/Cargo.toml b/packages/dao-testing/Cargo.toml index 677709d53..51d0685b4 100644 --- a/packages/dao-testing/Cargo.toml +++ b/packages/dao-testing/Cargo.toml @@ -33,7 +33,6 @@ osmosis-test-tube = { workspace = true } rand = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } -token-bindings = { workspace = true } cw-core-v1 = { workspace = true, features = ["library"] } cw-hooks = { workspace = true }