contract; use std::storage::*; use std::string::String; use std::block::timestamp; use std::hash::{Hash, sha256}; use std::storage::storage_string::{*, StorageString}; use std::call_frames::msg_asset_id; use std::context::msg_amount; use standards::src20::{SRC20, TotalSupplyEvent}; use standards::src7::{SRC7, Metadata}; use standards::src3::SRC3; use standards::src5::{SRC5, State}; use sway_libs::asset::supply::{_burn, _mint}; use sway_libs::asset::metadata::*; use sway_libs::asset::base::{_total_assets,_total_supply, _set_name, _name, SetAssetAttributes}; use sway_libs::{admin::*, ownership::*}; pub enum MintError { CannotMintMoreThanOneNFTWithSubId: (), MaxNFTsMinted: (), NFTAlreadyMinted: (), } pub enum SetError { ValueAlreadySet: (), } configurable { /// The decimals of the asset minted by this contract. DECIMALS: u8 = 0u8, /// The symbol of the asset minted by this contract. SYMBOL: str[3] = __to_str_array("BID"), } storage { total_assets: u64 = 0, total_supply: StorageMap = StorageMap {}, name: StorageMap = StorageMap {}, metadata: StorageMetadata = StorageMetadata {}, } abi Constructor { #[storage(read, write)] fn constructor(owner: Identity, admin: Identity); } impl Constructor for Contract { #[storage(read, write)] fn constructor(owner: Identity, admin: Identity) { initialize_ownership(owner); add_admin(admin); } } abi Admin { #[storage(read, write)] fn revoke_admin(admin: Identity); #[storage(read, write)] fn add_admin(admin: Identity); #[storage(read, write)] fn transfer_ownership(new_owner: Identity); } impl Admin for Contract { #[storage(read, write)] fn revoke_admin(admin: Identity) { only_owner(); revoke_admin(admin); } #[storage(read, write)] fn add_admin(admin: Identity) { only_owner(); add_admin(admin); } #[storage(read, write)] fn transfer_ownership(new_owner: Identity) { only_owner(); transfer_ownership(new_owner); } } impl SRC20 for Contract { #[storage(read)] fn total_assets() -> u64 { _total_assets(storage.total_assets) } #[storage(read)] fn total_supply(asset: AssetId) -> Option { _total_supply(storage.total_supply, asset) } #[storage(read)] fn name(asset: AssetId) -> Option { _name(storage.name, asset) } #[storage(read)] fn symbol(asset: AssetId) -> Option { match storage.total_supply.get(asset).try_read() { Some(_) => Some(String::from_ascii_str(from_str_array(SYMBOL))), None => None, } } #[storage(read)] fn decimals(asset: AssetId) -> Option { match storage.total_supply.get(asset).try_read() { Some(_) => Some(DECIMALS), None => None, } } } impl SRC7 for Contract { #[storage(read)] fn metadata(asset: AssetId, key: String) -> Option { storage.metadata.get(asset, key) } } impl SRC3 for Contract { #[storage(read, write)] fn mint(recipient: Identity, sub_id: Option, amount: u64) { only_admin(); require(sub_id.is_some(), MintError::CannotMintMoreThanOneNFTWithSubId); // Checks to ensure this is a valid mint. let asset = AssetId::new(ContractId::this(), sub_id.unwrap()); require(amount == 1, MintError::CannotMintMoreThanOneNFTWithSubId); require( storage .total_supply .get(asset) .try_read() .is_none(), MintError::NFTAlreadyMinted, ); // Mint the NFT let _ = _mint( storage .total_assets, storage .total_supply, recipient, sub_id.unwrap(), amount, ); } #[payable] #[storage(read, write)] fn burn(sub_id: SubId, amount: u64) { only_admin(); _burn(storage.total_supply, sub_id, amount); } } impl SRC5 for Contract { #[storage(read)] fn owner() -> State { _owner() } } impl SetAssetAttributes for Contract { #[storage(write)] fn set_name(asset: AssetId, name: String) { only_admin(); require( storage .name .get(asset) .read_slice() .is_none(), SetError::ValueAlreadySet, ); _set_name(storage.name, asset, name); } #[storage(write)] fn set_symbol(asset: AssetId, symbol: String) { require(false, SetError::ValueAlreadySet); } #[storage(write)] fn set_decimals(_asset: AssetId, _decimals: u8) { require(false, SetError::ValueAlreadySet); } } impl SetAssetMetadata for Contract { #[storage(read, write)] fn set_metadata(asset: AssetId, key: String, metadata: Metadata) { only_admin(); _set_metadata(storage.metadata, asset, key, metadata); } }