use cosmwasm_std::{DepsMut, StdError, Uint128};
use cw20::{EmbeddedLogo, Logo, LogoInfo, MarketingInfoResponse};
use cw20_base::msg::InstantiateMsg;
use cw20_base::state::{MinterData, TokenInfo, LOGO, MARKETING_INFO, TOKEN_INFO};
use cw20_base::ContractError;
pub fn instantiate_token_info_and_marketing(
deps: &mut DepsMut,
msg: InstantiateMsg,
total_supply: Uint128,
) -> Result<(), ContractError> {
if let Some(limit) = msg.get_cap() {
if total_supply > limit {
return Err(StdError::generic_err("Initial supply greater than cap").into());
}
}
let mint = match msg.mint {
Some(m) => Some(MinterData {
minter: deps.api.addr_validate(&m.minter)?,
cap: m.cap,
}),
None => None,
};
let data = TokenInfo {
name: msg.name,
symbol: msg.symbol,
decimals: msg.decimals,
total_supply,
mint,
};
TOKEN_INFO.save(deps.storage, &data)?;
if let Some(marketing) = msg.marketing {
let logo = if let Some(logo) = marketing.logo {
verify_logo(&logo)?;
LOGO.save(deps.storage, &logo)?;
match logo {
Logo::Url(url) => Some(LogoInfo::Url(url)),
Logo::Embedded(_) => Some(LogoInfo::Embedded),
}
} else {
None
};
let data = MarketingInfoResponse {
project: marketing.project,
description: marketing.description,
marketing: marketing
.marketing
.map(|addr| deps.api.addr_validate(&addr))
.transpose()?,
logo,
};
MARKETING_INFO.save(deps.storage, &data)?;
}
Ok(())
}
const LOGO_SIZE_CAP: usize = 5 * 1024;
fn verify_xml_preamble(data: &[u8]) -> Result<(), ContractError> {
let preamble = data
.split_inclusive(|c| *c == b'>')
.next()
.ok_or(ContractError::InvalidXmlPreamble {})?;
const PREFIX: &[u8] = b"<?xml ";
const POSTFIX: &[u8] = b"?>";
if !(preamble.starts_with(PREFIX) && preamble.ends_with(POSTFIX)) {
Err(ContractError::InvalidXmlPreamble {})
} else {
Ok(())
}
}
fn verify_xml_logo(logo: &[u8]) -> Result<(), ContractError> {
verify_xml_preamble(logo)?;
if logo.len() > LOGO_SIZE_CAP {
Err(ContractError::LogoTooBig {})
} else {
Ok(())
}
}
fn verify_png_logo(logo: &[u8]) -> Result<(), ContractError> {
const HEADER: [u8; 8] = [0x89, b'P', b'N', b'G', 0x0d, 0x0a, 0x1a, 0x0a];
if logo.len() > LOGO_SIZE_CAP {
Err(ContractError::LogoTooBig {})
} else if !logo.starts_with(&HEADER) {
Err(ContractError::InvalidPngHeader {})
} else {
Ok(())
}
}
fn verify_logo(logo: &Logo) -> Result<(), ContractError> {
match logo {
Logo::Embedded(EmbeddedLogo::Svg(logo)) => verify_xml_logo(logo),
Logo::Embedded(EmbeddedLogo::Png(logo)) => verify_png_logo(logo),
Logo::Url(_) => Ok(()), }
}