use cosmwasm_schema::cw_serde;
use cosmwasm_std::{
attr, Addr, Api, CustomQuery, DepsMut, Env, MessageInfo, Response, StdError, StdResult,
};
use cw_storage_plus::Item;
const MAX_PROPOSAL_TTL: u64 = 1209600;
pub const LP_SUBDENOM: &str = "astroport/share";
#[cw_serde]
pub struct OwnershipProposal {
pub owner: Addr,
pub ttl: u64,
}
pub fn propose_new_owner<C, T>(
deps: DepsMut<C>,
info: MessageInfo,
env: Env,
new_owner: String,
expires_in: u64,
owner: Addr,
proposal: Item<OwnershipProposal>,
) -> StdResult<Response<T>>
where
C: CustomQuery,
{
if info.sender != owner {
return Err(StdError::generic_err("Unauthorized"));
}
let new_owner = deps.api.addr_validate(new_owner.as_str())?;
if new_owner == owner {
return Err(StdError::generic_err("New owner cannot be same"));
}
if MAX_PROPOSAL_TTL < expires_in {
return Err(StdError::generic_err(format!(
"Parameter expires_in cannot be higher than {MAX_PROPOSAL_TTL}"
)));
}
proposal.save(
deps.storage,
&OwnershipProposal {
owner: new_owner.clone(),
ttl: env.block.time.seconds() + expires_in,
},
)?;
Ok(Response::new().add_attributes(vec![
attr("action", "propose_new_owner"),
attr("new_owner", new_owner),
]))
}
pub fn drop_ownership_proposal<C, T>(
deps: DepsMut<C>,
info: MessageInfo,
owner: Addr,
proposal: Item<OwnershipProposal>,
) -> StdResult<Response<T>>
where
C: CustomQuery,
{
if info.sender != owner {
return Err(StdError::generic_err("Unauthorized"));
}
proposal.remove(deps.storage);
Ok(Response::new().add_attributes(vec![attr("action", "drop_ownership_proposal")]))
}
pub fn claim_ownership<C, T>(
deps: DepsMut<C>,
info: MessageInfo,
env: Env,
proposal: Item<OwnershipProposal>,
cb: fn(DepsMut<C>, Addr) -> StdResult<()>,
) -> StdResult<Response<T>>
where
C: CustomQuery,
{
let p = proposal
.load(deps.storage)
.map_err(|_| StdError::generic_err("Ownership proposal not found"))?;
if info.sender != p.owner {
return Err(StdError::generic_err("Unauthorized"));
}
if env.block.time.seconds() > p.ttl {
return Err(StdError::generic_err("Ownership proposal expired"));
}
proposal.remove(deps.storage);
cb(deps, p.owner.clone())?;
Ok(Response::new().add_attributes(vec![
attr("action", "claim_ownership"),
attr("new_owner", p.owner),
]))
}
pub fn validate_addresses(api: &dyn Api, admins: &[String]) -> StdResult<Vec<Addr>> {
admins.iter().map(|addr| api.addr_validate(addr)).collect()
}