The Token Factory allows you to create your own native denoms, as recognised by the Cosmos SDK Bank Module.
This allows your protocol to issue its own token, without needing to support the CW20 standard. It means that all tokens on the Kujira network are compatible as gas-fee payments, and can be collected as protocol revenue and distributed to KUJI stakers.
Create a denom
kujirad tx denom create-denom mydenom
Mint it
kujirad tx denom mint 10000factory/kujira12345/mydenom kujira123...
and Burn it
kujirad tx denom burn 10000factory/kujira12345/mydenom
These commands can also be issued via your smart contracts. Please refer to the bindings published in kujira-rs:
{% embed url="https://docs.rs/kujira/0.7.5/kujira/msg/enum.KujiraMsg.html" %}
In order for the contract to be able to mint and burn a denom, it will need to be created by the contract itself, often upon instantation:
use kujira::msg::{DenomMsg, KujiraMsg};
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
deps: DepsMut<KujiraQuery>,
env: Env,
_info: MessageInfo,
msg: InstantiateMsg,
) -> Result<Response<KujiraMsg>, ContractError> {
let addr = env.contract.address;
let denom = format!("factory/{addr}/{denom}");
let config = Config::new(msg.owner, denom);
CONFIG.save(deps.storage, &config)?;
Ok(Response::default()
.add_message(DenomMsg::Create {
subdenom: msg.denom,
}))
}
Now your contract is the owner of the denom, we can mint and burn tokens. Here is an example contract whose purpose is to provide a permissioned list of addresses that can mint and burn, instead of just the admin:
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
deps: DepsMut<KujiraQuery>,
_env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> Result<Response<KujiraMsg>, ContractError> {
let mut c = CONFIG.load(deps.storage)?;
match msg {
ExecuteMsg::Burn {} => {
let amt = amount(&c.denom, info.funds)?;
c.validate_permitted(info.sender)?;
Ok(Response::default()
.add_attributes(vec![attr("action", "burn"), attr("amount", amt)])
.add_message(CosmosMsg::Custom(KujiraMsg::Denom(DenomMsg::Burn {
denom: c.denom,
amount: amt,
}))))
}
ExecuteMsg::Mint { amount, recipient } => {
c.validate_permitted(info.sender)?;
Ok(Response::default()
.add_attributes(vec![attr("action", "mint"), attr("amount", amount)])
.add_message(CosmosMsg::Custom(KujiraMsg::Denom(DenomMsg::Mint {
denom: c.denom,
amount,
recipient,
}))))
}
ExecuteMsg::Permit { address } => {
c.validate_owner(info.sender)?;
c.permit(address.clone());
CONFIG.save(deps.storage, &c)?;
Ok(Response::default()
.add_attributes(vec![attr("action", "permit"), attr("address", address)]))
}
}
}