From c92275c7995556984bafb12f464eb024eeaeac82 Mon Sep 17 00:00:00 2001 From: Ash Date: Fri, 27 Sep 2024 09:41:41 -0700 Subject: [PATCH 1/8] initial proxy contract --- contracts/proxy/Cargo.toml | 23 +++++ contracts/proxy/src/contract.rs | 41 +++++++++ contracts/proxy/src/error.rs | 22 +++++ contracts/proxy/src/execute.rs | 145 ++++++++++++++++++++++++++++++++ contracts/proxy/src/lib.rs | 9 ++ contracts/proxy/src/msg.rs | 32 +++++++ contracts/proxy/src/state.rs | 6 ++ 7 files changed, 278 insertions(+) create mode 100644 contracts/proxy/Cargo.toml create mode 100644 contracts/proxy/src/contract.rs create mode 100644 contracts/proxy/src/error.rs create mode 100644 contracts/proxy/src/execute.rs create mode 100644 contracts/proxy/src/lib.rs create mode 100644 contracts/proxy/src/msg.rs create mode 100644 contracts/proxy/src/state.rs diff --git a/contracts/proxy/Cargo.toml b/contracts/proxy/Cargo.toml new file mode 100644 index 0000000..ad75f20 --- /dev/null +++ b/contracts/proxy/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "proxy" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +# enable feature if you want to disable entry points +library = [] + +[dependencies] +cosmwasm-schema = { workspace = true } +cosmwasm-std = { workspace = true } +cw2 = { workspace = true } +cw-storage-plus = { workspace = true } +thiserror = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +schemars = { workspace = true } +cosmos-sdk-proto = { workspace = true } \ No newline at end of file diff --git a/contracts/proxy/src/contract.rs b/contracts/proxy/src/contract.rs new file mode 100644 index 0000000..915726c --- /dev/null +++ b/contracts/proxy/src/contract.rs @@ -0,0 +1,41 @@ +use cosmwasm_std::{ + entry_point, to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult, +}; +use crate::error::ContractResult; +use crate::{execute, CONTRACT_NAME, CONTRACT_VERSION}; +use crate::msg::{ExecuteMsg, InstantiateMsg}; + +#[entry_point] +pub fn instantiate( + deps: DepsMut, + _env: Env, + info: MessageInfo, + msg: InstantiateMsg, +) -> ContractResult { + cw2::set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + execute::init( + deps, + info, + msg.admin, + msg.code_ids, + ) +} + +#[entry_point] +pub fn execute( + deps: DepsMut, + _env: Env, + info: MessageInfo, + msg: ExecuteMsg, +) -> ContractResult { + match msg { + ExecuteMsg::ProxyMsgs {msgs} => execute::proxy_msgs(deps, info, msgs), + ExecuteMsg::AddCodeIDs { + code_ids + } => execute::add_code_ids(deps, info, code_ids), + ExecuteMsg::RemoveCodeIDs { + code_ids + } => execute::remove_code_ids(deps, info, code_ids), + ExecuteMsg::UpdateAdmin { new_admin } => execute::update_admin(deps, info, new_admin), + } +} \ No newline at end of file diff --git a/contracts/proxy/src/error.rs b/contracts/proxy/src/error.rs new file mode 100644 index 0000000..58eb5c8 --- /dev/null +++ b/contracts/proxy/src/error.rs @@ -0,0 +1,22 @@ +#[derive(Debug, thiserror::Error)] +pub enum ContractError { + #[error(transparent)] + Std(#[from] cosmwasm_std::StdError), + + #[error(transparent)] + Encode(#[from] cosmos_sdk_proto::prost::EncodeError), + + #[error(transparent)] + Decode(#[from] cosmos_sdk_proto::prost::DecodeError), + + #[error("unauthorized")] + Unauthorized, + + #[error("invalid_code_id")] + InvalidCodeID{contract: String, code_id: u64}, + + #[error("invalid_msg_type")] + InvalidMsgType +} + +pub type ContractResult = Result; diff --git a/contracts/proxy/src/execute.rs b/contracts/proxy/src/execute.rs new file mode 100644 index 0000000..39c5733 --- /dev/null +++ b/contracts/proxy/src/execute.rs @@ -0,0 +1,145 @@ +use cosmos_sdk_proto::cosmwasm::wasm::v1::QueryContractInfoRequest; +use cosmos_sdk_proto::traits::MessageExt; +use cosmwasm_std::{to_json_binary, Addr, CosmosMsg, Deps, DepsMut, Env, Event, MessageInfo, Response, WasmMsg}; +use crate::error::ContractError::{InvalidCodeID, InvalidMsgType, Unauthorized}; +use crate::error::ContractResult; +use crate::msg::ProxyMsg; +use crate::state::{ADMIN, CODE_IDS}; + +pub fn init( + deps: DepsMut, + _: MessageInfo, + admin: Option, + code_ids: Vec, +) -> ContractResult { + ADMIN.save(deps.storage, &admin)?; + + for code_id in code_ids.clone() { + CODE_IDS.save(deps.storage, code_id, &true)?; + }; + + let admin_str: String = match admin { + None => String::new(), + Some(a) => a.into_string(), + }; + + let code_ids_strs: Vec = code_ids.iter().map(|n| n.to_string()).collect(); + let code_ids_str = code_ids_strs.join(", "); + + Ok(Response::new().add_event( + Event::new("create_proxy_instance") + .add_attributes(vec![ + ("admin", admin_str), + ("code_ids", code_ids_str), + ]), + )) +} + +pub fn is_admin( + deps: Deps, + address: Addr, +) -> ContractResult<()> { + let admin = ADMIN.load(deps.storage)?; + match admin { + None => Err(Unauthorized), + Some(a) => { + if a != address { + Err(Unauthorized) + } else { + Ok(()) + } + } + } +} + +pub fn update_admin(deps: DepsMut, info: MessageInfo, new_admin: Option) -> ContractResult { + is_admin(deps.as_ref(), info.sender.clone())?; + + ADMIN.save(deps.storage, &new_admin)?; + + let admin_str: String = match new_admin { + None => String::new(), + Some(a) => a.into_string(), + }; + + Ok( + Response::new().add_event(Event::new("updated_treasury_admin").add_attributes(vec![ + ("old admin", info.sender.into_string()), + ("new admin", admin_str), + ])), + ) +} + +pub fn proxy_msgs( + deps: DepsMut, + info: MessageInfo, + msgs: Vec +) -> ContractResult { + + let mut proxy_msgs: Vec = Vec::with_capacity(msgs.len()); + + for msg in msgs { + let (proxy_msg, contract_addr) = match msg { + WasmMsg::Execute { contract_addr, msg, funds } => (ProxyMsg{sender: info.sender.clone(), msg, funds}, contract_addr), + _ => return Err(InvalidMsgType) + }; + let contract_info = deps.querier.query_wasm_contract_info(contract_addr.clone())?; + if !CODE_IDS.has(deps.storage, contract_info.code_id) { + return Err(InvalidCodeID {contract: contract_addr, code_id: contract_info.code_id}); + } + + let exec_msg = WasmMsg::Execute {contract_addr, msg: to_json_binary(&proxy_msg)?, funds: proxy_msg.funds}; + proxy_msgs.push(exec_msg); + } + + Ok( + Response::new().add_event(Event::new("proxied_msgs")).add_messages(proxy_msgs) + ) +} + + +pub fn add_code_ids( + deps: DepsMut, + info: MessageInfo, + code_ids: Vec, +) -> ContractResult { + is_admin(deps.as_ref(), info.sender.clone())?; + + for code_id in code_ids.clone() { + CODE_IDS.save(deps.storage, code_id, &true)?; + }; + + let code_ids_strs: Vec = code_ids.iter().map(|n| n.to_string()).collect(); + let code_ids_str = code_ids_strs.join(", "); + + Ok(Response::new().add_event( + Event::new("updated_proxy_code_ids") + .add_attributes(vec![ + ("admin", info.sender.as_str()), + ("new_code_ids", code_ids_str.as_str()), + ]), + )) +} + +pub fn remove_code_ids( + deps: DepsMut, + info: MessageInfo, + code_ids: Vec, +) -> ContractResult { + is_admin(deps.as_ref(), info.sender.clone())?; + + for code_id in code_ids.clone() { + CODE_IDS.remove(deps.storage, code_id); + }; + + let code_ids_strs: Vec = code_ids.iter().map(|n| n.to_string()).collect(); + let code_ids_str = code_ids_strs.join(", "); + + Ok(Response::new().add_event( + Event::new("updated_proxy_code_ids") + .add_attributes(vec![ + ("admin", info.sender.as_str()), + ("new_code_ids", code_ids_str.as_str()), + ]), + )) +} \ No newline at end of file diff --git a/contracts/proxy/src/lib.rs b/contracts/proxy/src/lib.rs new file mode 100644 index 0000000..ab0ab53 --- /dev/null +++ b/contracts/proxy/src/lib.rs @@ -0,0 +1,9 @@ +#[cfg(not(feature = "library"))] +pub mod contract; +mod msg; +mod state; +mod execute; +mod error; + +pub const CONTRACT_NAME: &str = "proxy"; +pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/contracts/proxy/src/msg.rs b/contracts/proxy/src/msg.rs new file mode 100644 index 0000000..ec2e738 --- /dev/null +++ b/contracts/proxy/src/msg.rs @@ -0,0 +1,32 @@ +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::{Addr, Binary, Coin, CosmosMsg, WasmMsg}; + + +#[cw_serde] +pub struct InstantiateMsg { + pub admin: Option, + pub code_ids: Vec, +} + +#[cw_serde] +pub enum ExecuteMsg { + ProxyMsgs { + msgs: Vec, + }, + UpdateAdmin { + new_admin: Option, + }, + AddCodeIDs { + code_ids: Vec, + }, + RemoveCodeIDs { + code_ids: Vec, + } +} + +#[cw_serde] +pub struct ProxyMsg { + pub sender: Addr, + pub msg: Binary, + pub funds: Vec, +} \ No newline at end of file diff --git a/contracts/proxy/src/state.rs b/contracts/proxy/src/state.rs new file mode 100644 index 0000000..78d57eb --- /dev/null +++ b/contracts/proxy/src/state.rs @@ -0,0 +1,6 @@ +use cosmwasm_std::Addr; +use cw_storage_plus::{Item, Map}; +use cosmwasm_schema::cw_serde; + +pub const ADMIN: Item> = Item::new("admin"); +pub const CODE_IDS: Map = Map::new("code_ids"); From 6a97cf7e7304c7f44d91d3771523b6e411013ae9 Mon Sep 17 00:00:00 2001 From: Ash Date: Mon, 30 Sep 2024 16:07:50 -0700 Subject: [PATCH 2/8] example proxyable contract --- contracts/cw721-proxy/Cargo.toml | 22 ++++++ contracts/cw721-proxy/src/contract.rs | 44 +++++++++++ contracts/cw721-proxy/src/error.rs | 23 ++++++ contracts/cw721-proxy/src/execute.rs | 78 +++++++++++++++++++ contracts/cw721-proxy/src/extension.rs | 23 ++++++ contracts/cw721-proxy/src/lib.rs | 12 +++ contracts/cw721-proxy/src/msg.rs | 103 +++++++++++++++++++++++++ contracts/cw721-proxy/src/state.rs | 35 +++++++++ contracts/proxy/src/contract.rs | 25 ++---- contracts/proxy/src/error.rs | 8 +- contracts/proxy/src/execute.rs | 98 +++++++++++++---------- contracts/proxy/src/lib.rs | 4 +- contracts/proxy/src/msg.rs | 19 ++--- contracts/proxy/src/state.rs | 2 +- 14 files changed, 417 insertions(+), 79 deletions(-) create mode 100644 contracts/cw721-proxy/Cargo.toml create mode 100644 contracts/cw721-proxy/src/contract.rs create mode 100644 contracts/cw721-proxy/src/error.rs create mode 100644 contracts/cw721-proxy/src/execute.rs create mode 100644 contracts/cw721-proxy/src/extension.rs create mode 100644 contracts/cw721-proxy/src/lib.rs create mode 100644 contracts/cw721-proxy/src/msg.rs create mode 100644 contracts/cw721-proxy/src/state.rs diff --git a/contracts/cw721-proxy/Cargo.toml b/contracts/cw721-proxy/Cargo.toml new file mode 100644 index 0000000..6dcae52 --- /dev/null +++ b/contracts/cw721-proxy/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "cw721-proxy" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +# enable feature if you want to disable entry points +library = [] + +[dependencies] +cosmwasm-schema = "^1.5" +cosmwasm-std = "^1.5" +cw2 = "^1.1" +serde = { workspace = true } +cw721 = {git = "https://github.com/public-awesome/cw-nfts.git", version = "0.19.0"} +cw-ownable = "2.1.0" +cw-storage-plus = "^1.1" +thiserror = "1.0.64" \ No newline at end of file diff --git a/contracts/cw721-proxy/src/contract.rs b/contracts/cw721-proxy/src/contract.rs new file mode 100644 index 0000000..be5eb9e --- /dev/null +++ b/contracts/cw721-proxy/src/contract.rs @@ -0,0 +1,44 @@ +use crate::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}; +use crate::state::DefaultCw721ProxyContract; +use crate::{ContractError, CONTRACT_NAME, CONTRACT_VERSION}; +use cosmwasm_std::entry_point; +use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Response}; +use cw721::extension::Cw721Extensions; +use cw721::traits::{Cw721Execute, Cw721Query}; +pub use cw721::*; +pub use cw_ownable::{Action, Ownership, OwnershipError}; +use extension::Cw721BaseExtensions; + +#[entry_point] +pub fn instantiate( + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: InstantiateMsg, +) -> Result { + let contract = DefaultCw721ProxyContract::default(); + contract.instantiate_with_version(deps, &env, &info, msg, CONTRACT_NAME, CONTRACT_VERSION) +} + +#[entry_point] +pub fn execute( + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: ExecuteMsg, +) -> Result { + let contract = DefaultCw721ProxyContract::default(); + contract.execute(deps, &env, &info, msg) +} + +#[entry_point] +pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result { + let contract = DefaultCw721ProxyContract::default(); + contract.query(deps, &env, msg) +} + +#[entry_point] +pub fn migrate(deps: DepsMut, env: Env, msg: MigrateMsg) -> Result { + let contract = DefaultCw721ProxyContract::default(); + contract.migrate(deps, env, msg, CONTRACT_NAME, CONTRACT_VERSION) +} diff --git a/contracts/cw721-proxy/src/error.rs b/contracts/cw721-proxy/src/error.rs new file mode 100644 index 0000000..7e56d75 --- /dev/null +++ b/contracts/cw721-proxy/src/error.rs @@ -0,0 +1,23 @@ +use cw721::error::Cw721ContractError; + +#[derive(Debug, thiserror::Error)] +pub enum ContractError { + #[error(transparent)] + Std(#[from] cosmwasm_std::StdError), + + #[error(transparent)] + Cw721(#[from] Cw721ContractError), + + // #[error(transparent)] + // Encode(#[from] cosmos_sdk_proto::prost::EncodeError), + // + // #[error(transparent)] + // Decode(#[from] cosmos_sdk_proto::prost::DecodeError), + #[error("unauthorized")] + Unauthorized, + + #[error("invalid_msg_type")] + InvalidMsgType, +} + +pub type ContractResult = Result; diff --git a/contracts/cw721-proxy/src/execute.rs b/contracts/cw721-proxy/src/execute.rs new file mode 100644 index 0000000..cdda3ec --- /dev/null +++ b/contracts/cw721-proxy/src/execute.rs @@ -0,0 +1,78 @@ +use crate::msg::{get_inner, ExecuteMsg, InnerExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}; +use crate::state::DefaultCw721ProxyContract; +use crate::ContractError; +use crate::ContractError::Unauthorized; +use cosmwasm_std::{Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response}; +use cw721::traits::{Cw721Execute, Cw721Query}; + +impl DefaultCw721ProxyContract<'static> { + pub fn instantiate( + &self, + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: InstantiateMsg, + ) -> Result, ContractError> { + // set the proxy addr + self.proxy_addr.save(deps.storage, &msg.proxy_addr)?; + + // passthrough the rest + Ok(self + .base_contract + .instantiate(deps, &env, &info, msg.inner_msg)?) + } + + pub fn execute_proxy( + &self, + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: InnerExecuteMsg, + ) -> Result, ContractError> { + Ok(self.base_contract.execute(deps, &env, &info, msg)?) + } + + pub fn execute( + &self, + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: ExecuteMsg, + ) -> Result, ContractError> { + match msg { + ExecuteMsg::UpdateExtension { msg: proxy_msg } => { + let proxy_addr = self.proxy_addr.load(deps.storage)?; + if info.sender.ne(&proxy_addr) { + return Err(Unauthorized); + } + + let new_info = MessageInfo { + sender: proxy_msg.sender, + funds: info.funds, + }; + self.execute_proxy(deps, env, new_info, proxy_msg.msg) + } + _ => { + let inner_msg: InnerExecuteMsg = get_inner(msg)?; + self.execute_proxy(deps, env, info, inner_msg) + } + } + } + + pub fn query(&self, deps: Deps, env: Env, msg: QueryMsg) -> Result { + Ok(self.base_contract.query(deps, &env, msg)?) + } + + pub fn migrate( + &self, + deps: DepsMut, + env: Env, + msg: MigrateMsg, + contract_name: &str, + contract_version: &str, + ) -> Result { + Ok(self + .base_contract + .migrate(deps, env, msg, contract_name, contract_version)?) + } +} diff --git a/contracts/cw721-proxy/src/extension.rs b/contracts/cw721-proxy/src/extension.rs new file mode 100644 index 0000000..27e2722 --- /dev/null +++ b/contracts/cw721-proxy/src/extension.rs @@ -0,0 +1,23 @@ +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{Addr, Binary, Empty}; +use cw721::state::Cw721Config; +use cw721::{ + DefaultOptionalCollectionExtension, DefaultOptionalCollectionExtensionMsg, + DefaultOptionalNftExtension, DefaultOptionalNftExtensionMsg, +}; +use std::marker::PhantomData; + +pub struct Cw721Proxy<'a> { + pub config: Cw721Config<'a, DefaultOptionalNftExtension>, + pub(crate) _collection_extension: PhantomData, + pub(crate) _nft_extension_msg: PhantomData, + pub(crate) _collection_extension_msg: PhantomData, + pub(crate) _extension_msg: PhantomData, + pub(crate) _extension_query_msg: PhantomData, + pub(crate) _custom_response_msg: PhantomData, +} + +pub struct ProxyMsg { + sender: Addr, + msg: Binary, +} diff --git a/contracts/cw721-proxy/src/lib.rs b/contracts/cw721-proxy/src/lib.rs new file mode 100644 index 0000000..0fd0033 --- /dev/null +++ b/contracts/cw721-proxy/src/lib.rs @@ -0,0 +1,12 @@ +#[cfg(not(feature = "library"))] +pub mod contract; +mod error; +mod execute; +mod extension; +mod msg; +mod state; + +pub use crate::error::ContractError; + +pub const CONTRACT_NAME: &str = "cw721-proxy"; +pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/contracts/cw721-proxy/src/msg.rs b/contracts/cw721-proxy/src/msg.rs new file mode 100644 index 0000000..63b8887 --- /dev/null +++ b/contracts/cw721-proxy/src/msg.rs @@ -0,0 +1,103 @@ +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{Addr, Empty}; + +use crate::ContractError; +use crate::ContractError::InvalidMsgType; +use cw721::{ + msg::{Cw721ExecuteMsg, Cw721InstantiateMsg, Cw721MigrateMsg, Cw721QueryMsg}, + DefaultOptionalCollectionExtension, DefaultOptionalCollectionExtensionMsg, + EmptyOptionalNftExtension, EmptyOptionalNftExtensionMsg, +}; + +#[cw_serde] +pub struct InstantiateMsg { + pub proxy_addr: Addr, + + pub inner_msg: Cw721InstantiateMsg, +} + +pub type ExecuteMsg = + Cw721ExecuteMsg; +// pub type InstantiateMsg = Cw721InstantiateMsg; +pub type MigrateMsg = Cw721MigrateMsg; +pub type QueryMsg = + Cw721QueryMsg; + +pub type InnerExecuteMsg = + Cw721ExecuteMsg; + +#[cw_serde] +pub struct ProxyMsg { + pub sender: Addr, + pub msg: InnerExecuteMsg, +} + +pub fn get_inner(msg: ExecuteMsg) -> Result { + match msg { + ExecuteMsg::UpdateOwnership(_0) => Ok(InnerExecuteMsg::UpdateCreatorOwnership(_0)), + ExecuteMsg::UpdateMinterOwnership(_0) => Ok(InnerExecuteMsg::UpdateCreatorOwnership(_0)), + ExecuteMsg::UpdateCreatorOwnership(_0) => Ok(InnerExecuteMsg::UpdateCreatorOwnership(_0)), + ExecuteMsg::UpdateCollectionInfo { collection_info } => { + Ok(InnerExecuteMsg::UpdateCollectionInfo { collection_info }) + } + ExecuteMsg::TransferNft { + recipient, + token_id, + } => Ok(InnerExecuteMsg::TransferNft { + recipient, + token_id, + }), + ExecuteMsg::SendNft { + contract, + token_id, + msg, + } => Ok(InnerExecuteMsg::SendNft { + contract, + token_id, + msg, + }), + ExecuteMsg::Approve { + spender, + token_id, + expires, + } => Ok(InnerExecuteMsg::Approve { + spender, + token_id, + expires, + }), + ExecuteMsg::Revoke { spender, token_id } => { + Ok(InnerExecuteMsg::Revoke { spender, token_id }) + } + ExecuteMsg::ApproveAll { operator, expires } => { + Ok(InnerExecuteMsg::ApproveAll { operator, expires }) + } + ExecuteMsg::RevokeAll { operator } => Ok(InnerExecuteMsg::RevokeAll { operator }), + ExecuteMsg::Mint { + token_id, + owner, + token_uri, + extension, + } => Ok(InnerExecuteMsg::Mint { + token_id, + owner, + token_uri, + extension, + }), + ExecuteMsg::Burn { token_id } => Ok(InnerExecuteMsg::Burn { token_id }), + ExecuteMsg::UpdateExtension { msg } => Err(InvalidMsgType), // cannot convert a proxy msg into an inner msg + ExecuteMsg::UpdateNftInfo { + token_id, + token_uri, + extension, + } => Ok(InnerExecuteMsg::UpdateNftInfo { + token_id, + token_uri, + extension, + }), + ExecuteMsg::SetWithdrawAddress { address } => { + Ok(InnerExecuteMsg::SetWithdrawAddress { address }) + } + ExecuteMsg::RemoveWithdrawAddress {} => Ok(InnerExecuteMsg::RemoveWithdrawAddress {}), + ExecuteMsg::WithdrawFunds { amount } => Ok(InnerExecuteMsg::WithdrawFunds { amount }), + } +} diff --git a/contracts/cw721-proxy/src/state.rs b/contracts/cw721-proxy/src/state.rs new file mode 100644 index 0000000..8d6f808 --- /dev/null +++ b/contracts/cw721-proxy/src/state.rs @@ -0,0 +1,35 @@ +use cosmwasm_std::Addr; +use cw721::extension::Cw721BaseExtensions; +use cw_storage_plus::Item; + +/* +pub struct DefaultCw721ExpirationContract<'a> { + pub expiration_days: Item<'a, u16>, // max 65535 days + pub mint_timestamps: Map<'a, &'a str, Timestamp>, + pub base_contract: Cw721OnchainExtensions<'a>, +} + +impl Default for DefaultCw721ExpirationContract<'static> { + fn default() -> Self { + Self { + expiration_days: Item::new("expiration_days"), + mint_timestamps: Map::new("mint_timestamps"), + base_contract: Cw721OnchainExtensions::default(), + } + } +} + */ + +pub struct DefaultCw721ProxyContract<'a> { + pub proxy_addr: Item<'a, Addr>, + pub base_contract: Cw721BaseExtensions<'a>, +} + +impl Default for DefaultCw721ProxyContract<'static> { + fn default() -> Self { + Self { + proxy_addr: Item::new("proxy_addr"), + base_contract: Cw721BaseExtensions::default(), + } + } +} diff --git a/contracts/proxy/src/contract.rs b/contracts/proxy/src/contract.rs index 915726c..a0b42db 100644 --- a/contracts/proxy/src/contract.rs +++ b/contracts/proxy/src/contract.rs @@ -1,9 +1,9 @@ +use crate::error::ContractResult; +use crate::msg::{ExecuteMsg, InstantiateMsg}; +use crate::{execute, CONTRACT_NAME, CONTRACT_VERSION}; use cosmwasm_std::{ entry_point, to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult, }; -use crate::error::ContractResult; -use crate::{execute, CONTRACT_NAME, CONTRACT_VERSION}; -use crate::msg::{ExecuteMsg, InstantiateMsg}; #[entry_point] pub fn instantiate( @@ -13,12 +13,7 @@ pub fn instantiate( msg: InstantiateMsg, ) -> ContractResult { cw2::set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; - execute::init( - deps, - info, - msg.admin, - msg.code_ids, - ) + execute::init(deps, info, msg.admin, msg.code_ids) } #[entry_point] @@ -29,13 +24,9 @@ pub fn execute( msg: ExecuteMsg, ) -> ContractResult { match msg { - ExecuteMsg::ProxyMsgs {msgs} => execute::proxy_msgs(deps, info, msgs), - ExecuteMsg::AddCodeIDs { - code_ids - } => execute::add_code_ids(deps, info, code_ids), - ExecuteMsg::RemoveCodeIDs { - code_ids - } => execute::remove_code_ids(deps, info, code_ids), + ExecuteMsg::ProxyMsgs { msgs } => execute::proxy_msgs(deps, info, msgs), + ExecuteMsg::AddCodeIDs { code_ids } => execute::add_code_ids(deps, info, code_ids), + ExecuteMsg::RemoveCodeIDs { code_ids } => execute::remove_code_ids(deps, info, code_ids), ExecuteMsg::UpdateAdmin { new_admin } => execute::update_admin(deps, info, new_admin), } -} \ No newline at end of file +} diff --git a/contracts/proxy/src/error.rs b/contracts/proxy/src/error.rs index 58eb5c8..6515b7f 100644 --- a/contracts/proxy/src/error.rs +++ b/contracts/proxy/src/error.rs @@ -8,15 +8,15 @@ pub enum ContractError { #[error(transparent)] Decode(#[from] cosmos_sdk_proto::prost::DecodeError), - + #[error("unauthorized")] Unauthorized, #[error("invalid_code_id")] - InvalidCodeID{contract: String, code_id: u64}, - + InvalidCodeID { contract: String, code_id: u64 }, + #[error("invalid_msg_type")] - InvalidMsgType + InvalidMsgType, } pub type ContractResult = Result; diff --git a/contracts/proxy/src/execute.rs b/contracts/proxy/src/execute.rs index 39c5733..9422f2b 100644 --- a/contracts/proxy/src/execute.rs +++ b/contracts/proxy/src/execute.rs @@ -1,10 +1,12 @@ -use cosmos_sdk_proto::cosmwasm::wasm::v1::QueryContractInfoRequest; -use cosmos_sdk_proto::traits::MessageExt; -use cosmwasm_std::{to_json_binary, Addr, CosmosMsg, Deps, DepsMut, Env, Event, MessageInfo, Response, WasmMsg}; use crate::error::ContractError::{InvalidCodeID, InvalidMsgType, Unauthorized}; use crate::error::ContractResult; use crate::msg::ProxyMsg; use crate::state::{ADMIN, CODE_IDS}; +use cosmos_sdk_proto::cosmwasm::wasm::v1::QueryContractInfoRequest; +use cosmos_sdk_proto::traits::MessageExt; +use cosmwasm_std::{ + to_json_binary, Addr, CosmosMsg, Deps, DepsMut, Env, Event, MessageInfo, Response, WasmMsg, +}; pub fn init( deps: DepsMut, @@ -16,7 +18,7 @@ pub fn init( for code_id in code_ids.clone() { CODE_IDS.save(deps.storage, code_id, &true)?; - }; + } let admin_str: String = match admin { None => String::new(), @@ -28,17 +30,11 @@ pub fn init( Ok(Response::new().add_event( Event::new("create_proxy_instance") - .add_attributes(vec![ - ("admin", admin_str), - ("code_ids", code_ids_str), - ]), + .add_attributes(vec![("admin", admin_str), ("code_ids", code_ids_str)]), )) } -pub fn is_admin( - deps: Deps, - address: Addr, -) -> ContractResult<()> { +pub fn is_admin(deps: Deps, address: Addr) -> ContractResult<()> { let admin = ADMIN.load(deps.storage)?; match admin { None => Err(Unauthorized), @@ -52,7 +48,11 @@ pub fn is_admin( } } -pub fn update_admin(deps: DepsMut, info: MessageInfo, new_admin: Option) -> ContractResult { +pub fn update_admin( + deps: DepsMut, + info: MessageInfo, + new_admin: Option, +) -> ContractResult { is_admin(deps.as_ref(), info.sender.clone())?; ADMIN.save(deps.storage, &new_admin)?; @@ -73,31 +73,49 @@ pub fn update_admin(deps: DepsMut, info: MessageInfo, new_admin: Option) - pub fn proxy_msgs( deps: DepsMut, info: MessageInfo, - msgs: Vec + msgs: Vec, ) -> ContractResult { - let mut proxy_msgs: Vec = Vec::with_capacity(msgs.len()); for msg in msgs { let (proxy_msg, contract_addr) = match msg { - WasmMsg::Execute { contract_addr, msg, funds } => (ProxyMsg{sender: info.sender.clone(), msg, funds}, contract_addr), - _ => return Err(InvalidMsgType) + WasmMsg::Execute { + contract_addr, + msg, + funds, + } => ( + ProxyMsg { + sender: info.sender.clone(), + msg, + funds, + }, + contract_addr, + ), + _ => return Err(InvalidMsgType), }; - let contract_info = deps.querier.query_wasm_contract_info(contract_addr.clone())?; + let contract_info = deps + .querier + .query_wasm_contract_info(contract_addr.clone())?; if !CODE_IDS.has(deps.storage, contract_info.code_id) { - return Err(InvalidCodeID {contract: contract_addr, code_id: contract_info.code_id}); + return Err(InvalidCodeID { + contract: contract_addr, + code_id: contract_info.code_id, + }); } - let exec_msg = WasmMsg::Execute {contract_addr, msg: to_json_binary(&proxy_msg)?, funds: proxy_msg.funds}; + let exec_msg = WasmMsg::Execute { + contract_addr, + msg: to_json_binary(&proxy_msg)?, + funds: proxy_msg.funds, + }; proxy_msgs.push(exec_msg); } - Ok( - Response::new().add_event(Event::new("proxied_msgs")).add_messages(proxy_msgs) - ) + Ok(Response::new() + .add_event(Event::new("proxied_msgs")) + .add_messages(proxy_msgs)) } - pub fn add_code_ids( deps: DepsMut, info: MessageInfo, @@ -107,18 +125,17 @@ pub fn add_code_ids( for code_id in code_ids.clone() { CODE_IDS.save(deps.storage, code_id, &true)?; - }; + } let code_ids_strs: Vec = code_ids.iter().map(|n| n.to_string()).collect(); let code_ids_str = code_ids_strs.join(", "); - Ok(Response::new().add_event( - Event::new("updated_proxy_code_ids") - .add_attributes(vec![ - ("admin", info.sender.as_str()), - ("new_code_ids", code_ids_str.as_str()), - ]), - )) + Ok( + Response::new().add_event(Event::new("updated_proxy_code_ids").add_attributes(vec![ + ("admin", info.sender.as_str()), + ("new_code_ids", code_ids_str.as_str()), + ])), + ) } pub fn remove_code_ids( @@ -130,16 +147,15 @@ pub fn remove_code_ids( for code_id in code_ids.clone() { CODE_IDS.remove(deps.storage, code_id); - }; + } let code_ids_strs: Vec = code_ids.iter().map(|n| n.to_string()).collect(); let code_ids_str = code_ids_strs.join(", "); - Ok(Response::new().add_event( - Event::new("updated_proxy_code_ids") - .add_attributes(vec![ - ("admin", info.sender.as_str()), - ("new_code_ids", code_ids_str.as_str()), - ]), - )) -} \ No newline at end of file + Ok( + Response::new().add_event(Event::new("updated_proxy_code_ids").add_attributes(vec![ + ("admin", info.sender.as_str()), + ("new_code_ids", code_ids_str.as_str()), + ])), + ) +} diff --git a/contracts/proxy/src/lib.rs b/contracts/proxy/src/lib.rs index ab0ab53..71e293a 100644 --- a/contracts/proxy/src/lib.rs +++ b/contracts/proxy/src/lib.rs @@ -1,9 +1,9 @@ #[cfg(not(feature = "library"))] pub mod contract; +mod error; +mod execute; mod msg; mod state; -mod execute; -mod error; pub const CONTRACT_NAME: &str = "proxy"; pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/contracts/proxy/src/msg.rs b/contracts/proxy/src/msg.rs index ec2e738..32d9c4c 100644 --- a/contracts/proxy/src/msg.rs +++ b/contracts/proxy/src/msg.rs @@ -1,7 +1,6 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::{Addr, Binary, Coin, CosmosMsg, WasmMsg}; - #[cw_serde] pub struct InstantiateMsg { pub admin: Option, @@ -10,18 +9,10 @@ pub struct InstantiateMsg { #[cw_serde] pub enum ExecuteMsg { - ProxyMsgs { - msgs: Vec, - }, - UpdateAdmin { - new_admin: Option, - }, - AddCodeIDs { - code_ids: Vec, - }, - RemoveCodeIDs { - code_ids: Vec, - } + ProxyMsgs { msgs: Vec }, + UpdateAdmin { new_admin: Option }, + AddCodeIDs { code_ids: Vec }, + RemoveCodeIDs { code_ids: Vec }, } #[cw_serde] @@ -29,4 +20,4 @@ pub struct ProxyMsg { pub sender: Addr, pub msg: Binary, pub funds: Vec, -} \ No newline at end of file +} diff --git a/contracts/proxy/src/state.rs b/contracts/proxy/src/state.rs index 78d57eb..13907bf 100644 --- a/contracts/proxy/src/state.rs +++ b/contracts/proxy/src/state.rs @@ -1,6 +1,6 @@ +use cosmwasm_schema::cw_serde; use cosmwasm_std::Addr; use cw_storage_plus::{Item, Map}; -use cosmwasm_schema::cw_serde; pub const ADMIN: Item> = Item::new("admin"); pub const CODE_IDS: Map = Map::new("code_ids"); From 6876b0274148de5e3001fbbe81cbdc151d1e35e0 Mon Sep 17 00:00:00 2001 From: Ash Date: Mon, 30 Sep 2024 16:25:43 -0700 Subject: [PATCH 3/8] cleanup --- contracts/cw721-proxy/src/execute.rs | 38 +++++++++++++------------- contracts/cw721-proxy/src/extension.rs | 23 ---------------- contracts/cw721-proxy/src/lib.rs | 3 +- contracts/cw721-proxy/src/state.rs | 18 ------------ contracts/proxy/Cargo.toml | 6 +++- 5 files changed, 25 insertions(+), 63 deletions(-) delete mode 100644 contracts/cw721-proxy/src/extension.rs diff --git a/contracts/cw721-proxy/src/execute.rs b/contracts/cw721-proxy/src/execute.rs index cdda3ec..8f584c9 100644 --- a/contracts/cw721-proxy/src/execute.rs +++ b/contracts/cw721-proxy/src/execute.rs @@ -3,33 +3,31 @@ use crate::state::DefaultCw721ProxyContract; use crate::ContractError; use crate::ContractError::Unauthorized; use cosmwasm_std::{Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response}; +use cw721::msg::Cw721InstantiateMsg; use cw721::traits::{Cw721Execute, Cw721Query}; impl DefaultCw721ProxyContract<'static> { - pub fn instantiate( + pub fn instantiate_with_version( &self, deps: DepsMut, - env: Env, - info: MessageInfo, + env: &Env, + info: &MessageInfo, msg: InstantiateMsg, + contract_name: &str, + contract_version: &str, ) -> Result, ContractError> { // set the proxy addr self.proxy_addr.save(deps.storage, &msg.proxy_addr)?; // passthrough the rest - Ok(self - .base_contract - .instantiate(deps, &env, &info, msg.inner_msg)?) - } - - pub fn execute_proxy( - &self, - deps: DepsMut, - env: Env, - info: MessageInfo, - msg: InnerExecuteMsg, - ) -> Result, ContractError> { - Ok(self.base_contract.execute(deps, &env, &info, msg)?) + Ok(self.base_contract.instantiate_with_version( + deps, + &env, + &info, + msg.inner_msg, + contract_name, + contract_version, + )?) } pub fn execute( @@ -48,13 +46,15 @@ impl DefaultCw721ProxyContract<'static> { let new_info = MessageInfo { sender: proxy_msg.sender, - funds: info.funds, + funds: info.clone().funds, }; - self.execute_proxy(deps, env, new_info, proxy_msg.msg) + Ok(self + .base_contract + .execute(deps, &env, &new_info, proxy_msg.msg)?) } _ => { let inner_msg: InnerExecuteMsg = get_inner(msg)?; - self.execute_proxy(deps, env, info, inner_msg) + Ok(self.base_contract.execute(deps, &env, &info, inner_msg)?) } } } diff --git a/contracts/cw721-proxy/src/extension.rs b/contracts/cw721-proxy/src/extension.rs deleted file mode 100644 index 27e2722..0000000 --- a/contracts/cw721-proxy/src/extension.rs +++ /dev/null @@ -1,23 +0,0 @@ -use cosmwasm_schema::cw_serde; -use cosmwasm_std::{Addr, Binary, Empty}; -use cw721::state::Cw721Config; -use cw721::{ - DefaultOptionalCollectionExtension, DefaultOptionalCollectionExtensionMsg, - DefaultOptionalNftExtension, DefaultOptionalNftExtensionMsg, -}; -use std::marker::PhantomData; - -pub struct Cw721Proxy<'a> { - pub config: Cw721Config<'a, DefaultOptionalNftExtension>, - pub(crate) _collection_extension: PhantomData, - pub(crate) _nft_extension_msg: PhantomData, - pub(crate) _collection_extension_msg: PhantomData, - pub(crate) _extension_msg: PhantomData, - pub(crate) _extension_query_msg: PhantomData, - pub(crate) _custom_response_msg: PhantomData, -} - -pub struct ProxyMsg { - sender: Addr, - msg: Binary, -} diff --git a/contracts/cw721-proxy/src/lib.rs b/contracts/cw721-proxy/src/lib.rs index 0fd0033..956488e 100644 --- a/contracts/cw721-proxy/src/lib.rs +++ b/contracts/cw721-proxy/src/lib.rs @@ -2,8 +2,7 @@ pub mod contract; mod error; mod execute; -mod extension; -mod msg; +pub mod msg; mod state; pub use crate::error::ContractError; diff --git a/contracts/cw721-proxy/src/state.rs b/contracts/cw721-proxy/src/state.rs index 8d6f808..a286ad6 100644 --- a/contracts/cw721-proxy/src/state.rs +++ b/contracts/cw721-proxy/src/state.rs @@ -2,24 +2,6 @@ use cosmwasm_std::Addr; use cw721::extension::Cw721BaseExtensions; use cw_storage_plus::Item; -/* -pub struct DefaultCw721ExpirationContract<'a> { - pub expiration_days: Item<'a, u16>, // max 65535 days - pub mint_timestamps: Map<'a, &'a str, Timestamp>, - pub base_contract: Cw721OnchainExtensions<'a>, -} - -impl Default for DefaultCw721ExpirationContract<'static> { - fn default() -> Self { - Self { - expiration_days: Item::new("expiration_days"), - mint_timestamps: Map::new("mint_timestamps"), - base_contract: Cw721OnchainExtensions::default(), - } - } -} - */ - pub struct DefaultCw721ProxyContract<'a> { pub proxy_addr: Item<'a, Addr>, pub base_contract: Cw721BaseExtensions<'a>, diff --git a/contracts/proxy/Cargo.toml b/contracts/proxy/Cargo.toml index ad75f20..1ce45e9 100644 --- a/contracts/proxy/Cargo.toml +++ b/contracts/proxy/Cargo.toml @@ -20,4 +20,8 @@ thiserror = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } schemars = { workspace = true } -cosmos-sdk-proto = { workspace = true } \ No newline at end of file +cosmos-sdk-proto = { workspace = true } + +[dev-dependencies] +cw721-proxy = {path = "../cw721-proxy"} +cw721 = {git = "https://github.com/public-awesome/cw-nfts.git", version = "0.19.0"} From 3cdc8172efdbca27273951e4b9362a04d9cb948f Mon Sep 17 00:00:00 2001 From: Ash Date: Mon, 30 Sep 2024 16:41:53 -0700 Subject: [PATCH 4/8] linting --- contracts/cw721-proxy/src/contract.rs | 7 ++----- contracts/cw721-proxy/src/execute.rs | 5 ++--- contracts/cw721-proxy/src/msg.rs | 2 +- contracts/proxy/src/contract.rs | 2 +- contracts/proxy/src/execute.rs | 4 +--- contracts/proxy/src/msg.rs | 4 ++-- contracts/proxy/src/state.rs | 1 - 7 files changed, 9 insertions(+), 16 deletions(-) diff --git a/contracts/cw721-proxy/src/contract.rs b/contracts/cw721-proxy/src/contract.rs index be5eb9e..16300bb 100644 --- a/contracts/cw721-proxy/src/contract.rs +++ b/contracts/cw721-proxy/src/contract.rs @@ -3,11 +3,8 @@ use crate::state::DefaultCw721ProxyContract; use crate::{ContractError, CONTRACT_NAME, CONTRACT_VERSION}; use cosmwasm_std::entry_point; use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Response}; -use cw721::extension::Cw721Extensions; -use cw721::traits::{Cw721Execute, Cw721Query}; pub use cw721::*; pub use cw_ownable::{Action, Ownership, OwnershipError}; -use extension::Cw721BaseExtensions; #[entry_point] pub fn instantiate( @@ -28,13 +25,13 @@ pub fn execute( msg: ExecuteMsg, ) -> Result { let contract = DefaultCw721ProxyContract::default(); - contract.execute(deps, &env, &info, msg) + contract.execute(deps, env, info, msg) } #[entry_point] pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result { let contract = DefaultCw721ProxyContract::default(); - contract.query(deps, &env, msg) + contract.query(deps, env, msg) } #[entry_point] diff --git a/contracts/cw721-proxy/src/execute.rs b/contracts/cw721-proxy/src/execute.rs index 8f584c9..7b4eeac 100644 --- a/contracts/cw721-proxy/src/execute.rs +++ b/contracts/cw721-proxy/src/execute.rs @@ -3,7 +3,6 @@ use crate::state::DefaultCw721ProxyContract; use crate::ContractError; use crate::ContractError::Unauthorized; use cosmwasm_std::{Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response}; -use cw721::msg::Cw721InstantiateMsg; use cw721::traits::{Cw721Execute, Cw721Query}; impl DefaultCw721ProxyContract<'static> { @@ -22,8 +21,8 @@ impl DefaultCw721ProxyContract<'static> { // passthrough the rest Ok(self.base_contract.instantiate_with_version( deps, - &env, - &info, + env, + info, msg.inner_msg, contract_name, contract_version, diff --git a/contracts/cw721-proxy/src/msg.rs b/contracts/cw721-proxy/src/msg.rs index 63b8887..0c21c88 100644 --- a/contracts/cw721-proxy/src/msg.rs +++ b/contracts/cw721-proxy/src/msg.rs @@ -84,7 +84,7 @@ pub fn get_inner(msg: ExecuteMsg) -> Result { extension, }), ExecuteMsg::Burn { token_id } => Ok(InnerExecuteMsg::Burn { token_id }), - ExecuteMsg::UpdateExtension { msg } => Err(InvalidMsgType), // cannot convert a proxy msg into an inner msg + ExecuteMsg::UpdateExtension { .. } => Err(InvalidMsgType), // cannot convert a proxy msg into an inner msg ExecuteMsg::UpdateNftInfo { token_id, token_uri, diff --git a/contracts/proxy/src/contract.rs b/contracts/proxy/src/contract.rs index a0b42db..ac19d4a 100644 --- a/contracts/proxy/src/contract.rs +++ b/contracts/proxy/src/contract.rs @@ -2,7 +2,7 @@ use crate::error::ContractResult; use crate::msg::{ExecuteMsg, InstantiateMsg}; use crate::{execute, CONTRACT_NAME, CONTRACT_VERSION}; use cosmwasm_std::{ - entry_point, to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult, + entry_point, DepsMut, Env, MessageInfo, Response, }; #[entry_point] diff --git a/contracts/proxy/src/execute.rs b/contracts/proxy/src/execute.rs index 9422f2b..9d8e095 100644 --- a/contracts/proxy/src/execute.rs +++ b/contracts/proxy/src/execute.rs @@ -2,10 +2,8 @@ use crate::error::ContractError::{InvalidCodeID, InvalidMsgType, Unauthorized}; use crate::error::ContractResult; use crate::msg::ProxyMsg; use crate::state::{ADMIN, CODE_IDS}; -use cosmos_sdk_proto::cosmwasm::wasm::v1::QueryContractInfoRequest; -use cosmos_sdk_proto::traits::MessageExt; use cosmwasm_std::{ - to_json_binary, Addr, CosmosMsg, Deps, DepsMut, Env, Event, MessageInfo, Response, WasmMsg, + to_json_binary, Addr, Deps, DepsMut, Event, MessageInfo, Response, WasmMsg, }; pub fn init( diff --git a/contracts/proxy/src/msg.rs b/contracts/proxy/src/msg.rs index 32d9c4c..062984e 100644 --- a/contracts/proxy/src/msg.rs +++ b/contracts/proxy/src/msg.rs @@ -1,5 +1,5 @@ -use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::{Addr, Binary, Coin, CosmosMsg, WasmMsg}; +use cosmwasm_schema::{cw_serde}; +use cosmwasm_std::{Addr, Binary, Coin, WasmMsg}; #[cw_serde] pub struct InstantiateMsg { diff --git a/contracts/proxy/src/state.rs b/contracts/proxy/src/state.rs index 13907bf..3c36fbf 100644 --- a/contracts/proxy/src/state.rs +++ b/contracts/proxy/src/state.rs @@ -1,4 +1,3 @@ -use cosmwasm_schema::cw_serde; use cosmwasm_std::Addr; use cw_storage_plus::{Item, Map}; From 6005a4dc4a631f5189b2df9bb833635c997bf6a8 Mon Sep 17 00:00:00 2001 From: Ash Date: Mon, 30 Sep 2024 16:47:15 -0700 Subject: [PATCH 5/8] fmt --- contracts/proxy/src/contract.rs | 4 +--- contracts/proxy/src/execute.rs | 4 +--- contracts/proxy/src/msg.rs | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/contracts/proxy/src/contract.rs b/contracts/proxy/src/contract.rs index ac19d4a..0adb1bb 100644 --- a/contracts/proxy/src/contract.rs +++ b/contracts/proxy/src/contract.rs @@ -1,9 +1,7 @@ use crate::error::ContractResult; use crate::msg::{ExecuteMsg, InstantiateMsg}; use crate::{execute, CONTRACT_NAME, CONTRACT_VERSION}; -use cosmwasm_std::{ - entry_point, DepsMut, Env, MessageInfo, Response, -}; +use cosmwasm_std::{entry_point, DepsMut, Env, MessageInfo, Response}; #[entry_point] pub fn instantiate( diff --git a/contracts/proxy/src/execute.rs b/contracts/proxy/src/execute.rs index 9d8e095..2af2023 100644 --- a/contracts/proxy/src/execute.rs +++ b/contracts/proxy/src/execute.rs @@ -2,9 +2,7 @@ use crate::error::ContractError::{InvalidCodeID, InvalidMsgType, Unauthorized}; use crate::error::ContractResult; use crate::msg::ProxyMsg; use crate::state::{ADMIN, CODE_IDS}; -use cosmwasm_std::{ - to_json_binary, Addr, Deps, DepsMut, Event, MessageInfo, Response, WasmMsg, -}; +use cosmwasm_std::{to_json_binary, Addr, Deps, DepsMut, Event, MessageInfo, Response, WasmMsg}; pub fn init( deps: DepsMut, diff --git a/contracts/proxy/src/msg.rs b/contracts/proxy/src/msg.rs index 062984e..5a5b436 100644 --- a/contracts/proxy/src/msg.rs +++ b/contracts/proxy/src/msg.rs @@ -1,4 +1,4 @@ -use cosmwasm_schema::{cw_serde}; +use cosmwasm_schema::cw_serde; use cosmwasm_std::{Addr, Binary, Coin, WasmMsg}; #[cw_serde] From 45017ddb86fa34cff58dad09262d49bac82018fa Mon Sep 17 00:00:00 2001 From: Ash Date: Mon, 30 Sep 2024 16:54:25 -0700 Subject: [PATCH 6/8] clear unused var --- contracts/proxy/src/execute.rs | 6 +++--- contracts/proxy/src/msg.rs | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/contracts/proxy/src/execute.rs b/contracts/proxy/src/execute.rs index 2af2023..b25e970 100644 --- a/contracts/proxy/src/execute.rs +++ b/contracts/proxy/src/execute.rs @@ -74,7 +74,7 @@ pub fn proxy_msgs( let mut proxy_msgs: Vec = Vec::with_capacity(msgs.len()); for msg in msgs { - let (proxy_msg, contract_addr) = match msg { + let (proxy_msg, contract_addr, funds) = match msg { WasmMsg::Execute { contract_addr, msg, @@ -83,9 +83,9 @@ pub fn proxy_msgs( ProxyMsg { sender: info.sender.clone(), msg, - funds, }, contract_addr, + funds, ), _ => return Err(InvalidMsgType), }; @@ -102,7 +102,7 @@ pub fn proxy_msgs( let exec_msg = WasmMsg::Execute { contract_addr, msg: to_json_binary(&proxy_msg)?, - funds: proxy_msg.funds, + funds, }; proxy_msgs.push(exec_msg); } diff --git a/contracts/proxy/src/msg.rs b/contracts/proxy/src/msg.rs index 5a5b436..43c1ec8 100644 --- a/contracts/proxy/src/msg.rs +++ b/contracts/proxy/src/msg.rs @@ -19,5 +19,4 @@ pub enum ExecuteMsg { pub struct ProxyMsg { pub sender: Addr, pub msg: Binary, - pub funds: Vec, } From 02133aa71ccbeb76d8ddade4d5c955087fe1ddd8 Mon Sep 17 00:00:00 2001 From: Ash Date: Mon, 30 Sep 2024 16:59:14 -0700 Subject: [PATCH 7/8] linting --- contracts/cw721-proxy/src/error.rs | 4 +--- contracts/proxy/src/msg.rs | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/contracts/cw721-proxy/src/error.rs b/contracts/cw721-proxy/src/error.rs index 7e56d75..1957be0 100644 --- a/contracts/cw721-proxy/src/error.rs +++ b/contracts/cw721-proxy/src/error.rs @@ -1,12 +1,10 @@ -use cw721::error::Cw721ContractError; - #[derive(Debug, thiserror::Error)] pub enum ContractError { #[error(transparent)] Std(#[from] cosmwasm_std::StdError), #[error(transparent)] - Cw721(#[from] Cw721ContractError), + Cw721(#[from] cw721::error::Cw721ContractError), // #[error(transparent)] // Encode(#[from] cosmos_sdk_proto::prost::EncodeError), diff --git a/contracts/proxy/src/msg.rs b/contracts/proxy/src/msg.rs index 43c1ec8..f828f45 100644 --- a/contracts/proxy/src/msg.rs +++ b/contracts/proxy/src/msg.rs @@ -1,5 +1,5 @@ use cosmwasm_schema::cw_serde; -use cosmwasm_std::{Addr, Binary, Coin, WasmMsg}; +use cosmwasm_std::{Addr, Binary, WasmMsg}; #[cw_serde] pub struct InstantiateMsg { From d0b4c1f0979070edbdf5221fcc654e08339df92e Mon Sep 17 00:00:00 2001 From: Ash Date: Wed, 2 Oct 2024 15:39:40 +0100 Subject: [PATCH 8/8] example --- contracts/proxy/src/execute.rs | 79 +++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 35 deletions(-) diff --git a/contracts/proxy/src/execute.rs b/contracts/proxy/src/execute.rs index b25e970..031c208 100644 --- a/contracts/proxy/src/execute.rs +++ b/contracts/proxy/src/execute.rs @@ -30,41 +30,13 @@ pub fn init( )) } -pub fn is_admin(deps: Deps, address: Addr) -> ContractResult<()> { - let admin = ADMIN.load(deps.storage)?; - match admin { - None => Err(Unauthorized), - Some(a) => { - if a != address { - Err(Unauthorized) - } else { - Ok(()) - } - } - } -} - -pub fn update_admin( - deps: DepsMut, - info: MessageInfo, - new_admin: Option, -) -> ContractResult { - is_admin(deps.as_ref(), info.sender.clone())?; - - ADMIN.save(deps.storage, &new_admin)?; - - let admin_str: String = match new_admin { - None => String::new(), - Some(a) => a.into_string(), - }; - - Ok( - Response::new().add_event(Event::new("updated_treasury_admin").add_attributes(vec![ - ("old admin", info.sender.into_string()), - ("new admin", admin_str), - ])), - ) -} +// main logic: this contract is meant to allow a single address to represent +// multiple or dynamic other contracts. In this case, it is any contract that +// is backed by a particular code ID. The sender sends wrapped msgs of the +// WasmMsg::Execute type, which includes the target contract, and the msg binary. +// This proxy contract will make any necessary in-flight checks (code ID here) +// and then submit new ProxyMsg msgs to the target contract. The receiving +// contract must understand and authenticate such msgs pub fn proxy_msgs( deps: DepsMut, @@ -112,6 +84,43 @@ pub fn proxy_msgs( .add_messages(proxy_msgs)) } +// administration msgs + +pub fn is_admin(deps: Deps, address: Addr) -> ContractResult<()> { + let admin = ADMIN.load(deps.storage)?; + match admin { + None => Err(Unauthorized), + Some(a) => { + if a != address { + Err(Unauthorized) + } else { + Ok(()) + } + } + } +} + +pub fn update_admin( + deps: DepsMut, + info: MessageInfo, + new_admin: Option, +) -> ContractResult { + is_admin(deps.as_ref(), info.sender.clone())?; + + ADMIN.save(deps.storage, &new_admin)?; + + let admin_str: String = match new_admin { + None => String::new(), + Some(a) => a.into_string(), + }; + + Ok( + Response::new().add_event(Event::new("updated_treasury_admin").add_attributes(vec![ + ("old admin", info.sender.into_string()), + ("new admin", admin_str), + ])), + ) +} pub fn add_code_ids( deps: DepsMut, info: MessageInfo,