Skip to content

Commit

Permalink
Allow optional fees and implement cw-ownable for cw-admin-factory
Browse files Browse the repository at this point in the history
Fees will go to the owner
  • Loading branch information
ismellike committed Sep 8, 2023
1 parent bf3ef9c commit f2c1001
Show file tree
Hide file tree
Showing 8 changed files with 298 additions and 17 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions contracts/external/cw-admin-factory/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ cw-storage-plus = { workspace = true }
cw2 = { workspace = true }
thiserror = { workspace = true }
cw-utils = { workspace = true }
cw-ownable = { workspace = true }

[dev-dependencies]
cosmwasm-schema = { workspace = true }
Expand Down
102 changes: 93 additions & 9 deletions contracts/external/cw-admin-factory/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
use cosmwasm_std::{
Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, StdResult, SubMsg, WasmMsg,
to_binary, Attribute, BankMsg, Binary, Coin, Coins, Deps, DepsMut, Env, MessageInfo, Reply,
Response, StdResult, SubMsg, WasmMsg,
};

use cw2::set_contract_version;
use cw_ownable::{assert_owner, get_ownership, initialize_owner, update_ownership};
use cw_utils::parse_reply_instantiate_data;

use crate::error::ContractError;
use crate::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg};
use crate::state::FEE;

pub(crate) const CONTRACT_NAME: &str = "crates.io:cw-admin-factory";
pub(crate) const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");
Expand All @@ -19,17 +22,23 @@ pub fn instantiate(
deps: DepsMut,
_env: Env,
info: MessageInfo,
_msg: InstantiateMsg,
msg: InstantiateMsg,
) -> Result<Response, ContractError> {
set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;

let ownership = initialize_owner(deps.storage, deps.api, msg.owner.as_deref())?;
let attributes = update_fee_inner(deps, msg.fee)?;

Ok(Response::new()
.add_attribute("method", "instantiate")
.add_attribute("creator", info.sender))
.add_attribute("creator", info.sender)
.add_attributes(attributes)
.add_attributes(ownership.into_attributes()))
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
_deps: DepsMut,
deps: DepsMut,
env: Env,
info: MessageInfo,
msg: ExecuteMsg,
Expand All @@ -39,35 +48,110 @@ pub fn execute(
instantiate_msg: msg,
code_id,
label,
} => instantiate_contract(env, info, msg, code_id, label),
} => instantiate_contract(deps, env, info, msg, code_id, label),
ExecuteMsg::UpdateFee { fee } => execute_update_fee(deps, info, fee),
ExecuteMsg::UpdateOwnership(action) => {
let ownership = update_ownership(deps, &env.block, &info.sender, action)?;
Ok(Response::default().add_attributes(ownership.into_attributes()))
}
}
}

pub fn instantiate_contract(
deps: DepsMut,
env: Env,
info: MessageInfo,
instantiate_msg: Binary,
code_id: u64,
label: String,
) -> Result<Response, ContractError> {
// Validate and get coins struct
let mut funds = Coins::try_from(info.funds)?;

// Check for a fee and attach a bank send message if found
let mut response = Response::default();
match FEE.may_load(deps.storage)? {
Some(fee) => {
// Get the funds recipient
let ownership = get_ownership(deps.storage)?;

if ownership.owner.is_none() {
return Err(ContractError::Ownership(
cw_ownable::OwnershipError::NoOwner {},
));
}

// Subtract the fee from the funds
for coin in &fee {
funds.sub(coin.clone())?;
}

let msg = BankMsg::Send {
to_address: ownership.owner.unwrap().to_string(),
amount: fee,
};

response = response.add_message(msg);
}
None => {}
};

// Instantiate the specified contract with factory as the admin.
let instantiate = WasmMsg::Instantiate {
admin: Some(env.contract.address.to_string()),
code_id,
msg: instantiate_msg,
funds: info.funds,
funds: funds.into_vec(),
label,
};

let msg = SubMsg::reply_on_success(instantiate, INSTANTIATE_CONTRACT_REPLY_ID);
Ok(Response::default()

Ok(response
.add_attribute("action", "instantiate_cw_core")
.add_submessage(msg))
}

pub fn execute_update_fee(
deps: DepsMut,
info: MessageInfo,
fee: Option<Vec<Coin>>,
) -> Result<Response, ContractError> {
assert_owner(deps.storage, &info.sender)?;

let attributes = update_fee_inner(deps, fee)?;

Ok(Response::default()
.add_attribute("action", "execute_update_fee")
.add_attribute("sender", info.sender)
.add_attributes(attributes))
}

/// Updates the fee configuration and returns the fee attributes
fn update_fee_inner(
deps: DepsMut,
fee: Option<Vec<Coin>>,
) -> Result<Vec<Attribute>, ContractError> {
let fee = fee.map(|x| Coins::try_from(x)).transpose()?;
let fee_string = fee.as_ref().map_or("None".to_owned(), ToString::to_string);

match fee {
Some(fee) => FEE.save(deps.storage, &fee.into_vec())?,
None => FEE.remove(deps.storage),
}

Ok(vec![Attribute {
key: "fee".to_owned(),
value: fee_string,
}])
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn query(_deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
match msg {}
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
match msg {
QueryMsg::Ownership {} => to_binary(&get_ownership(deps.storage)?),
QueryMsg::Fee {} => to_binary(&FEE.may_load(deps.storage)?),
}
}

#[cfg_attr(not(feature = "library"), entry_point)]
Expand Down
9 changes: 8 additions & 1 deletion contracts/external/cw-admin-factory/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use cosmwasm_std::StdError;
use cosmwasm_std::{CoinsError, StdError};
use cw_ownable::OwnershipError;
use cw_utils::ParseReplyError;
use thiserror::Error;

Expand All @@ -7,6 +8,12 @@ pub enum ContractError {
#[error("{0}")]
Std(#[from] StdError),

#[error("{0}")]
Coins(#[from] CoinsError),

#[error("{0}")]
Ownership(#[from] OwnershipError),

#[error("Unauthorized")]
Unauthorized {},

Expand Down
1 change: 1 addition & 0 deletions contracts/external/cw-admin-factory/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
pub mod contract;
mod error;
pub mod msg;
pub mod state;

#[cfg(test)]
mod tests;
Expand Down
18 changes: 15 additions & 3 deletions contracts/external/cw-admin-factory/src/msg.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
use cosmwasm_schema::{cw_serde, QueryResponses};
use cosmwasm_std::Binary;
use cosmwasm_std::{Binary, Coin};
use cw_ownable::{cw_ownable_execute, cw_ownable_query};

#[cw_serde]
pub struct InstantiateMsg {}
pub struct InstantiateMsg {
pub owner: Option<String>,
pub fee: Option<Vec<Coin>>,
}

#[cw_ownable_execute]
#[cw_serde]
pub enum ExecuteMsg {
/// Instantiates the target contract with the provided instantiate message and code id and
Expand All @@ -13,11 +18,18 @@ pub enum ExecuteMsg {
code_id: u64,
label: String,
},
UpdateFee {
fee: Option<Vec<Coin>>,
},
}

#[cw_ownable_query]
#[cw_serde]
#[derive(QueryResponses)]
pub enum QueryMsg {}
pub enum QueryMsg {
#[returns(Option<Vec<Coin>>)]
Fee {},
}

#[cw_serde]
pub struct MigrateMsg {}
4 changes: 4 additions & 0 deletions contracts/external/cw-admin-factory/src/state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
use cosmwasm_std::Coin;
use cw_storage_plus::Item;

pub const FEE: Item<Vec<Coin>> = Item::new("fee");
Loading

0 comments on commit f2c1001

Please sign in to comment.